/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.tools; import java.util.*; import com.vividsolutions.jts.util.Assert; import com.vividsolutions.jump.feature.*; public class AttributeMapping { private List aAttributeNames; private List bAttributeNames; private List aNewAttributeNames; private List bNewAttributeNames; private FeatureSchema aSchema; private FeatureSchema bSchema; protected AttributeMapping() { //for testing [Jon Aquino] } /** * Constructs an AttributeMapping that will transfer all the attributes from * two feature collections A and B. If A and B have attributes with the same * name, they will be postfixed with _1 and _2 respectively. Case sensitive. * If you only wish to map attributes for one schema, simply pass in a * new FeatureSchema for the other schema. * @param a schema for first feature collection from which to transfer attributes * @param b schema for second feature collection from which to transfer attributes */ public AttributeMapping(FeatureSchema a, FeatureSchema b) { init(a, nonSpatialAttributeNames(a, null, null), nonSpatialAttributeNames(a, b, "_1"), b, nonSpatialAttributeNames(b, null, null), nonSpatialAttributeNames(b, a, "_2")); } /** * Constructs an AttributeMapping. * @param aSchema metadata for feature-collection A * @param aAttributeNames non-spatial feature-collection-A attributes to transfer * @param aNewAttributeNames corresponding names in the feature collection receiving the attributes * @param bSchema metadata for feature-collection B * @param bAttributeNames non-spatial feature-collection-B attributes to transfer * @param bNewAttributeNames corresponding names in the feature collection receiving the attributes */ public AttributeMapping(FeatureSchema aSchema, List aAttributeNames, List aNewAttributeNames, FeatureSchema bSchema, List bAttributeNames, List bNewAttributeNames) { init(aSchema, aAttributeNames, aNewAttributeNames, bSchema, bAttributeNames, bNewAttributeNames); } private List nonSpatialAttributeNames(FeatureSchema schema, FeatureSchema other, String postfix) { ArrayList attributeNames = new ArrayList(); for (int i = 0; i < schema.getAttributeCount(); i++) { if (schema.getAttributeType(i) == AttributeType.GEOMETRY) { continue; } String attributeName = schema.getAttributeName(i); if ((other != null) && other.hasAttribute(attributeName)) { attributeName += postfix; } attributeNames.add(attributeName); } return attributeNames; } private void init(FeatureSchema aSchema, List aAttributeNames, List aNewAttributeNames, FeatureSchema bSchema, List bAttributeNames, List bNewAttributeNames) { Assert.isTrue(isDisjoint(aNewAttributeNames, bNewAttributeNames)); Assert.isTrue(aAttributeNames.size() == aNewAttributeNames.size()); Assert.isTrue(bAttributeNames.size() == bNewAttributeNames.size()); this.aSchema = aSchema; this.bSchema = bSchema; this.aAttributeNames = new ArrayList(aAttributeNames); this.bAttributeNames = new ArrayList(bAttributeNames); this.aNewAttributeNames = new ArrayList(aNewAttributeNames); this.bNewAttributeNames = new ArrayList(bNewAttributeNames); } /** * Returns a new FeatureSchema with the destination attributes of the mapping * and a spatial attribute with the given name * @param geometryName name to assign to the spatial attribute */ public CombinedSchema createSchema(String geometryName) { CombinedSchema newSchema = new CombinedSchema(); addAttributes(newSchema, aSchema, aAttributeNames, aNewAttributeNames, newSchema.aNewToOldAttributeIndexMap); newSchema.lastNewAttributeIndexForA = newSchema.getAttributeCount() - 1; addAttributes(newSchema, bSchema, bAttributeNames, bNewAttributeNames, newSchema.bNewToOldAttributeIndexMap); newSchema.addAttribute(geometryName, AttributeType.GEOMETRY); return newSchema; } public static class CombinedSchema extends FeatureSchema { private static final long serialVersionUID = -8627306219650589202L; private Map aNewToOldAttributeIndexMap = new HashMap(); private Map bNewToOldAttributeIndexMap = new HashMap(); public int toAOldAttributeIndex(int newAttributeIndex) { return ((Integer)aNewToOldAttributeIndexMap.get(new Integer(newAttributeIndex))).intValue(); } public int toBOldAttributeIndex(int newAttributeIndex) { return ((Integer)bNewToOldAttributeIndexMap.get(new Integer(newAttributeIndex))).intValue(); } private int lastNewAttributeIndexForA; public boolean isFromA(int newAttributeIndex) { return newAttributeIndex <= lastNewAttributeIndexForA; }; } private void addAttributes(FeatureSchema newSchema, FeatureSchema sourceSchema, List attributeNames, List newAttributeNames, Map newToOldAttributeIndexMap) { for (int i = 0; i < attributeNames.size(); i++) { String attributeName = (String) attributeNames.get(i); String newAttributeName = (String) newAttributeNames.get(i); AttributeType type = sourceSchema.getAttributeType(attributeName); if (type == AttributeType.GEOMETRY) { continue; } newSchema.addAttribute(newAttributeName, type); newToOldAttributeIndexMap.put(new Integer(newSchema.getAttributeCount()-1), new Integer(i)); } } protected boolean isDisjoint(Collection a, Collection b) { HashSet c = new HashSet(); c.addAll(a); c.addAll(b); return c.size() == (a.size() + b.size()); } /** * Transfers attributes (not the geometry) from two features to a third * feature, using the mappings specified in the constructor. The third feature's * schema must be able to accomodate the attributes being transferred. * @param aFeature a feature from feature-collection A * @param bFeature a feature from feature-collection B (can be null) * @param cFeature the feature to transfer the A and B attributes to */ public void transferAttributes(Feature aFeature, Feature bFeature, Feature cFeature) { //-- [sstein: 27Mar2008] added check to avoid errors if ((aFeature != null) && (cFeature != null)){ transferAttributes(aFeature, cFeature, aAttributeNames, aNewAttributeNames); } if ((bFeature != null) && (cFeature != null)){ transferAttributes(bFeature, cFeature, bAttributeNames, bNewAttributeNames); } } private void transferAttributes(Feature source, Feature dest, List attributeNames, List newAttributeNames) { for (int i = 0; i < attributeNames.size(); i++) { String attributeName = (String) attributeNames.get(i); String newAttributeName = (String) newAttributeNames.get(i); AttributeType p = source.getSchema().getAttributeType(attributeName); int b=1+1; Assert.isTrue(source.getSchema().getAttributeType(attributeName) != AttributeType.GEOMETRY); dest.setAttribute(newAttributeName, source.getAttribute(attributeName)); } } }