001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.global.dto;
006:
007: import com.vividsolutions.jts.geom.Envelope;
008: import org.opengis.filter.Filter;
009: import org.vfny.geoserver.config.DataConfig;
010: import org.vfny.geoserver.global.FeatureTypeInfo;
011:
012: import java.io.File;
013: import java.util.ArrayList;
014: import java.util.LinkedList;
015: import java.util.List;
016:
017: /**
018: * Data Transfer Object used for GeoServer FeatureTypeInfo information.
019: *
020: * <p>
021: * FeatureTypeInfo is used because FeatureType is already used to represent
022: * schema information in GeoTools2.
023: * </p>
024: *
025: * <p>
026: * Data Transfer object are used to communicate between the GeoServer
027: * application and its configuration and persistent layers. As such the class
028: * is final - to allow for its future use as an on-the-wire message.
029: * </p>
030: * <pre>Example:<code>
031: * FeatureTypeInfoDTO ftiDto = new FeatureTypeInfoDTO();
032: * ftiDto.setName("My Feature Type");
033: * ftiDto.setTitle("The Best Feature Type");
034: * ftiDto.setSRS(23769);
035: * </code></pre>
036: *
037: * @author dzwiers, Refractions Research, Inc.
038: * @version $Id: FeatureTypeInfoDTO.java 8391 2008-02-13 16:44:23Z aaime $
039: */
040: public final class FeatureTypeInfoDTO implements DataTransferObject {
041: /** The Id of the datastore which should be used to get this featuretype. */
042: private String dataStoreId;
043:
044: /** A bounding box in EPSG:4326 for this featuretype */
045: private Envelope latLongBBox;
046:
047: /** A bounding box in native's CRS for this featuretype */
048: private Envelope nativeBBox;
049:
050: /** native wich EPGS code for the FeatureTypeInfo */
051: private int SRS;
052:
053: /** either reproject or force, see {@link FeatureTypeInfo} */
054: private int SRSHandling;
055:
056: /** Copy of the featuretype schema as a string. */
057: private List schema;
058:
059: /** The schema name. */
060: private String schemaName;
061:
062: /**
063: * The schemaBase name.
064: *
065: * <p>
066: * Example NullType, or PointPropertyType.
067: * </p>
068: */
069: private String schemaBase;
070:
071: /**
072: * The native featuretype name (the one used in the original datastore)
073: *
074: * <p>
075: * Often related to the title - like bc_roads_Type
076: * </p>
077: */
078: private String name;
079:
080: /**
081: * The alias for this feature type (if any)
082: */
083: private String alias;
084:
085: private String wmsPath;
086:
087: /**
088: * The featuretype directory name. This is used to write to, and is stored
089: * because it may be longer than the name, as this often includes
090: * information about the source of the featuretype.
091: */
092: private String dirName;
093:
094: /** The featuretype title */
095: private String title;
096:
097: /** The feature type abstract, short explanation of this featuretype. */
098: private String _abstract;
099:
100: /** A list of keywords to associate with this featuretype. */
101: private List keywords;
102:
103: /** A list of metadataURLs to associate with this featuretype. */
104: private List metadataLinks;
105:
106: /** Used to limit the number of decimals used in GML representations. */
107: private int numDecimals;
108:
109: /**
110: * the list of exposed attributes. If the list is empty or not present at
111: * all, all the FeatureTypeInfo's attributes are exposed, if is present,
112: * only those oattributes in this list will be exposed by the services
113: */
114: private Filter definitionQuery = null;
115:
116: /** The default style name. */
117: private String defaultStyle;
118:
119: /** Other Style Names. */
120: private ArrayList styles = new ArrayList();
121:
122: // Modif C. Kolbowicz - 06/10/2004
123:
124: /** The legend icon description. */
125: private LegendURLDTO legendURL;
126:
127: //-- Modif C. Kolbowicz - 06/10/2004
128:
129: /** Holds the location of the file that contains schema information.*/
130: private File schemaFile;
131:
132: /**
133: * This value is added the headers of generated maps, marking them as being both
134: * "cache-able" and designating the time for which they are to remain valid.
135: * The specific header added is "Cache-Control: max-age="
136: */
137: private String cacheMaxAge;
138:
139: /**
140: * Should we be adding the CacheControl: max-age header to outgoing maps which include this layer?
141: */
142: private boolean cachingEnabled;
143:
144: /**
145: * The maximum number of features to be served for this feature type (it's understood
146: * it's less than the global maxFeatures). 0 is used as the "no limit" flag
147: */
148: private int maxFeatures = 0;
149:
150: /**
151: * FeatureTypeInfo constructor.
152: *
153: * <p>
154: * does nothing
155: * </p>
156: */
157: public FeatureTypeInfoDTO() {
158: }
159:
160: public String getAlias() {
161: return alias;
162: }
163:
164: public void setAlias(String alias) {
165: this .alias = alias;
166: }
167:
168: /**
169: * FeatureTypeInfo constructor.
170: *
171: * <p>
172: * Creates a copy of the FeatureTypeInfo provided. If the FeatureTypeInfo
173: * provided is null then default values are used. All the data structures
174: * are cloned.
175: * </p>
176: *
177: * @param dto The featuretype to copy.
178: *
179: * @throws NullPointerException DOCUMENT ME!
180: */
181: public FeatureTypeInfoDTO(FeatureTypeInfoDTO dto) {
182: if (dto == null) {
183: throw new NullPointerException(
184: "Non null FeatureTypeInfoDTO required");
185: }
186:
187: dataStoreId = dto.getDataStoreId();
188: latLongBBox = CloneLibrary.clone(dto.getLatLongBBox());
189: nativeBBox = CloneLibrary.clone(dto.getNativeBBox());
190: SRS = dto.getSRS();
191: SRSHandling = dto.getSRSHandling();
192: schema = dto.getSchemaAttributes();
193: name = dto.getName();
194: alias = dto.getAlias();
195: wmsPath = dto.getWmsPath();
196: title = dto.getTitle();
197: _abstract = dto.getAbstract();
198: numDecimals = dto.getNumDecimals();
199: definitionQuery = dto.getDefinitionQuery();
200:
201: // Modif C. Kolbowicz - 06/10/2004
202: legendURL = dto.getLegendURL();
203:
204: //-- Modif C. Kolbowicz - 06/10/2004
205: try {
206: keywords = CloneLibrary.clone(dto.getKeywords()); //clone?
207: } catch (Exception e) {
208: keywords = new LinkedList();
209: }
210:
211: try {
212: metadataLinks = CloneLibrary.clone(dto.getMetadataLinks()); //clone?
213: } catch (Exception e) {
214: metadataLinks = new LinkedList();
215: }
216:
217: defaultStyle = dto.getDefaultStyle();
218: styles = dto.getStyles();
219:
220: dirName = dto.getDirName();
221: schemaName = dto.getSchemaName();
222: schemaBase = dto.getSchemaBase();
223:
224: cachingEnabled = dto.isCachingEnabled();
225: cacheMaxAge = dto.getCacheMaxAge();
226:
227: maxFeatures = dto.getMaxFeatures();
228: }
229:
230: /**
231: * Implement clone as a deep copy.
232: *
233: * @return A copy of this FeatureTypeInfo
234: *
235: * @see java.lang.Object#clone()
236: */
237: public Object clone() {
238: return new FeatureTypeInfoDTO(this );
239: }
240:
241: /**
242: * Implement equals.
243: *
244: * <p>
245: * recursively tests to determine if the object passed in is a copy of this
246: * object.
247: * </p>
248: *
249: * @param obj The FeatureTypeInfo object to test.
250: *
251: * @return true when the object passed is the same as this object.
252: *
253: * @see java.lang.Object#equals(java.lang.Object)
254: */
255: public boolean equals(Object obj) {
256: if ((obj == null) || !(obj instanceof FeatureTypeInfoDTO)) {
257: return false;
258: }
259:
260: FeatureTypeInfoDTO f = (FeatureTypeInfoDTO) obj;
261: boolean r = true;
262: r = r && (dataStoreId == f.getDataStoreId());
263:
264: if (latLongBBox != null) {
265: r = r && latLongBBox.equals(f.getLatLongBBox());
266: } else if (f.getLatLongBBox() != null) {
267: return false;
268: }
269:
270: if (nativeBBox != null) {
271: r = r && nativeBBox.equals(f.getNativeBBox());
272: } else if (f.getNativeBBox() != null) {
273: return false;
274: }
275:
276: r = r && (SRS == f.getSRS());
277:
278: r = r && (SRSHandling == f.getSRSHandling());
279:
280: if (schema != null) {
281: r = r && schema.equals(f.getSchemaAttributes());
282: } else if (f.getSchemaAttributes() != null) {
283: return false;
284: }
285:
286: // Modif C. Kolbowicz - 06/10/2004
287: if (legendURL != null) {
288: r = r && schema.equals(f.getLegendURL());
289: } else if (f.getLegendURL() != null) {
290: return false;
291: }
292:
293: //-- Modif C. Kolbowicz - 06/10/2004
294: r = r && (defaultStyle == f.getDefaultStyle());
295: r = r && (styles == f.getStyles());
296: r = r && (name == f.getName());
297: r = r && (alias == f.getAlias());
298: r = r && (wmsPath == f.getWmsPath());
299: r = r && (title == f.getTitle());
300: r = r && (_abstract == f.getAbstract());
301: r = r && (numDecimals == f.getNumDecimals());
302: r = r && (maxFeatures == f.getMaxFeatures());
303:
304: if (definitionQuery != null) {
305: r = r && definitionQuery.equals(f.getDefinitionQuery());
306: } else if (f.getDefinitionQuery() != null) {
307: return false;
308: }
309:
310: if (keywords != null) {
311: r = r && EqualsLibrary.equals(keywords, f.getKeywords());
312: } else if (f.getKeywords() != null) {
313: return false;
314: }
315:
316: if (metadataLinks != null) {
317: r = r
318: && EqualsLibrary.equals(metadataLinks, f
319: .getMetadataLinks());
320: } else if (f.getMetadataLinks() != null) {
321: return false;
322: }
323:
324: r = r && (dirName == f.getDirName());
325: r = r && (schemaName == f.getSchemaName());
326: r = r && (schemaBase == f.getSchemaBase());
327:
328: r = r && (isCachingEnabled() == f.isCachingEnabled());
329: r = r
330: && ((getCacheMaxAge() != null) && getCacheMaxAge()
331: .equals(f.getCacheMaxAge()));
332:
333: return r;
334: }
335:
336: /**
337: * Implement hashCode.
338: *
339: * @return Service hashcode or 0
340: *
341: * @see java.lang.Object#hashCode()
342: */
343: public int hashCode() {
344: int r = 1;
345:
346: if (name != null) {
347: r *= name.hashCode();
348: }
349:
350: if (alias != null) {
351: r *= alias.hashCode();
352: }
353:
354: if (dataStoreId != null) {
355: r *= dataStoreId.hashCode();
356: }
357:
358: // Modif C. Kolbowicz - 06/10/2004
359: if (legendURL != null) {
360: r *= legendURL.hashCode();
361: }
362:
363: //-- Modif C. Kolbowicz - 06/10/2004
364: if (title != null) {
365: r *= title.hashCode();
366: }
367:
368: if (SRS != 0) {
369: r = SRS % r;
370: }
371:
372: r += SRSHandling;
373:
374: if (cacheMaxAge != null) {
375: r *= cacheMaxAge.hashCode();
376: }
377:
378: if (cachingEnabled) {
379: r += 1;
380: }
381:
382: r += maxFeatures;
383:
384: return r;
385: }
386:
387: /**
388: * Short description of FeatureType.
389: *
390: * @return Description of FeatureType
391: */
392: public String getAbstract() {
393: return _abstract;
394: }
395:
396: /**
397: * Identifier of DataStore used to create FeatureType.
398: *
399: * @return DataStore identifier
400: */
401: public String getDataStoreId() {
402: return dataStoreId;
403: }
404:
405: /**
406: * List of keywords (limitied to text).
407: *
408: * @return List of Keywords about this FeatureType
409: */
410: public List getKeywords() {
411: return keywords;
412: }
413:
414: /**
415: * List of metadataURLs (limited to text).
416: *
417: * @return List of metadataURLs about this FeatureType
418: */
419: public List getMetadataLinks() {
420: return metadataLinks;
421: }
422:
423: /**
424: * Convience method for dataStoreId.typeName.
425: *
426: * <p>
427: * This key may be used to store this FeatureType in a Map for later.
428: * </p>
429: *
430: * @return dataStoreId.typeName
431: */
432: public String getKey() {
433: return getDataStoreId() + DataConfig.SEPARATOR + getName();
434: }
435:
436: /**
437: * The extent of this FeatureType.
438: *
439: * <p>
440: * Extent is measured against the tranditional LatLong coordinate system.
441: * </p>
442: *
443: * @return Envelope of FeatureType
444: */
445: public Envelope getLatLongBBox() {
446: return latLongBBox;
447: }
448:
449: /**
450: * Sets the feature type's envelope in its
451: * native CRS for cached storage.
452: *
453: * @param envelope
454: */
455: public void setNativeBBox(Envelope envelope) {
456: nativeBBox = envelope;
457: }
458:
459: /**
460: * The extent of this FeatureType.<p>Extent is measured against the
461: * FeatureType's native coordinate system.</p>
462: *
463: * @return Envelope of FeatureType
464: */
465: public Envelope getNativeBBox() {
466: return nativeBBox;
467: }
468:
469: /**
470: * Name of featureType, must match typeName provided by DataStore.
471: *
472: * @return typeName of FeatureType
473: */
474: public String getName() {
475: return name;
476: }
477:
478: /**
479: * Spatial Reference System for FeatureType.
480: *
481: * <p>
482: * Makes use of the standard EPSG codes?
483: * </p>
484: *
485: * @return WPSG Spatial Reference System for FeatureType
486: */
487: public int getSRS() {
488: return SRS;
489: }
490:
491: public int getSRSHandling() {
492: return SRSHandling;
493: }
494:
495: /**
496: * Title used to identify FeatureType to user.
497: *
498: * @return FeatureType title
499: */
500: public String getTitle() {
501: return title;
502: }
503:
504: /**
505: * setAbstract purpose.
506: *
507: * <p>
508: * Description ...
509: * </p>
510: *
511: * @param string
512: */
513: public void setAbstract(String string) {
514: _abstract = string;
515: }
516:
517: /**
518: * setDataStore purpose.
519: *
520: * <p>
521: * Description ...
522: * </p>
523: *
524: * @param store
525: */
526: public void setDataStoreId(String store) {
527: dataStoreId = store;
528: }
529:
530: /**
531: * setKeywords purpose.
532: *
533: * <p>
534: * Description ...
535: * </p>
536: *
537: * @param list
538: */
539: public void setKeywords(List list) {
540: keywords = list;
541: }
542:
543: /**
544: * Sets the MetadataURL list for this feature type
545: *
546: * @param list
547: */
548: public void setMetadataLinks(List list) {
549: metadataLinks = list;
550: }
551:
552: /**
553: * setKeywords purpose.
554: *
555: * <p>
556: * Description ...
557: * </p>
558: *
559: * @param key
560: *
561: * @return boolean true when added.
562: */
563: public boolean addKeyword(String key) {
564: if (keywords == null) {
565: keywords = new LinkedList();
566: }
567:
568: return keywords.add(key);
569: }
570:
571: /**
572: * setKeywords purpose.
573: *
574: * <p>
575: * Description ...
576: * </p>
577: *
578: * @param key
579: *
580: * @return true whwn removed
581: */
582: public boolean removeKeyword(String key) {
583: return keywords.remove(key);
584: }
585:
586: /**
587: * setLatLongBBox purpose.
588: *
589: * <p>
590: * Description ...
591: * </p>
592: *
593: * @param envelope
594: */
595: public void setLatLongBBox(Envelope envelope) {
596: latLongBBox = envelope;
597: }
598:
599: /**
600: * setName purpose.
601: *
602: * <p>
603: * Description ...
604: * </p>
605: *
606: * @param string
607: */
608: public void setName(String string) {
609: name = string;
610: }
611:
612: /**
613: * setSRS purpose.
614: *
615: * <p>
616: * Description ...
617: * </p>
618: *
619: * @param i
620: */
621: public void setSRS(int i) {
622: SRS = i;
623: }
624:
625: public void setSRSHandling(int i) {
626: SRSHandling = i;
627: }
628:
629: /**
630: * setTitle purpose.
631: *
632: * <p>
633: * Description ...
634: * </p>
635: *
636: * @param string
637: */
638: public void setTitle(String string) {
639: title = string;
640: }
641:
642: /**
643: * getNumDecimals purpose.
644: *
645: * <p>
646: * Description ...
647: * </p>
648: *
649: * @return
650: */
651: public int getNumDecimals() {
652: return numDecimals;
653: }
654:
655: /**
656: * setNumDecimals purpose.
657: *
658: * <p>
659: * Description ...
660: * </p>
661: *
662: * @param i
663: */
664: public void setNumDecimals(int i) {
665: numDecimals = i;
666: }
667:
668: /**
669: * getDefinitionQuery purpose.
670: *
671: * <p>
672: * Description ...
673: * </p>
674: *
675: * @return
676: */
677: public Filter getDefinitionQuery() {
678: return definitionQuery;
679: }
680:
681: /**
682: * setDefinitionQuery purpose.
683: *
684: * <p>
685: * Description ...
686: * </p>
687: *
688: * @param filter
689: */
690: public void setDefinitionQuery(Filter filter) {
691: definitionQuery = filter;
692: }
693:
694: /**
695: * getDefaultStyle purpose.
696: *
697: * <p>
698: * Description ...
699: * </p>
700: *
701: * @return
702: */
703: public String getDefaultStyle() {
704: //HACK: So our UI doesn't seem to allow the setting of styles or
705: //default styles or anything, despite the fact that shit chokes when none
706: //is present. This is making it so the beta release can not have any data
707: //stores added to it. This is a hacky ass way to get around it, just
708: //write out a normal style if it is null. This can obviously be done
709: //better, and I have no idea why this default style shit is required - wfs
710: //does not care about a style. Should be able to seamlessly at least do
711: //something for wms.
712: if ((defaultStyle == null) || defaultStyle.equals("")) {
713: defaultStyle = "normal";
714: }
715:
716: return defaultStyle;
717: }
718:
719: /**
720: * setDefaultStyle purpose.
721: *
722: * <p>
723: * Description ...
724: * </p>
725: *
726: * @param string
727: */
728: public void setDefaultStyle(String string) {
729: defaultStyle = string;
730: }
731:
732: /**
733: * getSchema purpose.
734: *
735: * <p>
736: * Returns An ordered list of AttributeTypeInfoDTOs
737: * </p>
738: *
739: * @return An ordered list of AttributeTypeInfoDTOs
740: */
741: public List getSchemaAttributes() {
742: return schema;
743: }
744:
745: /**
746: * setSchema purpose.
747: *
748: * <p>
749: * Stores a list of AttributeTypeInfoDTOs.
750: * </p>
751: *
752: * @param schemaElements An ordered list of AttributeTypeInfoDTOs
753: */
754: public void setSchemaAttributes(List schemaElements) {
755: this .schema = schemaElements;
756: }
757:
758: /**
759: * getDirName purpose.
760: *
761: * <p>
762: * Returns the featuretype directory name.
763: * </p>
764: *
765: * @return the featuretype directory name
766: */
767: public String getDirName() {
768: return dirName;
769: }
770:
771: /**
772: * setDirName purpose.
773: *
774: * <p>
775: * Description ...
776: * </p>
777: *
778: * @param string
779: */
780: public void setDirName(String string) {
781: dirName = string;
782: }
783:
784: /**
785: * getSchemaName purpose.
786: *
787: * <p>
788: * Description ...
789: * </p>
790: *
791: * @return
792: */
793: public String getSchemaName() {
794: return schemaName;
795: }
796:
797: /**
798: * setSchemaName purpose.
799: *
800: * <p>
801: * Description ...
802: * </p>
803: *
804: * @param string
805: */
806: public void setSchemaName(String string) {
807: schemaName = string;
808: }
809:
810: /**
811: * getSchemaBase purpose.
812: *
813: * <p>
814: * Usually generated as: getName + "_Type"
815: * </p>
816: *
817: * @return
818: */
819: public String getSchemaBase() {
820: return schemaBase;
821: }
822:
823: /**
824: * setSchemaBase purpose.
825: *
826: * <p>
827: * Description ...
828: * </p>
829: *
830: * @param string
831: */
832: public void setSchemaBase(String string) {
833: schemaBase = string;
834: }
835:
836: // Modif C. Kolbowicz - 06/10/2004
837:
838: /**
839: * Gets a reference to an optional legend icon.
840: *
841: * @return Value of property legendURL.
842: */
843: public LegendURLDTO getLegendURL() {
844: return this .legendURL;
845: }
846:
847: //-- Modif C. Kolbowicz - 06/10/2004
848: // Modif C. Kolbowicz - 06/10/2004
849:
850: /**
851: * Returns a reference to an optional legend icon.
852: *
853: * @param legendURL New value of property legendURL.
854: */
855: public void setLegendURL(LegendURLDTO legendURL) {
856: this .legendURL = legendURL;
857: }
858:
859: /**
860: * Gets the schema.xml file associated with this FeatureType. This is set
861: * during the reading of configuration, it is not persisted as an element
862: * of the FeatureTypeInfoDTO, since it is just whether the schema.xml file
863: * was persisted, and its location. If there is no schema.xml file then
864: * this method will return a File object with the location where the schema
865: * file would be located, but the file will return false for exists().
866: */
867: public File getSchemaFile() {
868: return this .schemaFile;
869: }
870:
871: /**
872: * Sets the schema file. Note that a non-exisiting file can be set here,
873: * to indicate that no schema.xml file is present.
874: */
875: public void setSchemaFile(File schemaFile) {
876: this .schemaFile = schemaFile;
877: }
878:
879: //-- Modif C. Kolbowicz - 06/10/2004
880: public String toString() {
881: return "[FeatureTypeInfoDTO: " + name + ", alias: " + alias
882: + ", datastoreId: " + dataStoreId + ", latLongBBOX: "
883: + latLongBBox + "\n SRS: " + SRS + ", schema:"
884: + schema + ", schemaName: " + schemaName
885: + ", dirName: " + dirName + ", title: " + title
886: + "\n definitionQuery: " + definitionQuery
887: + ", defaultStyle: " + defaultStyle + ", legend icon: "
888: + legendURL + ", caching?: " + cachingEnabled
889: + ", max-age: " + cacheMaxAge + ", maxFeatures: "
890: + maxFeatures;
891: }
892:
893: public String getWmsPath() {
894: return wmsPath;
895: }
896:
897: public void setWmsPath(String wmsPath) {
898: this .wmsPath = wmsPath;
899: }
900:
901: public boolean isCachingEnabled() {
902: return cachingEnabled;
903: }
904:
905: public void setCachingEnabled(boolean cachingEnabled) {
906: this .cachingEnabled = cachingEnabled;
907: }
908:
909: public String getCacheMaxAge() {
910: return cacheMaxAge;
911: }
912:
913: public void setCacheMaxAge(String cacheMaxAge) {
914: this .cacheMaxAge = cacheMaxAge;
915: }
916:
917: public ArrayList getStyles() {
918: return styles;
919: }
920:
921: public void addStyle(String styleName) {
922: if (!styles.contains(styleName)) {
923: styles.add(styleName);
924: }
925: }
926:
927: public void setStyles(ArrayList styles) {
928: this .styles = styles;
929: }
930:
931: public int getMaxFeatures() {
932: return maxFeatures;
933: }
934:
935: public void setMaxFeatures(int maxFeatures) {
936: this.maxFeatures = maxFeatures;
937: }
938: }
|