001: /*******************************************************************************
002: * Portions created by Sebastian Thomschke are copyright (c) 2005-2007 Sebastian
003: * Thomschke.
004: *
005: * All Rights Reserved. This program and the accompanying materials
006: * are made available under the terms of the Eclipse Public License v1.0
007: * which accompanies this distribution, and is available at
008: * http://www.eclipse.org/legal/epl-v10.html
009: *
010: * Contributors:
011: * Sebastian Thomschke - initial implementation.
012: *******************************************************************************/package net.sf.oval.configuration.annotation;
013:
014: import java.lang.annotation.Annotation;
015: import java.lang.reflect.Field;
016: import java.util.Collection;
017: import java.util.List;
018:
019: import javax.persistence.Basic;
020: import javax.persistence.Column;
021: import javax.persistence.GeneratedValue;
022: import javax.persistence.ManyToOne;
023: import javax.persistence.OneToMany;
024: import javax.persistence.OneToOne;
025: import javax.persistence.Version;
026:
027: import net.sf.oval.Check;
028: import net.sf.oval.configuration.Configurer;
029: import net.sf.oval.configuration.pojo.elements.ClassConfiguration;
030: import net.sf.oval.configuration.pojo.elements.ConstraintSetConfiguration;
031: import net.sf.oval.configuration.pojo.elements.FieldConfiguration;
032: import net.sf.oval.constraint.AssertValidCheck;
033: import net.sf.oval.constraint.LengthCheck;
034: import net.sf.oval.constraint.NotNullCheck;
035: import net.sf.oval.exception.OValException;
036: import net.sf.oval.internal.CollectionFactoryHolder;
037:
038: /**
039: * Constraints configurer that interprets certain EJB3 JPA annotations:
040: * <ul>
041: * <li>javax.persistence.Basic(optional=false) => net.sf.oval.constraints.NotNullCheck
042: * <li>javax.persistence.OneToOne(optional=false) => net.sf.oval.constraints.NotNullCheck
043: * <li>javax.persistence.ManyToOne(optional=false) => net.sf.oval.constraints.NotNullCheck
044: * <li>javax.persistence.Column(nullable=false) => net.sf.oval.constraints.NotNullCheck
045: * <li>javax.persistence.Column(length=5) => net.sf.oval.constraints.LengthCheck
046: * </ul>
047: * @author Sebastian Thomschke
048: */
049: public class JPAAnnotationsConfigurer implements Configurer {
050: private final static NotNullCheck NOT_NULL = new NotNullCheck();
051: private final static AssertValidCheck ASSERT_VALID = new AssertValidCheck();
052:
053: protected Boolean applyFieldConstraintsToSetters;
054: protected Boolean applyFieldConstraintsToConstructors;
055:
056: /**
057: * @return the applyFieldConstraintsToConstructors
058: */
059: public Boolean getApplyFieldConstraintsToConstructors() {
060: return applyFieldConstraintsToConstructors;
061: }
062:
063: public ClassConfiguration getClassConfiguration(final Class<?> clazz)
064: throws OValException {
065: final ClassConfiguration config = new ClassConfiguration();
066: config.type = clazz;
067: config.applyFieldConstraintsToConstructors = applyFieldConstraintsToConstructors;
068: config.applyFieldConstraintsToSetters = applyFieldConstraintsToSetters;
069:
070: /*
071: * determine field checks
072: */
073: for (final Field field : config.type.getDeclaredFields()) {
074: final List<Check> checks = CollectionFactoryHolder
075: .getFactory().createList(4);
076:
077: // loop over all annotations of the current field
078: for (final Annotation annotation : field.getAnnotations()) {
079: if (annotation instanceof Basic) {
080: initializeChecks((Basic) annotation, checks, field);
081: } else if (annotation instanceof Column) {
082: initializeChecks((Column) annotation, checks, field);
083: } else if (annotation instanceof OneToOne) {
084: initializeChecks((OneToOne) annotation, checks,
085: field);
086: } else if (annotation instanceof ManyToOne) {
087: initializeChecks((ManyToOne) annotation, checks,
088: field);
089: } else if (annotation instanceof OneToMany) {
090: initializeChecks((OneToMany) annotation, checks,
091: field);
092: }
093: }
094: if (checks.size() > 0) {
095: if (config.fieldConfigurations == null)
096: config.fieldConfigurations = CollectionFactoryHolder
097: .getFactory().createSet(8);
098:
099: final FieldConfiguration fc = new FieldConfiguration();
100: fc.name = field.getName();
101: fc.checks = checks;
102: config.fieldConfigurations.add(fc);
103: }
104: }
105: return config;
106: }
107:
108: public ConstraintSetConfiguration getConstraintSetConfiguration(
109: final String constraintSetId) throws OValException {
110: return null;
111: }
112:
113: protected void initializeChecks(final Basic annotation,
114: final Collection<Check> checks, final Field field) {
115: assert annotation != null;
116: assert checks != null;
117:
118: if (!annotation.optional()) {
119: checks.add(JPAAnnotationsConfigurer.NOT_NULL);
120: }
121: }
122:
123: protected void initializeChecks(final Column annotation,
124: final Collection<Check> checks, final Field field) {
125: assert annotation != null;
126: assert checks != null;
127:
128: /* If the value is generated (annotated with @GeneratedValue) it is allowed to be null
129: * before the entity has been persisted, same is true in case of optimistic locking
130: * when a field is annotated with @Version.
131: * Therefore and because of the fact that there is no generic way to determine if an entity
132: * has been persisted already, a not-null check will not be performed for such fields.
133: */
134: if (!annotation.nullable()
135: && !field.isAnnotationPresent(GeneratedValue.class)
136: && !field.isAnnotationPresent(Version.class)) {
137: checks.add(JPAAnnotationsConfigurer.NOT_NULL);
138: }
139:
140: final LengthCheck lengthCheck = new LengthCheck();
141: lengthCheck.setMax(annotation.length());
142: checks.add(lengthCheck);
143: }
144:
145: protected void initializeChecks(final ManyToOne annotation,
146: final Collection<Check> checks, final Field field) {
147: assert annotation != null;
148: assert checks != null;
149:
150: if (!annotation.optional()) {
151: checks.add(JPAAnnotationsConfigurer.NOT_NULL);
152: }
153: checks.add(JPAAnnotationsConfigurer.ASSERT_VALID);
154: }
155:
156: protected void initializeChecks(final OneToMany annotation,
157: final Collection<Check> checks, final Field field) {
158: assert annotation != null;
159: assert checks != null;
160:
161: checks.add(JPAAnnotationsConfigurer.ASSERT_VALID);
162: }
163:
164: protected void initializeChecks(final OneToOne annotation,
165: final Collection<Check> checks, final Field field) {
166: assert annotation != null;
167: assert checks != null;
168:
169: if (!annotation.optional()) {
170: checks.add(JPAAnnotationsConfigurer.NOT_NULL);
171: }
172: checks.add(JPAAnnotationsConfigurer.ASSERT_VALID);
173: }
174:
175: /**
176: * @return the applyFieldConstraintsToSetter
177: */
178: public Boolean isApplyFieldConstraintsToSetter() {
179: return applyFieldConstraintsToSetters;
180: }
181:
182: /**
183: * @param applyFieldConstraintsToConstructors the applyFieldConstraintsToConstructors to set
184: */
185: public void setApplyFieldConstraintsToConstructors(
186: final Boolean applyFieldConstraintsToConstructors) {
187: this .applyFieldConstraintsToConstructors = applyFieldConstraintsToConstructors;
188: }
189:
190: /**
191: * @param applyFieldConstraintsToSetters the applyFieldConstraintsToSetter to set
192: */
193: public void setApplyFieldConstraintsToSetters(
194: final Boolean applyFieldConstraintsToSetters) {
195: this.applyFieldConstraintsToSetters = applyFieldConstraintsToSetters;
196: }
197:
198: }
|