Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/services/MetaDataService.java @ 1065:cf421645a2d3
Made cache statistics available as MBeans (eg in JConsole).
gnv-artifacts/trunk@1157 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Fri, 04 Jun 2010 08:47:52 +0000 |
parents | 2423cefe7d39 |
children | f953c9a559d8 |
line wrap: on
line source
package de.intevation.gnv.artifacts.services; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.xml.xpath.XPathConstants; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; import de.intevation.artifactdatabase.DefaultService; import de.intevation.artifactdatabase.XMLUtils; import de.intevation.artifacts.ArtifactNamespaceContext; import de.intevation.artifacts.CallMeta; import de.intevation.artifacts.ServiceFactory; import de.intevation.gnv.artifacts.services.requestobjects.DefaultFIS; import de.intevation.gnv.artifacts.services.requestobjects.DefaultLayer; import de.intevation.gnv.artifacts.services.requestobjects.DefaultMapService; import de.intevation.gnv.artifacts.services.requestobjects.DefaultParameter; import de.intevation.gnv.artifacts.services.requestobjects.FIS; import de.intevation.gnv.artifacts.services.requestobjects.Layer; import de.intevation.gnv.artifacts.services.requestobjects.MapService; import de.intevation.gnv.artifacts.services.requestobjects.Parameter; import de.intevation.gnv.geobackend.base.Result; import de.intevation.gnv.geobackend.base.query.QueryExecutor; import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; import de.intevation.gnv.geobackend.base.query.exception.QueryException; import de.intevation.gnv.utils.ArtifactXMLUtilities; /** * This Class Provides the Functionality to return only those * Artifacfactories which fulfill the conditions of the Request. * * This Service is used to implement the Functionality of the MV-GNV-Interface * by looking if an Region of an FIS is intersecting the Area which is send * during the Request or which FIS belongs to the requested MapServices. * * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a> * */ public class MetaDataService extends DefaultService { /** * the logger, used to log exceptions and additionally information */ private static Logger log = Logger.getLogger(MetaDataService.class); private final static String FIS_REGION_QUERY_ID = "mapviewer_interface_fis_region"; private final static String MAPSERVICES_HAS_FIS_QUERY_ID = "mapviewer_interface_mapservices_has_fis"; private final static String MAPSERVICES_HAS_PARAMETER_QUERY_ID = "mapviewer_interface_mapservices_has_parameter"; private final static String MAPSERVICES_HAS_PARAMETER_USING_LAYER_QUERY_ID = "mapviewer_interface_mapservices_has_parameter_using_layer"; private static String ATTRIBUTE_ID = "id"; private static String ATTRIBUTE_NAME = "name"; private static String ATTRIBUTE_TYPE = "type"; private static String ATTRIBUTE_URL = "url"; private static String ATTRIBUTE_GROUPLAYER = "isgrouplayer"; private static String ATTRIBUTE_PARENTID = "parentid"; private static String ATTRIBUTE_SRS = "srs"; private static String XPATH_LOACTION_NODE = "art:GetMetaData/art:location"; private static String XPATH_MAPSERVICES_NODESET = "art:GetMetaData/" + "art:mapservices/" + "art:mapservice"; private static String XPATH_LAYER_NODESET = "art:layer"; /** * The UID of this Class. */ private static final long serialVersionUID = -8446483887497236372L; /** * Constructor */ public MetaDataService() { super(); } @Override public Document process(Document data, Object globalContext, CallMeta callMeta) { log.debug("MetaDataService.process"); Document document = null; try { Geometry g = this.parseGeometry(data); Collection<MapService> mapServices = this.parseMapServices(data); Collection<FIS> resultFIS = this.unionFIS(this.getFIS(g), this.getFIS(mapServices)); document = XMLUtils.newDocument(); this.writeFIS2Document(document, resultFIS); log.debug(ArtifactXMLUtilities.writeDocument2String(document)); } catch (MetaDataServiceException e) { log.error(e,e); document = ArtifactXMLUtilities .createExceptionReport(e.getMessage(), document); } return document; } private Geometry parseGeometry(Document data) throws MetaDataServiceException{ log.debug("MetaDataService.parseGeometry"); Element locationNode = (Element) XMLUtils.xpath( data, XPATH_LOACTION_NODE, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE ); Geometry returnValue = null; if (locationNode != null) { String srs = locationNode.getAttribute(ATTRIBUTE_SRS); // TODO: use SRS to transform the Geometry to target-System. String geometryValue = locationNode.getTextContent(); if (geometryValue != null){ try { returnValue = new WKTReader().read(geometryValue); } catch (ParseException e) { log.error(e,e); throw new MetaDataServiceException("The given Geometry" + "String is not a " + "valid WKT."); } } } return returnValue; } private Collection<MapService> parseMapServices(Document data){ log.debug("MetaDataService.parseMapServices"); NodeList mapServices = (NodeList) XMLUtils.xpath(data, XPATH_MAPSERVICES_NODESET, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); Collection<MapService> returnValue = null; if (mapServices != null){ returnValue = new ArrayList<MapService>(mapServices.getLength()); for (int i = 0; i < mapServices.getLength(); i++){ Element mapServiceNode = (Element)mapServices.item(i); String id = mapServiceNode.getAttribute(ATTRIBUTE_ID); String type = mapServiceNode.getAttribute(ATTRIBUTE_TYPE); String url = mapServiceNode.getAttribute(ATTRIBUTE_URL); Collection<Layer> layer = null; NodeList layerNodes = (NodeList) XMLUtils.xpath(mapServiceNode, XPATH_LAYER_NODESET, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); if (layerNodes != null){ layer = new ArrayList<Layer>(layerNodes.getLength()); for (int j = 0; j < layerNodes.getLength(); j++){ Element layerNode = (Element)layerNodes.item(j); String layerId = layerNode.getAttribute(ATTRIBUTE_ID); String layerName = layerNode.getAttribute(ATTRIBUTE_NAME); boolean isGroupLayer = Boolean.parseBoolean(layerNode .getAttribute( ATTRIBUTE_GROUPLAYER)); String parentId = layerNode .getAttribute(ATTRIBUTE_PARENTID); layer.add(new DefaultLayer(layerId, layerName, isGroupLayer, parentId)); } } MapService mapService = new DefaultMapService(id, layer, type, url); returnValue.add(mapService); } } return returnValue; } private Collection<FIS> unionFIS(Collection<FIS> fromGeometry, Collection<FIS> fromMapservices){ log.debug("MetaDataService.unionFIS"); Collection<FIS> returnValue = null; if (fromGeometry == null || fromGeometry.isEmpty()){ returnValue = fromMapservices; }else if (fromMapservices == null || fromMapservices.isEmpty()){ returnValue = fromGeometry; }else{ returnValue = new ArrayList<FIS>(); Iterator<FIS> it = fromMapservices.iterator(); while (it.hasNext()){ FIS fis = it.next(); if (fromGeometry.contains(fis)){ returnValue.add(fis); } } } return returnValue; } /** * Puts the retrieved FIS into the given XML-Document. * @param document the Document where the FIS should be put in. * @param fis the retrieved FIS which should be written into * the XML-Document. */ private void writeFIS2Document(Document document, Collection<FIS> fis){ if (fis != null){ Iterator<FIS> it = fis.iterator(); XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( document, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX ); Node rootNode = creator.create("result"); document.appendChild(rootNode); Node factoriesNode = creator.create("factories"); rootNode.appendChild(factoriesNode); while (it.hasNext()){ FIS tmpFIS = it.next(); Element fisNode = creator.create("factory"); fisNode.setAttribute("art:name",tmpFIS.getID()); Collection<Parameter> parameter = tmpFIS.getParameter(); if(parameter != null){ Iterator<Parameter> pit = parameter.iterator(); while (pit.hasNext()){ Parameter p = pit.next(); Element parameterNode = creator.create("parameter"); parameterNode.setAttribute(ATTRIBUTE_ID, p.getID()); parameterNode.setAttribute(ATTRIBUTE_NAME, p.getName()); fisNode.appendChild(parameterNode); } } factoriesNode.appendChild(fisNode); } } } /** * Returns all FIS which Areas is intersected by this given Geometry * @param g the Geometry which should be used to determine the FIS. * @return all FIS which Areas is intersected by this given Geometry * @throws MetaDataServiceException */ protected Collection<FIS> getFIS(Geometry g) throws MetaDataServiceException{ log.debug("MetaDataService.getFIS ==> Geometry"); Collection<FIS> resultValue = null; if (g != null){ try { QueryExecutor queryExecutor = QueryExecutorFactory .getInstance() .getQueryExecutor(); Collection<Result> result = queryExecutor.executeQuery(FIS_REGION_QUERY_ID, new String[]{g.toString()}); if (result != null){ resultValue = new ArrayList<FIS>(result.size()); Iterator<Result> it = result.iterator(); while (it.hasNext()){ Result value = it.next(); String fis_id = value.getString(0).trim(); resultValue.add(new DefaultFIS(fis_id)); } } } catch (QueryException e) { log.error(e,e); throw new MetaDataServiceException("Cannot Query FIS from DB."); } } return resultValue; } /** * Returns all FIS which were represented by the given Mapservices * @param mapServices the Mapservices which should determine the FIS. * @return all FIS which where represented my the given Mapservices. * @throws MetaDataServiceException */ protected Collection<FIS> getFIS(Collection<MapService> mapServices) throws MetaDataServiceException{ log.debug("MetaDataService.getFIS ==> MapServices"); Collection<FIS> resultValue = null; if (mapServices != null && !mapServices.isEmpty()){ try { String mapServiceNames = ""; Iterator<MapService> mit = mapServices.iterator(); while(mit.hasNext()){ if (mapServiceNames.length() > 0){ mapServiceNames += " , "; } mapServiceNames += "'"+mit.next().getID()+"'"; } QueryExecutor queryExecutor = QueryExecutorFactory .getInstance() .getQueryExecutor(); Collection<Result> result = queryExecutor.executeQuery( MAPSERVICES_HAS_FIS_QUERY_ID, new String[]{mapServiceNames}); if (result != null){ resultValue = new ArrayList<FIS>(result.size()); Iterator<Result> it = result.iterator(); while (it.hasNext()){ Result value = it.next(); String fisId = value.getString(0).trim(); String mapServiceID = value.getString(1).trim(); // FIRST LOOK IF ONE MAPSERVICE REPRESENTS ONLY ONE PARAM Collection<Result> result2 = queryExecutor.executeQuery( MAPSERVICES_HAS_PARAMETER_QUERY_ID, new String[]{"'"+mapServiceID+"'"}); Collection<Parameter> parameter = null; if (result2 != null && result2.size() == 1){ Iterator<Result> it2 = result2.iterator(); parameter = new ArrayList<Parameter>(1); while (it2.hasNext()){ Result parameterValue = it2.next(); String parameterID = parameterValue.getString(0) .trim(); parameter.add(new DefaultParameter(parameterID, parameterID)); } }else{ // IF FALSE LOOK IF THE GIVEN LAYERs TO AN MAPSERVICE // REPRESENTS DIFFERENT PARAMS MapService service = this.getMapService(mapServices, mapServiceID); Collection<Layer> layer = service.getLayer(); if (layer != null && !layer.isEmpty()){ String layerQueryString = this.createLayerQueryString(layer); Collection<Result> parameterResult = queryExecutor.executeQuery( MAPSERVICES_HAS_PARAMETER_USING_LAYER_QUERY_ID, new String[]{"'"+mapServiceID+"'", layerQueryString}); if (parameterResult != null && !parameterResult.isEmpty()){ Iterator<Result> it2 = parameterResult.iterator(); parameter = new ArrayList<Parameter>(parameterResult.size()); while (it2.hasNext()){ Result parameterValue = it2.next(); String parameterID = parameterValue.getString(0) .trim(); parameter.add(new DefaultParameter(parameterID, parameterID)); } } } } FIS fis = this.getFIS(resultValue, fisId); if (fis != null){ if (parameter != null){ fis.addParameter(parameter); } }else{ resultValue.add(new DefaultFIS(fisId, parameter)); } } } } catch (QueryException e) { log.error(e,e); throw new MetaDataServiceException("Cannot Query FIS from DB."); } } return resultValue; } private FIS getFIS (Collection<FIS> fis, String fisId){ Iterator<FIS> it = fis.iterator(); while(it.hasNext()){ FIS tmpFIS = it.next(); if (tmpFIS.getID().equals(fisId)){ return tmpFIS; } } return null; } private MapService getMapService(Collection<MapService> mapServices, String mapServiceID){ log.debug("MetaDataService.getMapService"); Iterator<MapService> it = mapServices.iterator(); while (it.hasNext()){ MapService service = it.next(); if (service.getID().equals(mapServiceID)){ return service; } } return null; } private String createLayerQueryString(Collection<Layer> layer){ log.debug("MetaDataService.createLayerQueryString"); StringBuffer sb = new StringBuffer();; Iterator<Layer> it = layer.iterator(); synchronized (sb) { while (it.hasNext()){ Layer l = it.next(); if (!l.isGroupLayer()){ sb.append(l.getID()); if (it.hasNext()){ sb.append(" , "); } } } } String returnValue = sb.toString(); if (returnValue.endsWith(" , ")){ returnValue = returnValue.substring(0,returnValue .lastIndexOf(",")) .trim(); } return returnValue; } @Override public void setup(ServiceFactory factory, Object globalContext) { log.debug("MetaDataService.setup"); super.setup(factory, globalContext); // TODO: Perhaps it is necessary to init the QueryIds here. } }