package japicmp.output.extapi.jpa.model; import com.google.common.base.Optional; import japicmp.model.*; import japicmp.output.extapi.jpa.JpaAnalyzer; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.util.LinkedList; import java.util.List; public class JpaTable { private final List<JpaAttribute> attributes = new LinkedList<>(); private final JApiClass jApiClass; private final JpaName jpaName; private JApiChangeStatus changeStatus; public JpaTable(JApiClass jApiClass, JApiAnnotation entityAnnotation) { this.jApiClass = jApiClass; this.jpaName = extractName(entityAnnotation, jApiClass); extractAttributes(); changeStatus = computeChangeStatus(); } private JpaName extractName(JApiAnnotation entityAnnotation, JApiClass jApiClass) { JApiChangeStatus changeStatusClass = jApiClass.getChangeStatus(); String tableName = computeTablename(); List<JApiAnnotationElement> elements = entityAnnotation.getElements(); for (JApiAnnotationElement element : elements) { String name = element.getName(); if ("name".equals(name)) { JApiChangeStatus elementChangeStatus = element.getChangeStatus(); switch (elementChangeStatus) { case NEW: String newName = removeQuotationMarks(element.getNewValue().get().toString()); if (changeStatusClass == JApiChangeStatus.NEW) { return new JpaName(Optional.<String>absent(), Optional.of(newName), JApiChangeStatus.NEW); } if (tableName.equals(newName)) { return new JpaName(Optional.of(newName), Optional.of(newName), JApiChangeStatus.UNCHANGED); } else { return new JpaName(Optional.of(tableName), Optional.of(newName), JApiChangeStatus.MODIFIED); } case REMOVED: String oldName = removeQuotationMarks(element.getOldValue().get().toString()); if (changeStatusClass == JApiChangeStatus.REMOVED) { return new JpaName(Optional.of(oldName), Optional.<String>absent(), JApiChangeStatus.REMOVED); } if (tableName.equals(oldName)) { return new JpaName(Optional.of(oldName), Optional.of(oldName), JApiChangeStatus.UNCHANGED); } else { return new JpaName(Optional.of(oldName), Optional.of(tableName), JApiChangeStatus.MODIFIED); } case MODIFIED: newName = removeQuotationMarks(element.getNewValue().get().toString()); oldName = removeQuotationMarks(element.getOldValue().get().toString()); return new JpaName(Optional.of(oldName), Optional.of(newName), JApiChangeStatus.MODIFIED); case UNCHANGED: newName = removeQuotationMarks(element.getNewValue().get().toString()); return new JpaName(Optional.of(newName), Optional.of(newName), JApiChangeStatus.UNCHANGED); } } break; } if (changeStatusClass == JApiChangeStatus.NEW) { return new JpaName(Optional.<String>absent(), Optional.of(tableName), JApiChangeStatus.NEW); } else if (changeStatusClass == JApiChangeStatus.REMOVED) { return new JpaName(Optional.of(tableName), Optional.<String>absent(), JApiChangeStatus.REMOVED); } return new JpaName(Optional.of(tableName), Optional.of(tableName), JApiChangeStatus.UNCHANGED); } private String removeQuotationMarks(String s) { return s.replace("\"", ""); } private JApiChangeStatus computeChangeStatus() { JApiChangeStatus changeStatus = jApiClass.getChangeStatus(); if (changeStatus == JApiChangeStatus.MODIFIED) { changeStatus = JApiChangeStatus.UNCHANGED; } if (jpaName.getChangeStatus() != JApiChangeStatus.UNCHANGED) { changeStatus = JApiChangeStatus.MODIFIED; } return changeStatus; } private void extractAttributes() { List<JApiField> fields = jApiClass.getFields(); for (JApiField field : fields) { Optional<JApiAnnotation> transientAnnotationOfFieldOptional = getTransientAnnotationOfField(field); Optional<JApiAnnotation> transientAnnotationOfPropertyOptional = getTransientAnnotationOfProperty(field); if (!transientAnnotationOfFieldOptional.isPresent() && !transientAnnotationOfPropertyOptional.isPresent()) { JApiChangeStatus fieldChangeStatus = field.getChangeStatus(); if (fieldChangeStatus == JApiChangeStatus.NEW) { JpaAttribute jpaAttribute = new JpaAttribute(JApiChangeStatus.NEW); } } } } private Optional<JApiAnnotation> getTransientAnnotationOfField(JApiField field) { Optional<JApiAnnotation> returnValue = Optional.absent(); for (JApiAnnotation annotation : field.getAnnotations()) { if (JpaAnalyzer.JPA_ANNOTATION_TRANSIENT.equals(annotation.getFullyQualifiedName())) { returnValue = Optional.of(annotation); break; } } return returnValue; } private Optional<JApiAnnotation> getTransientAnnotationOfProperty(JApiField field) { Optional<JApiAnnotation> returnValue = Optional.absent(); Optional<JApiMethod> propertyMethodOptional = getPropertyMethod(field); if (propertyMethodOptional.isPresent()) { JApiMethod propertyMethod = propertyMethodOptional.get(); for (JApiAnnotation annotation : propertyMethod.getAnnotations()) { if (JpaAnalyzer.JPA_ANNOTATION_TRANSIENT.equals(annotation.getFullyQualifiedName())) { returnValue = Optional.of(annotation); break; } } } return returnValue; } private Optional<JApiMethod> getPropertyMethod(JApiField field) { Optional<JApiMethod> propertyMethod = Optional.absent(); String fieldName = field.getName(); String getterName = "get" + (Character.isUpperCase(fieldName.charAt(0)) ? fieldName : fieldName.length() > 1 ? Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1) : Character.toUpperCase(fieldName.charAt(0))); for (JApiMethod method : jApiClass.getMethods()) { if (getterName.equals(method.getName())) { propertyMethod = Optional.of(method); break; } } if (!propertyMethod.isPresent()) { String isName = "is" + getterName.substring(3); for (JApiMethod method : jApiClass.getMethods()) { if (isName.equals(method.getName())) { propertyMethod = Optional.of(method); break; } } } return propertyMethod; } @XmlElementWrapper(name = "attributes") @XmlElement(name = "attribute") public List<JpaAttribute> getAttributes() { return attributes; } @XmlAttribute(name = "fullyQualifiedName") public String getFullyQualifiedName() { return jApiClass.getFullyQualifiedName(); } public String computeTablename() { String className = toClassName(jApiClass.getFullyQualifiedName()); return toJpaName(className); } static String toJpaName(String javaName) { boolean lastCharWasUpperCase = true; StringBuilder jpaName = new StringBuilder(); for (int i = 0; i < javaName.length(); i++) { char c = javaName.charAt(i); if (Character.isUpperCase(c)) { if (!lastCharWasUpperCase) { jpaName.append("_"); } jpaName.append(c); lastCharWasUpperCase = true; } else { jpaName.append(Character.toUpperCase(c)); lastCharWasUpperCase = false; } } return jpaName.toString(); } private String toClassName(String className) { String[] parts = className.split("\\."); if (parts.length > 0) { className = parts[parts.length - 1]; } return className; } @XmlAttribute(name = "changeStatus") public String getChangeStatus() { return changeStatus.toString(); } @XmlElement(name = "name") public JpaName getJpaName() { return this.jpaName; } }