/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wfs.xml;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.geotools.feature.type.ProfileImpl;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.Name;
import org.opengis.feature.type.Schema;
/**
* A special profile of a pariticular {@link Schema} which maintains a unique
* mapping of java class to xml schema type.
*
* @author Justin Deoliveira, The Open Planning Project
*
*/
public class TypeMappingProfile /*extends ProfileImpl*/ {
/**
* Set of profiles to do mappings from.
*/
Set/*<Profile>*/ profiles;
// public TypeMappingProfile(Schema schema, Set profile) {
// super(schema, profile);
// }
public TypeMappingProfile(Set profiles) {
this.profiles = profiles;
}
/**
* Obtains the {@link AttributeDescriptor} mapped to a particular class.
* <p>
* If an exact match cannot be made, then those types which are supertypes
* of clazz are examined.
* </p>
* @param clazz The class.
*
* @return The AttributeType, or <code>null</code> if no atttribute
* type mapped to <code>clazz</code>
*/
public AttributeType type(Class clazz) {
ArrayList assignable = new ArrayList();
for (Iterator p = profiles.iterator(); p.hasNext(); ) {
ProfileImpl profile = (ProfileImpl) p.next();
for (Iterator i = profile.values().iterator(); i.hasNext();) {
AttributeType type = (AttributeType) i.next();
if (type.getBinding().isAssignableFrom(clazz)) {
assignable.add(type);
}
if (clazz.equals(type.getBinding())) {
return type;
}
}
}
if (assignable.isEmpty()) {
return null;
}
if (assignable.size() == 1) {
return (AttributeType) assignable.get(0);
} else {
//sort
Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
AttributeType a1 = (AttributeType) o1;
AttributeType a2 = (AttributeType) o2;
Class c1 = a1.getBinding();
Class c2 = a2.getBinding();
if (c1.equals(c2)) {
return 0;
}
if (c1.isAssignableFrom(c2)) {
return 1;
}
return -1;
}
};
Collections.sort(assignable, comparator);
if (!assignable.get(0).equals(assignable.get(1))) {
return (AttributeType) assignable.get(0);
}
}
return null;
}
/**
* Obtains the {@link Name} of the {@link AttributeDescriptor} mapped
* to a particular class.
*
* @param clazz The class.
*
* @return The Name, or <code>null</code> if no atttribute type mapped
* to <code>clazz</code>
*/
public Name name(Class clazz) {
ArrayList assignable = new ArrayList();
for (Iterator p = profiles.iterator(); p.hasNext(); ) {
ProfileImpl profile = (ProfileImpl) p.next();
for (Iterator i = profile.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
AttributeType type = (AttributeType) entry.getValue();
if (type.getBinding().isAssignableFrom(clazz)) {
assignable.add(entry);
}
if (clazz.equals(type.getBinding())) {
return (Name) entry.getKey();
}
}
}
if (assignable.isEmpty()) {
return null;
}
if (assignable.size() == 1) {
return (Name) ((Map.Entry) assignable.get(0)).getKey();
} else {
//sort
Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
Map.Entry e1 = (Map.Entry) o1;
Map.Entry e2 = (Map.Entry) o2;
AttributeType a1 = (AttributeType) e1.getValue();
AttributeType a2 = (AttributeType) e2.getValue();
Class c1 = a1.getBinding();
Class c2 = a2.getBinding();
if (c1.equals(c2)) {
return 0;
}
if (c1.isAssignableFrom(c2)) {
return 1;
}
return -1;
}
};
Collections.sort(assignable, comparator);
Map.Entry e1 = (Map.Entry) assignable.get(0);
Map.Entry e2 = (Map.Entry) assignable.get(1);
AttributeType a1 = (AttributeType) e1.getValue();
AttributeType a2 = (AttributeType) e2.getValue();
if (!a1.equals(a2)) {
return (Name) e1.getKey();
}
}
return null;
}
}