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