package com.aemreunal.domain; /* * *********************** * * Copyright (c) 2015 * * * * This code belongs to: * * * * @author Ahmet Emre Ünal * * S001974 * * * * aemreunal@gmail.com * * emre.unal@ozu.edu.tr * * * * aemreunal.com * * *********************** * */ import net.minidev.json.JSONObject; import java.io.Serializable; import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; import javax.persistence.*; import javax.validation.constraints.Size; import org.springframework.hateoas.ResourceSupport; import org.springframework.web.bind.annotation.ResponseBody; import com.aemreunal.helper.ImageProperties; import com.aemreunal.helper.json.JsonBuilderFactory; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity @Table(name = "regions") @ResponseBody @JsonIgnoreProperties(value = { "beacons", "project", "mapImageFileName", "designatedBeacons" }) public class Region extends ResourceSupport implements Serializable, Comparable { public static final int NAME_MAX_LENGTH = 50; public static final int DESCRIPTION_MAX_LENGTH = 200; public static final int DISPLAY_NAME_MAX_LENGTH = 50; public static final int UUID_MAX_LENGTH = 36; // UUID hex string (including dashes) is 36 characters long /* *------------------------------------------------------------ * BEGIN: Region 'ID' attribute */ @Id @Column(name = "region_id") @GeneratedValue(strategy = GenerationType.AUTO) @Access(AccessType.PROPERTY) private Long regionId; /* * END: Region 'ID' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'name' attribute */ @Column(name = "name", nullable = false, length = NAME_MAX_LENGTH) @Size(min = 1, max = NAME_MAX_LENGTH) @Access(AccessType.PROPERTY) private String name = ""; /* * END: Region 'name' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'description' attribute */ @Column(name = "description", nullable = false, length = DESCRIPTION_MAX_LENGTH) @Size(max = DESCRIPTION_MAX_LENGTH) @Access(AccessType.PROPERTY) private String description = ""; /* * END: Region 'description' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Beacon 'display name' attribute * * A 'display name' is a user-friendly text that can be displayed on a client as * the name of this region/location. For example, the region description may be * "AB2, Floor 4, North", which isn't a user-friendly way to describe a location. * This text can be "Student Center, 4th floor", which can be displayed to a user * to describe the area this region represents. */ @Column(name = "display_name", nullable = false, length = DISPLAY_NAME_MAX_LENGTH) @Size(max = DISPLAY_NAME_MAX_LENGTH) @Access(AccessType.PROPERTY) private String displayName = ""; /* * END: Beacon 'display name' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'Map image' attribute * * The length is UUID_MAX_LENGTH, because image names are set as UUIDs. */ @Column(name = "map_image_name", nullable = false, length = UUID_MAX_LENGTH) @Size(min = UUID_MAX_LENGTH, max = UUID_MAX_LENGTH) @Access(AccessType.PROPERTY) private String mapImageFileName = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; /* * END: Region 'Map image' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'region width' attribute * * Represents region width in width of the image as pixels. */ @Column(name = "region_width", nullable = false) @Access(AccessType.PROPERTY) private Integer regionWidth = 0; /* * END: Region 'region width' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'region height' attribute * * Represents region height in height of the image as pixels. */ @Column(name = "region_height", nullable = false) @Access(AccessType.PROPERTY) private Integer regionHeight = 0; /* * END: Region 'region height' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'beacons' attribute * * Currently, Beacon is the owner of its relationship to Region. * ManyToOne are (almost) always the owner side of a bidirectional relationship in the JPA spec * * Should Beacon even know/care about which region(s) it belongs to? * * Correct mapping: 2.2.5.3.1.1. Bidirectional * http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html * * @JoinTable(name="region_members", * joinColumns = @JoinColumn(name="region_id"), * inverseJoinColumns = @JoinColumn(name="beacon_id")) * * TODO:XNYLXIWD determine who should own this relationship */ @OneToMany(targetEntity = Beacon.class, mappedBy = "region", fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.REMOVE) @Access(AccessType.PROPERTY) private Set<Beacon> beacons = new LinkedHashSet<Beacon>(); /* * END: Region 'beacons' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'project' attribute */ @ManyToOne(targetEntity = Project.class, optional = false, fetch = FetchType.LAZY) @JoinTable(name = "projects_to_regions", joinColumns = @JoinColumn(name = "region_id"), inverseJoinColumns = @JoinColumn(name = "project_id")) @Access(AccessType.PROPERTY) private Project project; /* * END: Region 'project' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'creationDate' attribute */ @Column(name = "creation_date", nullable = false) @Access(AccessType.PROPERTY) private Date creationDate = null; // @CreatedDate /* * END: Region 'creationDate' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Region 'lastUpdateDate' attribute */ @Column(name = "last_update_date", nullable = false) @Access(AccessType.PROPERTY) private Date lastUpdatedDate = null; // @LastModifiedDate /* * END: Region 'lastUpdateDate' attribute *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Constructors */ public Region() { // Empty constructor for Spring & Hibernate } /* * END: Constructors *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Helpers */ public void setImageProperties(ImageProperties imageProperties) { this.setMapImageFileName(imageProperties.getImageFileName()); this.setRegionWidth(imageProperties.getImageWidth()); this.setRegionHeight(imageProperties.getImageHeight()); } public boolean beaconCoordsAreValid(Beacon beacon) { Integer beaconX = beacon.getxCoordinate(); Integer beaconY = beacon.getyCoordinate(); boolean xIsValid = beaconX >= 0 && beaconX < this.getRegionWidth(); boolean yIsValid = beaconY >= 0 && beaconY < this.getRegionHeight(); return xIsValid && yIsValid; } public void markAsUpdated() { setLastUpdatedDate(new Date()); } public JSONObject getQueryResponse() { return JsonBuilderFactory.object() .add("regionId", getRegionId()) .add("displayName", getDisplayName()) .add("regionWidth", getRegionWidth()) .add("regionHeight", getRegionHeight()) .add("lastUpdatedDate", getLastUpdatedDate()) .add("links", getLinks()) .build(); } /* * END: Helpers *------------------------------------------------------------ */ /* *------------------------------------------------------------ * BEGIN: Getters & Setters */ public Long getRegionId() { return regionId; } public void setRegionId(Long regionId) { this.regionId = regionId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getDisplayName() { return displayName; } public void setDisplayName(String displayName) { this.displayName = displayName; } public String getMapImageFileName() { return mapImageFileName; } public void setMapImageFileName(String mapImageFileName) { this.mapImageFileName = mapImageFileName; } public Integer getRegionWidth() { return regionWidth; } public void setRegionWidth(Integer regionWidth) { this.regionWidth = regionWidth; } public Integer getRegionHeight() { return regionHeight; } public void setRegionHeight(Integer regionHeight) { this.regionHeight = regionHeight; } public Set<Beacon> getBeacons() { return beacons; } public void setBeacons(Set<Beacon> beacons) { this.beacons = beacons; } public Project getProject() { return project; } public void setProject(Project project) { this.project = project; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Date getLastUpdatedDate() { return lastUpdatedDate; } public void setLastUpdatedDate(Date lastUpdatedDate) { this.lastUpdatedDate = lastUpdatedDate; } /* * END: Getters & Setters *------------------------------------------------------------ */ @PrePersist private void setInitialProperties() { // Set beacon creation date if (creationDate == null) { Date now = new Date(); setCreationDate(now); setLastUpdatedDate(now); } } @Override public String toString() { return "[Region: " + getRegionId() + ", Project: " + getProject().getProjectId() + "]"; } @Override public boolean equals(Object obj) { if (obj instanceof Region) { return ((Region) obj).getRegionId().equals(this.getRegionId()); } return false; } @Override public int compareTo(Object o) { if (o instanceof Region) { return this.getRegionId().compareTo(((Region) o).getRegionId()); } return 0; } }