/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.feature.type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geotools.feature.NameImpl;
import org.opengis.feature.Property;
import org.opengis.feature.type.ComplexType;
import org.opengis.feature.type.Name;
import org.opengis.feature.type.PropertyDescriptor;
import org.opengis.filter.Filter;
import org.opengis.util.InternationalString;
/**
* A replacement for {@link ComplexTypeImpl} with lazy evaluation of descriptors, to support
* cyclically-defined types. Note that type equality is defined by name, so do not allow different
* types with the same name to be put in any Collection.
*
*
*
* Inspired by {@link ComplexTypeImpl}.
*
* @author Ben Caradoc-Davies (CSIRO Earth Science and Resource Engineering)
* @see ComplexTypeImpl
*
* @source $URL$
*/
public abstract class AbstractLazyComplexTypeImpl extends AbstractLazyAttributeTypeImpl implements
ComplexType {
private Collection descriptors;
private Map descriptorMap;
/**
* Constructor arguments have the same meaning as in {@link ComplexTypeImpl}.
*
* @param name
* @param identified
* @param isAbstract
* @param restrictions
* @param description
*/
public AbstractLazyComplexTypeImpl(Name name, boolean identified, boolean isAbstract,
List restrictions, InternationalString description) {
super(name, Collection.class, identified, isAbstract, restrictions, description);
}
/**
* Subclasses must override this method to return the list of descriptors that define the
* properties of this type. This method will only be called once at most.
*
*
*
* If the type has no properties, return either an empty collection or null.
*
* @return a collection of descriptors or null if empty
*/
public abstract Collection buildDescriptors();
/**
* Check whether descriptors have been built. If not, construct and sanitise them.
*/
private void requireDescriptors() {
if (descriptors == null) {
Collection builtDescriptors = buildDescriptors();
if (builtDescriptors == null) {
descriptors = Collections.emptyList();
descriptorMap = Collections.emptyMap();
} else {
Collection localDescriptors = new ArrayList(
builtDescriptors);
Map localDescriptorMap = new HashMap();
for (PropertyDescriptor descriptor : localDescriptors) {
localDescriptorMap.put(descriptor.getName(), descriptor);
}
descriptors = Collections.unmodifiableCollection(localDescriptors);
descriptorMap = Collections.unmodifiableMap(localDescriptorMap);
}
}
}
/**
* @see org.geotools.feature.type.AbstractLazyAttributeTypeImpl#getBinding()
*/
@SuppressWarnings("unchecked")
@Override
public Class> getBinding() {
return (Class>) super.getBinding();
}
/**
* @see org.opengis.feature.type.ComplexType#getDescriptors()
*/
public Collection getDescriptors() {
requireDescriptors();
return descriptors;
}
/**
* @see org.opengis.feature.type.ComplexType#getDescriptor(org.opengis.feature.type.Name)
*/
public PropertyDescriptor getDescriptor(Name name) {
requireDescriptors();
return descriptorMap.get(name);
}
/**
* The namespace-ignorant version of {@link #getDescriptor(Name)}. Note that we honour the same
* permissive algorithm as {@link ComplexTypeImpl}: (1) try no-namespace, (2) try
* container-namespace, (2) search for match ignoring namespace. *Shudder*
*
* @see org.opengis.feature.type.ComplexType#getDescriptor(java.lang.String)
* @deprecated Any code that uses this method instead of {@link #getDescriptor(Name)} is
* inherently unsafe.
*/
@Deprecated
public PropertyDescriptor getDescriptor(String name) {
requireDescriptors();
PropertyDescriptor result = getDescriptor(new NameImpl(name));
if (result == null) {
result = getDescriptor(new NameImpl(getName().getNamespaceURI(), name));
if (result == null) {
for (PropertyDescriptor pd : descriptors) {
if (pd.getName().getLocalPart().equals(name)) {
return pd;
}
}
}
}
return result;
}
/**
* @see org.opengis.feature.type.ComplexType#isInline()
*/
public boolean isInline() {
return false;
}
/**
* @see org.geotools.feature.type.AbstractLazyAttributeTypeImpl#toString()
*/
@Override
public String toString() {
return "LazyComplexType: " + getName();
}
}