cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/TaxonRelationshipType.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/package-info.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/package.html -text
+cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/validation/EntityConstraintViolation.java -text
+cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/validation/EntityValidationResult.java -text
+cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/validation/SeverityType.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/view/AuditEvent.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/view/AuditEventRecord.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/view/AuditEventRecordImpl.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/parser/TaxonNameParserHistory.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/parser/TimePeriodParser.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/parser/location/CoordinateConverter.java -text
+cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/CRUDEventType.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/Level2.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/Level3.java -text
+cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/Severity.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/ValidationException.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/annotation/BasionymsMustShareEpithetsAndAuthors.java -text
cdmlib-model/src/main/java/eu/etaxonomy/cdm/validation/annotation/ChildTaxaMustBeLowerRankThanParent.java -text
--- /dev/null
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/ \r
+package eu.etaxonomy.cdm.model.validation;\r
+\r
+import javax.persistence.Entity;\r
+import javax.persistence.FetchType;\r
+import javax.persistence.ManyToOne;\r
+import javax.validation.ConstraintValidator;\r
+import javax.xml.bind.annotation.XmlAccessType;\r
+import javax.xml.bind.annotation.XmlAccessorType;\r
+import javax.xml.bind.annotation.XmlElement;\r
+import javax.xml.bind.annotation.XmlRootElement;\r
+import javax.xml.bind.annotation.XmlType;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.hibernate.annotations.Cascade;\r
+import org.hibernate.annotations.CascadeType;\r
+import org.hibernate.annotations.Type;\r
+\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.validation.Severity;\r
+\r
+/**\r
+ * An {@code EntityConstraintViolation} represents a single error resulting from the\r
+ * validation of an entity. It basically is a database model for the\r
+ * {@link ConstraintValidator} class of the javax.validation framework.\r
+ * \r
+ * @author admin.ayco.holleman\r
+ * \r
+ */\r
+\r
+@XmlAccessorType(XmlAccessType.FIELD)\r
+//@formatter:off\r
+@XmlType(name = "EntityConstraintViolation", propOrder = {\r
+ "PropertyPath",\r
+ "UserFriendlyFieldName",\r
+ "InvalidValue",\r
+ "Severity",\r
+ "Message",\r
+ "Validator",\r
+ "EntityValidationResult"\r
+})\r
+//@formatter:on\r
+@XmlRootElement(name = "EntityConstraintViolation")\r
+@Entity\r
+public class EntityConstraintViolation extends CdmBase {\r
+ private static final long serialVersionUID = 6685798691716413950L;\r
+\r
+ @SuppressWarnings("unused")\r
+ private static final Logger logger = Logger.getLogger(EntityConstraintViolation.class);\r
+\r
+\r
+ public static EntityConstraintViolation NewInstance(){\r
+ return new EntityConstraintViolation();\r
+ }\r
+\r
+ @XmlElement(name = "PropertyPath")\r
+ private String propertyPath;\r
+\r
+ @XmlElement(name = "UserFriendlyFieldName")\r
+ private String userFriendlyFieldName;\r
+\r
+ @XmlElement(name = "InvalidValue")\r
+ private String invalidValue;\r
+\r
+ @XmlElement(name = "Severity")\r
+ @Type(type = "eu.etaxonomy.cdm.model.validation.SeverityType")\r
+ private Severity severity;\r
+\r
+ @XmlElement(name = "Message")\r
+ private String message;\r
+\r
+ @XmlElement(name = "Validator")\r
+ private String validator;\r
+\r
+ @XmlElement(name = "EntityValidationResult")\r
+ @ManyToOne(fetch = FetchType.LAZY)\r
+ @Cascade({ CascadeType.ALL })\r
+ private EntityValidationResult entityValidationResult;\r
+\r
+\r
+ protected EntityConstraintViolation(){\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the path from the root bean to the field with the invalid value. Ordinarily\r
+ * this simply is the simple name of the field of the validated entity (see\r
+ * {@link EntityValidationResult#getValidatedEntityClass()}). Only if you have used @Valid\r
+ * annotations, and the error was in a parent or child entity, will this be a\r
+ * dot-separated path (e.g. "addresses[0].street" or "company.name").\r
+ */\r
+ public String getPropertyPath(){\r
+ return propertyPath;\r
+ }\r
+ public void setPropertyPath(String propertyPath){\r
+ this.propertyPath = propertyPath;\r
+ }\r
+\r
+\r
+ /**\r
+ * A user-friendly name for the property path.\r
+ */\r
+ public String getUserFriendlyFieldName(){\r
+ return userFriendlyFieldName;\r
+ }\r
+ public void setUserFriendlyFieldName(String userFriendlyFieldName){\r
+ this.userFriendlyFieldName = userFriendlyFieldName;\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the value that violated the constraint.\r
+ * @return\r
+ */\r
+ public String getInvalidValue(){\r
+ return invalidValue;\r
+ }\r
+\r
+ public void setInvalidValue(String invalidValue){\r
+ this.invalidValue = invalidValue;\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the severity of the constraint violation.\r
+ * \r
+ * @return\r
+ */\r
+ public Severity getSeverity(){\r
+ return severity;\r
+ }\r
+ public void setSeverity(Severity severity){\r
+ this.severity = severity;\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the error message associated with the constraint violation.\r
+ * \r
+ * @return The error message\r
+ */\r
+ public String getMessage(){\r
+ return message;\r
+ }\r
+ public void setMessage(String message){\r
+ this.message = message;\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the fully qualified class name of the {@link ConstraintValidator} responsible\r
+ * for invalidating the entity.\r
+ * \r
+ * @param validator\r
+ */\r
+ public String getValidator(){\r
+ return validator;\r
+ }\r
+ public void setValidator(String validator){\r
+ this.validator = validator;\r
+ }\r
+\r
+\r
+ public EntityValidationResult getEntityValidationResult(){\r
+ return entityValidationResult;\r
+ }\r
+ public void setEntityValidationResult(EntityValidationResult entityValidationResult){\r
+ this.entityValidationResult = entityValidationResult;\r
+ }\r
+\r
+}\r
--- /dev/null
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/ \r
+package eu.etaxonomy.cdm.model.validation;\r
+\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import java.util.UUID;\r
+\r
+import javax.persistence.Column;\r
+import javax.persistence.Entity;\r
+import javax.persistence.EnumType;\r
+import javax.persistence.Enumerated;\r
+import javax.persistence.OneToMany;\r
+import javax.validation.Validator;\r
+import javax.xml.bind.annotation.XmlAccessType;\r
+import javax.xml.bind.annotation.XmlAccessorType;\r
+import javax.xml.bind.annotation.XmlElement;\r
+import javax.xml.bind.annotation.XmlElementWrapper;\r
+import javax.xml.bind.annotation.XmlRootElement;\r
+import javax.xml.bind.annotation.XmlType;\r
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.hibernate.annotations.Cascade;\r
+import org.hibernate.annotations.CascadeType;\r
+import org.hibernate.annotations.Fetch;\r
+import org.hibernate.annotations.FetchMode;\r
+import org.hibernate.annotations.Type;\r
+import org.hibernate.search.annotations.FieldBridge;\r
+\r
+import eu.etaxonomy.cdm.hibernate.search.UuidBridge;\r
+import eu.etaxonomy.cdm.jaxb.UUIDAdapter;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.validation.CRUDEventType;\r
+\r
+/**\r
+ * An {@code EntityValidationResult} models the result of validating one entity, that is,\r
+ * the outcome of calling {@link Validator#validate(Object, Class...)}. More than one\r
+ * constraint {@link EntityConstraintViolation} may be violated while validating the\r
+ * entity.\r
+ * \r
+ * @see EntityValidationResult\r
+ * \r
+ * @author ayco_holleman\r
+ * \r
+ */\r
+\r
+@XmlAccessorType(XmlAccessType.FIELD)\r
+//@formatter:off\r
+@XmlType(name = "EntityValidationResult", propOrder = {\r
+ "ValidatedEntityId",\r
+ "ValidatedEntityUuid",\r
+ "ValidatedEntityClass",\r
+ "UserFriendlyDescription",\r
+ "UserFriendlyTypeName",\r
+ "CrudEventType",\r
+ "ConstraintViolations"\r
+})\r
+//@formatter:on\r
+@XmlRootElement(name = "EntityValidationResult")\r
+@Entity\r
+public class EntityValidationResult extends CdmBase {\r
+\r
+ private static final long serialVersionUID = 9120571815593117363L;\r
+\r
+ @SuppressWarnings("unused")\r
+ private static final Logger logger = Logger.getLogger(EntityValidationResult.class);\r
+\r
+\r
+ public static EntityValidationResult newInstance(){\r
+ return new EntityValidationResult();\r
+ }\r
+\r
+ @XmlElement(name = "ValidatedEntityId")\r
+ private int validatedEntityId;\r
+\r
+ @XmlElement(name = "ValidatedEntityUuid")\r
+ @XmlJavaTypeAdapter(UUIDAdapter.class)\r
+ @Type(type = "uuidUserType")\r
+ @Column(length=36) //TODO needed? Type UUID will always assure that is exactly 36\r
+ @FieldBridge(impl = UuidBridge.class) //TODO required?\r
+ private UUID validatedEntityUuid;\r
+\r
+ @XmlElement(name = "ValidatedEntityClass")\r
+ private String validatedEntityClass;\r
+\r
+ @XmlElement(name = "UserFriendlyDescription")\r
+ private String userFriendlyDescription;\r
+\r
+ @XmlElement(name = "UserFriendlyTypeName")\r
+ private String userFriendlyTypeName;\r
+\r
+ @XmlElement(name = "CrudEventType")\r
+ @Enumerated(EnumType.STRING)\r
+ private CRUDEventType crudEventType;\r
+\r
+ @XmlElementWrapper(name = "EntityConstraintViolations")\r
+ @OneToMany(mappedBy = "entityValidationResult")\r
+ @Cascade({ CascadeType.ALL })\r
+ @Fetch(value = FetchMode.JOIN)\r
+ private Set<EntityConstraintViolation> entityConstraintViolations;\r
+\r
+\r
+ protected EntityValidationResult(){\r
+ super();\r
+ }\r
+\r
+\r
+ public int getValidatedEntityId(){\r
+ return validatedEntityId;\r
+ }\r
+\r
+\r
+ public void setValidatedEntityId(int validatedEntityId){\r
+ this.validatedEntityId = validatedEntityId;\r
+ }\r
+\r
+\r
+ public UUID getValidatedEntityUuid(){\r
+ return validatedEntityUuid;\r
+ }\r
+\r
+\r
+ public void setValidatedEntityUuid(UUID validatedEntityUuid){\r
+ this.validatedEntityUuid = validatedEntityUuid;\r
+ }\r
+\r
+\r
+ public String getValidatedEntityClass(){\r
+ return validatedEntityClass;\r
+ }\r
+\r
+\r
+ public void setValidatedEntityClass(String validatedEntityClass){\r
+ this.validatedEntityClass = validatedEntityClass;\r
+ }\r
+\r
+\r
+ public String getUserFriendlyTypeName(){\r
+ return userFriendlyTypeName;\r
+ }\r
+\r
+\r
+ public void setUserFriendlyTypeName(String userFriendlyTypeName){\r
+ this.userFriendlyTypeName = userFriendlyTypeName;\r
+ }\r
+\r
+\r
+ public CRUDEventType getCrudEventType(){\r
+ return crudEventType;\r
+ }\r
+\r
+\r
+ public void setCrudEventType(CRUDEventType crudEventType){\r
+ this.crudEventType = crudEventType;\r
+ }\r
+\r
+\r
+ public String getUserFriendlyDescription(){\r
+ return userFriendlyDescription;\r
+ }\r
+\r
+\r
+ public void setUserFriendlyDescription(String userFriendlyDescription){\r
+ this.userFriendlyDescription = userFriendlyDescription;\r
+ }\r
+\r
+\r
+ public Set<EntityConstraintViolation> getEntityConstraintViolations(){\r
+ if (entityConstraintViolations == null) {\r
+ entityConstraintViolations = new HashSet<EntityConstraintViolation>();\r
+ }\r
+ return entityConstraintViolations;\r
+ }\r
+\r
+\r
+ public void addEntityConstraintViolation(EntityConstraintViolation ecv){\r
+ if (ecv != null) {\r
+ getEntityConstraintViolations().add(ecv);\r
+ }\r
+ }\r
+\r
+\r
+ public void removeEntityConstraintViolation(EntityConstraintViolation ecv){\r
+ if (ecv != null) {\r
+ getEntityConstraintViolations().remove(ecv);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/ \r
+package eu.etaxonomy.cdm.model.validation;\r
+\r
+import java.io.Serializable;\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+\r
+import org.hibernate.HibernateException;\r
+import org.hibernate.engine.spi.SessionImplementor;\r
+import org.hibernate.usertype.UserType;\r
+\r
+import eu.etaxonomy.cdm.validation.Severity;\r
+\r
+/**\r
+ * A Hibernate {@code UserType} for persisting {@link Severity} instances.\r
+ * \r
+ * @see EntityConstraintViolation\r
+ * \r
+ * @author ayco_holleman\r
+ * \r
+ */\r
+public class SeverityType implements UserType {\r
+\r
+ @Override\r
+ public int[] sqlTypes(){\r
+ return new int[] { java.sql.Types.VARCHAR };\r
+ }\r
+\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public Class returnedClass(){\r
+ return Severity.class;\r
+ \r
+ }\r
+\r
+\r
+ @Override\r
+ public boolean equals(Object x, Object y) throws HibernateException{\r
+ if (x == null) {\r
+ if (y == null) {\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ if (y == null) {\r
+ return false;\r
+ }\r
+ return ((Severity) x).equals(y);\r
+ }\r
+\r
+\r
+ @Override\r
+ public int hashCode(Object x) throws HibernateException{\r
+ return x.getClass().hashCode();\r
+ }\r
+\r
+\r
+ @Override\r
+ public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException{\r
+ String severity = rs.getString(names[0]);\r
+ return rs.wasNull() ? null : Severity.forName(severity);\r
+ }\r
+\r
+\r
+ @Override\r
+ public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException{\r
+ st.setString(index, value == null ? null : value.toString());\r
+ }\r
+\r
+\r
+ @Override\r
+ public Object deepCopy(Object value) throws HibernateException{\r
+ return value;\r
+ }\r
+\r
+\r
+ @Override\r
+ public boolean isMutable(){\r
+ return false;\r
+ }\r
+\r
+\r
+ @Override\r
+ public Serializable disassemble(Object value) throws HibernateException{\r
+ return null;\r
+ }\r
+\r
+\r
+ @Override\r
+ public Object assemble(Serializable cached, Object owner) throws HibernateException{\r
+ return null;\r
+ }\r
+\r
+\r
+ @Override\r
+ public Object replace(Object original, Object target, Object owner) throws HibernateException{\r
+ return original;\r
+ }\r
+\r
+}\r
--- /dev/null
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/ \r
+\r
+package eu.etaxonomy.cdm.validation;\r
+\r
+/**\r
+ * The CRUD event that triggered a validation. When an entity violates some constraint, it\r
+ * might be helpful to report back to the user what type of CRUD event caused the violation.\r
+ * Note that validation may not not have been triggered by any CRUD event at all, e.g. during\r
+ * some batch-like validation process. Level-2 validation can never be triggered by a DELETE\r
+ * event, because Level-2 validation only validates the entity itself. However, a DELETE event\r
+ * <i>can</i> possibly trigger a Level-3 validation, because that disrupts the object graph the\r
+ * entity was part of.\r
+ * \r
+ * @author ayco holleman\r
+ * \r
+ */\r
+public enum CRUDEventType{\r
+ NONE, INSERT, UPDATE, DELETE\r
+}\r
--- /dev/null
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/ \r
+\r
+package eu.etaxonomy.cdm.validation;\r
+\r
+import java.util.Set;\r
+\r
+import javax.validation.ConstraintViolation;\r
+import javax.validation.Payload;\r
+\r
+/**\r
+ * A class conveying the severity of a {@link ConstraintViolation}. Severity levels are\r
+ * extraneous to the javax.validation framework and can only be conveyed using generic\r
+ * {@link Payload} objects. Unfortunately, only the class of those objects is communicated\r
+ * back to the client. The class <i>is</i> the message. Concrete instances or {@code enum}\r
+ * s (an obvious choice for severity levels) cannot function as {@code Payload} objects.\r
+ * The Severity class enables you to program using true Severity instances (one for each\r
+ * level), while behind the scenes only the class of those instances is taken into\r
+ * account.\r
+ * \r
+ * @author ayco holleman\r
+ */\r
+public abstract class Severity implements Payload {\r
+\r
+ public static final Notice NOTICE = new Notice();\r
+ public static final Warning WARNING = new Warning();\r
+ public static final Error ERROR = new Error();\r
+\r
+ //@formatter:off\r
+ public static final class Notice extends Severity {};\r
+ public static final class Warning extends Severity {};\r
+ public static final class Error extends Severity {};\r
+ //@formatter:on\r
+\r
+ /**\r
+ * Get {@code Severity} object for the specified {@code String} representation. Does the\r
+ * opposite of {@link #toString()}.\r
+ * \r
+ * @param name\r
+ * The {@code String} representation of {@code Severity} object you want.\r
+ * \r
+ * @return The {@code Severity} object\r
+ */\r
+ public static Severity forName(String name)\r
+ {\r
+ if (name.equals(Error.class.getSimpleName())) {\r
+ return ERROR;\r
+ }\r
+ if (name.equals(Warning.class.getSimpleName())) {\r
+ return WARNING;\r
+ }\r
+ return NOTICE;\r
+ }\r
+\r
+\r
+ /**\r
+ * Get the {@code Severity} of the specified {@code ConstraintViolation}.\r
+ * \r
+ * @param error\r
+ * The {@code ConstraintViolation}\r
+ * \r
+ * @return The {@code Severity}\r
+ */\r
+ public static Severity getSeverity(ConstraintViolation<?> error)\r
+ {\r
+ Set<Class<? extends Payload>> payloads = error.getConstraintDescriptor().getPayload();\r
+ for (Class<? extends Payload> payload : payloads) {\r
+ if (payload == Error.class) {\r
+ return ERROR;\r
+ }\r
+ if (payload == Warning.class) {\r
+ return WARNING;\r
+ }\r
+ if (payload == Notice.class) {\r
+ return NOTICE;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+\r
+ private Severity()\r
+ {\r
+ }\r
+\r
+\r
+ @Override\r
+ public String toString()\r
+ {\r
+ return getClass().getSimpleName();\r
+ }\r
+}\r
<mapping class="eu.etaxonomy.cdm.model.taxon.Classification"/>\r
<mapping class="eu.etaxonomy.cdm.model.taxon.TaxonRelationship"/>\r
<mapping class="eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType"/>\r
+ \r
+ <!-- Validation Package -->\r
+ <mapping class="eu.etaxonomy.cdm.model.validation.EntityValidationResult"/>\r
+ <mapping class="eu.etaxonomy.cdm.model.validation.EntityConstraintViolation"/>\r
+ \r
<!-- View Package -->\r
<mapping class="eu.etaxonomy.cdm.model.view.AuditEvent"/>\r
\r