/* * ==================================================================== * * Copyright (C) 2007 - 2012 GeoSolutions S.A.S. * http://www.geo-solutions.it * * GPLv3 + Classpath exception * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. * * ==================================================================== * * This software consists of voluntary contributions made by developers * of GeoSolutions. For more information on GeoSolutions, please see * <http://www.geo-solutions.it/>. * */ package it.geosolutions.geostore.core.model; import it.geosolutions.geostore.core.model.enums.DataType; import java.io.Serializable; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; import javax.persistence.UniqueConstraint; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; /** * Class Attribute. * * @author Tobia di Pisa (tobia.dipisa at geo-solutions.it) * @author Emanuele Tajariol (etj at geo-solutions.it) */ @Entity(name = "Attribute") @Table(name = "gs_attribute", uniqueConstraints = { @UniqueConstraint(columnNames = { "name", "resource_id" }) }) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "gs_attribute") @XmlRootElement(name = "Attribute") public class Attribute implements Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = -1298676702253831972L; @Id @GeneratedValue private Long id; @Column(name = "name", nullable = false, updatable = true) @Index(name = "idx_attribute_name") private String name; @Column(name = "attribute_text", nullable = true, updatable = true) @Index(name = "idx_attribute_text") private String textValue; @Column(name = "attribute_number", nullable = true, updatable = true) @Index(name = "idx_attribute_number") private Double numberValue; @Column(name = "attribute_date", nullable = true, updatable = true) @Index(name = "idx_attribute_date") @Temporal(TemporalType.TIMESTAMP) private Date dateValue; @Column(name = "attribute_type", nullable = false, updatable = false) @Index(name = "idx_attribute_type") @Enumerated(EnumType.STRING) private DataType type; @ManyToOne(optional = false) @Index(name = "idx_attribute_resource") @ForeignKey(name = "fk_attribute_resource") private Resource resource; /** * Only used for XML un/marshalling */ public final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); /** * @throws Exception */ @PreUpdate @PrePersist public void onPreUpdate() throws Exception { if (textValue == null && numberValue == null && dateValue == null) { throw new NullPointerException("Null value not allowed in attribute: " + this.toString()); } else if ((this.textValue == null && (this.numberValue != null ^ this.dateValue != null)) || (this.numberValue == null && (this.textValue != null ^ this.dateValue != null)) || (this.dateValue == null && (this.textValue != null ^ this.numberValue != null))) { this.type = this.textValue != null ? DataType.STRING : (this.numberValue != null ? DataType.NUMBER : DataType.DATE); } else { throw new Exception("Only one DataType can be not-null inside the Attribute entity: " + this.toString()); } } /** * @return the id */ @XmlTransient public long getId() { return id; } /** * @param id the id to set */ public void setId(long id) { this.id = id; } /** * @return the attribute */ public String getName() { return name; } /** * @param name the attribute to set */ public void setName(String name) { this.name = name; } /** * @return the textValue */ @XmlTransient public String getTextValue() { return textValue; } /** * @param textValue the textValue to set */ public void setTextValue(String textValue) { this.textValue = textValue; } /** * @return the numberValue */ @XmlTransient public Double getNumberValue() { return numberValue; } /** * @param numberValue the numberValue to set */ public void setNumberValue(Double numberValue) { this.numberValue = numberValue; } /** * @return the dateValue */ @XmlTransient public Date getDateValue() { return dateValue; } /** * @param dateValue the dateValue to set */ public void setDateValue(Date dateValue) { this.dateValue = dateValue; } /** * Only used for XML marshalling */ @Transient @XmlElement public String getValue() { switch (type) { case DATE: return DATE_FORMAT.format(dateValue); case NUMBER: return numberValue.toString(); case STRING: return textValue.toString(); default: throw new IllegalStateException("Unknown type " + type); } } /** * Only used for XML unmarshalling */ protected void setValue(String text) { if (type != null) { setValue(text, type); } else { throw new IllegalStateException("Setting value with no type selected"); } } protected void setValue(String text, DataType type) { switch (type) { case DATE: try { dateValue = DATE_FORMAT.parse(text); } catch (Exception e) { throw new IllegalArgumentException("Can't parse date [" + text + "]", e); } break; case NUMBER: try { numberValue = Double.valueOf(text); } catch (NumberFormatException e) { throw new IllegalArgumentException("Can't parse double [" + text + "]", e); } break; case STRING: textValue = text; break; default: throw new IllegalStateException("Unknown type " + type); } } /** * THe XMLAttribute annotation is to make sure that type will be unmarshalled before value. * * @return the type */ @XmlAttribute public DataType getType() { return type; } /** * @param type the type to set */ public void setType(DataType type) { this.type = type; } /** * @return the resource */ @XmlTransient public Resource getResource() { return resource; } /** * @param resource the resource to set */ public void setResource(Resource resource) { this.resource = resource; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()).append('['); if (id != null) { builder.append("id=").append(id); } else builder.append("id is null"); if (name != null) { builder.append(", name=").append(name); } if (textValue != null) { builder.append(", textValue=").append(textValue); } if (numberValue != null) { builder.append(", numberValue=").append(numberValue); } if (dateValue != null) { builder.append(", dateValue=").append(dateValue); } if (textValue == null && numberValue == null && dateValue == null) { builder.append(", value is null"); } if (type != null) { builder.append(", type=").append(type); } builder.append(']'); return builder.toString(); } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((dateValue == null) ? 0 : dateValue.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((numberValue == null) ? 0 : numberValue.hashCode()); result = prime * result + ((resource == null) ? 0 : resource.hashCode()); result = prime * result + ((textValue == null) ? 0 : textValue.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Attribute other = (Attribute) obj; if (dateValue == null) { if (other.dateValue != null) return false; } else if (!dateValue.equals(other.dateValue)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (numberValue == null) { if (other.numberValue != null) return false; } else if (!numberValue.equals(other.numberValue)) return false; if (resource == null) { if (other.resource != null) return false; } else if (!resource.equals(other.resource)) return false; if (textValue == null) { if (other.textValue != null) return false; } else if (!textValue.equals(other.textValue)) return false; if (type != other.type) return false; return true; } }