001: //$HeadURL$
002: /*---------------- FILE HEADER ------------------------------------------
003: This file is part of deegree.
004: Copyright (C) 2001-2008 by:
005: Department of Geography, University of Bonn
006: http://www.giub.uni-bonn.de/deegree/
007: lat/lon GmbH
008: http://www.lat-lon.de
009:
010: This library is free software; you can redistribute it and/or
011: modify it under the terms of the GNU Lesser General Public
012: License as published by the Free Software Foundation; either
013: version 2.1 of the License, or (at your option) any later version.
014: This library is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018: You should have received a copy of the GNU Lesser General Public
019: License along with this library; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: Contact:
022:
023: Andreas Poth
024: lat/lon GmbH
025: Aennchenstr. 19
026: 53177 Bonn
027: Germany
028: E-Mail: poth@lat-lon.de
029:
030: Prof. Dr. Klaus Greve
031: Department of Geography
032: University of Bonn
033: Meckenheimer Allee 166
034: 53115 Bonn
035: Germany
036: E-Mail: greve@giub.uni-bonn.de
037: ---------------------------------------------------------------------------*/
038:
039: package org.deegree.ogcwebservices.csw.discovery;
040:
041: import java.io.IOException;
042: import java.net.URI;
043: import java.net.URISyntaxException;
044: import java.net.URL;
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.List;
048: import java.util.Map;
049:
050: import org.deegree.datatypes.QualifiedName;
051: import org.deegree.framework.log.ILogger;
052: import org.deegree.framework.log.LoggerFactory;
053: import org.deegree.framework.xml.XMLParsingException;
054: import org.deegree.framework.xml.XMLTools;
055: import org.deegree.i18n.Messages;
056: import org.deegree.model.filterencoding.AbstractFilter;
057: import org.deegree.model.filterencoding.ComplexFilter;
058: import org.deegree.model.filterencoding.Filter;
059: import org.deegree.model.filterencoding.FilterConstructionException;
060: import org.deegree.ogcbase.CommonNamespaces;
061: import org.deegree.ogcbase.ExceptionCode;
062: import org.deegree.ogcbase.PropertyPath;
063: import org.deegree.ogcbase.PropertyPathFactory;
064: import org.deegree.ogcbase.SortProperty;
065: import org.deegree.ogcwebservices.InvalidParameterValueException;
066: import org.deegree.ogcwebservices.MissingParameterValueException;
067: import org.deegree.ogcwebservices.OGCWebServiceException;
068: import org.deegree.ogcwebservices.OperationNotSupportedException;
069: import org.deegree.ogcwebservices.csw.discovery.GetRecords.RESULT_TYPE;
070: import org.w3c.dom.Element;
071: import org.w3c.dom.Node;
072: import org.xml.sax.SAXException;
073:
074: /**
075: *
076: *
077: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
078: * @author last edited by: $Author: poth $
079: *
080: * @version $Revision: 6251 $, $Date: 2007-03-19 16:59:28 +0100 (Mo, 19 Mrz 2007) $
081: */
082: public class GetRecordsDocument_2_0_2 extends GetRecordsDocument {
083:
084: private static final ILogger LOG = LoggerFactory
085: .getLogger(GetRecordsDocument_2_0_2.class);
086:
087: private static final String XML_TEMPLATE = "GetRecords2.0.2Template.xml";
088:
089: /**
090: * Extracts a <code>GetRecords</code> representation of this object.
091: *
092: * @param id
093: * unique ID of the request
094: * @return GetRecords representation of this object
095: * @throws MissingParameterValueException
096: * @throws InvalidParameterValueException
097: * @throws OperationNotSupportedException
098: * if an CqlText constrained is requested
099: * @throws OGCWebServiceException
100: * if something else went wrong
101: */
102: public GetRecords parse(String id) throws OGCWebServiceException {
103:
104: // '<csw202:GetRecords>'-element (required)
105: try {
106: Element contextNode = (Element) XMLTools.getRequiredNode(
107: this .getRootElement(), "self::csw202:GetRecords",
108: nsContext);
109: // 'service'-attribute (mandatory for 2.0.2, must be CSW)
110: String service = XMLTools.getRequiredNodeAsString(
111: contextNode, "@service", nsContext);
112: if (!"CSW".equals(service)) {
113: throw new OGCWebServiceException(
114: "GetRecordsDocument_2_0_2",
115: Messages
116: .getMessage("CSW_INVALID_SERVICE_PARAM"),
117: ExceptionCode.INVALIDPARAMETERVALUE);
118: }
119:
120: boolean isEBRIM = (contextNode.getOwnerDocument()
121: .lookupPrefix(
122: CommonNamespaces.OASIS_EBRIMNS
123: .toASCIIString()) != null);
124:
125: // 'version'-attribute (mandatory for 2.0.2)
126: String version = XMLTools.getRequiredNodeAsString(
127: contextNode, "@version", nsContext);
128: if (!"2.0.2".equals(version)) {
129: throw new OGCWebServiceException(
130: "GetRecordsDocument_2_0_2", Messages
131: .getMessage(
132: "CSW_NOT_SUPPORTED_VERSION",
133: GetRecords.DEFAULT_VERSION,
134: "2.0.2", version),
135: ExceptionCode.INVALIDPARAMETERVALUE);
136: }
137:
138: // 'requestId'-attribute (optional)
139: String requestId = XMLTools.getNodeAsString(contextNode,
140: "@requestId", nsContext, id);
141:
142: // 'resultType'-attribute
143: // type="csw202:ResultType" use="optional" default="hits"
144: String resultTypeString = XMLTools.getNodeAsString(
145: contextNode, "@resultType", nsContext,
146: GetRecords.RESULT_TYPE_STRING_HITS);
147: RESULT_TYPE resultType = RESULT_TYPE.RESULTS;
148: if (GetRecords.RESULT_TYPE_STRING_HITS
149: .equalsIgnoreCase(resultTypeString)) {
150: resultType = RESULT_TYPE.HITS;
151: } else if (GetRecords.RESULT_TYPE_STRING_RESULTS
152: .equalsIgnoreCase(resultTypeString)) {
153: resultType = RESULT_TYPE.RESULTS;
154: } else if (GetRecords.RESULT_TYPE_STRING_VALIDATE
155: .equalsIgnoreCase(resultTypeString)) {
156: resultType = RESULT_TYPE.VALIDATE;
157: } else {
158: throw new OGCWebServiceException(Messages.getMessage(
159: "CSW_INVALID_RESULTTYPE", resultTypeString,
160: GetRecords.RESULT_TYPE_STRING_HITS,
161: GetRecords.RESULT_TYPE_STRING_RESULTS,
162: GetRecords.RESULT_TYPE_STRING_VALIDATE),
163: ExceptionCode.INVALIDPARAMETERVALUE);
164: }
165:
166: // 'outputFormat'-attribute
167: // type="xsd:string" use="optional" default="text/xml"
168: String outputFormat = XMLTools.getNodeAsString(contextNode,
169: "@outputFormat", nsContext,
170: GetRecords.DEFAULT_OUTPUTFORMAT);
171:
172: String defaultOutputSchema = GetRecords.DEFAULT_OUTPUTSCHEMA;
173: if (isEBRIM) {
174: defaultOutputSchema = CommonNamespaces.OASIS_EBRIMNS
175: .toASCIIString();
176: }
177: // 'outputSchema'-attribute
178: // type="xsd:anyURI" use="optional" default="OGCCORE"
179: String outputSchema = XMLTools.getNodeAsString(contextNode,
180: "@outputSchema", nsContext, defaultOutputSchema);
181:
182: // 'startPosition'-attribute
183: // type="xsd:positiveInteger" use="optional" default="1"
184: int startPosition = XMLTools.getNodeAsInt(contextNode,
185: "@startPosition", nsContext,
186: GetRecords.DEFAULT_STARTPOSITION);
187: if (startPosition < 1) {
188: throw new OGCWebServiceException(Messages.getMessage(
189: "CSW_INVALID_STARTPOSITION", new Integer(
190: startPosition)),
191: ExceptionCode.INVALIDPARAMETERVALUE);
192: }
193:
194: // 'maxRecords'-attribute
195: // type="xsd:nonNegativeInteger" use="optional" default="10"
196: int maxRecords = XMLTools.getNodeAsInt(contextNode,
197: "@maxRecords", nsContext,
198: GetRecords.DEFAULT_MAX_RECORDS);
199:
200: // '<csw202:DistributedSearch>'-element (optional)
201: Node distributedSearchElement = XMLTools.getNode(
202: contextNode, "csw202:DistributedSearch", nsContext);
203: int hopCount = GetRecords.DEFAULT_HOPCOUNT;
204: if (distributedSearchElement != null) {
205: hopCount = XMLTools.getNodeAsInt(contextNode,
206: "@hopCount", nsContext,
207: GetRecords.DEFAULT_HOPCOUNT);
208: }
209:
210: // '<csw202:ResponseHandler>'-elements (optional)
211: String rHandler = XMLTools.getNodeAsString(contextNode,
212: "csw202:ResponseHandler", nsContext, null);
213: URI responseHandler = null;
214: if (rHandler != null) {
215: try {
216: responseHandler = new URI(rHandler);
217: } catch (URISyntaxException e) {
218: throw new OGCWebServiceException(Messages
219: .getMessage("CSW_INVALID_RESPONSE_HANDLER",
220: rHandler),
221: ExceptionCode.INVALIDPARAMETERVALUE);
222: }
223: LOG
224: .logWarning(Messages
225: .getMessage("CSW_NO_REPONSE_HANDLER_IMPLEMENTATION"));
226:
227: }
228:
229: // '<csw202:Query>'-elements (required)
230: // List nl = XMLTools.getRequiredNodes( contextNode, "csw202:Query", nsContext );
231: Element queryNode = (Element) XMLTools.getRequiredNode(
232: contextNode, "csw202:Query", nsContext);
233:
234: Map<String, QualifiedName> declaredVariables = new HashMap<String, QualifiedName>();
235: List<QualifiedName> queryTypeNames = new ArrayList<QualifiedName>();
236:
237: // 'typeName'-attribute use="required"
238: String tNames = XMLTools.getRequiredNodeAsString(queryNode,
239: "@typeNames", nsContext);
240: String[] simpleTypeNames = tNames.split(" ");
241: // only bind the prefixes to namespaces if the version is 2.0.0
242: boolean bindTypeNamesToNS = !GetRecords.DEFAULT_VERSION
243: .equals(version);
244: // Find any variables
245: for (String typeName : simpleTypeNames) {
246: findVariablesInTypeName(typeName, queryNode,
247: queryTypeNames, declaredVariables,
248: bindTypeNamesToNS);
249: }
250:
251: // '<csw202:ElementSetName>'-element (optional)
252: Element elementSetNameElement = (Element) XMLTools.getNode(
253: queryNode, "csw202:ElementSetName", nsContext);
254: String elementSetName = null;
255: List<QualifiedName> elementSetNameTypeNames = null;
256: Map<String, QualifiedName> elementSetNameVariables = null;
257: List<PropertyPath> elementNames = null;
258: // choice construct
259: if (elementSetNameElement != null) {
260: // must contain one of the values 'brief', 'summary' or
261: // 'full'
262: elementSetName = XMLTools.getRequiredNodeAsString(
263: elementSetNameElement, "text()", nsContext,
264: new String[] { "brief", "summary", "full" });
265: tNames = elementSetNameElement
266: .getAttribute("typeNames");
267: if (tNames != null) {
268: String[] esnTypeNames = tNames.split(" ");
269: elementSetNameVariables = new HashMap<String, QualifiedName>();
270: elementSetNameTypeNames = new ArrayList<QualifiedName>();
271: for (String tn : esnTypeNames) {
272: if (tn.trim().startsWith("$")) {
273: String tmpVar = tn.trim().substring(1);
274: if (!declaredVariables.containsKey(tmpVar)) {
275: String msg = Messages
276: .getMessage(
277: "CSW_ELEMENT_SET_NAME_TYPENAME_ALIAS",
278: tmpVar);
279: throw new OGCWebServiceException(
280: msg,
281: ExceptionCode.INVALIDPARAMETERVALUE);
282: }
283: elementSetNameVariables.put(tmpVar,
284: declaredVariables.get(tmpVar));
285: } else {
286: QualifiedName qName = parseQNameFromString(
287: tn.trim(), elementSetNameElement,
288: bindTypeNamesToNS);
289: elementSetNameTypeNames.add(qName);
290: }
291: }
292: }
293:
294: } else {
295: // '<csw202:ElementName>'-element (required, if no
296: // '<csw202:ElementSetName>' is given)
297: List elementNameList = XMLTools.getNodes(queryNode,
298: "csw202:ElementName", nsContext);
299: if (elementNameList.size() == 0) {
300: throw new XMLParsingException(
301: Messages
302: .getMessage("CSW_MISSING_QUERY_ELEMENT(SET)NAME"));
303: }
304: for (Object en : elementNameList) {
305: Node n = (Node) en;
306: QualifiedName elementName = XMLTools
307: .getNodeAsQualifiedName(n, "text()",
308: nsContext, null);
309: if (elementName != null) {
310: elementNames.add(PropertyPathFactory
311: .createPropertyPath(elementName));
312: }
313: }
314:
315: }
316:
317: // '<csw202:Constraint>'-element (optional)
318: Element constraintElement = (Element) XMLTools.getNode(
319: queryNode, "csw202:Constraint", nsContext);
320: Filter constraint = null;
321: if (constraintElement != null) {
322: String ver = XMLTools.getRequiredNodeAsString(
323: constraintElement, "@version", nsContext);
324: if (!"1.0.0".equals(ver) && !"1.1.0".equals(ver)) {
325: throw new OGCWebServiceException(Messages
326: .getMessage(
327: "CSW_INVALID_CONSTRAINT_VERSION",
328: ver),
329: ExceptionCode.INVALIDPARAMETERVALUE);
330: }
331: Node filterElement = XMLTools.getNode(
332: constraintElement, "ogc:Filter", nsContext);
333: if (filterElement != null) {
334: try {
335: constraint = AbstractFilter.buildFromDOM(
336: (Element) filterElement, false);
337: } catch (FilterConstructionException fce) {
338: throw new OGCWebServiceException(
339: Messages
340: .getMessage(
341: "CSW_INVALID_CONSTRAINT_CONTENT",
342: fce.getMessage()),
343: ExceptionCode.INVALIDPARAMETERVALUE);
344: }
345: } else {
346: String cqlText = XMLTools.getNodeAsString(
347: constraintElement, "csw202:CqlText",
348: nsContext, null);
349: if (cqlText == null) {
350: throw new OGCWebServiceException(Messages
351: .getMessage("CSW_CQL_NOR_FILTER"),
352: ExceptionCode.INVALIDPARAMETERVALUE);
353: }
354:
355: throw new OGCWebServiceException(Messages
356: .getMessage("CSW_NO_CQL_IMPLEMENTATION"),
357: ExceptionCode.OPERATIONNOTSUPPORTED);
358: }
359: }
360: // find undeclared referenced variables used in the filter element.
361: if (constraint instanceof ComplexFilter) {
362: checkReferencedVariables((ComplexFilter) constraint,
363: declaredVariables);
364: }
365:
366: // '<ogc:SortBy>'-element (optional)
367: Node sortByElement = XMLTools.getNode(queryNode,
368: "ogc:SortBy", nsContext);
369: SortProperty[] sortProperties = null;
370: if (sortByElement != null) {
371: List sortPropertyList = XMLTools.getNodes(
372: sortByElement, "ogc:SortProperty", nsContext);
373: if (sortPropertyList.size() == 0) {
374: throw new OGCWebServiceException(Messages
375: .getMessage("CSW_NO_SORTPROPERTY_LIST"),
376: ExceptionCode.INVALIDPARAMETERVALUE);
377:
378: }
379: sortProperties = new SortProperty[sortPropertyList
380: .size()];
381: for (int j = 0; j < sortPropertyList.size(); j++) {
382: sortProperties[j] = SortProperty
383: .create((Element) sortPropertyList.get(j));
384: }
385: }
386:
387: Query query = new Query(elementSetName,
388: elementSetNameTypeNames, elementSetNameVariables,
389: elementNames, constraint, sortProperties,
390: queryTypeNames, declaredVariables);
391:
392: // in the future the vendorSpecificParameters
393: Map<String, String> vendorSpecificParameters = parseDRMParams(this
394: .getRootElement());
395: return new GetRecords(requestId, version,
396: vendorSpecificParameters, null, resultType,
397: outputFormat, outputSchema, startPosition,
398: maxRecords, hopCount, responseHandler, query);
399: } catch (XMLParsingException xmlpe) {
400: LOG.logError("CatalogGetRecords", xmlpe);
401: throw new OGCWebServiceException(xmlpe.getMessage(),
402: ExceptionCode.MISSINGPARAMETERVALUE);
403: } catch (URISyntaxException urise) {
404: LOG.logError("CatalogGetRecords", urise);
405: throw new OGCWebServiceException(urise.getMessage(),
406: ExceptionCode.MISSINGPARAMETERVALUE);
407: }
408: }
409:
410: /*
411: * (non-Javadoc)
412: *
413: * @see org.deegree.framework.xml.XMLFragment#createEmptyDocument()
414: */
415: void createEmptyDocument() throws IOException, SAXException {
416: URL url = GetRecordsDocument.class.getResource(XML_TEMPLATE);
417: if (url == null) {
418: throw new IOException("The resource '" + XML_TEMPLATE
419: + " could not be found.");
420: }
421: load(url);
422: }
423:
424: }
|