package org.cagrid.core.resource; import java.lang.reflect.Field; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import javax.xml.bind.annotation.XmlElement; import javax.xml.namespace.QName; import org.cagrid.core.common.JAXBUtils; import static org.cagrid.core.common.JAXBUtils.DEFAULT_NAMESPACE_VALUE; public class ResourcePropertyDescriptor<T> { /** * Map the descriptors by field, if present. */ public static Map<String, ResourcePropertyDescriptor<?>> mapByField( Collection<ResourcePropertyDescriptor<?>> resourcePropertyDescriptors) { Map<String, ResourcePropertyDescriptor<?>> descriptorsByField = new HashMap<String, ResourcePropertyDescriptor<?>>(); for (ResourcePropertyDescriptor<?> resourcePropertyDescriptor : resourcePropertyDescriptors) { String fieldName = resourcePropertyDescriptor.getFieldName(); if (fieldName != null) { descriptorsByField.put(fieldName, resourcePropertyDescriptor); } } return descriptorsByField; } /** * Analyze a (usually generated) class hierarchy that holds a resource's * properties. */ public static Collection<ResourcePropertyDescriptor<?>> analyzeResourcePropertiesHolder( Class<?> klass) { Collection<ResourcePropertyDescriptor<?>> resourcePropertyDescriptors = new HashSet<ResourcePropertyDescriptor<?>>(); for (; (klass != null) && (klass != Object.class); klass = klass .getSuperclass()) { analyzeResourcePropertiesHolder(klass, resourcePropertyDescriptors); } return resourcePropertyDescriptors; } /** * Analyze a (usually generated) class that holds a resource's properties. */ public static Collection<ResourcePropertyDescriptor<?>> analyzeResourcePropertiesHolder( Class<?> klass, Collection<ResourcePropertyDescriptor<?>> resourcePropertyDescriptors) { // Look for a default namespace. String defaultNamespace = JAXBUtils.getNamespace(klass); for (Field field : klass.getDeclaredFields()) { XmlElement xmlElement = field.getAnnotation(XmlElement.class); if (xmlElement == null) continue; String resourcePropertyNamespace = xmlElement.namespace(); if (DEFAULT_NAMESPACE_VALUE.equals(resourcePropertyNamespace)) { resourcePropertyNamespace = defaultNamespace; } String resourcePropertyName = xmlElement.name(); QName resourcePropertyQName = new QName(resourcePropertyNamespace, resourcePropertyName); Class<?> resourcePropertyClass = field.getType(); String fieldName = field.getName(); @SuppressWarnings({ "rawtypes", "unchecked" }) ResourcePropertyDescriptor<?> resourcePropertyDescriptor = new ResourcePropertyDescriptor( resourcePropertyQName, resourcePropertyClass, fieldName); resourcePropertyDescriptors.add(resourcePropertyDescriptor); } return resourcePropertyDescriptors; } private final QName resourcePropertyQName; private final Class<T> resourcePropertyClass; private final String fieldName; private final int hashCode; public ResourcePropertyDescriptor(QName resourcePropertyQName, Class<T> resourcePropertyClass, String fieldName) { this.resourcePropertyQName = resourcePropertyQName; this.resourcePropertyClass = resourcePropertyClass; this.fieldName = fieldName; hashCode = resourcePropertyQName.hashCode(); } public QName getResourcePropertyQName() { return resourcePropertyQName; } public Class<T> getResourcePropertyClass() { return resourcePropertyClass; } public String getFieldName() { return fieldName; } @Override public boolean equals(Object obj) { if (!(obj instanceof ResourcePropertyDescriptor)) return false; ResourcePropertyDescriptor<?> that = (ResourcePropertyDescriptor<?>) obj; return resourcePropertyQName.equals(that.resourcePropertyQName); } @Override public int hashCode() { return hashCode; } @Override public String toString() { String s = resourcePropertyQName.toString() + "[" + resourcePropertyClass.getName() + "]"; if (fieldName != null) { s += " (" + fieldName + ")"; } return s; } }