001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/csw/manager/TransactionDocument.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53115 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042: ---------------------------------------------------------------------------*/
043: package org.deegree.ogcwebservices.csw.manager;
044:
045: import java.io.IOException;
046: import java.io.InputStream;
047: import java.net.MalformedURLException;
048: import java.net.URI;
049: import java.util.ArrayList;
050: import java.util.HashMap;
051: import java.util.List;
052: import java.util.Map;
053:
054: import org.deegree.framework.log.ILogger;
055: import org.deegree.framework.log.LoggerFactory;
056: import org.deegree.framework.xml.ElementList;
057: import org.deegree.framework.xml.XMLException;
058: import org.deegree.framework.xml.XMLFragment;
059: import org.deegree.framework.xml.XMLParsingException;
060: import org.deegree.framework.xml.XMLTools;
061: import org.deegree.i18n.Messages;
062: import org.deegree.model.filterencoding.AbstractFilter;
063: import org.deegree.model.filterencoding.Filter;
064: import org.deegree.ogcbase.CommonNamespaces;
065: import org.deegree.ogcwebservices.InvalidParameterValueException;
066: import org.deegree.ogcwebservices.MissingParameterValueException;
067: import org.deegree.ogcwebservices.OGCWebServiceException;
068: import org.deegree.ogcwebservices.csw.AbstractCSWRequestDocument;
069: import org.w3c.dom.Document;
070: import org.w3c.dom.Element;
071: import org.xml.sax.SAXException;
072:
073: /**
074: * The Transaction operation defines an interface for creating, modifying and deleting catalogue
075: * records. The specific payload being manipulated must be defined in a profile.
076: *
077: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
078: * @author last edited by: $Author: apoth $
079: *
080: * @version $Revision: 9345 $, $Date: 2007-12-27 08:22:25 -0800 (Thu, 27 Dec 2007) $
081: *
082: */
083: public class TransactionDocument extends AbstractCSWRequestDocument {
084:
085: private static final long serialVersionUID = 7914686453810419662L;
086:
087: protected static final ILogger LOG = LoggerFactory
088: .getLogger(TransactionDocument.class);
089:
090: /**
091: * initializes an empty TransactionDocument
092: *
093: */
094: public TransactionDocument() {
095: try {
096: setSystemId(XMLFragment.DEFAULT_URL);
097: } catch (MalformedURLException e) {
098: LOG.logError(e.getMessage(), e);
099: }
100: }
101:
102: /**
103: *
104: * @throws IOException
105: * @throws SAXException
106: */
107: public void createEmptyDocument() {
108: Document doc = XMLTools.create();
109: Element root = doc.createElementNS(CommonNamespaces.CSWNS
110: .toASCIIString(), "csw:Transaction");
111: setRootElement(root);
112:
113: }
114:
115: /**
116: * initializes a TransactionDocument by reading a DOM object from the passed
117: *
118: * @see InputStream
119: *
120: * @param transRoot
121: * @throws XMLException
122: * @throws IOException
123: */
124: public TransactionDocument(Element transRoot) throws XMLException {
125: setRootElement(transRoot);
126: //setSystemId( XMLFragment.DEFAULT_URL );
127: }
128:
129: /**
130: * parses a CS-W 2.0 transaction request
131: * @param id of the TransactionRequest
132: *
133: * @return a new transaction parsed from the this xml-encoded request.
134: * @throws XMLParsingException
135: * @throws InvalidParameterValueException
136: * @throws MissingParameterValueException
137: */
138: public Transaction parse(String id) throws XMLParsingException,
139: OGCWebServiceException {
140:
141: LOG.logDebug("parsing CS-W Transaction request");
142: String version = XMLTools.getNodeAsString(getRootElement(),
143: "@version", nsContext, null);
144: boolean verbose = XMLTools.getNodeAsBoolean(getRootElement(),
145: "./@verboseResponse", nsContext, false);
146:
147: List<Operation> ops = new ArrayList<Operation>();
148:
149: ElementList el = XMLTools.getChildElements(getRootElement());
150: for (int i = 0; i < el.getLength(); i++) {
151: Element e = el.item(i);
152: // TODO check for qualified name
153: if ("Insert".equals(e.getLocalName())) {
154: ops.add(parseInsert(e));
155: } else if ("Update".equals(e.getLocalName())) {
156: ops.add(parseUpdate(e));
157: } else if ("Delete".equals(e.getLocalName())) {
158: ops.add(parseDelete(e));
159: }
160: }
161:
162: //in the future the vendorSpecificParameters
163: Map<String, String> vendorSpecificParameters = parseDRMParams(this
164: .getRootElement());
165:
166: return new Transaction(version, id, vendorSpecificParameters,
167: ops, verbose);
168: }
169:
170: /**
171: * parses a Delete element contained in a CS-W Transaction.
172: *
173: * @param element
174: * @return the Delete class parsed from the given Delete element.
175: * @throws XMLParsingException
176: * @throws MissingParameterValueException
177: * @throws InvalidParameterValueException
178: */
179: private Delete parseDelete(Element element)
180: throws XMLParsingException, MissingParameterValueException,
181: InvalidParameterValueException {
182:
183: LOG.logDebug("parsing CS-W Transaction-Delete");
184:
185: String handle = XMLTools.getNodeAsString(element, "@handle",
186: nsContext, null);
187: String tmp = XMLTools.getNodeAsString(element, "@typeName",
188: nsContext, null);
189: URI typeName = null;
190: if (tmp != null) {
191: // part of the corrected CS-W 2.0 spec
192: try {
193: typeName = new URI(tmp);
194: } catch (Exception e) {
195: throw new XMLParsingException(
196: "if defined attribute 'typeName' must be "
197: + "a valid URI");
198: }
199: }
200:
201: Element elem = (Element) XMLTools.getRequiredNode(element,
202: "./csw:Constraint", nsContext);
203: String ver = XMLTools.getNodeAsString(elem, "@version",
204: nsContext, null);
205: if (ver == null) {
206: String s = Messages
207: .getMessage("CSW_MISSING_CONSTRAINT_VERSION");
208: throw new MissingParameterValueException(s);
209: }
210: if (!"1.0.0".equals(ver) && !"1.1.0".equals(ver)) {
211: String s = Messages.getMessage(
212: "CSW_INVALID_CONSTRAINT_VERSION", ver);
213: throw new InvalidParameterValueException(s);
214: }
215:
216: elem = (Element) XMLTools.getRequiredNode(elem, "./ogc:Filter",
217: nsContext);
218:
219: Filter constraint = AbstractFilter.buildFromDOM(elem, "1.0.0"
220: .equals(ver));
221: return new Delete(handle, typeName, constraint);
222: }
223:
224: /**
225: * parses a Update element contained in a CS-W Transaction.
226: *
227: * @param element
228: * @return the update class containing all parsed values
229: * @throws XMLParsingException
230: * @throws MissingParameterValueException
231: * @throws InvalidParameterValueException
232: */
233: private Update parseUpdate(Element element)
234: throws XMLParsingException, MissingParameterValueException,
235: InvalidParameterValueException {
236:
237: LOG.logDebug("parsing CS-W Transaction-Update");
238:
239: String handle = XMLTools.getNodeAsString(element, "@handle",
240: nsContext, null);
241: String tmp = XMLTools.getNodeAsString(element, "@typeName",
242: nsContext, null);
243: URI typeName = null;
244: if (tmp != null) {
245: // part of the corrected CS-W 2.0 spec
246: try {
247: typeName = new URI(tmp);
248: } catch (Exception e) {
249: throw new XMLParsingException(
250: "if defined attribute 'typeName' must be a valid URI");
251: }
252: }
253: Element elem = (Element) XMLTools.getRequiredNode(element,
254: "./csw:Constraint", nsContext);
255: String ver = XMLTools.getNodeAsString(elem, "@version",
256: nsContext, null);
257: if (ver == null) {
258: String s = Messages
259: .getMessage("CSW_MISSING_CONSTRAINT_VERSION");
260: throw new MissingParameterValueException(s);
261: }
262: if (!"1.0.0".equals(ver) && !"1.1.0".equals(ver)) {
263: String s = Messages.getMessage(
264: "CSW_INVALID_CONSTRAINT_VERSION", ver);
265: throw new InvalidParameterValueException(s);
266: }
267:
268: elem = (Element) XMLTools.getRequiredNode(elem, "./ogc:Filter",
269: nsContext);
270:
271: Filter constraint = AbstractFilter.buildFromDOM(elem, "1.0.0"
272: .equals(ver));
273:
274: List children = null;
275: List rp = XMLTools.getNodes(getRootElement(),
276: "./csw:RecordProperty", nsContext);
277: if (rp.size() != 0) {
278: // at the moment will always be null because it is part of the
279: // CS-W 2.0 corrected version that will not be implemented yet
280: } else {
281: children = XMLTools.getNodes(element, "./child::*",
282: nsContext);
283: if (children.size() == 0) {
284: throw new XMLParsingException(
285: "one record must be defined within a CS-W update element");
286: }
287: }
288: return new Update(handle, typeName, constraint,
289: (Element) children.get(0), null);
290: }
291:
292: /**
293: * parses a Insert element contained in a CS-W Transaction.
294: *
295: * @param element
296: * @return an Insert instance
297: * @throws XMLParsingException
298: */
299: private Insert parseInsert(Element element)
300: throws XMLParsingException {
301:
302: LOG.logDebug("parsing CS-W Transaction-Insert");
303:
304: String handle = XMLTools.getNodeAsString(element, "@handle",
305: nsContext, "");
306: List<Element> recList = new ArrayList<Element>();
307: List children = XMLTools.getNodes(element, "*", nsContext);
308: if (children.size() == 0) {
309: LOG
310: .logError("at least one record must be defined within a CS-W insert element");
311: throw new XMLParsingException(
312: "at least one record must be defined "
313: + "within a CS-W insert element");
314: }
315:
316: String prefixForRim = null;
317: for (Object n : children) {
318: LOG
319: .logDebug("TransactionDocument(insert): adding the element: "
320: + element.getLocalName()
321: + " to the records list. ");
322: if (prefixForRim == null) {
323: prefixForRim = ((Element) n)
324: .lookupPrefix(CommonNamespaces.OASIS_EBRIMNS
325: .toASCIIString());
326: }
327: recList.add((Element) n);
328: }
329:
330: //check if the rim namespace is used
331: //nsForRim = XMLTools.getNamespaceForPrefix( "rim", element );
332:
333: LOG
334: .logDebug("TransactionDocument: for the insert operation found following prefix: "
335: + prefixForRim);
336: if (prefixForRim != null) {
337: List<Element> nl = XMLTools.getElements(element,
338: "rim:ExtrinsicObject", nsContext);
339: Map<String, Element> extrinsicObjects = new HashMap<String, Element>(
340: nl.size());
341: LOG
342: .logDebug("TransactionDocument: number of ExtrinsicObjects found: "
343: + extrinsicObjects.size());
344: for (Element n : nl) {
345: String id = XMLTools.getRequiredNodeAsString(n, "@id",
346: nsContext);
347: if ("".equals(id.trim())) {
348: throw new XMLParsingException(
349: "The value of the id attribute in a {"
350: + CommonNamespaces.OASIS_EBRIMNS
351: .toASCIIString()
352: + "}extrinsicObject may not be empty");
353: }
354: LOG.logDebug("TransactionDocument: found the id " + id);
355: extrinsicObjects.put(id.trim(), n);
356: }
357: return new Insert(handle, recList, extrinsicObjects);
358: }
359: // if no ebrim is done, create the old insert class.
360: return new Insert(handle, recList);
361: }
362: }
|