/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* Copyright (C) 2010 thorsten
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package Sirius.server.search.builtin;
import Sirius.server.middleware.interfaces.domainserver.MetaService;
import Sirius.server.middleware.types.MetaObjectNode;
import Sirius.server.middleware.types.Node;
import Sirius.server.search.CidsServerSearch;
import com.vividsolutions.jts.geom.Geometry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
* DOCUMENT ME!
*
* @author thorsten
* @version $Revision$, $Date$
*/
public class GeoSearch extends CidsServerSearch {
//~ Instance fields --------------------------------------------------------
Geometry searchGeometry = null;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new GeoSearch object.
*
* @param searchGeometry DOCUMENT ME!
*/
public GeoSearch(final Geometry searchGeometry) {
this.searchGeometry = searchGeometry;
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param domainKey DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getGeoSearchSql(final Object domainKey) {
// final String ssql = "WITH recursive derived_index(ocid,oid,stringrep,acid,aid,depth) AS "
// + "( "
// + "SELECT class_id,object_id,stringrep,class_id,object_id,0 "
// + "FROM GEOSUCHE2 WHERE class_id IN"
// + "( "
// + "WITH recursive derived_child(father,child,depth) AS ( "
// + "SELECT father,father,0 FROM cs_class_hierarchy WHERE father in <cidsClassesInStatement> "
// + "UNION ALL "
// + "SELECT ch.father,ch.child,dc.depth+1 FROM derived_child dc,cs_class_hierarchy ch WHERE ch.father=dc.child) "
// + "SELECT DISTINCT child FROM derived_child LIMIT 100 "
// + ") "
// + "AND geo_field && GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>') AND intersects(geo_field,GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>')) "
// + "UNION ALL "
// + "SELECT aam.class_id,aam.object_id,stringrep, aam.attr_class_id, aam.attr_object_id,di.depth+1 FROM cs_attr_object aam,derived_index di WHERE aam.attr_class_id =di.ocid AND aam.attr_object_id=di.oid "
// + ") "
// + "SELECT DISTINCT ocid,oid,stringrep FROM derived_index WHERE ocid in <cidsClassesInStatement> LIMIT 10000000 ";
//
final String sql = ""
+ "SELECT DISTINCT i.class_id , "
+ " i.object_id, "
+ " s.stringrep "
+ "FROM geom g, "
+ " cs_attr_object_derived i "
+ " LEFT OUTER JOIN cs_stringrepcache s "
+ " ON ( "
+ " s.class_id =i.class_id "
+ " AND s.object_id=i.object_id "
+ " ) "
+ "WHERE i.attr_class_id = "
+ " ( SELECT cs_class.id "
+ " FROM cs_class "
+ " WHERE cs_class.table_name::text = 'GEOM'::text "
+ " ) "
+ "AND i.attr_object_id = g.id "
+ "AND i.class_id IN <cidsClassesInStatement> "
+ "AND geo_field && GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>') "
+ "AND intersects(geo_field,GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>')) "
+ "ORDER BY 1,2,3";
final String sqlAlt = ""
+ "\nWITH recursive derived_index(ocid,oid,acid,aid,depth) AS "
+ "\n( SELECT class_id, "
+ "\n object_id, "
+ "\n class_id , "
+ "\n object_id, "
+ "\n 0 "
+ "\nFROM geosuche2 "
+ "\nWHERE class_id IN( WITH recursive derived_child(father,child,depth) AS "
+ "\n ( SELECT father, "
+ "\n father , "
+ "\n 0 "
+ "\n FROM cs_class_hierarchy "
+ "\n WHERE father IN <cidsClassesInStatement> "
+ "\n "
+ "\n UNION ALL "
+ "\n "
+ "\n SELECT ch.father, "
+ "\n ch.child , "
+ "\n dc.depth+1 "
+ "\n FROM derived_child dc, "
+ "\n cs_class_hierarchy ch "
+ "\n WHERE ch.father=dc.child "
+ "\n ) "
+ "\n SELECT DISTINCT child "
+ "\n FROM derived_child LIMIT 100 ) "
+ "\nAND geo_field && GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>') "
+ "\nAND intersects(geo_field,GeometryFromText('SRID=<cidsSearchGeometrySRID>;<cidsSearchGeometryWKT>')) "
+ "\n "
+ "\nUNION ALL "
+ "\n "
+ "\nSELECT aam.class_id , "
+ "\n aam.object_id , "
+ "\n aam.attr_class_id , "
+ "\n aam.attr_object_id, "
+ "\n di.depth+1 "
+ "\nFROM cs_attr_object aam, "
+ "\n derived_index di "
+ "\nWHERE aam.attr_class_id =di.ocid "
+ "\nAND aam.attr_object_id=di.oid "
+ "\n) "
+ "\nSELECT DISTINCT ocid, "
+ "\n oid , "
+ "\n stringrep "
+ "\nFROM derived_index "
+ "\n LEFT OUTER JOIN cs_stringrepcache "
+ "\n ON ( "
+ "\n ocid=class_id "
+ "\n AND oid =object_id "
+ "\n ) "
+ "\nWHERE ocid IN <cidsClassesInStatement> LIMIT 10000000 ";
final String cidsSearchGeometryWKT = searchGeometry.toText();
final String sridString = Integer.toString(searchGeometry.getSRID());
final String classesInStatement = getClassesInSnippetsPerDomain().get((String)domainKey);
if ((cidsSearchGeometryWKT == null) || (cidsSearchGeometryWKT.trim().length() == 0)
|| (sridString == null)
|| (sridString.trim().length() == 0)) {
// TODO: Notify user?
getLog().error(
"Search geometry or srid is not given. Can't perform a search without those information.");
return null;
}
if (getLog().isDebugEnabled()) {
getLog().debug("cidsClassesInStatement=" + classesInStatement);
}
if (getLog().isDebugEnabled()) {
getLog().debug("cidsSearchGeometryWKT=" + cidsSearchGeometryWKT);
}
if (getLog().isDebugEnabled()) {
getLog().debug("cidsSearchGeometrySRID=" + sridString);
}
if ((classesInStatement == null) || (classesInStatement.trim().length() == 0)) {
getLog().warn("There are no search classes defined for domain '" + domainKey
+ "'. This domain will be skipped.");
return null;
}
return sql.replaceAll("<cidsClassesInStatement>", classesInStatement)
.replaceAll("<cidsSearchGeometryWKT>", cidsSearchGeometryWKT)
.replaceAll("<cidsSearchGeometrySRID>", sridString);
}
@Override
public Collection performServerSearch() {
final ArrayList<Node> aln = new ArrayList<Node>();
try {
getLog().info("geosearch started");
// Deppensuche sequentiell
final HashSet keyset = new HashSet(getActiveLoaclServers().keySet());
for (final Object domainKey : keyset) {
final MetaService ms = (MetaService)getActiveLoaclServers().get(domainKey);
final String sqlStatement = getGeoSearchSql(domainKey);
if (sqlStatement != null) {
getLog().info("geosearch: " + sqlStatement);
final ArrayList<ArrayList> result = ms.performCustomSearch(sqlStatement);
for (final ArrayList al : result) {
final int cid = (Integer)al.get(0);
final int oid = (Integer)al.get(1);
String name = null;
try {
name = (String)al.get(2);
} catch (Exception e) {
}
final MetaObjectNode mon = new MetaObjectNode((String)domainKey, oid, cid, name);
aln.add(mon);
}
}
}
} catch (Exception e) {
getLog().error("Problem during GEOSEARCH", e);
}
return aln;
}
}