package de.ifgi.lod4wfs.factory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.log4j.Logger; import org.apache.solr.common.SolrDocumentList; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import de.ifgi.lod4wfs.core.GlobalSettings; import de.ifgi.lod4wfs.core.SOLRRecord; import de.ifgi.lod4wfs.core.Utils; import de.ifgi.lod4wfs.core.WFSFeature; import de.ifgi.lod4wfs.infrastructure.SOLRConnector; public class AdapterSOLR4WFS { private static AdapterSOLR4WFS instance; private FactorySOLRFeatures factorySOLR; private static Logger logger = Logger.getLogger("SOLR4WFS-Adapter"); public AdapterSOLR4WFS(){ factorySOLR = new FactorySOLRFeatures(); } public static AdapterSOLR4WFS getInstance() { if (instance == null) { instance = new AdapterSOLR4WFS(); } return instance; } private WFSFeature expandSOLRFeature(WFSFeature feature){ //TODO: verificar a necessidade de expandir prefixos!!! String featureName = FactoryWFS.getInstance().getLoadedModelFeature().expandPrefix((feature.getName())); ArrayList<WFSFeature> solrFeatureList = new ArrayList<WFSFeature>(); solrFeatureList = FactoryWFS.getInstance().getLoadedSOLRFeatures(); for (int i = 0; i < solrFeatureList.size(); i++) { if (featureName.equals(solrFeatureList.get(i).getName())){ feature = solrFeatureList.get(i); } } return feature; } public String describeFeatureType(WFSFeature feature){ String describeFeatureTypeResponse = new String(); ArrayList<SOLRRecord> fields = new ArrayList<SOLRRecord>(); feature = this.expandSOLRFeature(feature); fields = factorySOLR.getSOLRFeatureFields(feature); try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse("wfs/DescribeFeature_100.xml"); logger.info("Creating DescribeFeatureType XML document for [" + feature.getName() + "] ..."); XPath xpath = XPathFactory.newInstance().newXPath(); NodeList myNodeList = (NodeList) xpath.compile("//extension/sequence/text()").evaluate(document, XPathConstants.NODESET); String layerPrefix = FactoryWFS.getInstance().getLoadedModelFeature().shortForm(feature.getName()); layerPrefix = layerPrefix.substring(0,layerPrefix.indexOf(":") + 1); Element requestElement = document.getDocumentElement(); requestElement.setAttribute("targetNamespace", FactoryWFS.getInstance().getLoadedModelFeature().expandPrefix(layerPrefix)); for (Map.Entry<String, String> entry : FactoryWFS.getInstance().getLoadedModelFeature().getNsPrefixMap().entrySet()) { requestElement.setAttribute("xmlns:" + entry.getKey(), entry.getValue()); } for (int i = 0; i < fields.size(); i++) { Element sequence = document.createElement("xsd:element"); sequence.setAttribute("maxOccurs","1"); sequence.setAttribute("minOccurs","0"); sequence.setAttribute("name", fields.get(i).getName()); sequence.setAttribute("nillable","true"); if(fields.get(i).getName().equals(feature.getSOLRGeometryField())){ sequence.setAttribute("type",factorySOLR.getSOLRGeometryType(feature)); } else { sequence.setAttribute("type",fields.get(i).getType()); } myNodeList.item(0).getParentNode().insertBefore(sequence, myNodeList.item(0)); } describeFeatureTypeResponse = Utils.printXMLDocument(document); describeFeatureTypeResponse = describeFeatureTypeResponse.replace("PARAM_NAME", feature.getName()); describeFeatureTypeResponse = describeFeatureTypeResponse.replace("PARAM_TYPE", feature.getName()); describeFeatureTypeResponse = describeFeatureTypeResponse.replace("PARAM_SERVER_PORT", Integer.toString(GlobalSettings.getDefaultPort())); describeFeatureTypeResponse = describeFeatureTypeResponse.replace("PARAM_SERVICE", GlobalSettings.getDefaultServiceName()); describeFeatureTypeResponse = describeFeatureTypeResponse.replace("PARAM_SERVER", java.net.InetAddress.getLocalHost().getHostName()); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (XPathExpressionException e) { e.printStackTrace(); } return describeFeatureTypeResponse; } public String getFeature(WFSFeature feature) { String getFeatureResponse = new String(); String layerPrefix = new String(); layerPrefix = GlobalSettings.getSOLRPrefix(); feature = this.expandSOLRFeature(feature); ArrayList<SOLRRecord> fields = new ArrayList<SOLRRecord>(); fields = factorySOLR.getSOLRFeatureFields(feature); logger.info("Performing query at " + feature.getEndpoint() + " to retrieve the geometries of [" + feature.getName() + "] ..."); SolrDocumentList rs = new SolrDocumentList(); SOLRConnector solrConnector = new SOLRConnector(); rs = solrConnector.executeQuery(feature); try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder; documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse("wfs/GetFeature_100.xml"); /** * Build Name Spaces in the XML header. */ Element requestElement = document.getDocumentElement(); for (Map.Entry<String, String> entry : FactoryWFS.getInstance().getLoadedModelFeature().getNsPrefixMap().entrySet()) { requestElement.setAttribute("xmlns:" + entry.getKey(), entry.getValue()); } logger.info("Creating GetFeature XML document with " + rs.size() + " records for [" + feature.getName() + "] ..."); XPath xpath = XPathFactory.newInstance().newXPath(); NodeList myNodeList = (NodeList) xpath.compile("//FeatureCollection/text()").evaluate(document, XPathConstants.NODESET); int invalid = 0; int empty = 0; for (int i = 0; i < rs.size(); i++) { String currentGeometryName = "SOLRGEO_"; Element currentGeometryElement = document.createElement(FactoryWFS.getInstance().getLoadedModelFeature().shortForm(feature.getName())); currentGeometryElement.setAttribute("fid", currentGeometryName + "" + i); Element rootGeometry = document.createElement("gml:featureMember"); for (int j = 0; j < fields.size(); j++) { Element elementGeometryPredicate = document.createElement(layerPrefix + ":" + feature.getGeometryVariable()); if(fields.get(j).getName().equals(feature.getGeometryVariable())){ if(rs.get(i).getFieldValue(feature.getGeometryVariable()) == null){ logger.error("Record skipped at SOLR Feature [" + feature.getName() + "]. The field [" + feature.getGeometryVariable() + "] is empty."); empty = empty +1; } else { String wkt = new String(); wkt = rs.get(i).getFieldValue(feature.getGeometryVariable()).toString(); wkt = wkt.replace("[", "").replace("]", ""); if (Utils.isWKT(wkt)){ String gml = Utils.convertWKTtoGML(wkt); Element GMLnode = documentBuilder.parse(new ByteArrayInputStream(gml.getBytes())).getDocumentElement(); Node dup = document.importNode(GMLnode, true); elementGeometryPredicate.appendChild(dup); rootGeometry.appendChild(elementGeometryPredicate); currentGeometryElement.appendChild(elementGeometryPredicate); rootGeometry.appendChild(currentGeometryElement); } else { invalid = invalid + 1; logger.error("Record skipped at SOLR Feature [" + feature.getName() + "]. Invalid WKT geometry for [" + feature.getGeometryVariable() + "]: " + wkt); } } } else { Element elementAttribute = document.createElement(layerPrefix + ":" + fields.get(j).getName()); if(rs.get(i).getFieldValue(fields.get(j).getName().toString()) != null){ String fieldValue = new String(); fieldValue = rs.get(i).getFieldValue(fields.get(j).getName().toString()).toString().replace("[", "").replace("]", ""); elementAttribute.appendChild(document.createCDATASection(fieldValue)); } else { elementAttribute.appendChild(document.createCDATASection("-")); } currentGeometryElement.appendChild(elementAttribute); } } myNodeList.item(1).getParentNode().insertBefore(rootGeometry, myNodeList.item(1)); } if (empty != 0){ logger.error(empty + " records skipped at SOLR Feature [" + feature.getName() + "]. Geometry field [" + feature.getGeometryVariable() + "] is empty."); } if (invalid != 0){ logger.error(empty + " records skipped at SOLR Feature [" + feature.getName() + "]. Geometry field [" + feature.getGeometryVariable() + "] with invalid WKT geometries."); } logger.info("XML Document for ["+ feature.getName() +"] successfully created."); getFeatureResponse = Utils.printXMLDocument(document); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (XPathExpressionException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return getFeatureResponse; } public String getSOLRGeometryType(WFSFeature feature){ feature.setLimit(1); return null; } }