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.geoserver.feature;
006:
007: import org.geotools.data.DataUtilities;
008: import org.geotools.data.FeatureReader;
009: import org.geotools.data.FeatureWriter;
010: import org.geotools.feature.AttributeType;
011: import org.geotools.feature.Feature;
012: import org.geotools.feature.FeatureCollection;
013: import org.geotools.feature.FeatureIterator;
014: import org.geotools.feature.FeatureType;
015: import org.geotools.feature.IllegalAttributeException;
016: import org.geotools.feature.collection.DelegateFeatureIterator;
017: import java.io.IOException;
018: import java.util.Iterator;
019: import java.util.NoSuchElementException;
020:
021: /**
022: * FeatureCollection with "casts" features from on feature type to another.
023: *
024: * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
025: *
026: */
027: public class RetypingFeatureCollection extends
028: DecoratingFeatureCollection {
029: FeatureType target;
030:
031: public RetypingFeatureCollection(FeatureCollection delegate,
032: FeatureType target) {
033: super (delegate);
034: this .target = target;
035: }
036:
037: public FeatureType getSchema() {
038: return target;
039: }
040:
041: public Iterator iterator() {
042: return new RetypingIterator(delegate.iterator(), target);
043: }
044:
045: public void close(Iterator iterator) {
046: RetypingIterator retyping = (RetypingIterator) iterator;
047: delegate.close(retyping.delegate);
048: }
049:
050: public FeatureIterator features() {
051: return new DelegateFeatureIterator(this , iterator());
052: }
053:
054: public void close(FeatureIterator iterator) {
055: DelegateFeatureIterator delegate = (DelegateFeatureIterator) iterator;
056: delegate.close();
057: }
058:
059: static Feature retype(Feature source, FeatureType target)
060: throws IllegalAttributeException {
061: Object[] attributes = new Object[target.getAttributeCount()];
062:
063: for (int i = 0; i < target.getAttributeCount(); i++) {
064: AttributeType attributeType = target.getAttributeType(i);
065: Object value = null;
066:
067: if (source.getFeatureType().getAttributeType(
068: attributeType.getName()) != null) {
069: value = source.getAttribute(attributeType.getName());
070: }
071:
072: attributes[i] = value;
073: }
074:
075: String id = reTypeId(source.getID(), source.getFeatureType(),
076: target);
077: return target.create(attributes, id);
078: }
079:
080: /**
081: * Given a feature id following the <typename>.<internalId> convention, the original
082: * type and the destination type, this converts the id from <original>.<internalid>
083: * to <target>.<internalid>
084: * @param id
085: * @param original
086: * @param target
087: * @return
088: */
089: public static String reTypeId(String sourceId,
090: FeatureType original, FeatureType target) {
091: final String originalTypeName = original.getTypeName();
092: final String destTypeName = target.getTypeName();
093: if (destTypeName.equals(originalTypeName))
094: return sourceId;
095:
096: final String prefix = originalTypeName + ".";
097: if (sourceId.startsWith(prefix)) {
098: return destTypeName + "."
099: + sourceId.substring(prefix.length());
100: } else
101: return sourceId;
102: }
103:
104: public static class RetypingIterator implements Iterator {
105: FeatureType target;
106: Iterator delegate;
107:
108: public RetypingIterator(Iterator delegate, FeatureType target) {
109: this .delegate = delegate;
110: this .target = target;
111: }
112:
113: public boolean hasNext() {
114: return delegate.hasNext();
115: }
116:
117: public Object next() {
118: try {
119: return RetypingFeatureCollection.retype(
120: (Feature) delegate.next(), target);
121: } catch (IllegalAttributeException e) {
122: throw new RuntimeException(e);
123: }
124: }
125:
126: public void remove() {
127: delegate.remove();
128: }
129: }
130:
131: public static class RetypingFeatureReader implements FeatureReader {
132: FeatureReader delegate;
133: FeatureType target;
134:
135: public RetypingFeatureReader(FeatureReader delegate,
136: FeatureType target) {
137: this .delegate = delegate;
138: this .target = target;
139: }
140:
141: public void close() throws IOException {
142: delegate.close();
143: delegate = null;
144: target = null;
145: }
146:
147: public FeatureType getFeatureType() {
148: return target;
149: }
150:
151: public boolean hasNext() throws IOException {
152: return delegate.hasNext();
153: }
154:
155: public Feature next() throws IOException,
156: IllegalAttributeException, NoSuchElementException {
157: return RetypingFeatureCollection.retype(delegate.next(),
158: target);
159: }
160: }
161:
162: public static class RetypingFeatureWriter implements FeatureWriter {
163: FeatureWriter delegate;
164: FeatureType target;
165: private Feature current;
166: private Feature retyped;
167:
168: public RetypingFeatureWriter(FeatureWriter delegate,
169: FeatureType target) {
170: this .delegate = delegate;
171: this .target = target;
172: }
173:
174: public void close() throws IOException {
175: delegate.close();
176: delegate = null;
177: target = null;
178: }
179:
180: public FeatureType getFeatureType() {
181: return target;
182: }
183:
184: public boolean hasNext() throws IOException {
185: return delegate.hasNext();
186: }
187:
188: public Feature next() throws IOException {
189: try {
190: current = delegate.next();
191: retyped = RetypingFeatureCollection.retype(current,
192: target);
193: return retyped;
194: } catch (IllegalAttributeException e) {
195: throw (IOException) new IOException(
196: "Error occurred while retyping feature")
197: .initCause(e);
198: }
199: }
200:
201: public void remove() throws IOException {
202: delegate.write();
203: }
204:
205: public void write() throws IOException {
206: try {
207: for (int i = 0; i < target.getAttributeCount(); i++) {
208: AttributeType at = target.getAttributeType(i);
209: Object value = retyped.getAttribute(i);
210: current.setAttribute(at.getLocalName(), value);
211: }
212: delegate.write();
213: } catch (IllegalAttributeException e) {
214: throw (IOException) new IOException(
215: "Error occurred while retyping feature")
216: .initCause(e);
217: }
218: }
219: }
220: }
|