| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.olingo.client.core.serialization; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import javax.xml.stream.XMLEventReader; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.events.Attribute; |
| import javax.xml.stream.events.StartElement; |
| import javax.xml.stream.events.XMLEvent; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.olingo.commons.api.Constants; |
| import org.apache.olingo.commons.api.data.GeoUtils; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; |
| import org.apache.olingo.commons.api.edm.geo.Geospatial; |
| import org.apache.olingo.commons.api.edm.geo.GeospatialCollection; |
| import org.apache.olingo.commons.api.edm.geo.LineString; |
| import org.apache.olingo.commons.api.edm.geo.MultiLineString; |
| import org.apache.olingo.commons.api.edm.geo.MultiPoint; |
| import org.apache.olingo.commons.api.edm.geo.MultiPolygon; |
| import org.apache.olingo.commons.api.edm.geo.Point; |
| import org.apache.olingo.commons.api.edm.geo.Polygon; |
| import org.apache.olingo.commons.api.edm.geo.SRID; |
| import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble; |
| |
| class AtomGeoValueDeserializer { |
| |
| private List<Point> points(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| final List<Point> result = new ArrayList<Point>(); |
| |
| boolean foundEndProperty = false; |
| while (reader.hasNext() && !foundEndProperty) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) { |
| final String[] pointInfo = event.asCharacters().getData().split(" "); |
| |
| final Point point = new Point(GeoUtils.getDimension(type), srid); |
| try { |
| point.setX(EdmDouble.getInstance().valueOfString(pointInfo[0], null, null, |
| Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class)); |
| point.setY(EdmDouble.getInstance().valueOfString(pointInfo[1], null, null, |
| Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class)); |
| } catch (EdmPrimitiveTypeException e) { |
| throw new XMLStreamException("While deserializing point coordinates as double", e); |
| } |
| result.add(point); |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndProperty = true; |
| } |
| } |
| |
| // handles bad input, e.g. things like <gml:pos/> |
| if (result.isEmpty()) { |
| result.add(new Point(GeoUtils.getDimension(type), srid)); |
| } |
| |
| return result; |
| } |
| |
| private MultiPoint multipoint(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| List<Point> points = Collections.<Point> emptyList(); |
| |
| boolean foundEndProperty = false; |
| while (reader.hasNext() && !foundEndProperty) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_POINTMEMBERS)) { |
| points = points(reader, event.asStartElement(), type, null); |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndProperty = true; |
| } |
| } |
| |
| return new MultiPoint(GeoUtils.getDimension(type), srid, points); |
| } |
| |
| private LineString lineString(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| return new LineString(GeoUtils.getDimension(type), srid, points(reader, start, type, null)); |
| } |
| |
| private Polygon polygon(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| LineString extPoints = null; |
| List<LineString> intRings = new ArrayList<LineString>(); |
| |
| boolean foundEndProperty = false; |
| while (reader.hasNext() && !foundEndProperty) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isStartElement()) { |
| if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_EXTERIOR)) { |
| List<Point> points = points(reader, event.asStartElement(), type, null); |
| extPoints = new LineString(GeoUtils.getDimension(type), srid, points); |
| } |
| if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_INTERIOR)) { |
| List<Point> points = points(reader, event.asStartElement(), type, null); |
| intRings.add(new LineString(GeoUtils.getDimension(type), srid, points)); |
| } |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndProperty = true; |
| } |
| } |
| |
| return new Polygon(GeoUtils.getDimension(type), srid, intRings, extPoints); |
| } |
| |
| private MultiLineString multiLineString(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| final List<LineString> lineStrings = new ArrayList<LineString>(); |
| |
| boolean foundEndProperty = false; |
| while (reader.hasNext() && !foundEndProperty) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_LINESTRING)) { |
| lineStrings.add(lineString(reader, event.asStartElement(), type, null)); |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndProperty = true; |
| } |
| } |
| |
| return new MultiLineString(GeoUtils.getDimension(type), srid, lineStrings); |
| } |
| |
| private MultiPolygon multiPolygon(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| final List<Polygon> polygons = new ArrayList<Polygon>(); |
| |
| boolean foundEndProperty = false; |
| while (reader.hasNext() && !foundEndProperty) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_POLYGON)) { |
| polygons.add(polygon(reader, event.asStartElement(), type, null)); |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndProperty = true; |
| } |
| } |
| |
| return new MultiPolygon(GeoUtils.getDimension(type), srid, polygons); |
| } |
| |
| private GeospatialCollection collection(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { |
| |
| final List<Geospatial> geospatials = new ArrayList<Geospatial>(); |
| |
| boolean foundEndCollection = false; |
| while (reader.hasNext() && !foundEndCollection) { |
| final XMLEvent event = reader.nextEvent(); |
| |
| if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_GEOMEMBERS)) { |
| boolean foundEndMembers = false; |
| while (reader.hasNext() && !foundEndMembers) { |
| final XMLEvent subevent = reader.nextEvent(); |
| |
| if (subevent.isStartElement()) { |
| geospatials.add(deserialize(reader, subevent.asStartElement(), |
| GeoUtils.getType(GeoUtils.getDimension(type), subevent.asStartElement().getName().getLocalPart()))); |
| } |
| |
| if (subevent.isEndElement() && Constants.QNAME_GEOMEMBERS.equals(subevent.asEndElement().getName())) { |
| foundEndMembers = true; |
| } |
| } |
| } |
| |
| if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { |
| foundEndCollection = true; |
| } |
| } |
| |
| return new GeospatialCollection(GeoUtils.getDimension(type), srid, geospatials); |
| } |
| |
| public Geospatial deserialize(final XMLEventReader reader, final StartElement start, |
| final EdmPrimitiveTypeKind type) throws XMLStreamException { |
| |
| SRID srid = null; |
| final Attribute srsName = start.getAttributeByName(Constants.QNAME_ATTR_SRSNAME); |
| if (srsName != null) { |
| srid = SRID.valueOf(StringUtils.substringAfterLast(srsName.getValue(), "/")); |
| } |
| |
| Geospatial value; |
| |
| switch (type) { |
| case GeographyPoint: |
| case GeometryPoint: |
| value = points(reader, start, type, srid).get(0); |
| break; |
| |
| case GeographyMultiPoint: |
| case GeometryMultiPoint: |
| value = multipoint(reader, start, type, srid); |
| break; |
| |
| case GeographyLineString: |
| case GeometryLineString: |
| value = lineString(reader, start, type, srid); |
| break; |
| |
| case GeographyMultiLineString: |
| case GeometryMultiLineString: |
| value = multiLineString(reader, start, type, srid); |
| break; |
| |
| case GeographyPolygon: |
| case GeometryPolygon: |
| value = polygon(reader, start, type, srid); |
| break; |
| |
| case GeographyMultiPolygon: |
| case GeometryMultiPolygon: |
| value = multiPolygon(reader, start, type, srid); |
| break; |
| |
| case GeographyCollection: |
| case GeometryCollection: |
| value = collection(reader, start, type, srid); |
| break; |
| |
| default: |
| value = null; |
| } |
| |
| return value; |
| } |
| |
| } |