Strabon

changeset 644:e053a82353ab

projected variables in stSPARQL are now also included in KML results using the ExtendedData and Data tags of KML specification (https://developers.google.com/kml/documentation/kmlreference#extendeddata)
author Babis Nikolaou <charnik@di.uoa.gr>
date Wed Oct 24 15:47:45 2012 +0300 (2012-10-24)
parents b1caa46da857
children 77cd63e44ce7
files resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java
line diff
     1.1 --- a/resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java	Thu Oct 18 20:40:36 2012 +0300
     1.2 +++ b/resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java	Wed Oct 24 15:47:45 2012 +0300
     1.3 @@ -10,9 +10,12 @@
     1.4  import java.io.IOException;
     1.5  import java.io.OutputStream;
     1.6  import java.util.ArrayList;
     1.7 +import java.util.Hashtable;
     1.8  import java.util.List;
     1.9 +
    1.10  import javax.xml.bind.JAXBException;
    1.11  import javax.xml.namespace.QName;
    1.12 +
    1.13  import org.geotools.kml.KML;
    1.14  import org.geotools.kml.KMLConfiguration;
    1.15  import org.geotools.xml.Encoder;
    1.16 @@ -33,6 +36,7 @@
    1.17  import org.openrdf.sail.generaldb.model.XMLGSDatatypeUtil;
    1.18  import org.slf4j.Logger;
    1.19  import org.slf4j.LoggerFactory;
    1.20 +
    1.21  import com.vividsolutions.jts.geom.Geometry;
    1.22  import com.vividsolutions.jts.geom.GeometryCollection;
    1.23  import com.vividsolutions.jts.geom.LineString;
    1.24 @@ -49,69 +53,100 @@
    1.25   * @author Panayiotis Smeros <psmeros@di.uoa.gr>
    1.26   * 
    1.27   */
    1.28 -public class stSPARQLResultsKMLWriter implements TupleQueryResultWriter
    1.29 -{
    1.30 +public class stSPARQLResultsKMLWriter implements TupleQueryResultWriter {
    1.31  	private static final Logger logger = LoggerFactory.getLogger(org.openrdf.query.resultio.sparqlkml.stSPARQLResultsKMLWriter.class);
    1.32 -	private static final String ROOT_TAG = "kml";
    1.33 -	private static final String NAMESPACE = "http://www.opengis.net/kml/2.2";
    1.34 -	private static final String RESULT_SET_TAG = "Folder";
    1.35 -	private static final String PLACEMARK_TAG = "Placemark";
    1.36 -	private static final String NAME_TAG = "name";
    1.37 -	private static final String DESC_TAG = "description";
    1.38 -	private static final String STYLE_TAG = "Style";
    1.39 -	private static final String STYLEMAP_TAG = "StyleMap";
    1.40 -	private static final String LINESTYLE_TAG = "LineStyle";
    1.41 -	private static final String POLYSTYLE_TAG = "PolyStyle";
    1.42 -	private static final String STYLE_ID = "resultStyle";
    1.43 -	private static final String TABLE_ROW_BEGIN = "<TR>";
    1.44 -	private static final String TABLE_ROW_END = "</TR>";
    1.45 -	private static final String TABLE_DATA_BEGIN = "<TD>";
    1.46 -	private static final String TABLE_DATA_END = "</TD>";
    1.47 -	private static final String NEWLINE = "\n";
    1.48 -	private static final String TABLE_DESC_BEGIN = "<![CDATA[<TABLE border=\"1\">" + NEWLINE;
    1.49 -	private static final String TABLE_DESC_END = "</TABLE>]]>" + NEWLINE;
    1.50 -	private static final String GEOMETRY_NAME = "Geometry";
    1.51 -	private static final String MULTIGEOMETRY = "MultiGeometry";
    1.52 +
    1.53 +	// KML tags/attributes
    1.54 +	private static final String ROOT_TAG 			= "kml";
    1.55 +	private static final String NAMESPACE 			= "http://www.opengis.net/kml/2.2";
    1.56 +	private static final String RESULT_SET_TAG 		= "Folder";
    1.57 +	private static final String PLACEMARK_TAG 		= "Placemark";
    1.58 +	private static final String NAME_TAG 			= "name";
    1.59 +	private static final String DESC_TAG 			= "description";
    1.60 +	private static final String STYLE_TAG 			= "Style";
    1.61 +	private static final String STYLEMAP_TAG 		= "StyleMap";
    1.62 +	private static final String LINESTYLE_TAG 		= "LineStyle";
    1.63 +	private static final String POLYSTYLE_TAG 		= "PolyStyle";
    1.64 +	private static final String EXT_DATA_TAG 		= "ExtendedData";
    1.65 +	private static final String DATA_TAG 			= "Data";
    1.66 +	private static final String VALUE_TAG			= "value";
    1.67 +	private static final String NAME_ATTR			= NAME_TAG;
    1.68 +
    1.69 +	private static final String STYLE_ID 			= "resultStyle";
    1.70 +	private static final String TABLE_ROW_BEGIN 	= "<TR>";
    1.71 +	private static final String TABLE_ROW_END 		= "</TR>";
    1.72 +	private static final String TABLE_DATA_BEGIN 	= "<TD>";
    1.73 +	private static final String TABLE_DATA_END 		= "</TD>";
    1.74 +	private static final String NEWLINE 			= "\n";
    1.75 +	private static final String TABLE_DESC_BEGIN 	= "<![CDATA[<TABLE border=\"1\">"+ NEWLINE;
    1.76 +	private static final String TABLE_DESC_END 		= "</TABLE>]]>" + NEWLINE;
    1.77 +
    1.78 +	private static final String GEOMETRY_NAME 		= "Geometry";
    1.79 +	private static final String MULTIGEOMETRY 		= "MultiGeometry";
    1.80 +
    1.81  	// Styling options
    1.82  	private static final int numOfStyles = 5;
    1.83  	private static final String[][] styles = {
    1.84 -		// note that colors are encoded as "aabbggrr" strings where
    1.85 -		// aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff);
    1.86 -		// rr=red
    1.87 -		// (00 to ff).
    1.88 -		// id, line width, line color, polygon fill, mouse over line width,
    1.89 -		// mouse over line color mouse over polygon fill
    1.90 -	//{STYLE_ID + "1", "1.5", "7d0000ff", "ad0000ff", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "2", "1.5", "7d0000ff", "ad0000ff", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "3", "1.5", "7d550000", "ad550000", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "4", "1.5", "7d005500", "ad005500", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "5", "1.5", "7d000055", "ad000055", "1.5", "7d0000ff", "ad0000ff"}};
    1.91 -		{STYLE_ID + "1", "1.5", "000000ff", "000000ff", "1.5", "000000ff", "000000ff"}, {STYLE_ID + "2", "1.5", "000000ff", "000000ff", "1.5", "000000ff", "000000ff"}, {STYLE_ID + "3", "1.5", "7d550000", "ad550000", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "4", "1.5", "7d005500", "ad005500", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "5", "1.5", "7dff0000", "adff0000", "1.5", "7dff0000", "adff0000"}};
    1.92 +			// note that colors are encoded as "aabbggrr" strings where
    1.93 +			// aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff);
    1.94 +			// rr=red
    1.95 +			// (00 to ff).
    1.96 +			// id, line width, line color, polygon fill, mouse over line width,
    1.97 +			// mouse over line color mouse over polygon fill
    1.98 +			// {STYLE_ID + "1", "1.5", "7d0000ff", "ad0000ff", "1.5",
    1.99 +			// "7d0000ff", "ad0000ff"}, {STYLE_ID + "2", "1.5", "7d0000ff",
   1.100 +			// "ad0000ff", "1.5", "7d0000ff", "ad0000ff"}, {STYLE_ID + "3",
   1.101 +			// "1.5", "7d550000", "ad550000", "1.5", "7d0000ff", "ad0000ff"},
   1.102 +			// {STYLE_ID + "4", "1.5", "7d005500", "ad005500", "1.5",
   1.103 +			// "7d0000ff", "ad0000ff"}, {STYLE_ID + "5", "1.5", "7d000055",
   1.104 +			// "ad000055", "1.5", "7d0000ff", "ad0000ff"}};
   1.105 +			{ STYLE_ID + "1", "1.5", "000000ff", "000000ff", "1.5", "000000ff",
   1.106 +					"000000ff" },
   1.107 +			{ STYLE_ID + "2", "1.5", "000000ff", "000000ff", "1.5", "000000ff",
   1.108 +					"000000ff" },
   1.109 +			{ STYLE_ID + "3", "1.5", "7d550000", "ad550000", "1.5", "7d0000ff",
   1.110 +					"ad0000ff" },
   1.111 +			{ STYLE_ID + "4", "1.5", "7d005500", "ad005500", "1.5", "7d0000ff",
   1.112 +					"ad0000ff" },
   1.113 +			{ STYLE_ID + "5", "1.5", "7dff0000", "adff0000", "1.5", "7dff0000",
   1.114 +					"adff0000" } };
   1.115 +
   1.116  	/**
   1.117  	 * The underlying XML formatter.
   1.118  	 */
   1.119  	private stSPARQLXMLWriter xmlWriter;
   1.120 +
   1.121  	/**
   1.122  	 * The number of results seen.
   1.123  	 */
   1.124  	private int nresults;
   1.125 +
   1.126  	/**
   1.127  	 * The number of geometries seen.
   1.128  	 */
   1.129  	private int ngeometries;
   1.130 +
   1.131  	/**
   1.132  	 * The JTS wrapper
   1.133  	 */
   1.134  	private JTSWrapper jts;
   1.135 +
   1.136  	/**
   1.137  	 * Stream for manipulating geometries
   1.138  	 */
   1.139  	private ByteArrayOutputStream baos;
   1.140 +
   1.141  	/**
   1.142  	 * Description string holding the projected variables of the SPARQL query
   1.143  	 */
   1.144  	private StringBuilder descHeader;
   1.145 +
   1.146  	/**
   1.147  	 * Description string holding the values for the projected variables of the
   1.148  	 * SPARQL query
   1.149  	 */
   1.150  	private StringBuilder descData;
   1.151 +
   1.152  	/**
   1.153  	 * Indentation used in tags that are constructed manually
   1.154  	 */
   1.155 @@ -123,13 +158,11 @@
   1.156  	 * 
   1.157  	 * @param out
   1.158  	 */
   1.159 -	public stSPARQLResultsKMLWriter(OutputStream out)
   1.160 -	{
   1.161 +	public stSPARQLResultsKMLWriter(OutputStream out) {
   1.162  		this(new stSPARQLXMLWriter(out));
   1.163  	}
   1.164  
   1.165 -	public stSPARQLResultsKMLWriter(stSPARQLXMLWriter writer)
   1.166 -	{
   1.167 +	public stSPARQLResultsKMLWriter(stSPARQLXMLWriter writer) {
   1.168  		xmlWriter = writer;
   1.169  		xmlWriter.setPrettyPrint(true);
   1.170  		depth = 4;
   1.171 @@ -141,17 +174,18 @@
   1.172  		ngeometries = 0;
   1.173  	}
   1.174  
   1.175 -	@Override public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException
   1.176 -	{
   1.177 -		try
   1.178 -		{
   1.179 +	@Override
   1.180 +	public void startQueryResult(List<String> bindingNames)
   1.181 +			throws TupleQueryResultHandlerException {
   1.182 +		try {
   1.183 +
   1.184  			xmlWriter.startDocument();
   1.185  			xmlWriter.setAttribute("xmlns", NAMESPACE);
   1.186  			xmlWriter.startTag(ROOT_TAG);
   1.187  			xmlWriter.startTag(RESULT_SET_TAG);
   1.188 +
   1.189  			// add default styles
   1.190 -			for(String[] style: styles)
   1.191 -			{
   1.192 +			for (String[] style : styles) {
   1.193  				String id = style[0];
   1.194  				String lineWidth = style[1];
   1.195  				String lineColor = style[2];
   1.196 @@ -159,6 +193,7 @@
   1.197  				String mouseOverLineWidth = style[4];
   1.198  				String mouseOverLineColor = style[5];
   1.199  				String mouseOverPolygonFill = style[6];
   1.200 +
   1.201  				// append normal style
   1.202  				xmlWriter.setAttribute("id", "normal_" + id);
   1.203  				xmlWriter.startTag(STYLE_TAG);
   1.204 @@ -170,6 +205,7 @@
   1.205  				xmlWriter.textElement("color", polygonFill);
   1.206  				xmlWriter.endTag(POLYSTYLE_TAG);
   1.207  				xmlWriter.endTag(STYLE_TAG);
   1.208 +
   1.209  				// append highlight style
   1.210  				xmlWriter.setAttribute("id", "highlight_" + id);
   1.211  				xmlWriter.startTag(STYLE_TAG);
   1.212 @@ -181,6 +217,7 @@
   1.213  				xmlWriter.textElement("color", mouseOverPolygonFill);
   1.214  				xmlWriter.endTag(POLYSTYLE_TAG);
   1.215  				xmlWriter.endTag(STYLE_TAG);
   1.216 +
   1.217  				// define map style combining the above styles
   1.218  				xmlWriter.setAttribute("id", id);
   1.219  				xmlWriter.startTag(STYLEMAP_TAG);
   1.220 @@ -195,131 +232,154 @@
   1.221  				xmlWriter.endTag(STYLEMAP_TAG);
   1.222  			}
   1.223  			// end of default style definition
   1.224 -		}
   1.225 -		catch(IOException e)
   1.226 -		{
   1.227 +		} catch (IOException e) {
   1.228  			throw new TupleQueryResultHandlerException(e);
   1.229  		}
   1.230  	}
   1.231  
   1.232 -	@Override public void endQueryResult() throws TupleQueryResultHandlerException
   1.233 -	{
   1.234 -		try
   1.235 -		{
   1.236 +	@Override
   1.237 +	public void endQueryResult() throws TupleQueryResultHandlerException {
   1.238 +		try {
   1.239 +			
   1.240  			xmlWriter.endTag(RESULT_SET_TAG);
   1.241  			xmlWriter.endTag(ROOT_TAG);
   1.242  			xmlWriter.endDocument();
   1.243  			baos.close();
   1.244 -			if(ngeometries < nresults)
   1.245 -			{
   1.246 +			
   1.247 +			if (ngeometries < nresults) {
   1.248  				logger.warn("[Strabon.KMLWriter] No spatial binding found in the result. KML requires that at least one binding maps to a geometry.", nresults);
   1.249  			}
   1.250 -		}
   1.251 -		catch(IOException e)
   1.252 -		{
   1.253 +			
   1.254 +		} catch (IOException e) {
   1.255  			throw new TupleQueryResultHandlerException(e);
   1.256  		}
   1.257  	}
   1.258  
   1.259 -	@Override public void handleSolution(BindingSet bindingSet) throws TupleQueryResultHandlerException
   1.260 -	{
   1.261 -		try
   1.262 -		{
   1.263 -			int numOfGeometries=0;
   1.264 +	@Override
   1.265 +	public void handleSolution(BindingSet bindingSet) throws TupleQueryResultHandlerException {
   1.266 +		try {
   1.267 +			int numOfGeometries = 0;
   1.268 +
   1.269  			// true if there are bindings that do not correspond to geometries
   1.270  			boolean hasDesc = false;
   1.271 +
   1.272  			// increase result size
   1.273  			nresults++;
   1.274 +
   1.275  			// create description table and header
   1.276  			indent(descHeader, depth);
   1.277  			descHeader.append(TABLE_DESC_BEGIN);
   1.278  			indent(descHeader, depth);
   1.279 +			
   1.280  			List<String> geometries = new ArrayList<String>();
   1.281 +			Hashtable<String, String> extData = new Hashtable<String, String>();
   1.282 +
   1.283  			// parse binding set
   1.284 -			for(Binding binding: bindingSet)
   1.285 -			{
   1.286 +			for (Binding binding : bindingSet) {
   1.287 +
   1.288  				Value value = binding.getValue();
   1.289 +				
   1.290  				// check for geometry value
   1.291 -				if(XMLGSDatatypeUtil.isGeometryValue(value))
   1.292 -				{
   1.293 +				if (XMLGSDatatypeUtil.isGeometryValue(value)) {
   1.294  					numOfGeometries++;
   1.295  					ngeometries++;
   1.296 -					if(logger.isDebugEnabled())
   1.297 -					{
   1.298 +					if (logger.isDebugEnabled()) {
   1.299  						logger.debug("[Strabon] Found geometry: {}", value);
   1.300  					}
   1.301 +					
   1.302  					geometries.add(getGeometry(value));
   1.303 -				}
   1.304 -				else
   1.305 -				{ // URI, BlankNode, or Literal other than spatial
   1.306 -					// literal
   1.307 -					if(logger.isDebugEnabled())
   1.308 -					{
   1.309 +					
   1.310 +				} else { // URI, BlankNode, or Literal other than spatial literal
   1.311 +					if (logger.isDebugEnabled()) {
   1.312  						logger.debug("[Strabon.KMLWriter] Found URI/BlankNode/Literal ({}): {}", value.getClass(), value);
   1.313  					}
   1.314 +					
   1.315  					// mark that we found sth corresponding to the description
   1.316  					hasDesc = true;
   1.317 +					
   1.318  					// write description
   1.319  					writeDesc(binding);
   1.320 +					
   1.321 +					// fill also the extended data attribute of the Placemark
   1.322 +					extData.put(binding.getName(), getBindingValue(binding));
   1.323  				}
   1.324  			}
   1.325 -			if(numOfGeometries > 1)
   1.326 -			{
   1.327 +			
   1.328 +			if (numOfGeometries > 1) {
   1.329  				// write each polygon in separate placemarks
   1.330 -				for(String geometry: geometries)
   1.331 -				{
   1.332 +				for (String geometry : geometries) {
   1.333  					xmlWriter.startTag(PLACEMARK_TAG);
   1.334  					xmlWriter.textElement(NAME_TAG, GEOMETRY_NAME);
   1.335 -					xmlWriter.textElement("styleUrl", "#" + styles[geometries.indexOf(geometry) % (numOfStyles - 2)][0]);
   1.336 +					xmlWriter.textElement("styleUrl", "#"+ styles[geometries.indexOf(geometry) % (numOfStyles - 2)][0]);
   1.337  					xmlWriter.startTag(MULTIGEOMETRY);
   1.338  					xmlWriter.unescapedText(geometry);
   1.339  					xmlWriter.endTag(MULTIGEOMETRY);
   1.340  					xmlWriter.endTag(PLACEMARK_TAG);
   1.341  				}
   1.342  			}
   1.343 +			
   1.344  			// also write them in the same placemarks
   1.345  			xmlWriter.startTag(PLACEMARK_TAG);
   1.346  			xmlWriter.textElement(NAME_TAG, GEOMETRY_NAME);
   1.347  			xmlWriter.textElement("styleUrl", "#" + styles[(numOfStyles - 1)][0]);
   1.348  			xmlWriter.startTag(MULTIGEOMETRY);
   1.349 -			for(String geometry: geometries)
   1.350 -			{
   1.351 +			
   1.352 +			for (String geometry : geometries) {
   1.353  				xmlWriter.unescapedText(geometry);
   1.354  			}
   1.355 +			
   1.356  			xmlWriter.endTag(MULTIGEOMETRY);
   1.357 +			
   1.358  			// we have found and constructed a description for this result.
   1.359  			// Write it down.
   1.360 -			if(hasDesc)
   1.361 -			{
   1.362 +			if (hasDesc) {
   1.363  				// end the placeholder for the description data
   1.364  				indent(descData, depth);
   1.365 +				
   1.366  				// append to the table header the actual content from
   1.367  				// the bindings
   1.368  				descHeader.append(descData);
   1.369 +				
   1.370  				// close the table for the description
   1.371  				descHeader.append(NEWLINE);
   1.372  				indent(descHeader, depth);
   1.373  				descHeader.append(TABLE_DESC_END);
   1.374 +				
   1.375  				// begin the "description" tag
   1.376  				xmlWriter.startTag(DESC_TAG);
   1.377 +				
   1.378  				// write the actual description
   1.379  				xmlWriter.unescapedText(descHeader.toString());
   1.380 +				
   1.381  				// end the "description" tag
   1.382  				xmlWriter.endTag(DESC_TAG);
   1.383  			}
   1.384 +			
   1.385 +			// add the extended data
   1.386 +			if (extData.size() > 0) {
   1.387 +				xmlWriter.startTag(EXT_DATA_TAG);
   1.388 +				for (String key : extData.keySet()) {
   1.389 +					xmlWriter.setAttribute(NAME_ATTR, key);
   1.390 +					xmlWriter.startTag(DATA_TAG);
   1.391 +						xmlWriter.textElement(VALUE_TAG, extData.get(key));
   1.392 +					xmlWriter.endTag(DATA_TAG);
   1.393 +				}
   1.394 +				xmlWriter.endTag(EXT_DATA_TAG);
   1.395 +			}
   1.396 +			
   1.397 +			// end Placemark
   1.398 +			xmlWriter.endTag(PLACEMARK_TAG);
   1.399 +			
   1.400  			// clear description string builders
   1.401  			descHeader.setLength(0);
   1.402  			descData.setLength(0);
   1.403 -			xmlWriter.endTag(PLACEMARK_TAG);
   1.404 -		}
   1.405 -		catch(IOException e)
   1.406 -		{
   1.407 +			
   1.408 +		} catch (IOException e) {
   1.409  			throw new TupleQueryResultHandlerException(e);
   1.410  		}
   1.411  	}
   1.412  
   1.413 -	private String getGeometry(Value value)
   1.414 -	{
   1.415 +	private String getGeometry(Value value) {
   1.416  		String geometry = "";
   1.417  		QName geometryType = null;
   1.418  		// the underlying geometry in value
   1.419 @@ -328,118 +388,87 @@
   1.420  		int srid = -1;
   1.421  		// get the KML encoder
   1.422  		Encoder encoder = null;
   1.423 -		try
   1.424 -		{
   1.425 +		try {
   1.426  			encoder = new Encoder(new KMLConfiguration());
   1.427  			encoder.setIndenting(true);
   1.428 -			if(value instanceof GeneralDBPolyhedron)
   1.429 -			{
   1.430 +			if (value instanceof GeneralDBPolyhedron) {
   1.431  				GeneralDBPolyhedron dbpolyhedron = (GeneralDBPolyhedron) value;
   1.432  				geom = dbpolyhedron.getPolyhedron().getGeometry();
   1.433  				srid = dbpolyhedron.getPolyhedron().getGeometry().getSRID();
   1.434 -			}
   1.435 -			else
   1.436 -			{ // spatial literal
   1.437 +			} else { // spatial literal
   1.438  				Literal spatial = (Literal) value;
   1.439  				String geomRep = spatial.stringValue();
   1.440 -				if(XMLGSDatatypeUtil.isWKTLiteral(spatial))
   1.441 -				{ // WKT
   1.442 +				if (XMLGSDatatypeUtil.isWKTLiteral(spatial)) { // WKT
   1.443  					geom = jts.WKTread(WKTHelper.getWithoutSRID(geomRep));
   1.444  					srid = WKTHelper.getSRID(geomRep);
   1.445 -				}
   1.446 -				else
   1.447 -				{ // GML
   1.448 +				} else { // GML
   1.449  					geom = jts.GMLread(geomRep);
   1.450  					srid = geom.getSRID();
   1.451  				}
   1.452  			}
   1.453  			// transform the geometry to {@link GeoConstants#defaultSRID}
   1.454  			geom = jts.transform(geom, srid, GeoConstants.defaultSRID);
   1.455 -			if(geom instanceof Point)
   1.456 -			{
   1.457 +			if (geom instanceof Point) {
   1.458  				geometryType = KML.Point;
   1.459 -			}
   1.460 -			else if(geom instanceof Polygon)
   1.461 -			{
   1.462 +			} else if (geom instanceof Polygon) {
   1.463  				geometryType = KML.Polygon;
   1.464 -			}
   1.465 -			else if(geom instanceof LineString)
   1.466 -			{
   1.467 +			} else if (geom instanceof LineString) {
   1.468  				geometryType = KML.LineString;
   1.469 -			}
   1.470 -			else if(geom instanceof MultiPoint)
   1.471 -			{
   1.472 +			} else if (geom instanceof MultiPoint) {
   1.473 +				geometryType = KML.MultiGeometry;
   1.474 +			} else if (geom instanceof MultiLineString) {
   1.475 +				geometryType = KML.MultiGeometry;
   1.476 +			} else if (geom instanceof MultiPolygon) {
   1.477 +				geometryType = KML.MultiGeometry;
   1.478 +			} else if (geom instanceof GeometryCollection) {
   1.479  				geometryType = KML.MultiGeometry;
   1.480  			}
   1.481 -			else if(geom instanceof MultiLineString)
   1.482 -			{
   1.483 -				geometryType = KML.MultiGeometry;
   1.484 -			}
   1.485 -			else if(geom instanceof MultiPolygon)
   1.486 -			{
   1.487 -				geometryType = KML.MultiGeometry;
   1.488 -			}
   1.489 -			else if(geom instanceof GeometryCollection)
   1.490 -			{
   1.491 -				geometryType = KML.MultiGeometry;
   1.492 -			}
   1.493 -			if(geometryType == null)
   1.494 -			{
   1.495 +			if (geometryType == null) {
   1.496  				logger.warn("[Strabon.KMLWriter] Found unknown geometry type.");
   1.497 -			}
   1.498 -			else
   1.499 -			{
   1.500 +				
   1.501 +			} else {
   1.502  				encoder.encode(geom, geometryType, baos);
   1.503  				geometry = baos.toString().substring(38).replaceAll(" xmlns:kml=\"http://earth.google.com/kml/2.1\"", "").replaceAll("kml:", "");
   1.504  
   1.505 -				if(geometryType == KML.MultiGeometry)
   1.506 -				{
   1.507 -					geometry = geometry.substring(geometry.indexOf("<MultiGeometry>") + 15, geometry.indexOf("</MultiGeometry>"));
   1.508 +				if (geometryType == KML.MultiGeometry) {
   1.509 +					geometry = geometry.substring(geometry.indexOf("<MultiGeometry>") + 15,	geometry.indexOf("</MultiGeometry>"));
   1.510  				}
   1.511 -/*				if(geom instanceof Point)
   1.512 -				{
   1.513 -					geometry = geometry.substring(geometry.indexOf("<Point>"), geometry.indexOf("</Point>") + 8);
   1.514 -				}
   1.515 -				else if(geom instanceof Polygon)
   1.516 -				{
   1.517 -					geometry = geometry.substring(geometry.indexOf("<Polygon>"), geometry.indexOf("</Polygon>") + 10);
   1.518 -				}
   1.519 -				else if(geom instanceof LineString)
   1.520 -				{
   1.521 -					geometry = geometry.substring(geometry.indexOf("<LineString>"), geometry.indexOf("</LineString>") + 13);
   1.522 -				}
   1.523 -				else if(geom instanceof MultiPoint)
   1.524 -				{
   1.525 -					geometry = geometry.substring(geometry.indexOf("<MultiPoint>"), geometry.indexOf("</MultiPoint>") + 13);
   1.526 -				}
   1.527 -				else if(geom instanceof MultiLineString)
   1.528 -				{
   1.529 -					geometry = geometry.substring(geometry.indexOf("<MultiLineString>"), geometry.indexOf("</MultiLineString>") + 18);
   1.530 -				}
   1.531 -				else if(geom instanceof MultiPolygon)
   1.532 -				{
   1.533 -					geometry = geometry.substring(geometry.indexOf("<MultiPolygon>"), geometry.indexOf("</MultiPolygon>") + 15);
   1.534 -				}
   1.535 -				else if(geom instanceof GeometryCollection)
   1.536 -				{
   1.537 -					geometry = geometry.substring(geometry.indexOf("<GeometryCollection>"), geometry.indexOf("</GeometryCollection>") + 21);
   1.538 -				}
   1.539 -*/				
   1.540 +				
   1.541 +				/*
   1.542 +				 * if(geom instanceof Point) { geometry =
   1.543 +				 * geometry.substring(geometry.indexOf("<Point>"),
   1.544 +				 * geometry.indexOf("</Point>") + 8); } else if(geom instanceof
   1.545 +				 * Polygon) { geometry =
   1.546 +				 * geometry.substring(geometry.indexOf("<Polygon>"),
   1.547 +				 * geometry.indexOf("</Polygon>") + 10); } else if(geom
   1.548 +				 * instanceof LineString) { geometry =
   1.549 +				 * geometry.substring(geometry.indexOf("<LineString>"),
   1.550 +				 * geometry.indexOf("</LineString>") + 13); } else if(geom
   1.551 +				 * instanceof MultiPoint) { geometry =
   1.552 +				 * geometry.substring(geometry.indexOf("<MultiPoint>"),
   1.553 +				 * geometry.indexOf("</MultiPoint>") + 13); } else if(geom
   1.554 +				 * instanceof MultiLineString) { geometry =
   1.555 +				 * geometry.substring(geometry.indexOf("<MultiLineString>"),
   1.556 +				 * geometry.indexOf("</MultiLineString>") + 18); } else if(geom
   1.557 +				 * instanceof MultiPolygon) { geometry =
   1.558 +				 * geometry.substring(geometry.indexOf("<MultiPolygon>"),
   1.559 +				 * geometry.indexOf("</MultiPolygon>") + 15); } else if(geom
   1.560 +				 * instanceof GeometryCollection) { geometry =
   1.561 +				 * geometry.substring(geometry.indexOf("<GeometryCollection>"),
   1.562 +				 * geometry.indexOf("</GeometryCollection>") + 21); }
   1.563 +				 */
   1.564  				baos.reset();
   1.565  			}
   1.566 -		}
   1.567 -		catch(ParseException e)
   1.568 -		{
   1.569 +		} catch (ParseException e) {
   1.570  			logger.error("[Strabon.KMLWriter] Parse error exception of geometry: {}", e.getMessage());
   1.571 -		}
   1.572 -		catch(IOException e)
   1.573 -		{
   1.574 -			logger.error("[Strabon.KMLWriter] IOException during KML encoding of geometry: {}", e.getMessage());
   1.575 -		}
   1.576 -		catch(JAXBException e)
   1.577 -		{
   1.578 +			
   1.579 +		} catch (IOException e) {
   1.580 +			logger.error("[Strabon.KMLWriter] IOException during KML encoding of geometry: {}",	e.getMessage());
   1.581 +			
   1.582 +		} catch (JAXBException e) {
   1.583  			logger.error("[Strabon.KMLWriter] Exception during GML parsing: {}", e.getMessage());
   1.584  		}
   1.585 +		
   1.586  		return geometry;
   1.587  	}
   1.588  
   1.589 @@ -448,8 +477,7 @@
   1.590  	 * 
   1.591  	 * @param binding
   1.592  	 */
   1.593 -	private void writeDesc(Binding binding)
   1.594 -	{
   1.595 +	private void writeDesc(Binding binding) {
   1.596  		descData.append(NEWLINE);
   1.597  		indent(descData, depth + 1);
   1.598  		descData.append(TABLE_ROW_BEGIN);
   1.599 @@ -457,8 +485,7 @@
   1.600  		descData.append(binding.getName());
   1.601  		descData.append(TABLE_DATA_END);
   1.602  		descData.append(TABLE_DATA_BEGIN);
   1.603 -		if(binding.getValue() instanceof BNode)
   1.604 -		{
   1.605 +		if (binding.getValue() instanceof BNode) {
   1.606  			descData.append("_:");
   1.607  		}
   1.608  		descData.append(binding.getValue().stringValue());
   1.609 @@ -466,8 +493,17 @@
   1.610  		descData.append(TABLE_ROW_END);
   1.611  	}
   1.612  
   1.613 -	@Override public TupleQueryResultFormat getTupleQueryResultFormat()
   1.614 -	{
   1.615 +	private String getBindingValue(Binding binding) {
   1.616 +		String val = binding.getValue().stringValue();
   1.617 +		if (binding.getValue() instanceof BNode) {
   1.618 +			val = "_:" + val;
   1.619 +		}
   1.620 +		
   1.621 +		return val;
   1.622 +	}
   1.623 +	
   1.624 +	@Override
   1.625 +	public TupleQueryResultFormat getTupleQueryResultFormat() {
   1.626  		return stSPARQLQueryResultFormat.KML;
   1.627  	}
   1.628  
   1.629 @@ -478,10 +514,8 @@
   1.630  	 * @param sb
   1.631  	 * @param depth
   1.632  	 */
   1.633 -	private void indent(StringBuilder sb, int depth)
   1.634 -	{
   1.635 -		for(int i = 0; i < depth; i++)
   1.636 -		{
   1.637 +	private void indent(StringBuilder sb, int depth) {
   1.638 +		for (int i = 0; i < depth; i++) {
   1.639  			sb.append(xmlWriter.getIndentString());
   1.640  		}
   1.641  	}