001    //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/ogcwebservices/csw/manager/Manager_2_0_0.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    package org.deegree.ogcwebservices.csw.manager;
045    
046    import java.io.IOException;
047    import java.io.StringReader;
048    import java.io.StringWriter;
049    import java.net.MalformedURLException;
050    import java.net.URISyntaxException;
051    import java.net.URL;
052    import java.util.ArrayList;
053    import java.util.HashMap;
054    import java.util.Iterator;
055    import java.util.List;
056    import java.util.Map;
057    
058    import javax.xml.transform.TransformerException;
059    
060    import org.deegree.framework.log.ILogger;
061    import org.deegree.framework.log.LoggerFactory;
062    import org.deegree.framework.xml.DOMPrinter;
063    import org.deegree.framework.xml.XMLFragment;
064    import org.deegree.framework.xml.XMLParsingException;
065    import org.deegree.framework.xml.XMLTools;
066    import org.deegree.framework.xml.XSLTDocument;
067    import org.deegree.ogcbase.CommonNamespaces;
068    import org.deegree.ogcwebservices.EchoRequest;
069    import org.deegree.ogcwebservices.OGCWebServiceException;
070    import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionResponse;
071    import org.w3c.dom.Document;
072    import org.w3c.dom.Element;
073    import org.w3c.dom.NamedNodeMap;
074    import org.w3c.dom.Node;
075    import org.w3c.dom.NodeList;
076    import org.xml.sax.SAXException;
077    
078    /**
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
080     * 
081     * @author last edited by: $Author: apoth $
082     * 
083     * @version 2.0, $Revision: 9359 $, $Date: 2007-12-28 16:30:52 +0100 (Fr, 28 Dez 2007) $
084     */
085    
086    public class Manager_2_0_2 extends AbstractManager {
087    
088        private static final ILogger LOG = LoggerFactory.getLogger( Manager_2_0_2.class );
089    
090        private static final URL xsltURL = Manager_2_0_2.class.getResource( "iso_ap_1_0_full2brief.xsl" );
091    
092        /*
093         * (non-Javadoc)
094         * 
095         * @see org.deegree.ogcwebservices.csw.manager.Manager#harvestRecords(org.deegree.ogcwebservices.csw.manager.Harvest)
096         */
097        public EchoRequest harvestRecords( Harvest request )
098                                throws OGCWebServiceException {
099            try {
100                HarvesterFactory hf = new HarvesterFactory( harvester );
101                AbstractHarvester h = hf.findHarvester( request );
102                h.addRequest( request );
103                if ( !h.isRunning() ) {
104                    h.startHarvesting();
105                }
106                if ( request.getHarvestInterval() == null ) {
107                    // h.removeRequest( request );
108                }
109            } catch ( Exception e ) {
110                LOG.logError( "could not perform harvest operation", e );
111                throw new OGCWebServiceException( getClass().getName(), "could not perform harvest operation"
112                                                                        + e.getMessage() );
113            }
114    
115            return new EchoRequest( request.getId(), null );
116        }
117    
118        /*
119         * (non-Javadoc)
120         * 
121         * @see org.deegree.ogcwebservices.csw.manager.Manager#transaction(org.deegree.ogcwebservices.csw.manager.Transaction)
122         */
123        public TransactionResult transaction( Transaction request )
124                                throws OGCWebServiceException {
125            XMLFragment wfsTransactionDocument = null;
126    
127            try {
128                XMLFragment transactionDocument = XMLFactory.export( request );
129                String nsp = getAllNamespaceDeclarations( transactionDocument.getRootElement() );
130                StringWriter sww = new StringWriter( 15000 );
131                transactionDocument.write( sww );
132                transactionDocument.load( new StringReader( sww.getBuffer().toString() ), XMLFragment.DEFAULT_URL );
133    
134                synchronized ( IN_XSL ) {
135                    Map<String, String> param = new HashMap<String, String>();
136                    param.put( "NSP", nsp );
137                    try {
138                        wfsTransactionDocument = IN_XSL.transform( transactionDocument, XMLFragment.DEFAULT_URL, null,
139                                                                   param );
140                    } catch ( MalformedURLException e ) {
141                        LOG.logError( e.getMessage(), e );
142                    }
143                }
144    
145                if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
146                    LOG.logDebug( "The (first) resulting wfs:Transaction document: \n "
147                                  + wfsTransactionDocument.getAsPrettyString() );
148                }
149            } catch ( SAXException saxe ) {
150                String msg = org.deegree.i18n.Messages.get( "CSW_CREATE_TRANSACTION_ERROR", saxe.getMessage() );
151                LOG.logError( msg, saxe );
152                throw new OGCWebServiceException( msg );
153            } catch ( IOException ioe ) {
154                String msg = org.deegree.i18n.Messages.get( "CSW_CREATE_TRANSACTION_ERROR", ioe.getMessage() );
155                LOG.logError( msg, ioe );
156                throw new OGCWebServiceException( msg );
157            } catch ( TransformerException te ) {
158                String msg = org.deegree.i18n.Messages.get( "CSW_CREATE_TRANSACTION_ERROR", te.getMessage() );
159                LOG.logError( msg, te );
160                throw new OGCWebServiceException( msg );
161            } catch ( XMLParsingException xmle ) {
162                String msg = org.deegree.i18n.Messages.get( "CSW_CREATE_TRANSACTION_ERROR", xmle.getMessage() );
163                LOG.logError( msg, xmle );
164                throw new OGCWebServiceException( msg );
165            }
166    
167            org.deegree.ogcwebservices.wfs.operation.transaction.Transaction wfstrans = null;
168            try {
169                LOG.logDebug( "Creating a wfs transaction from the document" );
170                wfstrans = org.deegree.ogcwebservices.wfs.operation.transaction.Transaction.create(
171                                                                                                    request.getId(),
172                                                                                                    wfsTransactionDocument.getRootElement() );
173            } catch ( OGCWebServiceException ogcwe ) {
174                LOG.logError( ogcwe.getMessage(), ogcwe );
175                String msg = org.deegree.i18n.Messages.get( "CSW_CREATE_TRANSACTION_ERROR2", ogcwe.getMessage() );
176                throw new OGCWebServiceException( msg );
177            }
178    
179            Object wfsResponse = null;
180            try {
181                LOG.logDebug( "Sending the wfs transaction to the wfservice." );
182                wfsResponse = wfsService.doService( wfstrans );
183            } catch ( OGCWebServiceException e ) {
184                String msg = org.deegree.i18n.Messages.get( "CSW_PERFORMING_TRANSACTION_ERROR", e.getMessage() );
185                LOG.logError( msg, e );
186                throw new OGCWebServiceException( msg );
187            }
188    
189            if ( !( wfsResponse instanceof org.deegree.ogcwebservices.wfs.operation.transaction.TransactionResponse ) ) {
190                String msg = org.deegree.i18n.Messages.get( "CSW_WRONG_TRANSACTION_RESULTTYPE",
191                                                            wfsResponse.getClass().getName() );
192                LOG.logError( msg );
193                throw new OGCWebServiceException( msg );
194            }
195    
196            TransactionResponse transResp = (TransactionResponse) wfsResponse;
197            XMLFragment wfsTransRespDoc = null;
198            try {
199                LOG.logDebug( "Parsing the wfs response." );
200                wfsTransRespDoc = org.deegree.ogcwebservices.wfs.XMLFactory.export( transResp );
201            } catch ( IOException e ) {
202                String msg = "export of WFS Transaction response as XML failed: " + e.getMessage();
203                LOG.logError( msg, e );
204                throw new OGCWebServiceException( msg );
205            }
206    
207            // --------------------------------------------------------------
208            // the following section will replace the feature ids returned by
209            // the WFS for Insert requests by the ID of the inserted metadata sets
210            List<Document> briefDocs = new ArrayList<Document>();
211            List<Operation> ops = request.getOperations();
212            for ( int i = 0; i < ops.size(); i++ ) {
213                if ( ops.get( i ) instanceof Insert ) {
214                    try {
215                        briefDocs = getAsBriefDocuments( briefDocs, (Insert) ops.get( i ) );
216                    } catch ( Exception e ) {
217                        LOG.logError( e.getMessage(), e );
218                        throw new OGCWebServiceException( getClass().getName(), e.getMessage() );
219                    }
220                }
221            }
222            try {
223                if ( briefDocs.size() > 0 ) {
224                    wfsTransRespDoc = replaceIds( wfsTransRespDoc, briefDocs );
225                }
226            } catch ( Exception e ) {
227                LOG.logError( e.getMessage(), e );
228                throw new OGCWebServiceException( getClass().getName(), e.getMessage() );
229            }
230            // ---------------------------------------------------------------
231    
232            TransactionResultDocument cswTransactionDocument = null;
233            try {
234                XMLFragment tmp = OUT_XSL.transform( wfsTransRespDoc );
235                cswTransactionDocument = new TransactionResultDocument();
236                cswTransactionDocument.setRootElement( tmp.getRootElement() );
237            } catch ( TransformerException e ) {
238                String msg = org.deegree.i18n.Messages.get( "CSW_TRANSACTION_RESULT_TRANS_ERR", e.getMessage() );
239                LOG.logError( msg, e );
240                throw new OGCWebServiceException( msg );
241            }
242            TransactionResult result = null;
243            try {
244                result = cswTransactionDocument.parseTransactionResponse( request );
245            } catch ( XMLParsingException e ) {
246                String msg = org.deegree.i18n.Messages.get( "CSW_TRANSACTION_RESULT_PARSE_ERR" );
247                LOG.logError( msg, e );
248                throw new OGCWebServiceException( msg );
249            }
250            return result;
251        }
252    
253        private String getAllNamespaceDeclarations( Element doc ) {
254            Map<String, String> nsp = new HashMap<String, String>();
255            nsp = collect( nsp, doc );
256            Iterator<String> iter = nsp.keySet().iterator();
257            StringBuffer sb = new StringBuffer( 1000 );
258            while ( iter.hasNext() ) {
259                String s = iter.next();
260                String val = nsp.get( s );
261                sb.append( s ).append( ":" ).append( val );
262                if ( iter.hasNext() ) {
263                    sb.append( ';' );
264                }
265            }
266            return sb.toString();
267        }
268    
269        private Map<String, String> collect( Map<String, String> nsp, Node node ) {
270            NamedNodeMap nnm = node.getAttributes();
271            if ( nnm != null ) {
272                for ( int i = 0; i < nnm.getLength(); i++ ) {
273                    String s = nnm.item( i ).getNodeName();
274                    if ( s.startsWith( "xmlns:" ) ) {
275                        nsp.put( s.substring( 6, s.length() ), nnm.item( i ).getNodeValue() );
276                    }
277                }
278            }
279            
280            NodeList nl = node.getChildNodes();
281            if ( nl != null ) {
282                for ( int i = 0; i < nl.getLength(); i++ ) {
283                    collect( nsp, nl.item( i ) );
284                }
285            }
286            return nsp;
287        }
288    
289        /**
290         * replaces the id values of WFS Insert result with corresponding metadata brief representations
291         * 
292         * @param wfsTransRespDoc
293         * @param briefDocs
294         * @return an xmlFragment with the gml:Feature ids replaced with the id' s given in the list
295         * @throws URISyntaxException
296         * @throws XMLParsingException
297         */
298        private XMLFragment replaceIds( XMLFragment wfsTransRespDoc, List<Document> briefDocs )
299                                throws XMLParsingException {
300    
301            List nodes = XMLTools.getRequiredNodes( wfsTransRespDoc.getRootElement(),
302                                                    "./wfs:InsertResults/wfs:Feature/ogc:FeatureId",
303                                                    CommonNamespaces.getNamespaceContext() );
304            Element parent = null;
305            for ( int i = 0; i < nodes.size(); i++ ) {
306                Element elem = (Element) nodes.get( i );
307                parent = (Element) elem.getParentNode();
308                parent.removeChild( elem );
309            }
310            if ( parent != null ) {
311                for ( int i = 0; i < briefDocs.size(); i++ ) {
312                    parent = (Element) XMLTools.insertNodeInto( briefDocs.get( i ).getDocumentElement(), parent );
313                }
314            }
315    
316            return wfsTransRespDoc;
317        }
318    
319        /**
320         * all inserted records into threir brief representation
321         * 
322         * @param docs
323         * @param insert
324         * @return a list of brief metadata records
325         * @throws SAXException
326         * @throws IOException
327         * @throws TransformerException
328         */
329        private List<Document> getAsBriefDocuments( List<Document> docs, Insert insert )
330                                throws IOException, SAXException, TransformerException {
331            List<Element> records = insert.getRecords();
332    
333            XSLTDocument xslt = new XSLTDocument( xsltURL );
334    
335            for ( int i = 0; i < records.size(); i++ ) {
336                XMLFragment xml = new XMLFragment();
337                xml.setRootElement( records.get( i ) );
338                xml = xslt.transform( xml );
339                docs.add( xml.getRootElement().getOwnerDocument() );
340            }
341            return docs;
342        }
343    
344    }