package org.geogit.storage.hessian; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.geogit.api.ObjectId; import org.geogit.storage.ObjectReader; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.AttributeType; import org.opengis.feature.type.FeatureTypeFactory; import org.opengis.feature.type.GeometryType; import org.opengis.feature.type.Name; import org.opengis.filter.Filter; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.util.InternationalString; import com.caucho.hessian.io.Hessian2Input; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.vividsolutions.jts.geom.Geometry; public class HessianSimpleFeatureTypeReader implements ObjectReader<SimpleFeatureType> { private Name typeName; private SimpleFeatureTypeBuilder builder; private FeatureTypeFactory typeFactory; public HessianSimpleFeatureTypeReader(final Name typeName) { Preconditions.checkNotNull(typeName); this.typeName = typeName; this.builder = new SimpleFeatureTypeBuilder(); this.typeFactory = builder.getFeatureTypeFactory(); } @Override public SimpleFeatureType read(ObjectId id, InputStream rawData) throws IOException { Hessian2Input hin = new Hessian2Input(rawData); try { hin.startMessage(); String typeNamespace = hin.readString(); String typeName = hin.readString(); int attributeCount = hin.readInt(); SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); for(int i = 0; i < attributeCount; i++) { try { builder.add(readDescriptor(hin)); } catch(FactoryException ex) { Throwables.propagate(ex); } } hin.completeMessage(); builder.setName(new NameImpl( "".equals(typeNamespace) ? null : typeNamespace, typeName)); SimpleFeatureType type = builder.buildFeatureType(); return type; } finally { hin.close(); } } /** * The format will be written as follows: * <ol> * <li>EntityType - int</li> * <li>nillable - boolean</li> * <li>property namespace - String</li> * <li>property name - String</li> * <li>max - int</li> * <li>min - int</li> * <li>type namespace - String</li> * <li>type name - String</li> * </ol> * If the entity type is a geometry, then there is an additional (srid - String) field at the end. * * @param hout */ private AttributeDescriptor readDescriptor(Hessian2Input hin) throws IOException, FactoryException { int typeValue = hin.readInt(); GtEntityType type = GtEntityType.fromValue(typeValue); Class binding = type.getBinding(); boolean nillable = hin.readBoolean(); String pNamespace = hin.readString(); String pName = hin.readString(); int maxOccurs = hin.readInt(); int minOccurs = hin.readInt(); String tNamespace = hin.readString(); String tName = hin.readString(); String geomTypeName = null; String crsText = null; boolean crsCode = false; if(GtEntityType.GEOMETRY.equals(type)) { Object bObj = hin.readObject(); if(bObj instanceof Class) { binding = (Class)bObj; } crsCode = hin.readBoolean(); crsText = hin.readString(); } /* * Default values that are currently not encoded. */ boolean isIdentifiable = false; boolean isAbstract = false; List<Filter> restrictions = null; AttributeType superType = null; InternationalString description = null; Object defaultValue = null; Name propertyName = new NameImpl( "".equals(pNamespace) ? null : pNamespace, pName); Name typeName = new NameImpl( "".equals(tNamespace) ? null : tNamespace, tName); AttributeType attributeType; AttributeDescriptor attributeDescriptor; if(GtEntityType.GEOMETRY.equals(type)) { CoordinateReferenceSystem crs; if(crsCode) { if("urn:ogc:def:crs:EPSG::0".equals(crsText)) { crs = null; } else { crs = CRS.decode(crsText); } } else { crs = CRS.parseWKT(crsText); } attributeType = typeFactory.createGeometryType(typeName, binding, crs, isIdentifiable, isAbstract, restrictions, superType, description); attributeDescriptor = typeFactory.createGeometryDescriptor((GeometryType)attributeType, propertyName, minOccurs, maxOccurs, nillable, defaultValue); } else { attributeType = typeFactory.createAttributeType(typeName, binding, isIdentifiable, isAbstract, restrictions, superType, description); attributeDescriptor = typeFactory.createAttributeDescriptor(attributeType, propertyName, minOccurs, maxOccurs, nillable, defaultValue); } return attributeDescriptor; } }