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.wfsv.response.v1_1_0;
006:
007: import net.opengis.wfs.DeleteElementType;
008: import net.opengis.wfs.InsertElementType;
009: import net.opengis.wfs.PropertyType;
010: import net.opengis.wfs.TransactionType;
011: import net.opengis.wfs.UpdateElementType;
012: import net.opengis.wfs.WfsFactory;
013: import net.opengis.wfsv.GetDiffType;
014: import org.apache.xml.serialize.OutputFormat;
015: import org.eclipse.emf.common.util.EList;
016: import org.geoserver.ows.Response;
017: import org.geoserver.ows.util.OwsUtils;
018: import org.geoserver.ows.util.ResponseUtils;
019: import org.geoserver.platform.Operation;
020: import org.geoserver.platform.ServiceException;
021: import org.geoserver.wfs.WFS;
022: import org.geoserver.wfs.WFSException;
023: import org.geoserver.wfs.xml.v1_1_0.WFSConfiguration;
024: import org.geotools.data.postgis.FeatureDiff;
025: import org.geotools.data.postgis.FeatureDiffReader;
026: import org.geotools.feature.Feature;
027: import org.geotools.feature.FeatureType;
028: import org.geotools.xml.Encoder;
029: import org.opengis.filter.Filter;
030: import org.opengis.filter.FilterFactory;
031: import org.opengis.filter.identity.FeatureId;
032: import org.vfny.geoserver.global.Data;
033: import org.vfny.geoserver.global.FeatureTypeInfo;
034: import org.xml.sax.SAXException;
035: import java.io.IOException;
036: import java.io.OutputStream;
037: import java.util.Collections;
038: import java.util.HashMap;
039: import java.util.HashSet;
040: import java.util.Iterator;
041: import java.util.Map;
042: import java.util.Set;
043: import javax.xml.namespace.QName;
044:
045: /**
046: * WFS output format for a GetDiff operation whose output format is a WFS 1.1
047: * transaction
048: *
049: * @author Andrea Aime, TOPP
050: *
051: */
052: public class GetDiffTransactionOutputFormat extends Response {
053: /**
054: * WFS configuration
055: */
056: WFS wfs;
057: Data catalog;
058:
059: /**
060: * Xml configuration
061: */
062: WFSConfiguration configuration;
063:
064: /**
065: * Filter factory used to build fid filters
066: */
067: FilterFactory filterFactory;
068:
069: public GetDiffTransactionOutputFormat(WFS wfs, Data catalog,
070: WFSConfiguration configuration, FilterFactory filterFactory) {
071: super (FeatureDiffReader[].class);
072:
073: this .wfs = wfs;
074: this .configuration = configuration;
075: this .catalog = catalog;
076: this .filterFactory = filterFactory;
077: }
078:
079: /**
080: * @return "text/xml";
081: */
082: public String getMimeType(Object value, Operation operation)
083: throws ServiceException {
084: return "text/xml; subtype=wfs-transaction/1.1.0";
085: }
086:
087: /**
088: * Checks that the resultType is of type "hits".
089: */
090: public boolean canHandle(Operation operation) {
091: GetDiffType request = (GetDiffType) OwsUtils.parameter(
092: operation.getParameters(), GetDiffType.class);
093:
094: return (request != null)
095: && request.getOutputFormat().equals(
096: "text/xml; subtype=wfs-transaction/1.1.0");
097: }
098:
099: public void write(Object value, OutputStream output,
100: Operation operation) throws IOException, ServiceException {
101: final FeatureDiffReader[] diffReaders = (FeatureDiffReader[]) value;
102:
103: // create a new feature collcetion type with just the numbers
104: final TransactionType transaction = WfsFactory.eINSTANCE
105: .createTransactionType();
106:
107: for (int i = 0; i < diffReaders.length; i++) {
108: final FeatureDiffReader diffReader = diffReaders[i];
109:
110: // create a single insert element, a single delete element, and as
111: // many update elements as needed
112: final FeatureType schema = diffReader.getSchema();
113: final QName typeName = new QName(schema.getNamespace()
114: .getAuthority(), schema.getTypeName());
115: final Set deletedIds = new HashSet();
116: final InsertElementType insert = WfsFactory.eINSTANCE
117: .createInsertElementType();
118:
119: while (diffReader.hasNext()) {
120: FeatureDiff diff = diffReader.next();
121:
122: switch (diff.getState()) {
123: case FeatureDiff.INSERTED:
124: insert.getFeature().add(diff.getFeature());
125:
126: break;
127:
128: case FeatureDiff.DELETED:
129: deletedIds.add(filterFactory
130: .featureId(diff.getID()));
131:
132: break;
133:
134: case FeatureDiff.UPDATED:
135:
136: final UpdateElementType update = WfsFactory.eINSTANCE
137: .createUpdateElementType();
138: final EList properties = update.getProperty();
139:
140: Feature f = diff.getFeature();
141:
142: for (Iterator it = diff.getChangedAttributes()
143: .iterator(); it.hasNext();) {
144: final PropertyType property = WfsFactory.eINSTANCE
145: .createPropertyType();
146: String name = (String) it.next();
147: property.setName(new QName(name));
148: property.setValue(f.getAttribute(name));
149: properties.add(property);
150: }
151:
152: FeatureId featureId = filterFactory.featureId(diff
153: .getID());
154: final Filter filter = filterFactory.id(Collections
155: .singleton(featureId));
156: update.setFilter(filter);
157: update.setTypeName(typeName);
158: transaction.getUpdate().add(update);
159:
160: break;
161:
162: default:
163: throw new WFSException(
164: "Could not handle diff type "
165: + diff.getState());
166: }
167: }
168:
169: // create insert and delete elements if needed
170: if (insert.getFeature().size() > 0) {
171: transaction.getInsert().add(insert);
172: }
173:
174: if (deletedIds.size() > 0) {
175: final DeleteElementType delete = WfsFactory.eINSTANCE
176: .createDeleteElementType();
177: delete.setFilter(filterFactory.id(deletedIds));
178: delete.setTypeName(typeName);
179: transaction.getDelete().add(delete);
180: }
181: }
182:
183: Encoder encoder = new Encoder(configuration, configuration
184: .schema());
185: encoder.setSchemaLocation(
186: org.geoserver.wfs.xml.v1_1_0.WFS.NAMESPACE,
187: ResponseUtils.appendPath(wfs.getSchemaBaseURL(),
188: "wfs/1.1.0/wfs.xsd"));
189:
190: OutputFormat format = new OutputFormat();
191: format.setIndenting(true);
192: encoder.setOutputFormat(format);
193:
194: // set up schema locations
195: // round up the info objects for each feature collection
196: HashMap /* <String,Set> */ns2metas = new HashMap();
197:
198: for (int i = 0; i < diffReaders.length; i++) {
199: final FeatureDiffReader diffReader = diffReaders[i];
200: final FeatureType featureType = diffReader.getSchema();
201:
202: // load the metadata for the feature type
203: String namespaceURI = featureType.getNamespace().toString();
204: FeatureTypeInfo meta = catalog.getFeatureTypeInfo(
205: featureType.getTypeName(), namespaceURI);
206:
207: // add it to the map
208: Set metas = (Set) ns2metas.get(namespaceURI);
209:
210: if (metas == null) {
211: metas = new HashSet();
212: ns2metas.put(namespaceURI, metas);
213: }
214:
215: metas.add(meta);
216: }
217:
218: // declare application schema namespaces
219: for (Iterator i = ns2metas.entrySet().iterator(); i.hasNext();) {
220: Map.Entry entry = (Map.Entry) i.next();
221:
222: String namespaceURI = (String) entry.getKey();
223: Set metas = (Set) entry.getValue();
224:
225: StringBuffer typeNames = new StringBuffer();
226:
227: for (Iterator m = metas.iterator(); m.hasNext();) {
228: FeatureTypeInfo meta = (FeatureTypeInfo) m.next();
229: typeNames.append(meta.getName());
230:
231: if (m.hasNext()) {
232: typeNames.append(",");
233: }
234: }
235:
236: // set the schema location
237: encoder.setSchemaLocation(namespaceURI, ResponseUtils
238: .appendQueryString(wfs.getOnlineResource()
239: .toString(),
240: "service=WFS&version=1.1.0&request=DescribeFeatureType&typeName="
241: + typeNames.toString()));
242: }
243:
244: try {
245: System.out.println(transaction);
246: encoder.encode(transaction,
247: org.geoserver.wfs.xml.v1_1_0.WFS.TRANSACTION,
248: output);
249: } catch (SAXException e) {
250: //SAXException does not sets initCause(). Instead, it holds its own "exception" field.
251: if (e.getException() != null && e.getCause() == null) {
252: e.initCause(e.getException());
253: }
254: throw (IOException) new IOException("Encoding error ")
255: .initCause(e);
256: } finally {
257: for (int i = 0; i < diffReaders.length; i++) {
258: diffReaders[i].close();
259: }
260: }
261: }
262: }
|