/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jpa.tools.swing; import java.awt.Color; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; /** * Static utility for analyzing persistent metadata model using JPA 2.0. * * @author Pinaki Poddar * */ public class MetamodelHelper { public static final int ATTR_ID = 0; public static final int ATTR_VERSION = 1; public static final int ATTR_BASIC = 2; public static final int ATTR_SINGULAR_RELATION = 3; public static final int ATTR_PLURAL_RELATION = 4; public static final Color MIDNIGHT_BLUE = new Color(25,25,112); public static final Color DARK_GREEN = new Color(0,100,0); public static final Color KHAKI = new Color(240, 230, 140); public static String getDisplayName(Type<?> type) { if (type instanceof EntityType) { return getDisplayName((EntityType<?>)type); } return getDisplayName(type.getJavaType()); } /** * Gets the displayed name of a given entity type. */ public static String getDisplayName(EntityType<?> type) { return type.getName(); } public static String getDisplayName(Class<?> cls) { String fullName = cls.getName(); if (fullName.startsWith("java.") || fullName.startsWith("openbook.domain.")) { int i = fullName.lastIndexOf('.'); return fullName.substring(i+1); } return fullName; } public static String getDisplayName(Attribute<?,?> attr) { StringBuilder buffer = new StringBuilder(); buffer.append(getDisplayName(attr.getJavaType())); if (attr instanceof MapAttribute) { buffer.append("<").append(getDisplayName(((MapAttribute)attr).getKeyType())).append(",") .append(getDisplayName(((MapAttribute)attr).getElementType())).append(">"); } else if (attr instanceof PluralAttribute) { buffer.append("<").append(getDisplayName(((PluralAttribute)attr).getElementType())).append(">"); } buffer.append(" ").append(attr.getName()); return buffer.toString(); } public static <T> List<Attribute<? super T,?>> getAttributes(EntityType<T> type) { List<Attribute<? super T,?>> list = new ArrayList<Attribute<? super T,?>>(type.getAttributes()); Collections.sort(list, new AttributeComparator()); return list; } public static int getAttributeType(Attribute<?, ?> a) { if (a instanceof SingularAttribute) { SingularAttribute<?, ?> sa = (SingularAttribute<?, ?>)a; if (sa.isId()) return ATTR_ID; if (sa.isVersion()) return ATTR_VERSION; if (sa.isAssociation()) return ATTR_SINGULAR_RELATION; if (sa.isCollection()) return ATTR_PLURAL_RELATION; } else { if (a.isAssociation()) return ATTR_SINGULAR_RELATION; if (a.isCollection()) return ATTR_PLURAL_RELATION; } return ATTR_BASIC; } public static <T> Set<SingularAttribute<? super T, ?>> getIdAttributes(EntityType<T> type) { Set<SingularAttribute<? super T,?>> attrs = type.getSingularAttributes(); Set<SingularAttribute<? super T,?>> idAttrs = new HashSet<SingularAttribute<? super T,?>>(); for (SingularAttribute<? super T,?> attr : attrs) { if (attr.isId()) { idAttrs.add(attr); } } return idAttrs; } /** * Finds the derived target of the given type, if any. Otherwise null. */ public static <T> EntityType<?> derivedTarget(EntityType<T> type) { Set<SingularAttribute<? super T,?>> ids = getIdAttributes(type); for (SingularAttribute<? super T,?> id : ids) { EntityType<?> derived = getParentType(id); if (derived != null) { return derived; } } return null; } public static EntityType<?> getParentType(SingularAttribute<?,?> id) { if (id.getType() instanceof EntityType) { return (EntityType<?>)id.getType(); } return null; } public static boolean isId(Attribute<?,?> a) { if (a instanceof SingularAttribute) return ((SingularAttribute<?,?>)a).isId(); return false; } public static boolean isVersion(Attribute<?,?> a) { if (a instanceof SingularAttribute) return ((SingularAttribute<?,?>)a).isVersion(); return false; } public static Color getColor(Attribute<?,?> attr) { if (isId(attr)) return Color.RED; if (isVersion(attr)) return Color.DARK_GRAY; return getColor(attr.getPersistentAttributeType()); } public static Color getColor(Attribute.PersistentAttributeType type) { switch (type) { case BASIC : return Color.BLACK; case EMBEDDED: return Color.GRAY; case ONE_TO_ONE: return Color.BLUE; case MANY_TO_ONE: return MIDNIGHT_BLUE; case ONE_TO_MANY: return DARK_GREEN; case MANY_TO_MANY: return Color.PINK; case ELEMENT_COLLECTION: return KHAKI; default: return Color.BLACK; } } public static Integer getAttributeTypeCode(Attribute<?,?> attr) { if (isId(attr)) return 0; if (isVersion(attr)) return 1; switch (attr.getPersistentAttributeType()) { case BASIC : case EMBEDDED: return 2; case ONE_TO_ONE: case MANY_TO_ONE: return 3; case ONE_TO_MANY: case MANY_TO_MANY: case ELEMENT_COLLECTION: return 4; default: return 5; } } private static Map<Attribute<?,?>, Method> members = new HashMap<Attribute<?,?>, Method>(); private static Object[] EMPTY_ARGS = null; private static Class<?>[] EMPTY_CLASSES = null; /** * Gets the value of the given persistent attribute for the given instance. */ public static Object getValue(Attribute<?,?> attr, Object instance) { Member member = attr.getJavaMember(); Method getter = null; if (member instanceof Method) { getter = (Method)member; } else if (members.containsKey(attr)) { getter = members.get(attr); } else { getter = getMethod(attr.getDeclaringType().getJavaType(), attr.getName()); members.put(attr, getter); } if (getter == null) return null; try { return getter.invoke(instance, EMPTY_ARGS); } catch (Exception e) { return null; } } private static Method getMethod(Class<?> type, String p) { try { String getter = "get" + Character.toUpperCase(p.charAt(0))+p.substring(1); return type.getMethod(getter, EMPTY_CLASSES); } catch (Exception e) { e.printStackTrace(); } return null; } /** * Compares EntityType by their dependency of derived targets. * * @author Pinaki Poddar * */ public static class EntityComparator implements Comparator<EntityType<?>> { @Override public int compare(EntityType<?> o1, EntityType<?> o2) { if (derivedTarget(o1) == o2) return 1; if (derivedTarget(o2) == o1) return -1; return o1.getName().compareTo(o2.getName()); } } /** * Compares attribute by their qualification. * Identity * Version * Basic * Singular association * Plural association * * @author Pinaki Poddar * */ public static class AttributeComparator implements Comparator<Attribute<?,?>> { @Override public int compare(Attribute<?, ?> a1, Attribute<?, ?> a2) { Integer t1 = getAttributeTypeCode(a1); Integer t2 = getAttributeTypeCode(a2); if (t1.equals(t2)) { return a1.getName().compareTo(a2.getName()); } else { return t1.compareTo(t2); } } } }