001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.tools;
034:
035: import java.util.*;
036:
037: import com.vividsolutions.jts.util.Assert;
038: import com.vividsolutions.jump.feature.*;
039:
040: public class AttributeMapping {
041: private List aAttributeNames;
042: private List bAttributeNames;
043: private List aNewAttributeNames;
044: private List bNewAttributeNames;
045: private FeatureSchema aSchema;
046: private FeatureSchema bSchema;
047:
048: protected AttributeMapping() {
049: //for testing [Jon Aquino]
050: }
051:
052: /**
053: * Constructs an AttributeMapping that will transfer all the attributes from
054: * two feature collections A and B. If A and B have attributes with the same
055: * name, they will be postfixed with _1 and _2 respectively. Case sensitive.
056: * If you only wish to map attributes for one schema, simply pass in a
057: * new FeatureSchema for the other schema.
058: * @param a schema for first feature collection from which to transfer attributes
059: * @param b schema for second feature collection from which to transfer attributes
060: */
061: public AttributeMapping(FeatureSchema a, FeatureSchema b) {
062: init(a, nonSpatialAttributeNames(a, null, null),
063: nonSpatialAttributeNames(a, b, "_1"), b,
064: nonSpatialAttributeNames(b, null, null),
065: nonSpatialAttributeNames(b, a, "_2"));
066: }
067:
068: /**
069: * Constructs an AttributeMapping.
070: * @param aSchema metadata for feature-collection A
071: * @param aAttributeNames non-spatial feature-collection-A attributes to transfer
072: * @param aNewAttributeNames corresponding names in the feature collection receiving the attributes
073: * @param bSchema metadata for feature-collection B
074: * @param bAttributeNames non-spatial feature-collection-B attributes to transfer
075: * @param bNewAttributeNames corresponding names in the feature collection receiving the attributes
076: */
077: public AttributeMapping(FeatureSchema aSchema,
078: List aAttributeNames, List aNewAttributeNames,
079: FeatureSchema bSchema, List bAttributeNames,
080: List bNewAttributeNames) {
081: init(aSchema, aAttributeNames, aNewAttributeNames, bSchema,
082: bAttributeNames, bNewAttributeNames);
083: }
084:
085: private List nonSpatialAttributeNames(FeatureSchema schema,
086: FeatureSchema other, String postfix) {
087: ArrayList attributeNames = new ArrayList();
088:
089: for (int i = 0; i < schema.getAttributeCount(); i++) {
090: if (schema.getAttributeType(i) == AttributeType.GEOMETRY) {
091: continue;
092: }
093:
094: String attributeName = schema.getAttributeName(i);
095:
096: if ((other != null) && other.hasAttribute(attributeName)) {
097: attributeName += postfix;
098: }
099:
100: attributeNames.add(attributeName);
101: }
102:
103: return attributeNames;
104: }
105:
106: private void init(FeatureSchema aSchema, List aAttributeNames,
107: List aNewAttributeNames, FeatureSchema bSchema,
108: List bAttributeNames, List bNewAttributeNames) {
109: Assert
110: .isTrue(isDisjoint(aNewAttributeNames,
111: bNewAttributeNames));
112: Assert.isTrue(aAttributeNames.size() == aNewAttributeNames
113: .size());
114: Assert.isTrue(bAttributeNames.size() == bNewAttributeNames
115: .size());
116: this .aSchema = aSchema;
117: this .bSchema = bSchema;
118: this .aAttributeNames = new ArrayList(aAttributeNames);
119: this .bAttributeNames = new ArrayList(bAttributeNames);
120: this .aNewAttributeNames = new ArrayList(aNewAttributeNames);
121: this .bNewAttributeNames = new ArrayList(bNewAttributeNames);
122: }
123:
124: /**
125: * Returns a new FeatureSchema with the destination attributes of the mapping
126: * and a spatial attribute with the given name
127: * @param geometryName name to assign to the spatial attribute
128: */
129: public CombinedSchema createSchema(String geometryName) {
130: CombinedSchema newSchema = new CombinedSchema();
131: addAttributes(newSchema, aSchema, aAttributeNames,
132: aNewAttributeNames,
133: newSchema.aNewToOldAttributeIndexMap);
134: newSchema.lastNewAttributeIndexForA = newSchema
135: .getAttributeCount() - 1;
136: addAttributes(newSchema, bSchema, bAttributeNames,
137: bNewAttributeNames,
138: newSchema.bNewToOldAttributeIndexMap);
139: newSchema.addAttribute(geometryName, AttributeType.GEOMETRY);
140:
141: return newSchema;
142: }
143:
144: public static class CombinedSchema extends FeatureSchema {
145: private static final long serialVersionUID = -8627306219650589202L;
146: private Map aNewToOldAttributeIndexMap = new HashMap();
147: private Map bNewToOldAttributeIndexMap = new HashMap();
148:
149: public int toAOldAttributeIndex(int newAttributeIndex) {
150: return ((Integer) aNewToOldAttributeIndexMap
151: .get(new Integer(newAttributeIndex))).intValue();
152: }
153:
154: public int toBOldAttributeIndex(int newAttributeIndex) {
155: return ((Integer) bNewToOldAttributeIndexMap
156: .get(new Integer(newAttributeIndex))).intValue();
157: }
158:
159: private int lastNewAttributeIndexForA;
160:
161: public boolean isFromA(int newAttributeIndex) {
162: return newAttributeIndex <= lastNewAttributeIndexForA;
163: };
164: }
165:
166: private void addAttributes(FeatureSchema newSchema,
167: FeatureSchema sourceSchema, List attributeNames,
168: List newAttributeNames, Map newToOldAttributeIndexMap) {
169: for (int i = 0; i < attributeNames.size(); i++) {
170: String attributeName = (String) attributeNames.get(i);
171: String newAttributeName = (String) newAttributeNames.get(i);
172: AttributeType type = sourceSchema
173: .getAttributeType(attributeName);
174:
175: if (type == AttributeType.GEOMETRY) {
176: continue;
177: }
178:
179: newSchema.addAttribute(newAttributeName, type);
180: newToOldAttributeIndexMap.put(new Integer(newSchema
181: .getAttributeCount() - 1), new Integer(i));
182: }
183: }
184:
185: protected boolean isDisjoint(Collection a, Collection b) {
186: HashSet c = new HashSet();
187: c.addAll(a);
188: c.addAll(b);
189:
190: return c.size() == (a.size() + b.size());
191: }
192:
193: /**
194: * Transfers attributes (not the geometry) from two features to a third
195: * feature, using the mappings specified in the constructor. The third feature's
196: * schema must be able to accomodate the attributes being transferred.
197: * @param aFeature a feature from feature-collection A
198: * @param bFeature a feature from feature-collection B
199: * @param cFeature the feature to transfer the A and B attributes to
200: */
201: public void transferAttributes(Feature aFeature, Feature bFeature,
202: Feature cFeature) {
203: transferAttributes(aFeature, cFeature, aAttributeNames,
204: aNewAttributeNames);
205: transferAttributes(bFeature, cFeature, bAttributeNames,
206: bNewAttributeNames);
207: }
208:
209: private void transferAttributes(Feature source, Feature dest,
210: List attributeNames, List newAttributeNames) {
211: for (int i = 0; i < attributeNames.size(); i++) {
212: String attributeName = (String) attributeNames.get(i);
213: String newAttributeName = (String) newAttributeNames.get(i);
214: Assert.isTrue(source.getSchema().getAttributeType(
215: attributeName) != AttributeType.GEOMETRY);
216: dest.setAttribute(newAttributeName, source
217: .getAttribute(attributeName));
218: }
219: }
220: }
|