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