//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/portal/standard/csw/control/OverviewMetadataListener.java,v 1.16 2006/10/17 20:31:18 poth Exp $ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstraße 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.portal.standard.csw.control; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.xml.transform.TransformerException; import org.deegree.enterprise.control.FormEvent; import org.deegree.enterprise.control.RPCParameter; import org.deegree.enterprise.control.RPCStruct; import org.deegree.enterprise.control.RPCWebEvent; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.CharsetUtils; import org.deegree.framework.xml.DOMPrinter; import org.deegree.framework.xml.XMLParsingException; import org.deegree.framework.xml.XMLTools; import org.deegree.ogcbase.CommonNamespaces; import org.deegree.portal.standard.csw.CatalogClientException; import org.deegree.portal.standard.csw.MetadataTransformer; import org.deegree.portal.standard.csw.configuration.CSWClientConfiguration; import org.w3c.dom.Document; import org.w3c.dom.Node; /** * A <code>${type_name}</code> class.<br/> * TODO class description * * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a> * @author last edited by: $Author: poth $ * * @version 2.0, $Revision: 1.16 $, $Date: 2006/10/17 20:31:18 $ * * @since 2.0 */ public class OverviewMetadataListener extends SimpleSearchListener { private static final ILogger LOG = LoggerFactory.getLogger( OverviewMetadataListener.class ); static final String SESSION_METADATA = "SESSION_METADATA"; public void actionPerformed( FormEvent event ) { LOG.entering(); HttpSession session = ( (HttpServletRequest)this.getRequest() ).getSession( true ); config = (CSWClientConfiguration)session.getAttribute( Constants.CSW_CLIENT_CONFIGURATION ); nsContext = CommonNamespaces.getNamespaceContext(); // TODO remove if not needed // try { // nsNode = XMLTools.getNamespaceNode( config.getNamespaceBindings() ); // } catch( ParserConfigurationException e ) { // e.printStackTrace(); // gotoErrorPage( "Could not create namespace node for OverviewMetadataListener." // + e.getMessage() ); // LOG.exiting(); // return; // } RPCWebEvent rpcEvent = (RPCWebEvent)event; RPCParameter[] params; try { params = extractRPCParameters( rpcEvent ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Invalid rpcEvent: " + e.getMessage() ); LOG.exiting(); return; } // get transformation file name String fileName = "metaOverview2html.xsl"; // default value // FIXME replace format with current value String format = "Profiles.ISO19115"; HashMap xslMap = config.getProfileXSL( format ); if ( xslMap != null) { if ( xslMap.get( "full" ) != null ) { fileName = (String)xslMap.get( "full" ); } } String pathToXslFile = "file:" + getHomePath() + "WEB-INF/conf/igeoportal/" + fileName; if ( params == null || params.length == 0 ) { // get Metadata from the users session session = ( (HttpServletRequest)this.getRequest() ).getSession( true ); Object o = session.getAttribute( SESSION_METADATA ); if ( o != null ) { try { handleResult( o, pathToXslFile, "overview" ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Error handling result 1: \n" + e.getMessage() ); LOG.exiting(); return; } } } else { try { validateRequest( rpcEvent ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Invalid Request: " + e.getMessage() ); LOG.exiting(); return; } String rpcCatalog; RPCStruct rpcStruct; String rpcFormat; String rpcProtocol; try { rpcStruct = extractRPCStruct( rpcEvent, 0 ); rpcCatalog =(String)extractRPCMember( rpcStruct, RPC_CATALOG ); rpcFormat = (String)extractRPCMember( rpcStruct, RPC_FORMAT ); rpcProtocol = (String)extractRPCMember( rpcStruct, Constants.RPC_PROTOCOL ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Invalid rpcEvent: \n" + e.getMessage() ); LOG.exiting(); return; } // "GetRecordById"-request String req = null; HashMap result = null; try { req = createRequest( rpcStruct, rpcFormat, null ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Invalid Request: \n" + e.getMessage() ); LOG.exiting(); return; } try { List<String> dataCatalogs = new ArrayList<String>(1); dataCatalogs.add( rpcCatalog ); // key = data catalog name; value = csw:GetRecordByIdResponse result = performRequest( rpcProtocol, req, dataCatalogs, null ); // result is a HashMap that contains only one key-value-pair, // because dataCatalogs contains only one catalog. } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Server is not reachable or did not answer with valid XML: \n" + e.getMessage() ); return; } // handle result: take result and transform it to produce html output try { handleResult( result, pathToXslFile, "overview" ); } catch ( Exception e ) { e.printStackTrace(); gotoErrorPage( "Error handling result 2: \n" + e.getMessage() ); LOG.exiting(); return; } } LOG.exiting(); } protected void validateRequest( RPCWebEvent rpcEvent ) throws CatalogClientException { LOG.entering(); RPCParameter[] params = extractRPCParameters( rpcEvent ); if ( params.length != 1 ) { throw new CatalogClientException( "Request/Method Call must contain one parameter, not: " + params.length ); } RPCStruct struct = extractRPCStruct( rpcEvent, 0 ); // validity check for catalog String rpcCatalog = (String)extractRPCMember( struct, RPC_CATALOG ); String[] catalogs = config.getCatalogNames(); boolean containsCatalog = false; for ( int i = 0; i < catalogs.length; i++ ) { if ( catalogs[i].equals(rpcCatalog) ) { containsCatalog = true; break; } } if ( !containsCatalog ) { throw new CatalogClientException( "The catalog " + rpcCatalog + " is not " + "configured for this client."); } // validity check for format // is requested catalog capable to serve requested metadata format? List formats = config.getCatalogFormats( rpcCatalog ); String rpcFormat = (String)extractRPCMember( struct, RPC_FORMAT ); if ( ! formats.contains( rpcFormat ) ) { throw new CatalogClientException( "The catalog " + rpcCatalog + " does not " + "provide the requested format " + rpcFormat ); } // validity check for protocol // is requested catalog reachable through requested protocol? List protocols = config.getCatalogProtocols( rpcCatalog ); String rpcProtocol = (String)extractRPCMember( struct, Constants.RPC_PROTOCOL ); if ( ! protocols.contains( rpcProtocol ) ) { throw new CatalogClientException( "The catalog " + rpcCatalog + " does not " + "provide the requested protocol " + rpcProtocol ); } try { struct.getMember( Constants.RPC_IDENTIFIER ).getValue(); } catch (Exception e) { throw new CatalogClientException( "The identifier must be set." ); } // validity check for bounding box values RPCStruct bBox; try { bBox = (RPCStruct)struct.getMember( Constants.RPC_BBOX ).getValue(); } catch (Exception e) { throw new CatalogClientException( "The bounding box must be set." ); } double minx, miny, maxx, maxy; try { minx = ((Double)bBox.getMember( Constants.RPC_BBOXMINX ).getValue()).doubleValue(); miny = ((Double)bBox.getMember( Constants.RPC_BBOXMINY ).getValue()).doubleValue(); maxx = ((Double)bBox.getMember( Constants.RPC_BBOXMAXX ).getValue()).doubleValue(); maxy = ((Double)bBox.getMember( Constants.RPC_BBOXMAXY ).getValue()).doubleValue(); } catch (Exception e) { throw new CatalogClientException( "All bounding box values (minx, miny, maxx, maxy) " + "must be set as decimal numbers." ); } if ( minx > maxx || miny > maxy ) { throw new CatalogClientException("the requested bounding box has invalid values. \n" + "maxx must be larger than minx and maxy must be " + "larger than miny."); } LOG.exiting(); } // super.createRequest(); // super.performeRequest(); /** * @param result * @param pathToXslFile * e.g. file://$iGeoPortal_home$/WEB-INF/conf/igeoportal/metaOverview2html.xsl * @param metaVersion * e.g. overview, detailed * @throws XMLParsingException * @throws CatalogClientException * @throws TransformerException * @throws IOException */ protected void handleResult( Object result, String pathToXslFile, String metaVersion ) throws XMLParsingException, CatalogClientException, TransformerException, IOException { LOG.entering(); HttpSession session = ( (HttpServletRequest)this.getRequest() ).getSession( true ); // result is a very short hashmap with only one entry! Map map = (HashMap)result; // key = data catalog name; value = csw:GetRecordByIdResponse Iterator it = map.keySet().iterator(); String catalog = null; Document doc = null; String docString = null; URL u = null; StringBuffer htmlFragment = new StringBuffer( 5000 ); MetadataTransformer mt = null; try { u = new URL( pathToXslFile ); mt = new MetadataTransformer( u.getFile() ); } catch (MalformedURLException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } while( it.hasNext() ) { catalog = (String)it.next(); doc = (Document)map.get( catalog ); docString = DOMPrinter.nodeToString( doc, CharsetUtils.getSystemCharset() ); Reader reader = new StringReader(docString); List nl = extractMetadata( doc ); if ( nl.size() > 1 ) { throw new CatalogClientException( "The result contains a Document with too many metadata nodes." ); } String xPathToTitle = config.getXPathToDataTitleFull(); String title = extractValue( (Node)nl.get( 0 ), xPathToTitle ) ; String[] serviceCatalogs = null; Map catalogsMap = (HashMap)session.getAttribute( SESSION_AVAILABLESERVICECATALOGS ); if ( catalogsMap != null ) { serviceCatalogs = extractServiceCatalogs( catalogsMap, title ); } // transformation htmlFragment.append( mt.transformMetadata( reader, catalog, serviceCatalogs, 0, 0, metaVersion ) ); } this.getRequest().setAttribute( HTML_FRAGMENT, htmlFragment.toString() ); session.setAttribute( SESSION_METADATA, result ); LOG.exiting(); } /** * Extracts all Metadata nodes from the passed csw:GetRecordByIdResponse Document. * * @param doc The csw:GetRecordByIdResponse Document from which to extract the Metadata nodes. * @return Returns a NodeList of Metadata Elements for the passed Document. * @throws CatalogClientException * if metadata nodes could not be extracted from the passed Document. * @throws XMLParsingException */ protected List extractMetadata( Document doc ) throws CatalogClientException, XMLParsingException { List nl = null; String xPathToMetadata = "csw:GetRecordByIdResponse/child::*"; nl = XMLTools.getNodes( doc, xPathToMetadata, nsContext ); if ( nl == null || nl.size() < 1 ){ throw new CatalogClientException( "could not extract metadata nodes." ); } return nl; } /** * Extracts a List of available service catalogues from the Map in the session and returns its * contents as an Array of Strings. * * @param catalogsMap The Map containing the data title (as key) and the List of available * service catalogues names (as value) * @param title The key for the value in the passed Map. * @return Returns an Array of Strings for the available service catalogues. * If no service catalogues are available, an Array of one empty String is returned. */ protected String[] extractServiceCatalogs( Map catalogsMap, String title ) { String[] catalogs = null; List catalogsList = (ArrayList)catalogsMap.get( title ); if ( catalogsList != null ) { catalogs = new String[ catalogsList.size() ]; for( int i = 0; i < catalogsList.size(); i++ ) { catalogs[i] = (String)catalogsList.get(i); } } else { catalogs = new String[] { "" }; } return catalogs; } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: OverviewMetadataListener.java,v $ Revision 1.16 2006/10/17 20:31:18 poth *** empty log message *** Revision 1.15 2006/07/31 11:02:44 mays move constants from class Constants to the classes where they are needed Revision 1.14 2006/07/31 09:33:58 mays move Constants to package control, update imports Revision 1.13 2006/06/30 12:38:34 mays set serviceCatalogs if information is already provided in the session Revision 1.12 2006/06/30 08:43:18 mays clean up code and java doc Revision 1.11 2006/06/23 13:38:25 mays add/update csw control files ********************************************************************** */