blob: f44699d0abe1e2612941ecf012adf46d339ae19f [file] [log] [blame]
/**
* 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.rya.indexing.geotemporal.mongo;
import static java.util.Objects.requireNonNull;
import java.util.Date;
import java.util.List;
import org.apache.rya.api.domain.RyaIRI;
import org.apache.rya.indexing.TemporalInstant;
import org.apache.rya.indexing.TemporalInstantRfc3339;
import org.apache.rya.indexing.TemporalInterval;
import org.apache.rya.indexing.entity.storage.mongo.DocumentConverter;
import org.apache.rya.indexing.geotemporal.model.Event;
import org.apache.rya.indexing.mongodb.geo.GeoMongoDBStorageStrategy;
import org.bson.Document;
import org.joda.time.DateTime;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateList;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
public class EventDocumentConverter implements DocumentConverter<Event>{
public static final String SUBJECT = "_id";
public static final String GEO_KEY = "location";
public static final String INTERVAL_START = "start";
public static final String INTERVAL_END = "end";
public static final String INSTANT = "instant";
private final GeoMongoDBStorageStrategy geoAdapter = new GeoMongoDBStorageStrategy(0.0);
@Override
public Document toDocument(final Event event) {
requireNonNull(event);
final Document doc = new Document();
doc.append(SUBJECT, event.getSubject().getData());
if(event.getGeometry().isPresent()) {
if (event.getGeometry().get().getNumPoints() > 1) {
doc.append(GEO_KEY, geoAdapter.getCorrespondingPoints(event.getGeometry().get()));
} else {
doc.append(GEO_KEY, geoAdapter.getDBPoint(event.getGeometry().get()));
}
}
if(event.isInstant()) {
if(event.getInstant().isPresent()) {
doc.append(INSTANT, event.getInstant().get().getAsDateTime().toDate());
}
} else {
if(event.getInterval().isPresent()) {
doc.append(INTERVAL_START, event.getInterval().get().getHasBeginning().getAsDateTime().toDate());
doc.append(INTERVAL_END, event.getInterval().get().getHasEnd().getAsDateTime().toDate());
}
}
return doc;
}
@Override
public Event fromDocument(final Document document) throws DocumentConverterException {
requireNonNull(document);
final boolean isInstant;
// Preconditions.
if(!document.containsKey(SUBJECT)) {
throw new DocumentConverterException("Could not convert document '" + document +
"' because its '" + SUBJECT + "' field is missing.");
}
if(document.containsKey(INSTANT)) {
isInstant = true;
} else {
isInstant = false;
}
final String subject = document.getString(SUBJECT);
final Event.Builder builder = new Event.Builder()
.setSubject(new RyaIRI(subject));
if(document.containsKey(GEO_KEY)) {
final Document geoObj = (Document) document.get(GEO_KEY);
final GeometryFactory geoFact = new GeometryFactory();
final String typeString = (String) geoObj.get("type");
final CoordinateList coords = new CoordinateList();
final Geometry geo;
if (typeString.equals("Point")) {
final List<Double> point = (List<Double>) geoObj.get("coordinates");
final Coordinate coord = new Coordinate(point.get(0), point.get(1));
geo = geoFact.createPoint(coord);
} else if (typeString.equals("LineString")) {
final List<List<Double>> pointsList = (List<List<Double>>) geoObj.get("coordinates");
for (final List<Double> point : pointsList) {
coords.add(new Coordinate(point.get(0), point.get(1)));
}
geo = geoFact.createLineString(coords.toCoordinateArray());
} else {
final List<List<List<Double>>> pointsList = (List<List<List<Double>>>) geoObj.get("coordinates");
if(pointsList.size() == 1) {
final List<List<Double>> poly = pointsList.get(0);
for (final List<Double> point : poly) {
coords.add(new Coordinate(point.get(0), point.get(1)));
}
geo = geoFact.createPolygon(coords.toCoordinateArray());
} else {
final List<List<Double>> first = pointsList.get(0);
final CoordinateList shellCoords = new CoordinateList();
for (final List<Double> point : pointsList.get(0)) {
shellCoords.add(new Coordinate(point.get(0), point.get(1)));
}
final LinearRing shell = geoFact.createLinearRing(shellCoords.toCoordinateArray());
final List<List<List<Double>>> holesPoints = pointsList.subList(1, pointsList.size() - 1);
final LinearRing[] holes = new LinearRing[holesPoints.size()];
for(int ii = 0; ii < holes.length; ii++) {
final List<List<Double>> holePoints = holesPoints.get(ii);
final CoordinateList shells = new CoordinateList();
for (final List<Double> point : pointsList.get(0)) {
shells.add(new Coordinate(point.get(0), point.get(1)));
}
holes[ii] = geoFact.createLinearRing(shells.toCoordinateArray());
}
geo = geoFact.createPolygon(shell,
holes);
}
}
builder.setGeometry(geo);
}
if(isInstant) {
//we already know the key exists
final Date date = (Date) document.get(INSTANT);
final DateTime dt = new DateTime(date.getTime());
final TemporalInstant instant = new TemporalInstantRfc3339(dt);
builder.setTemporalInstant(instant);
} else if(document.containsKey(INTERVAL_START)){
Date date = (Date) document.get(INTERVAL_START);
DateTime dt = new DateTime(date.getTime());
final TemporalInstant begining = new TemporalInstantRfc3339(dt);
date = (Date) document.get(INTERVAL_END);
dt = new DateTime(date.getTime());
final TemporalInstant end = new TemporalInstantRfc3339(dt);
final TemporalInterval interval = new TemporalInterval(begining, end);
builder.setTemporalInterval(interval);
}
return builder.build();
}
}