package sk.nociar.jpacloner; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.unmodifiableList; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.util.List; import javax.persistence.ElementCollection; import javax.persistence.Embedded; import javax.persistence.EmbeddedId; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import sk.nociar.jpacloner.properties.PropertyReader; import sk.nociar.jpacloner.properties.PropertyWriter; /** * Info about JPA property (basic field or relation). */ public class JpaPropertyInfo { private final AccessibleObject accessibleObject; private final PropertyReader propertyReader; private final PropertyWriter propertyWriter; private final List<String> mappedBy; private final boolean isBasic; private final boolean isSingular; public JpaPropertyInfo(AccessibleObject accessibleObject, PropertyReader propertyReader, PropertyWriter propertyWriter) { this.accessibleObject = accessibleObject; this.propertyReader = propertyReader; this.propertyWriter = propertyWriter; final ManyToOne manyToOne = accessibleObject.getAnnotation(ManyToOne.class); final OneToOne oneToOne = accessibleObject.getAnnotation(OneToOne.class); final OneToMany oneToMany = accessibleObject.getAnnotation(OneToMany.class); final ManyToMany manyToMany = accessibleObject.getAnnotation(ManyToMany.class); final Embedded embedded = accessibleObject.getAnnotation(Embedded.class); final EmbeddedId embeddedId = accessibleObject.getAnnotation(EmbeddedId.class); final ElementCollection elementCollection = accessibleObject.getAnnotation(ElementCollection.class); if (allNull(manyToOne, oneToOne, oneToMany, manyToMany, embedded, embeddedId, elementCollection)) { // basic field isBasic = true; isSingular = true; mappedBy = null; } else { // relation/embedded field isBasic = false; isSingular = allNull(oneToMany, manyToMany, elementCollection); // handle mappedBy for @OneToOne or @OneToMany // NOTE handling of mappedBy for @ManyToMany is omitted intentionally String mappedName = null; if (oneToOne != null) { mappedName = oneToOne.mappedBy(); } else if (oneToMany != null) { mappedName = oneToMany.mappedBy(); } if (mappedName != null && !mappedName.trim().isEmpty()) { mappedName = mappedName.trim(); // NOTE: the mappedBy attribute may be used in @Embeddable if (mappedName.contains(".")) { mappedBy = unmodifiableList(asList(mappedName.split("\\."))); } else { mappedBy = singletonList(mappedName); } } else { mappedBy = null; } } } private boolean allNull(Annotation... annotations) { for (Annotation a : annotations) { if (a != null) { return false; } } return true; } public AccessibleObject getAccessibleObject() { return accessibleObject; } public Object getValue(Object instance) { return propertyReader.get(instance); } public void setValue(Object instance, Object value) { propertyWriter.set(instance, value); } public List<String> getMappedBy() { return mappedBy; } public boolean isBasic() { return isBasic; } public boolean isSingular() { return isSingular; } }