/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.vfny.geoserver.global.dto; import com.vividsolutions.jts.geom.Envelope; import org.opengis.filter.Filter; import org.vfny.geoserver.config.DataConfig; import org.vfny.geoserver.global.FeatureTypeInfo; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * Data Transfer Object used for GeoServer FeatureTypeInfo information. * * <p> * FeatureTypeInfo is used because FeatureType is already used to represent * schema information in GeoTools2. * </p> * * <p> * Data Transfer object are used to communicate between the GeoServer * application and its configuration and persistent layers. As such the class * is final - to allow for its future use as an on-the-wire message. * </p> * <pre>Example:<code> * FeatureTypeInfoDTO ftiDto = new FeatureTypeInfoDTO(); * ftiDto.setName("My Feature Type"); * ftiDto.setTitle("The Best Feature Type"); * ftiDto.setSRS(23769); * </code></pre> * * @author dzwiers, Refractions Research, Inc. * @version $Id$ */ public final class FeatureTypeInfoDTO implements DataTransferObject { /** The Id of the datastore which should be used to get this featuretype. */ private String dataStoreId; /** A bounding box in EPSG:4326 for this featuretype */ private Envelope latLongBBox; /** A bounding box in native's CRS for this featuretype */ private Envelope nativeBBox; /** native wich EPGS code for the FeatureTypeInfo */ private int SRS; /** either reproject or force, see {@link FeatureTypeInfo} */ private int SRSHandling; /** Copy of the featuretype schema as a string. */ private List schema; /** The schema name. */ private String schemaName; /** * The schemaBase name. * * <p> * Example NullType, or PointPropertyType. * </p> */ private String schemaBase; /** * The native featuretype name (the one used in the original datastore) * * <p> * Often related to the title - like bc_roads_Type * </p> */ private String name; /** * The alias for this feature type (if any) */ private String alias; private String wmsPath; /** * The featuretype directory name. This is used to write to, and is stored * because it may be longer than the name, as this often includes * information about the source of the featuretype. */ private String dirName; /** The featuretype title */ private String title; /** The feature type abstract, short explanation of this featuretype. */ private String _abstract; /** A list of keywords to associate with this featuretype. */ private List keywords; /** A list of metadataURLs to associate with this featuretype. */ private List metadataLinks; /** Used to limit the number of decimals used in GML representations. */ private int numDecimals; /** * the list of exposed attributes. If the list is empty or not present at * all, all the FeatureTypeInfo's attributes are exposed, if is present, * only those oattributes in this list will be exposed by the services */ private Filter definitionQuery = null; /** The default style name. */ private String defaultStyle; /** Other Style Names. */ private ArrayList styles = new ArrayList(); // Modif C. Kolbowicz - 06/10/2004 /** The legend icon description. */ private LegendURLDTO legendURL; //-- Modif C. Kolbowicz - 06/10/2004 /** Holds the location of the file that contains schema information.*/ private File schemaFile; /** * This value is added the headers of generated maps, marking them as being both * "cache-able" and designating the time for which they are to remain valid. * The specific header added is "Cache-Control: max-age=" */ private String cacheMaxAge; /** * Should we be adding the CacheControl: max-age header to outgoing maps which include this layer? */ private boolean cachingEnabled; /** * Should we list this layer when crawlers ask for the sitemap? */ private boolean indexingEnabled; /** * The maximum number of features to be served for this feature type (it's understood * it's less than the global maxFeatures). 0 is used as the "no limit" flag */ private int maxFeatures = 0; /** * The name of the property to use when regionating using the attribute strategy. */ private String regionateAttribute; private String regionateStrategy; private int regionateFeatureLimit; private String nameTemplate; /** * FeatureTypeInfo constructor. * * <p> * does nothing * </p> */ public FeatureTypeInfoDTO() { } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } /** * FeatureTypeInfo constructor. * * <p> * Creates a copy of the FeatureTypeInfo provided. If the FeatureTypeInfo * provided is null then default values are used. All the data structures * are cloned. * </p> * * @param dto The featuretype to copy. * * @throws NullPointerException DOCUMENT ME! */ public FeatureTypeInfoDTO(FeatureTypeInfoDTO dto) { if (dto == null) { throw new NullPointerException("Non null FeatureTypeInfoDTO required"); } dataStoreId = dto.getDataStoreId(); latLongBBox = CloneLibrary.clone(dto.getLatLongBBox()); nativeBBox = CloneLibrary.clone(dto.getNativeBBox()); SRS = dto.getSRS(); SRSHandling = dto.getSRSHandling(); schema = dto.getSchemaAttributes(); name = dto.getName(); alias = dto.getAlias(); wmsPath = dto.getWmsPath(); title = dto.getTitle(); _abstract = dto.getAbstract(); numDecimals = dto.getNumDecimals(); definitionQuery = dto.getDefinitionQuery(); // Modif C. Kolbowicz - 06/10/2004 legendURL = dto.getLegendURL(); //-- Modif C. Kolbowicz - 06/10/2004 try { keywords = CloneLibrary.clone(dto.getKeywords()); //clone? } catch (Exception e) { keywords = new LinkedList(); } try { metadataLinks = CloneLibrary.clone(dto.getMetadataLinks()); //clone? } catch (Exception e) { metadataLinks = new LinkedList(); } defaultStyle = dto.getDefaultStyle(); styles = dto.getStyles(); dirName = dto.getDirName(); schemaName = dto.getSchemaName(); schemaBase = dto.getSchemaBase(); cachingEnabled = dto.isCachingEnabled(); cacheMaxAge = dto.getCacheMaxAge(); indexingEnabled = dto.isIndexingEnabled(); regionateAttribute = dto.getRegionateAttribute(); regionateStrategy = dto.getRegionateStrategy(); regionateFeatureLimit = dto.getRegionateFeatureLimit(); nameTemplate = dto.getNameTemplate(); maxFeatures = dto.getMaxFeatures(); } /** * Implement clone as a deep copy. * * @return A copy of this FeatureTypeInfo * * @see java.lang.Object#clone() */ public Object clone() { return new FeatureTypeInfoDTO(this); } /** * Implement equals. * * <p> * recursively tests to determine if the object passed in is a copy of this * object. * </p> * * @param obj The FeatureTypeInfo object to test. * * @return true when the object passed is the same as this object. * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if ((obj == null) || !(obj instanceof FeatureTypeInfoDTO)) { return false; } FeatureTypeInfoDTO f = (FeatureTypeInfoDTO) obj; boolean r = true; r = r && (dataStoreId == f.getDataStoreId()); if (latLongBBox != null) { r = r && latLongBBox.equals(f.getLatLongBBox()); } else if (f.getLatLongBBox() != null) { return false; } if (nativeBBox != null) { r = r && nativeBBox.equals(f.getNativeBBox()); } else if (f.getNativeBBox() != null) { return false; } r = r && (SRS == f.getSRS()); r = r && (SRSHandling == f.getSRSHandling()); if (schema != null) { r = r && schema.equals(f.getSchemaAttributes()); } else if (f.getSchemaAttributes() != null) { return false; } // Modif C. Kolbowicz - 06/10/2004 if (legendURL != null) { r = r && schema.equals(f.getLegendURL()); } else if (f.getLegendURL() != null) { return false; } //-- Modif C. Kolbowicz - 06/10/2004 r = r && (defaultStyle == f.getDefaultStyle()); r = r && (styles == f.getStyles()); r = r && (name == f.getName()); r = r && (alias == f.getAlias()); r = r && (wmsPath == f.getWmsPath()); r = r && (title == f.getTitle()); r = r && (_abstract == f.getAbstract()); r = r && (numDecimals == f.getNumDecimals()); r = r && (maxFeatures == f.getMaxFeatures()); if (definitionQuery != null) { r = r && definitionQuery.equals(f.getDefinitionQuery()); } else if (f.getDefinitionQuery() != null) { return false; } if (keywords != null) { r = r && EqualsLibrary.equals(keywords, f.getKeywords()); } else if (f.getKeywords() != null) { return false; } if (metadataLinks != null) { r = r && EqualsLibrary.equals(metadataLinks, f.getMetadataLinks()); } else if (f.getMetadataLinks() != null) { return false; } r = r && (dirName == f.getDirName()); r = r && (schemaName == f.getSchemaName()); r = r && (schemaBase == f.getSchemaBase()); r = r && (isCachingEnabled() == f.isCachingEnabled()); r = r && ((getCacheMaxAge() != null) && getCacheMaxAge().equals(f.getCacheMaxAge())); return r; } /** * Implement hashCode. * * @return Service hashcode or 0 * * @see java.lang.Object#hashCode() */ public int hashCode() { int r = 1; if (name != null) { r *= name.hashCode(); } if (alias != null) { r *= alias.hashCode(); } if (dataStoreId != null) { r *= dataStoreId.hashCode(); } // Modif C. Kolbowicz - 06/10/2004 if (legendURL != null) { r *= legendURL.hashCode(); } //-- Modif C. Kolbowicz - 06/10/2004 if (title != null) { r *= title.hashCode(); } if (SRS != 0) { r = SRS % r; } r += SRSHandling; if (cacheMaxAge != null) { r *= cacheMaxAge.hashCode(); } if (cachingEnabled) { r += 1; } r += maxFeatures; return r; } /** * Short description of FeatureType. * * @return Description of FeatureType */ public String getAbstract() { return _abstract; } /** * Identifier of DataStore used to create FeatureType. * * @return DataStore identifier */ public String getDataStoreId() { return dataStoreId; } /** * List of keywords (limitied to text). * * @return List of Keywords about this FeatureType */ public List getKeywords() { return keywords; } /** * List of metadataURLs (limited to text). * * @return List of metadataURLs about this FeatureType */ public List getMetadataLinks() { return metadataLinks; } /** * Convience method for dataStoreId.typeName. * * <p> * This key may be used to store this FeatureType in a Map for later. * </p> * * @return dataStoreId.typeName */ public String getKey() { return getDataStoreId() + DataConfig.SEPARATOR + (getAlias() != null ? getAlias() : getName()); } /** * The extent of this FeatureType. * * <p> * Extent is measured against the tranditional LatLong coordinate system. * </p> * * @return Envelope of FeatureType */ public Envelope getLatLongBBox() { return latLongBBox; } /** * Sets the feature type's envelope in its * native CRS for cached storage. * * @param envelope */ public void setNativeBBox(Envelope envelope) { nativeBBox = envelope; } /** * The extent of this FeatureType.<p>Extent is measured against the * FeatureType's native coordinate system.</p> * * @return Envelope of FeatureType */ public Envelope getNativeBBox() { return nativeBBox; } /** * Name of featureType, must match typeName provided by DataStore. * * @return typeName of FeatureType */ public String getName() { return name; } /** * Spatial Reference System for FeatureType. * * <p> * Makes use of the standard EPSG codes? * </p> * * @return WPSG Spatial Reference System for FeatureType */ public int getSRS() { return SRS; } public int getSRSHandling() { return SRSHandling; } /** * Title used to identify FeatureType to user. * * @return FeatureType title */ public String getTitle() { return title; } /** * setAbstract purpose. * * <p> * Description ... * </p> * * @param string */ public void setAbstract(String string) { _abstract = string; } /** * setDataStore purpose. * * <p> * Description ... * </p> * * @param store */ public void setDataStoreId(String store) { dataStoreId = store; } /** * setKeywords purpose. * * <p> * Description ... * </p> * * @param list */ public void setKeywords(List list) { keywords = list; } /** * Sets the MetadataURL list for this feature type * * @param list */ public void setMetadataLinks(List list) { metadataLinks = list; } /** * setKeywords purpose. * * <p> * Description ... * </p> * * @param key * * @return boolean true when added. */ public boolean addKeyword(String key) { if (keywords == null) { keywords = new LinkedList(); } return keywords.add(key); } /** * setKeywords purpose. * * <p> * Description ... * </p> * * @param key * * @return true whwn removed */ public boolean removeKeyword(String key) { return keywords.remove(key); } /** * setLatLongBBox purpose. * * <p> * Description ... * </p> * * @param envelope */ public void setLatLongBBox(Envelope envelope) { latLongBBox = envelope; } /** * setName purpose. * * <p> * Description ... * </p> * * @param string */ public void setName(String string) { name = string; } /** * setSRS purpose. * * <p> * Description ... * </p> * * @param i */ public void setSRS(int i) { SRS = i; } public void setSRSHandling(int i) { SRSHandling = i; } /** * setTitle purpose. * * <p> * Description ... * </p> * * @param string */ public void setTitle(String string) { title = string; } /** * getNumDecimals purpose. * * <p> * Description ... * </p> * * @return */ public int getNumDecimals() { return numDecimals; } /** * setNumDecimals purpose. * * <p> * Description ... * </p> * * @param i */ public void setNumDecimals(int i) { numDecimals = i; } /** * getDefinitionQuery purpose. * * <p> * Description ... * </p> * * @return */ public Filter getDefinitionQuery() { return definitionQuery; } /** * setDefinitionQuery purpose. * * <p> * Description ... * </p> * * @param filter */ public void setDefinitionQuery(Filter filter) { definitionQuery = filter; } /** * getDefaultStyle purpose. * * <p> * Description ... * </p> * * @return */ public String getDefaultStyle() { //HACK: So our UI doesn't seem to allow the setting of styles or //default styles or anything, despite the fact that shit chokes when none //is present. This is making it so the beta release can not have any data //stores added to it. This is a hacky ass way to get around it, just //write out a normal style if it is null. This can obviously be done //better, and I have no idea why this default style shit is required - wfs //does not care about a style. Should be able to seamlessly at least do //something for wms. if ((defaultStyle == null) || defaultStyle.equals("")) { defaultStyle = "normal"; } return defaultStyle; } /** * setDefaultStyle purpose. * * <p> * Description ... * </p> * * @param string */ public void setDefaultStyle(String string) { defaultStyle = string; } /** * getSchema purpose. * * <p> * Returns An ordered list of AttributeTypeInfoDTOs * </p> * * @return An ordered list of AttributeTypeInfoDTOs */ public List getSchemaAttributes() { return schema; } /** * setSchema purpose. * * <p> * Stores a list of AttributeTypeInfoDTOs. * </p> * * @param schemaElements An ordered list of AttributeTypeInfoDTOs */ public void setSchemaAttributes(List schemaElements) { this.schema = schemaElements; } /** * getDirName purpose. * * <p> * Returns the featuretype directory name. * </p> * * @return the featuretype directory name */ public String getDirName() { return dirName; } /** * setDirName purpose. * * <p> * Description ... * </p> * * @param string */ public void setDirName(String string) { dirName = string; } /** * getSchemaName purpose. * * <p> * Description ... * </p> * * @return */ public String getSchemaName() { return schemaName; } /** * setSchemaName purpose. * * <p> * Description ... * </p> * * @param string */ public void setSchemaName(String string) { schemaName = string; } /** * getSchemaBase purpose. * * <p> * Usually generated as: getName + "_Type" * </p> * * @return */ public String getSchemaBase() { return schemaBase; } /** * setSchemaBase purpose. * * <p> * Description ... * </p> * * @param string */ public void setSchemaBase(String string) { schemaBase = string; } // Modif C. Kolbowicz - 06/10/2004 /** * Gets a reference to an optional legend icon. * * @return Value of property legendURL. */ public LegendURLDTO getLegendURL() { return this.legendURL; } //-- Modif C. Kolbowicz - 06/10/2004 // Modif C. Kolbowicz - 06/10/2004 /** * Returns a reference to an optional legend icon. * * @param legendURL New value of property legendURL. */ public void setLegendURL(LegendURLDTO legendURL) { this.legendURL = legendURL; } /** * Gets the schema.xml file associated with this FeatureType. This is set * during the reading of configuration, it is not persisted as an element * of the FeatureTypeInfoDTO, since it is just whether the schema.xml file * was persisted, and its location. If there is no schema.xml file then * this method will return a File object with the location where the schema * file would be located, but the file will return false for exists(). */ public File getSchemaFile() { return this.schemaFile; } /** * Sets the schema file. Note that a non-exisiting file can be set here, * to indicate that no schema.xml file is present. */ public void setSchemaFile(File schemaFile) { this.schemaFile = schemaFile; } //-- Modif C. Kolbowicz - 06/10/2004 public String toString() { return "[FeatureTypeInfoDTO: " + name + ", alias: " + alias + ", datastoreId: " + dataStoreId + ", latLongBBOX: " + latLongBBox + "\n SRS: " + SRS + ", schema:" + schema + ", schemaName: " + schemaName + ", dirName: " + dirName + ", title: " + title + "\n definitionQuery: " + definitionQuery + ", defaultStyle: " + defaultStyle + ", legend icon: " + legendURL + ", caching?: " + cachingEnabled + ", max-age: " + cacheMaxAge + ", maxFeatures: " + maxFeatures; } public String getWmsPath() { return wmsPath; } public void setWmsPath(String wmsPath) { this.wmsPath = wmsPath; } public boolean isCachingEnabled() { return cachingEnabled; } public boolean isIndexingEnabled(){ return indexingEnabled; } public String getRegionateAttribute(){ return regionateAttribute; } public String getRegionateStrategy(){ return regionateStrategy; } public int getRegionateFeatureLimit(){ return regionateFeatureLimit; } public String getNameTemplate() { return nameTemplate; } public void setCachingEnabled(boolean cachingEnabled) { this.cachingEnabled = cachingEnabled; } public void setIndexingEnabled(boolean indexingEnabled){ this.indexingEnabled = indexingEnabled; } public void setRegionateAttribute(String attr){ this.regionateAttribute = attr; } public void setRegionateStrategy(String strategy){ this.regionateStrategy = strategy; } public void setRegionateFeatureLimit(int limit){ this.regionateFeatureLimit = limit; } public void setNameTemplate(String name){ this.nameTemplate = name; } public String getCacheMaxAge() { return cacheMaxAge; } public void setCacheMaxAge(String cacheMaxAge) { this.cacheMaxAge = cacheMaxAge; } public ArrayList getStyles() { return styles; } public void addStyle(String styleName) { if (!styles.contains(styleName)) { styles.add(styleName); } } public void setStyles(ArrayList styles) { this.styles = styles; } public int getMaxFeatures() { return maxFeatures; } public void setMaxFeatures(int maxFeatures) { this.maxFeatures = maxFeatures; } }