Strabon

changeset 557:9f107d4df339

Modified the KML results writer to append several styles to the KML file.
Partially fixes Ticket #10
author Kostis Kyzirakos <kkyzir@di.uoa.gr>
date Mon Sep 17 23:01:48 2012 +0300 (2012-09-17)
parents 157780b4d79b
children 28812d96cfa5
files endpoint/WebContent/WEB-INF/connection.properties resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java
line diff
     1.1 --- a/endpoint/WebContent/WEB-INF/connection.properties	Mon Sep 17 21:02:57 2012 +0300
     1.2 +++ b/endpoint/WebContent/WEB-INF/connection.properties	Mon Sep 17 23:01:48 2012 +0300
     1.3 @@ -1,6 +1,7 @@
     1.4 -dbname 		= endpoint
     1.5 -username 	= postgres
     1.6 -password 	= postgres
     1.7 -port		= 5432
     1.8 -hostname	= localhost
     1.9 -dbengine	= postgis
    1.10 \ No newline at end of file
    1.11 +#Mon Sep 17 20:48:10 EEST 2012
    1.12 +hostname=localhost
    1.13 +port=5432
    1.14 +dbengine=postgis
    1.15 +password=p1r3as
    1.16 +dbname=dlr-gis
    1.17 +username=kkyzir
     2.1 --- a/resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java	Mon Sep 17 21:02:57 2012 +0300
     2.2 +++ b/resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java	Mon Sep 17 23:01:48 2012 +0300
     2.3 @@ -56,37 +56,54 @@
     2.4  public class stSPARQLResultsKMLWriter implements TupleQueryResultWriter {
     2.5  
     2.6  	private static final Logger logger = LoggerFactory.getLogger(org.openrdf.query.resultio.sparqlkml.stSPARQLResultsKMLWriter.class);
     2.7 -	
     2.8 +
     2.9  	private static final String ROOT_TAG 			= "kml";
    2.10  	private static final String NAMESPACE 			= "http://www.opengis.net/kml/2.2";
    2.11  	private static final String RESULT_SET_TAG		= "Folder";
    2.12 -	
    2.13 +
    2.14  	private static final String PLACEMARK_TAG		= "Placemark";
    2.15  	private static final String NAME_TAG			= "name";
    2.16  	private static final String DESC_TAG			= "description";
    2.17 -	
    2.18 +
    2.19 +	private static final String STYLE_TAG = "Style";
    2.20 +	private static final String STYLEMAP_TAG = "StyleMap";
    2.21 +	private static final String LINESTYLE_TAG = "LineStyle";
    2.22 +	private static final String POLYSTYLE_TAG = "PolyStyle";
    2.23 +	private static final String STYLE_ID = "resultStyle";
    2.24 +
    2.25  	private static final String TABLE_ROW_BEGIN		= "<TR>";
    2.26  	private static final String TABLE_ROW_END		= "</TR>";
    2.27  	private static final String TABLE_DATA_BEGIN	= "<TD>";
    2.28  	private static final String TABLE_DATA_END		= "</TD>";
    2.29 -	
    2.30 +
    2.31  	private static final String NEWLINE				= "\n";
    2.32 -	
    2.33 +
    2.34  	private static final String TABLE_DESC_BEGIN	= "<![CDATA[<TABLE border=\"1\">" + NEWLINE;
    2.35  	private static final String TABLE_DESC_END		= "</TABLE>]]>" + NEWLINE;
    2.36 -	
    2.37 +
    2.38  	private static final String GEOMETRY_NAME		= "Geometry";
    2.39 -	
    2.40 +
    2.41 +	//Styling options
    2.42 +	String [][] styles = {
    2.43 +			// note that colors are encoded as "aabbggrr" strings where  
    2.44 +			// aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff); rr=red (00 to ff). 
    2.45 +			// id, line width, line color, polygon fill, mouse over line width, mouse over line color mouse over polygon fill
    2.46 +			{STYLE_ID+"1", "1.5", "7dff0000", "7dff0000", "1.5", "7d0000ff", "7d0000ff"},
    2.47 +			{STYLE_ID+"2", "1.5", "7d00ff00", "7d00ff00", "1.5", "7d0000ff", "7d0000ff"},
    2.48 +			{STYLE_ID+"3", "1.5", "7d550000", "7d550000", "1.5", "7d0000ff", "7d0000ff"},
    2.49 +			{STYLE_ID+"4", "1.5", "7d005500", "7d005500", "1.5", "7d0000ff", "7d0000ff"},
    2.50 +			{STYLE_ID+"5", "1.5", "7d000055", "7d000055", "1.5", "7d0000ff", "7d0000ff"},
    2.51 +	};
    2.52  	/**
    2.53  	 * The underlying XML formatter.
    2.54  	 */
    2.55  	private stSPARQLXMLWriter xmlWriter;
    2.56 -	
    2.57 +
    2.58  	/**
    2.59  	 * The number of results seen.
    2.60  	 */
    2.61  	private int nresults;
    2.62 -	
    2.63 +
    2.64  	/**
    2.65  	 * The number of geometries seen.
    2.66  	 */
    2.67 @@ -96,29 +113,29 @@
    2.68  	 * The JTS wrapper
    2.69  	 */
    2.70  	private JTSWrapper jts;
    2.71 -	
    2.72 +
    2.73  	/**
    2.74  	 * Stream for manipulating geometries
    2.75  	 */
    2.76  	private ByteArrayOutputStream baos;
    2.77 -	
    2.78 +
    2.79  	/**
    2.80  	 * Description string holding the projected variables
    2.81  	 * of the SPARQL query
    2.82  	 */
    2.83  	private StringBuilder descHeader;
    2.84 -	
    2.85 +
    2.86  	/**
    2.87  	 * Description string holding the values for the
    2.88  	 * projected variables of the SPARQL query
    2.89  	 */
    2.90  	private StringBuilder descData;
    2.91 -	
    2.92 +
    2.93  	/**
    2.94  	 * Indentation used in tags that are constructed manually
    2.95  	 */
    2.96  	private int depth;
    2.97 -	
    2.98 +
    2.99  	/**
   2.100  	 * Creates an stSPARQLResultsKMLWriter that encodes the SPARQL
   2.101  	 * results in KML.
   2.102 @@ -128,24 +145,24 @@
   2.103  	public stSPARQLResultsKMLWriter(OutputStream out) {
   2.104  		this(new stSPARQLXMLWriter(out));
   2.105  	}
   2.106 -	
   2.107 +
   2.108  	public stSPARQLResultsKMLWriter(stSPARQLXMLWriter writer) {
   2.109  		xmlWriter = writer;
   2.110  		xmlWriter.setPrettyPrint(true);
   2.111 -		
   2.112 +
   2.113  		depth = 4;
   2.114 -				
   2.115 +
   2.116  		jts = JTSWrapper.getInstance();
   2.117 -		
   2.118 +
   2.119  		baos = new ByteArrayOutputStream();
   2.120 -		
   2.121 +
   2.122  		descHeader = new StringBuilder();
   2.123  		descData = new StringBuilder();
   2.124 -		
   2.125 +
   2.126  		nresults = 0;
   2.127  		ngeometries = 0;
   2.128  	}
   2.129 -	
   2.130 +
   2.131  	@Override
   2.132  	public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
   2.133  		try {
   2.134 @@ -154,6 +171,52 @@
   2.135  			xmlWriter.setAttribute("xmlns", NAMESPACE);
   2.136  			xmlWriter.startTag(ROOT_TAG);
   2.137  			xmlWriter.startTag(RESULT_SET_TAG);
   2.138 +			
   2.139 +			//add default styles
   2.140 +			for (String[] style: styles) {
   2.141 +				String id = style[0];
   2.142 +				String lineWidth = style[1];
   2.143 +				String lineColor = style[2];
   2.144 +				String polygonFill = style[3];
   2.145 +				String mouseOverLineWidth = style[4];
   2.146 +				String mouseOverLineColor = style[5];
   2.147 +				String mouseOverPolygonFill = style[6];
   2.148 +
   2.149 +				xmlWriter.setAttribute("id", "normal_"+id);
   2.150 +				xmlWriter.startTag(STYLE_TAG);			
   2.151 +				xmlWriter.startTag(LINESTYLE_TAG);
   2.152 +				xmlWriter.textElement("width", lineWidth);
   2.153 +				xmlWriter.textElement("color", lineColor);
   2.154 +				xmlWriter.endTag(LINESTYLE_TAG);
   2.155 +				xmlWriter.startTag(POLYSTYLE_TAG);
   2.156 +				xmlWriter.textElement("color", polygonFill);
   2.157 +				xmlWriter.endTag(POLYSTYLE_TAG);
   2.158 +				xmlWriter.endTag(STYLE_TAG);
   2.159 +
   2.160 +				xmlWriter.setAttribute("id", "highlight_"+id);
   2.161 +				xmlWriter.startTag(STYLE_TAG);			
   2.162 +				xmlWriter.startTag(LINESTYLE_TAG);
   2.163 +				xmlWriter.textElement("width", mouseOverLineWidth);
   2.164 +				xmlWriter.textElement("color", mouseOverLineColor);
   2.165 +				xmlWriter.endTag(LINESTYLE_TAG);
   2.166 +				xmlWriter.startTag(POLYSTYLE_TAG);
   2.167 +				xmlWriter.textElement("color", mouseOverPolygonFill);
   2.168 +				xmlWriter.endTag(POLYSTYLE_TAG);
   2.169 +				xmlWriter.endTag(STYLE_TAG);
   2.170 +
   2.171 +				xmlWriter.setAttribute("id", id);
   2.172 +				xmlWriter.startTag(STYLEMAP_TAG);
   2.173 +				xmlWriter.startTag("Pair");
   2.174 +				xmlWriter.textElement("key", "normal");
   2.175 +				xmlWriter.textElement("styleUrl", "#normal_"+id);
   2.176 +				xmlWriter.endTag("Pair");
   2.177 +				xmlWriter.startTag("Pair");
   2.178 +				xmlWriter.textElement("key", "highlight");
   2.179 +				xmlWriter.textElement("styleUrl", "#highlight_"+id);
   2.180 +				xmlWriter.endTag("Pair");
   2.181 +				xmlWriter.endTag(STYLEMAP_TAG);
   2.182 +			}
   2.183 +			//end of default style definition
   2.184  		}
   2.185  		catch (IOException e) {
   2.186  			throw new TupleQueryResultHandlerException(e);
   2.187 @@ -167,9 +230,9 @@
   2.188  			xmlWriter.endTag(ROOT_TAG);
   2.189  
   2.190  			xmlWriter.endDocument();
   2.191 -			
   2.192 +
   2.193  			baos.close();
   2.194 -			
   2.195 +
   2.196  			if (ngeometries < nresults) {
   2.197  				logger.warn("[Strabon.KMLWriter] No spatial binding found in the result. KML requires that at least one binding maps to a geometry.", nresults);
   2.198  			}
   2.199 @@ -184,16 +247,16 @@
   2.200  		try {
   2.201  			// true if there are bindings that do not correspond to geometries
   2.202  			boolean hasDesc = false;
   2.203 -			
   2.204 +
   2.205  			// increase result size
   2.206  			nresults++;
   2.207 -			
   2.208 +
   2.209  			// create description table and header
   2.210  			indent(descHeader, depth);
   2.211  			descHeader.append(TABLE_DESC_BEGIN);
   2.212  			indent(descHeader, depth);
   2.213  			descHeader.append(TABLE_ROW_BEGIN);
   2.214 -			
   2.215 +
   2.216  			// create description table data row
   2.217  			descData.append(NEWLINE);
   2.218  			indent(descData, depth);
   2.219 @@ -202,7 +265,11 @@
   2.220  			// write placemark tag
   2.221  			xmlWriter.startTag(PLACEMARK_TAG);
   2.222  			xmlWriter.textElement(NAME_TAG, GEOMETRY_NAME + nresults + "_" + ngeometries);
   2.223 -			
   2.224 +
   2.225 +			//TODO: Hardcoded style selection. Modify this line after adding 
   2.226 +			//support for multiple geometry variables in the select clause
   2.227 +			xmlWriter.textElement("styleUrl", "#"+styles[0][0]);
   2.228 +
   2.229  			// parse binding set
   2.230  			for (Binding binding : bindingSet) {
   2.231  				Value value = binding.getValue();
   2.232 @@ -210,57 +277,57 @@
   2.233  				// check for geometry value
   2.234  				if (XMLGSDatatypeUtil.isGeometryValue(value)) {
   2.235  					ngeometries++;
   2.236 -						
   2.237 +
   2.238  					if (logger.isDebugEnabled()) {
   2.239  						logger.debug("[Strabon] Found geometry: {}", value);
   2.240  					}
   2.241 -					
   2.242 +
   2.243  					xmlWriter.unescapedText(getKML(value));
   2.244 -				
   2.245 +
   2.246  				} else { // URI, BlankNode, or Literal other than spatial literal 
   2.247  					if (logger.isDebugEnabled()) {
   2.248  						logger.debug("[Strabon.KMLWriter] Found URI/BlankNode/Literal ({}): {}", value.getClass(), value);
   2.249  					}
   2.250 -					
   2.251 +
   2.252  					// mark that we found sth corresponding to the description
   2.253  					hasDesc = true;
   2.254 -					
   2.255 +
   2.256  					// write description
   2.257  					writeDesc(binding);
   2.258  				}
   2.259  			}
   2.260 -			
   2.261 +
   2.262  			// we have found and constructed a description for this result. Write it down.
   2.263  			if (hasDesc) {
   2.264  				// close the header of the description
   2.265  				descHeader.append(NEWLINE);
   2.266  				indent(descHeader, depth);
   2.267  				descHeader.append(TABLE_ROW_END);
   2.268 -				
   2.269 +
   2.270  				// end the placeholder for the description data
   2.271  				descData.append(NEWLINE);
   2.272  				indent(descData, depth);
   2.273  				descData.append(TABLE_ROW_END);
   2.274 -				
   2.275 +
   2.276  				// append to the table header the actual content from
   2.277  				// the bindings
   2.278  				descHeader.append(descData);
   2.279 -				
   2.280 +
   2.281  				// close the table for the description
   2.282  				descHeader.append(NEWLINE);
   2.283  				indent(descHeader, depth);
   2.284  				descHeader.append(TABLE_DESC_END);
   2.285 -				
   2.286 +
   2.287  				// begin the "description" tag
   2.288  				xmlWriter.startTag(DESC_TAG);
   2.289 -				
   2.290 +
   2.291  				// write the actual description
   2.292  				xmlWriter.unescapedText(descHeader.toString());
   2.293 -				
   2.294 +
   2.295  				// end the "description" tag
   2.296  				xmlWriter.endTag(DESC_TAG);
   2.297  			}
   2.298 -			
   2.299 +
   2.300  			// clear description string builders
   2.301  			descHeader.setLength(0);
   2.302  			descData.setLength(0);
   2.303 @@ -276,88 +343,88 @@
   2.304  	private String getKML(Value value) {
   2.305  		String kml = "";
   2.306  		QName geometryType = null;
   2.307 -		
   2.308 +
   2.309  		// the underlying geometry in value
   2.310  		Geometry geom = null;
   2.311 -		
   2.312 +
   2.313  		// the underlying SRID of the geometry
   2.314  		int srid = -1;
   2.315 -		
   2.316 +
   2.317  		// get the KML encoder
   2.318  		Encoder encoder = null;
   2.319 -		
   2.320 +
   2.321  		try {
   2.322  			encoder = new Encoder(new KMLConfiguration());
   2.323  			encoder.setIndenting(true);
   2.324 -			
   2.325 +
   2.326  			if (value instanceof GeneralDBPolyhedron) {
   2.327  				GeneralDBPolyhedron dbpolyhedron = (GeneralDBPolyhedron) value;
   2.328 -				
   2.329 +
   2.330  				geom = dbpolyhedron.getPolyhedron().getGeometry();
   2.331  				srid = dbpolyhedron.getPolyhedron().getGeometry().getSRID();
   2.332 -				
   2.333 +
   2.334  			} else { // spatial literal
   2.335  				Literal spatial = (Literal) value;
   2.336  				String geomRep = spatial.stringValue();
   2.337 -				
   2.338 +
   2.339  				if (XMLGSDatatypeUtil.isWKTLiteral(spatial)) { // WKT
   2.340  					geom = jts.WKTread(WKTHelper.getWithoutSRID(geomRep));
   2.341  					srid = WKTHelper.getSRID(geomRep);
   2.342 -					
   2.343 +
   2.344  				} else { // GML
   2.345  					geom = jts.GMLread(geomRep);
   2.346  					srid = geom.getSRID();
   2.347 -					
   2.348 +
   2.349  				}
   2.350  			}
   2.351 -			
   2.352 +
   2.353  			// transform the geometry to {@link GeoConstants#defaultSRID}
   2.354  			geom = jts.transform(geom, srid, GeoConstants.defaultSRID);
   2.355 -			
   2.356 +
   2.357  			if (geom instanceof Point) {
   2.358  				geometryType = KML.Point;
   2.359 -				
   2.360 +
   2.361  			} else if (geom instanceof Polygon) {
   2.362  				geometryType = KML.Polygon;
   2.363 -				
   2.364 +
   2.365  			} else if (geom instanceof LineString) {
   2.366  				geometryType = KML.LineString;
   2.367 -				
   2.368 +
   2.369  			} else if (geom instanceof MultiPoint) {
   2.370  				geometryType = KML.MultiGeometry;
   2.371 -				
   2.372 +
   2.373  			} else if (geom instanceof MultiLineString) {
   2.374  				geometryType = KML.MultiGeometry;
   2.375 -				
   2.376 +
   2.377  			} else if (geom instanceof MultiPolygon) {
   2.378  				geometryType = KML.MultiGeometry;
   2.379 -				
   2.380 +
   2.381  			} else if (geom instanceof GeometryCollection) {
   2.382  				geometryType = KML.MultiGeometry;
   2.383 -				
   2.384 +
   2.385  			} 
   2.386 -			
   2.387 +
   2.388  			if (geometryType == null) {
   2.389  				logger.warn("[Strabon.KMLWriter] Found unknown geometry type.");
   2.390 -				
   2.391 +
   2.392  			} else {
   2.393 -			
   2.394 +
   2.395  				encoder.encode(geom, geometryType, baos);
   2.396  				kml = baos.toString().substring(38).replaceAll(" xmlns:kml=\"http://earth.google.com/kml/2.1\"","").replaceAll("kml:","");
   2.397  				baos.reset();
   2.398  			}
   2.399 -			
   2.400 +
   2.401  		} catch (ParseException e) {
   2.402  			logger.error("[Strabon.KMLWriter] Parse error exception of geometry: {}", e.getMessage());
   2.403 -			
   2.404 +
   2.405  		} catch (IOException e) {
   2.406  			logger.error("[Strabon.KMLWriter] IOException during KML encoding of geometry: {}", e.getMessage());
   2.407 -			
   2.408 +
   2.409  		} catch (JAXBException e) {
   2.410  			logger.error("[Strabon.KMLWriter] Exception during GML parsing: {}", e.getMessage());
   2.411 -			
   2.412 +
   2.413  		}
   2.414 -		
   2.415 +
   2.416  		return kml;
   2.417  	}
   2.418  
   2.419 @@ -372,7 +439,7 @@
   2.420  		descHeader.append(TABLE_DATA_BEGIN);
   2.421  		descHeader.append(binding.getName());
   2.422  		descHeader.append(TABLE_DATA_END);
   2.423 -		
   2.424 +
   2.425  		descData.append(NEWLINE);
   2.426  		indent(descData, depth + 1);
   2.427  		descData.append(TABLE_DATA_BEGIN);
   2.428 @@ -381,14 +448,14 @@
   2.429  		}
   2.430  		descData.append(binding.getValue().stringValue());
   2.431  		descData.append(TABLE_DATA_END);
   2.432 -		
   2.433 +
   2.434  	}
   2.435  
   2.436  	@Override
   2.437  	public TupleQueryResultFormat getTupleQueryResultFormat() {
   2.438  		return stSPARQLQueryResultFormat.KML;
   2.439  	}
   2.440 -	
   2.441 +
   2.442  	/**
   2.443  	 * Adds indentation to the given string builder according to 
   2.444  	 * the specified depth.