001: //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/ogcwebservices/csw/discovery/GetRecordsDocument.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: ---------------------------------------------------------------------------*/
044:
045: package org.deegree.ogcwebservices.csw.discovery;
046:
047: import java.io.IOException;
048: import java.net.URI;
049: import java.net.URISyntaxException;
050: import java.net.URL;
051: import java.util.ArrayList;
052: import java.util.HashMap;
053: import java.util.List;
054: import java.util.Map;
055:
056: import org.deegree.datatypes.QualifiedName;
057: import org.deegree.framework.log.ILogger;
058: import org.deegree.framework.log.LoggerFactory;
059: import org.deegree.framework.util.StringTools;
060: import org.deegree.framework.xml.XMLParsingException;
061: import org.deegree.framework.xml.XMLTools;
062: import org.deegree.i18n.Messages;
063: import org.deegree.model.filterencoding.AbstractFilter;
064: import org.deegree.model.filterencoding.AbstractOperation;
065: import org.deegree.model.filterencoding.ComplexFilter;
066: import org.deegree.model.filterencoding.Expression;
067: import org.deegree.model.filterencoding.Filter;
068: import org.deegree.model.filterencoding.FilterConstructionException;
069: import org.deegree.model.filterencoding.LogicalOperation;
070: import org.deegree.model.filterencoding.Operation;
071: import org.deegree.model.filterencoding.PropertyIsBetweenOperation;
072: import org.deegree.model.filterencoding.PropertyIsCOMPOperation;
073: import org.deegree.model.filterencoding.PropertyIsInstanceOfOperation;
074: import org.deegree.model.filterencoding.PropertyIsLikeOperation;
075: import org.deegree.model.filterencoding.PropertyIsNullOperation;
076: import org.deegree.model.filterencoding.PropertyName;
077: import org.deegree.model.filterencoding.SpatialOperation;
078: import org.deegree.ogcbase.CommonNamespaces;
079: import org.deegree.ogcbase.ExceptionCode;
080: import org.deegree.ogcbase.PropertyPath;
081: import org.deegree.ogcbase.PropertyPathFactory;
082: import org.deegree.ogcbase.SortProperty;
083: import org.deegree.ogcwebservices.InvalidParameterValueException;
084: import org.deegree.ogcwebservices.MissingParameterValueException;
085: import org.deegree.ogcwebservices.OGCWebServiceException;
086: import org.deegree.ogcwebservices.OperationNotSupportedException;
087: import org.deegree.ogcwebservices.csw.AbstractCSWRequestDocument;
088: import org.deegree.ogcwebservices.csw.discovery.GetRecords.RESULT_TYPE;
089: import org.w3c.dom.Element;
090: import org.w3c.dom.Node;
091: import org.w3c.dom.NodeList;
092: import org.xml.sax.SAXException;
093:
094: /**
095: * Represents an XML GetRecords document of an OGC CSW 2.0.0 and 2.0.1 compliant service.
096: *
097: * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a>
098: * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
099: * @author last edited by: $Author: apoth $
100: *
101: * @version $Revision: 9307 $, $Date: 2007-12-21 08:37:43 +0100 (Fr, 21 Dez 2007) $
102: */
103: public class GetRecordsDocument extends AbstractCSWRequestDocument {
104:
105: private static final long serialVersionUID = 2796229558893029054L;
106:
107: private static final ILogger LOG = LoggerFactory
108: .getLogger(GetRecordsDocument.class);
109:
110: private static final String XML_TEMPLATE = "GetRecordsTemplate.xml";
111:
112: /**
113: * Extracts a <code>GetRecords</code> representation of this object.
114: *
115: * @param id
116: * unique ID of the request
117: * @return GetRecords representation of this object
118: * @throws MissingParameterValueException
119: * @throws InvalidParameterValueException
120: * @throws OperationNotSupportedException
121: * if an CqlText constrained is requested
122: * @throws OGCWebServiceException
123: * if something else went wrong
124: */
125: public GetRecords parse(String id) throws OGCWebServiceException {
126:
127: // '<csw:GetRecords>'-element (required)
128: try {
129: Element contextNode = (Element) XMLTools.getRequiredNode(
130: this .getRootElement(), "self::csw:GetRecords",
131: nsContext);
132: // 'service'-attribute (optional, must be CSW)
133: String service = XMLTools.getNodeAsString(contextNode,
134: "@service", nsContext, "CSW");
135: if (!"CSW".equals(service)) {
136: throw new OGCWebServiceException(
137: "GetRecordsDocument",
138: Messages
139: .getMessage("CSW_INVALID_SERVICE_PARAM"),
140: ExceptionCode.INVALIDPARAMETERVALUE);
141: }
142:
143: String defaultVersion = GetRecords.DEFAULT_VERSION;
144: boolean isEBRIM = (contextNode.getOwnerDocument()
145: .lookupPrefix(
146: CommonNamespaces.OASIS_EBRIMNS
147: .toASCIIString()) != null);
148: if (!isEBRIM) {
149: isEBRIM = isEbrimDefined(contextNode);
150: }
151: LOG
152: .logDebug("GetRecordsDocument: For the namespaceDefinition of the ebrim catalogue, the value is: "
153: + isEBRIM);
154: if (isEBRIM) {
155: defaultVersion = "2.0.1";
156: }
157:
158: // 'version'-attribute (optional)
159: String version = XMLTools.getNodeAsString(contextNode,
160: "@version", nsContext, defaultVersion);
161: if (!(GetRecords.DEFAULT_VERSION.equals(version) || "2.0.1"
162: .equals(version))) {
163: throw new OGCWebServiceException("GetRecordsDocument",
164: Messages.getMessage(
165: "CSW_NOT_SUPPORTED_VERSION",
166: GetRecords.DEFAULT_VERSION, "2.0.1",
167: version),
168: ExceptionCode.INVALIDPARAMETERVALUE);
169: }
170:
171: // 'requestId'-attribute (optional)
172: String requestId = XMLTools.getNodeAsString(contextNode,
173: "@requestId", nsContext, id);
174:
175: // 'resultType'-attribute
176: // type="csw:ResultType" use="optional" default="hits"
177: String resultTypeString = XMLTools.getNodeAsString(
178: contextNode, "@resultType", nsContext,
179: GetRecords.RESULT_TYPE_STRING_HITS);
180: RESULT_TYPE resultType = RESULT_TYPE.RESULTS;
181: if (GetRecords.RESULT_TYPE_STRING_HITS
182: .equalsIgnoreCase(resultTypeString)) {
183: resultType = RESULT_TYPE.HITS;
184: } else if (GetRecords.RESULT_TYPE_STRING_RESULTS
185: .equalsIgnoreCase(resultTypeString)) {
186: resultType = RESULT_TYPE.RESULTS;
187: } else if (GetRecords.RESULT_TYPE_STRING_VALIDATE
188: .equalsIgnoreCase(resultTypeString)) {
189: resultType = RESULT_TYPE.VALIDATE;
190: } else {
191: throw new OGCWebServiceException(Messages.getMessage(
192: "CSW_INVALID_RESULTTYPE", resultTypeString,
193: GetRecords.RESULT_TYPE_STRING_HITS,
194: GetRecords.RESULT_TYPE_STRING_RESULTS,
195: GetRecords.RESULT_TYPE_STRING_VALIDATE),
196: ExceptionCode.INVALIDPARAMETERVALUE);
197: }
198:
199: // 'outputFormat'-attribute
200: // type="xsd:string" use="optional" default="text/xml"
201: String outputFormat = XMLTools.getNodeAsString(contextNode,
202: "@outputFormat", nsContext,
203: GetRecords.DEFAULT_OUTPUTFORMAT);
204:
205: String defaultOutputSchema = GetRecords.DEFAULT_OUTPUTSCHEMA;
206: if (isEBRIM) {
207: defaultOutputSchema = CommonNamespaces.OASIS_EBRIMNS
208: .toASCIIString();
209: }
210: // 'outputSchema'-attribute
211: // type="xsd:anyURI" use="optional" default="OGCCORE"
212: String outputSchema = XMLTools.getNodeAsString(contextNode,
213: "@outputSchema", nsContext, defaultOutputSchema);
214:
215: // 'startPosition'-attribute
216: // type="xsd:positiveInteger" use="optional" default="1"
217: int startPosition = XMLTools.getNodeAsInt(contextNode,
218: "@startPosition", nsContext,
219: GetRecords.DEFAULT_STARTPOSITION);
220: if (startPosition < 1) {
221: throw new OGCWebServiceException(Messages.getMessage(
222: "CSW_INVALID_STARTPOSITION", new Integer(
223: startPosition)),
224: ExceptionCode.INVALIDPARAMETERVALUE);
225: }
226:
227: // 'maxRecords'-attribute
228: // type="xsd:nonNegativeInteger" use="optional" default="10"
229: int maxRecords = XMLTools.getNodeAsInt(contextNode,
230: "@maxRecords", nsContext,
231: GetRecords.DEFAULT_MAX_RECORDS);
232:
233: // '<csw:DistributedSearch>'-element (optional)
234: Node distributedSearchElement = XMLTools.getNode(
235: contextNode, "csw:DistributedSearch", nsContext);
236: int hopCount = GetRecords.DEFAULT_HOPCOUNT;
237: if (distributedSearchElement != null) {
238: hopCount = XMLTools.getNodeAsInt(contextNode,
239: "@hopCount", nsContext,
240: GetRecords.DEFAULT_HOPCOUNT);
241: }
242:
243: // '<csw:ResponseHandler>'-elements (optional)
244: String rHandler = XMLTools.getNodeAsString(contextNode,
245: "csw:ResponseHandler", nsContext, null);
246: URI responseHandler = null;
247: if (rHandler != null) {
248: try {
249: responseHandler = new URI(rHandler);
250: } catch (URISyntaxException e) {
251: throw new OGCWebServiceException(Messages
252: .getMessage("CSW_INVALID_RESPONSE_HANDLER",
253: rHandler),
254: ExceptionCode.INVALIDPARAMETERVALUE);
255: }
256: LOG
257: .logWarning(Messages
258: .getMessage("CSW_NO_REPONSE_HANDLER_IMPLEMENTATION"));
259:
260: }
261:
262: // '<csw:Query>'-elements (required)
263: // List nl = XMLTools.getRequiredNodes( contextNode, "csw:Query", nsContext );
264: Element queryNode = (Element) XMLTools.getRequiredNode(
265: contextNode, "csw:Query", nsContext);
266:
267: Map<String, QualifiedName> declaredVariables = new HashMap<String, QualifiedName>();
268: List<QualifiedName> queryTypeNames = new ArrayList<QualifiedName>();
269:
270: // 'typeName'-attribute use="required"
271: String tNames = XMLTools.getRequiredNodeAsString(queryNode,
272: "@typeNames", nsContext);
273: String[] simpleTypeNames = tNames.split(" ");
274: // only bind the prefixes to namespaces if the version is 2.0.0
275: boolean bindTypeNamesToNS = !GetRecords.DEFAULT_VERSION
276: .equals(version);
277: // Find any variables
278: for (String typeName : simpleTypeNames) {
279: findVariablesInTypeName(typeName, queryNode,
280: queryTypeNames, declaredVariables,
281: bindTypeNamesToNS);
282: }
283:
284: // '<csw:ElementSetName>'-element (optional)
285: Element elementSetNameElement = (Element) XMLTools.getNode(
286: queryNode, "csw:ElementSetName", nsContext);
287: String elementSetName = null;
288: List<QualifiedName> elementSetNameTypeNames = null;
289: Map<String, QualifiedName> elementSetNameVariables = null;
290: List<PropertyPath> elementNames = null;
291: // choice construct
292: if (elementSetNameElement != null) {
293: // must contain one of the values 'brief', 'summary' or
294: // 'full'
295: elementSetName = XMLTools.getRequiredNodeAsString(
296: elementSetNameElement, "text()", nsContext,
297: new String[] { "brief", "summary", "full" });
298: tNames = elementSetNameElement
299: .getAttribute("typeNames");
300: if (tNames != null) {
301: String[] esnTypeNames = tNames.split(" ");
302: elementSetNameVariables = new HashMap<String, QualifiedName>();
303: elementSetNameTypeNames = new ArrayList<QualifiedName>();
304: for (String tn : esnTypeNames) {
305: if (tn.trim().startsWith("$")) {
306: String tmpVar = tn.trim().substring(1);
307: if (!declaredVariables.containsKey(tmpVar)) {
308: throw new OGCWebServiceException(
309: Messages
310: .getMessage(
311: "CSW_ELEMENT_SET_NAME_TYPENAME_ALIAS",
312: tmpVar),
313: ExceptionCode.INVALIDPARAMETERVALUE);
314: }
315: elementSetNameVariables.put(tmpVar,
316: declaredVariables.get(tmpVar));
317: } else {
318: QualifiedName qName = parseQNameFromString(
319: tn.trim(), elementSetNameElement,
320: bindTypeNamesToNS);
321: elementSetNameTypeNames.add(qName);
322: }
323: }
324: }
325:
326: } else {
327: // '<csw:ElementName>'-element (required, if no
328: // '<csw:ElementSetName>' is given)
329: List elementNameList = XMLTools.getNodes(queryNode,
330: "csw:ElementName", nsContext);
331: if (elementNameList.size() == 0) {
332: throw new XMLParsingException(
333: Messages
334: .getMessage("CSW_MISSING_QUERY_ELEMENT(SET)NAME"));
335: }
336: for (Object en : elementNameList) {
337: Node n = (Node) en;
338: QualifiedName elementName = XMLTools
339: .getNodeAsQualifiedName(n, "text()",
340: nsContext, null);
341: if (elementName != null) {
342: elementNames.add(PropertyPathFactory
343: .createPropertyPath(elementName));
344: }
345: }
346:
347: }
348:
349: // '<csw:Constraint>'-element (optional)
350: Element constraintElement = (Element) XMLTools.getNode(
351: queryNode, "csw:Constraint", nsContext);
352: Filter constraint = null;
353: if (constraintElement != null) {
354: String ver = XMLTools.getRequiredNodeAsString(
355: constraintElement, "@version", nsContext);
356: if (!"1.0.0".equals(ver) && !"1.1.0".equals(ver)) {
357: throw new OGCWebServiceException(Messages
358: .getMessage(
359: "CSW_INVALID_CONSTRAINT_VERSION",
360: ver),
361: ExceptionCode.INVALIDPARAMETERVALUE);
362: }
363: Node filterElement = XMLTools.getNode(
364: constraintElement, "ogc:Filter", nsContext);
365: if (filterElement != null) {
366: try {
367: constraint = AbstractFilter.buildFromDOM(
368: (Element) filterElement, false);
369: } catch (FilterConstructionException fce) {
370: throw new OGCWebServiceException(
371: Messages
372: .getMessage(
373: "CSW_INVALID_CONSTRAINT_CONTENT",
374: fce.getMessage()),
375: ExceptionCode.INVALIDPARAMETERVALUE);
376: }
377: } else {
378: String cqlText = XMLTools.getNodeAsString(
379: constraintElement, "csw:CqlText",
380: nsContext, null);
381: if (cqlText == null) {
382: throw new OGCWebServiceException(Messages
383: .getMessage("CSW_CQL_NOR_FILTER"),
384: ExceptionCode.INVALIDPARAMETERVALUE);
385: }
386:
387: throw new OGCWebServiceException(Messages
388: .getMessage("CSW_NO_CQL_IMPLEMENTATION"),
389: ExceptionCode.OPERATIONNOTSUPPORTED);
390: }
391: }
392: // find undeclared referenced variables used in the filter element.
393: if (constraint instanceof ComplexFilter) {
394: checkReferencedVariables((ComplexFilter) constraint,
395: declaredVariables);
396: }
397:
398: // '<ogc:SortBy>'-element (optional)
399: Node sortByElement = XMLTools.getNode(queryNode,
400: "ogc:SortBy", nsContext);
401: SortProperty[] sortProperties = null;
402: if (sortByElement != null) {
403: List sortPropertyList = XMLTools.getNodes(
404: sortByElement, "ogc:SortProperty", nsContext);
405: if (sortPropertyList.size() == 0) {
406: throw new OGCWebServiceException(Messages
407: .getMessage("CSW_NO_SORTPROPERTY_LIST"),
408: ExceptionCode.INVALIDPARAMETERVALUE);
409:
410: }
411: sortProperties = new SortProperty[sortPropertyList
412: .size()];
413: for (int j = 0; j < sortPropertyList.size(); j++) {
414: sortProperties[j] = SortProperty
415: .create((Element) sortPropertyList.get(j));
416: }
417: }
418:
419: Query query = new Query(elementSetName,
420: elementSetNameTypeNames, elementSetNameVariables,
421: elementNames, constraint, sortProperties,
422: queryTypeNames, declaredVariables);
423:
424: // in the future the vendorSpecificParameters
425: Map<String, String> vendorSpecificParameters = parseDRMParams(this
426: .getRootElement());
427: return new GetRecords(requestId, version,
428: vendorSpecificParameters, null, resultType,
429: outputFormat, outputSchema, startPosition,
430: maxRecords, hopCount, responseHandler, query);
431: } catch (XMLParsingException xmlpe) {
432: LOG.logError("CatalogGetRecords", xmlpe);
433: throw new OGCWebServiceException(xmlpe.getMessage(),
434: ExceptionCode.INVALIDPARAMETERVALUE);
435: } catch (URISyntaxException urise) {
436: LOG.logError("CatalogGetRecords", urise);
437: throw new OGCWebServiceException(urise.getMessage(),
438: ExceptionCode.INVALIDPARAMETERVALUE);
439: }
440: }
441:
442: /**
443: * @param contextNode
444: * @return true if the namespace "urn:oasis:names:tc:ebxml- regrep:xsd:rim:3.0" was found in one
445: * of the nodes of the dom-tree.
446: */
447: protected boolean isEbrimDefined(Node contextNode) {
448:
449: boolean isEbRim = contextNode
450: .lookupPrefix(CommonNamespaces.OASIS_EBRIMNS
451: .toASCIIString()) != null;
452: if (!isEbRim) {
453: NodeList nl = contextNode.getChildNodes();
454: for (int i = 0; i < nl.getLength(); ++i) {
455: isEbRim = isEbrimDefined(nl.item(i));
456: if (isEbRim) {
457: return true;
458: }
459: }
460: }
461: return isEbRim;
462: }
463:
464: /**
465: * Helper method to find any declared variables in given Query/@typeNames
466: *
467: * @param typeName
468: * the type name to test
469: * @param queryNode
470: * the querynode (used to find a given prefix)
471: * @param typeNames
472: * a list to save the typeName (as QualifiedNames) in
473: * @param variables
474: * a Map containing the vars/QualifiedName mappings
475: * @param bindTypeNameToNS
476: * if the namespaces should be bounded to the typeNames
477: * @throws URISyntaxException
478: * if the prefix is not bound to a namespace
479: * @throws OGCWebServiceException
480: * if a variable name is unambiguous
481: */
482: public void findVariablesInTypeName(String typeName,
483: Node queryNode, List<QualifiedName> typeNames,
484: Map<String, QualifiedName> variables,
485: boolean bindTypeNameToNS) throws OGCWebServiceException,
486: URISyntaxException {
487: LOG.logDebug("testing for variables in typeName: " + typeName);
488: int variableIndex = typeName.lastIndexOf('=');
489: String tmpTypeName = typeName;
490: if (variableIndex != -1) {
491: // find the typeNames
492: tmpTypeName = typeName.substring(0, variableIndex).trim();
493: LOG.logDebug("typeName contains variables");
494: }
495:
496: // creating the qualified name
497: QualifiedName qName = parseQNameFromString(tmpTypeName,
498: queryNode, bindTypeNameToNS);
499: typeNames.add(qName);
500: if (variableIndex != -1) {
501: if ((variableIndex + 1) < typeName.length()) {
502: // find the variables which should be referenced with the $-sign
503: String allVars = typeName.substring(variableIndex + 1);
504: String[] vars = allVars.split(",");
505: for (String var : vars) {
506: LOG.logDebug("found var: " + var);
507: if (variables.put(var.trim(), qName) != null) {
508: String out = Messages.getMessage(
509: "CSW_AMBIGUOUS_VARIABLE_DEF", var
510: .trim());
511: throw new OGCWebServiceException("GetRecords",
512: out,
513: ExceptionCode.INVALIDPARAMETERVALUE);
514: }
515: }
516: }
517: }
518: }
519:
520: /**
521: * @param typeName
522: * to be transformed to a QName
523: * @param queryNode
524: * needed to get the namespace
525: * @param bindTypeNameToNS
526: * if true the namespace will be bound to the qualified name
527: * @return a QualifiedName representing the typeName
528: * @throws URISyntaxException
529: */
530: public QualifiedName parseQNameFromString(String typeName,
531: Node queryNode, boolean bindTypeNameToNS)
532: throws URISyntaxException {
533: int prefixIndex = typeName.indexOf(':');
534: String preFix = null;
535: URI nameSpace = null;
536: String localName = typeName;
537: if (prefixIndex != -1) {
538: preFix = typeName.substring(0, prefixIndex).trim();
539: if (bindTypeNameToNS) {
540: LOG
541: .logDebug("Trying to find namespace binding for the prefix: "
542: + preFix
543: + " on node queryNode: "
544: + queryNode.getNodeName());
545: nameSpace = XMLTools.getNamespaceForPrefix(preFix,
546: queryNode);
547: } else {
548: LOG
549: .logDebug("Not binding namespaces for the prefix: "
550: + preFix
551: + " on node queryNode: "
552: + queryNode.getNodeName()
553: + " because the version of the GetRecordsRequest is not 2.0.2");
554: }
555: // for version 2.0.0 no namespace checkin is required following versions should check if
556: // the returned namespace is null.
557: if ((prefixIndex + 1) < typeName.length()) {
558: localName = typeName.substring(prefixIndex + 1).trim();
559: } else {
560: localName = typeName.substring(prefixIndex).trim();
561: }
562: }
563: LOG.logDebug("found prefix: " + preFix);
564: LOG.logDebug("found localName: " + localName);
565: LOG.logDebug("found namespace: " + nameSpace);
566: return new QualifiedName(preFix, localName, nameSpace);
567: }
568:
569: /**
570: * Iterates over the Operations of a complexfilter to find if non declared variables are used.
571: *
572: * @param constraint
573: * @param variables
574: * @throws OGCWebServiceException
575: */
576: protected void checkReferencedVariables(ComplexFilter constraint,
577: Map<String, QualifiedName> variables)
578: throws OGCWebServiceException {
579: AbstractOperation topOperation = (AbstractOperation) constraint
580: .getOperation();
581: if (topOperation instanceof LogicalOperation) {
582: List<Operation> operations = ((LogicalOperation) topOperation)
583: .getArguments();
584: for (Operation op : operations) {
585: findNonDeclaredVariables((AbstractOperation) op,
586: variables);
587: }
588: } else {
589: findNonDeclaredVariables(topOperation, variables);
590: }
591: }
592:
593: /**
594: * (Recursively) finds a reference to a non declared variable in the propertyname of the given
595: * operation.
596: *
597: * @param operation
598: * to be checked
599: * @param variables
600: * which were declared
601: * @throws OGCWebServiceException
602: * if such a reference is found
603: */
604: protected void findNonDeclaredVariables(
605: AbstractOperation operation,
606: Map<String, QualifiedName> variables)
607: throws OGCWebServiceException {
608: if (operation instanceof LogicalOperation) {
609: List<Operation> operations = ((LogicalOperation) operation)
610: .getArguments();
611: for (Operation op : operations) {
612: findNonDeclaredVariables((AbstractOperation) op,
613: variables);
614: }
615: } else if (operation instanceof SpatialOperation) {
616: findNonDeclaredVariables(((SpatialOperation) operation)
617: .getPropertyName(), variables);
618: } else {
619: if (operation instanceof PropertyIsBetweenOperation) {
620: findNonDeclaredVariables(
621: ((PropertyIsBetweenOperation) operation)
622: .getPropertyName(), variables);
623: } else if (operation instanceof PropertyIsCOMPOperation) {
624: Expression expr = ((PropertyIsCOMPOperation) operation)
625: .getFirstExpression();
626: if (expr instanceof PropertyName) {
627: findNonDeclaredVariables(((PropertyName) expr),
628: variables);
629: }
630: expr = ((PropertyIsCOMPOperation) operation)
631: .getSecondExpression();
632: if (expr instanceof PropertyName) {
633: findNonDeclaredVariables(((PropertyName) expr),
634: variables);
635: }
636: } else if (operation instanceof PropertyIsInstanceOfOperation) {
637: findNonDeclaredVariables(
638: ((PropertyIsInstanceOfOperation) operation)
639: .getPropertyName(), variables);
640: } else if (operation instanceof PropertyIsLikeOperation) {
641: findNonDeclaredVariables(
642: ((PropertyIsLikeOperation) operation)
643: .getPropertyName(), variables);
644: } else if (operation instanceof PropertyIsNullOperation) {
645: findNonDeclaredVariables(
646: ((PropertyIsNullOperation) operation)
647: .getPropertyName(), variables);
648: }
649: }
650: }
651:
652: /**
653: * Parse the string representation of the the propertyname to find a variable reference to a non
654: * declared Variable.
655: *
656: * @param propName
657: * to check
658: * @param variables
659: * which were declared
660: * @throws InvalidParameterValueException
661: * if such a reference was found.
662: */
663: protected void findNonDeclaredVariables(PropertyName propName,
664: Map<String, QualifiedName> variables)
665: throws OGCWebServiceException {
666: String propertyPath = propName.toString();
667: String[] foundVariables = StringTools.extractStrings(
668: propertyPath, "$", "/");
669: if (foundVariables != null && foundVariables.length > 0) {
670: LOG
671: .logDebug("found following variables in properertyName: "
672: + propName.toString());
673: for (String var : foundVariables) {
674: LOG.logDebug("variable: " + var);
675: if (!variables.containsKey(var)) {
676: throw new OGCWebServiceException(
677: Messages.getMessage(
678: "CSW_VARIABLE_NOT_DEFINED", var),
679: ExceptionCode.INVALIDPARAMETERVALUE);
680: }
681: }
682: }
683: }
684:
685: /*
686: * (non-Javadoc)
687: *
688: * @see org.deegree.framework.xml.XMLFragment#createEmptyDocument()
689: */
690: void createEmptyDocument() throws IOException, SAXException {
691: URL url = GetRecordsDocument.class.getResource(XML_TEMPLATE);
692: if (url == null) {
693: throw new IOException("The resource '" + XML_TEMPLATE
694: + " could not be found.");
695: }
696: load(url);
697: }
698: }
|