In Geotools, there is a bug when trying to create fieldlength constrained attribute,
Which leads to the attribute field length are always set to 255 chars (except the Number class).
Even if you use following to create the AttributeType:
By stepping into the source of the Geotools, I found the problem is caused by the procedure where
the geotools convert the fieldLength to a filter, it always generate the type of PropertyEqualsTo,
but when the geotools generate the DB file header, it only apply the length value in case of following condition (in ShapefileDataStore.java):
if (f != null && f != Filter.EXCLUDE && f != Filter.INCLUDE &&
( (f instanceof PropertyIsLessThan )
|| (f instanceof PropertyIsLessThanOrEqualTo))) {
then the problem raised, all the fieldLength in previous step are ignored when creating db header and with length of the default 255!
Then , we could easily get our solution to work around those issues by generate customized filter with type
of PropertyIsLessThan or PropertyIsLessThanOrEqualTo, see following utility function:
public AttributeType createAttributeType(String attrName, Class<?> cls,
boolean isNillable,int fieldLength) {
LengthFunction length = (LengthFunction)ff.function("LengthFunction",
new Expression[]{ff.property(attrName)});
Filter cf = null;
try {
cf = ff.lessOrEqual(length, ff.literal(fieldLength));
} catch (IllegalFilterException e) {
e.printStackTrace();
}
if(cf == null){
cf = Filter.EXCLUDE;
}
return DefaultAttributeTypeFactory.newAttributeType(attrName,cls,isNillable,cf,null,null);
}
Then we could use above method to create our fieldLength valid attributeType as following:
//create feature schema
AttributeType geom = createAttributeType("geom",Polygon.class);
AttributeType ID = createAttributeType("id",String.class,true,10);
AttributeType name = createAttributeType("Name",String.class,true,50);
//19 = length of (yyyy-MM-dd hh:mm:ss)
AttributeType date = createAttributeType("BirthDate",Date.class,true,19);
FeatureType ft= FeatureTypeBuilder .newFeatureType(new AttributeType[]
{ geom,ID,name,date},featureName);
then the field-length works fine as we expect, and it will greatly decrease the size of .dbf file especially there is many records and many string attributes type in the shapefile.
Which leads to the attribute field length are always set to 255 chars (except the Number class).
Even if you use following to create the AttributeType:
DefaultAttributeTypeFactory.newAttributeType(String name, Class clazz, boolean isNillable, int fieldLength)
By stepping into the source of the Geotools, I found the problem is caused by the procedure where
the geotools convert the fieldLength to a filter, it always generate the type of PropertyEqualsTo,
but when the geotools generate the DB file header, it only apply the length value in case of following condition (in ShapefileDataStore.java):
if (f != null && f != Filter.EXCLUDE && f != Filter.INCLUDE &&
( (f instanceof PropertyIsLessThan )
|| (f instanceof PropertyIsLessThanOrEqualTo))) {
then the problem raised, all the fieldLength in previous step are ignored when creating db header and with length of the default 255!
Then , we could easily get our solution to work around those issues by generate customized filter with type
of PropertyIsLessThan or PropertyIsLessThanOrEqualTo, see following utility function:
public AttributeType createAttributeType(String attrName, Class<?> cls,
boolean isNillable,int fieldLength) {
LengthFunction length = (LengthFunction)ff.function("LengthFunction",
new Expression[]{ff.property(attrName)});
Filter cf = null;
try {
cf = ff.lessOrEqual(length, ff.literal(fieldLength));
} catch (IllegalFilterException e) {
e.printStackTrace();
}
if(cf == null){
cf = Filter.EXCLUDE;
}
return DefaultAttributeTypeFactory.newAttributeType(attrName,cls,isNillable,cf,null,null);
}
Then we could use above method to create our fieldLength valid attributeType as following:
//create feature schema
AttributeType geom = createAttributeType("geom",Polygon.class);
AttributeType ID = createAttributeType("id",String.class,true,10);
AttributeType name = createAttributeType("Name",String.class,true,50);
//19 = length of (yyyy-MM-dd hh:mm:ss)
AttributeType date = createAttributeType("BirthDate",Date.class,true,19);
FeatureType ft= FeatureTypeBuilder .newFeatureType(new AttributeType[]
{ geom,ID,name,date},featureName);
then the field-length works fine as we expect, and it will greatly decrease the size of .dbf file especially there is many records and many string attributes type in the shapefile.