diff gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/services/MetaDataService.java @ 597:cf38b983d1f3

Added the Implementation of the MetaDataService which will deliver FIS and Parameters that match to Mapservices, Region and Layers that were sent to the Service. gnv-artifacts/trunk@653 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Mon, 01 Feb 2010 14:52:05 +0000
parents
children 938ce81a6bd0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/services/MetaDataService.java	Mon Feb 01 14:52:05 2010 +0000
@@ -0,0 +1,343 @@
+/**
+ *
+ */
+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.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;
+
+/**
+ * @author Tim Englich <tim.englich@intevation.de>
+ *
+ */
+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 = "fis_region";
+    private final static String MAPSERVICES_HAS_FIS_QUERY_ID = 
+                                                      "mapservices_has_fis";
+    
+    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();
+    }
+
+    /**
+     * @see de.intevation.artifactdatabase.DefaultService#process(org.w3c.dom.Document, java.lang.Object, de.intevation.artifacts.CallMeta)
+     */
+    @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);
+        } catch (MetaDataServiceException e) {
+            log.error(e,e);
+            document = new 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
+     */
+    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);
+                        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.
+     */
+    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 fis_id = value.getString(0);
+                        
+                        // TODO: QUERY PARAMS
+                        // FIRST LOOK IF ONE MAPSERVICE REPRESENTS ONLY ONE PARAM
+                        // IF FALSE LOOK IF THE GIVEN LAYERs TO AN MAPSERVICE
+                        // REPRESENTS DIFFERENT PARAMS
+                        Collection<Parameter> parameter = null;
+                        resultValue.add(new DefaultFIS(fis_id, parameter));
+                    }
+                }
+            } catch (QueryException e) {
+                log.error(e,e);
+                throw new MetaDataServiceException("Cannot Query FIS from DB.");
+            }
+           
+        }
+        return resultValue;
+    }
+
+    /**
+     * @see de.intevation.artifactdatabase.DefaultService#setup(de.intevation.artifacts.ServiceFactory, java.lang.Object)
+     */
+    @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.
+    }
+
+}

http://dive4elements.wald.intevation.org