You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by kw...@apache.org on 2017/08/23 14:29:48 UTC
lucene-solr:master: LUCENE-7936: Add Geo3d framework for
serialization and deserialization.
Repository: lucene-solr
Updated Branches:
refs/heads/master 19a8be3c9 -> 6b8f98db9
LUCENE-7936: Add Geo3d framework for serialization and deserialization.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/6b8f98db
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/6b8f98db
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/6b8f98db
Branch: refs/heads/master
Commit: 6b8f98db93689370a6df47a8645c80b1b0b39480
Parents: 19a8be3
Author: Karl Wright <Da...@gmail.com>
Authored: Wed Aug 23 10:00:31 2017 -0400
Committer: Karl Wright <Da...@gmail.com>
Committed: Wed Aug 23 10:00:31 2017 -0400
----------------------------------------------------------------------
.../lucene/spatial3d/geom/BasePlanetObject.java | 12 +-
.../spatial3d/geom/GeoDegeneratePoint.java | 15 +-
.../apache/lucene/spatial3d/geom/GeoPoint.java | 24 ++-
.../lucene/spatial3d/geom/PlanetObject.java | 1 +
.../spatial3d/geom/SerializableObject.java | 200 +++++++++++++++++++
5 files changed, 248 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6b8f98db/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
index 13072fe..86ec61f 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
@@ -16,13 +16,16 @@
*/
package org.apache.lucene.spatial3d.geom;
+import java.io.OutputStream;
+import java.io.IOException;
+
/**
* All Geo3D shapes can derive from this base class, which furnishes
* some common code
*
* @lucene.internal
*/
-public abstract class BasePlanetObject implements PlanetObject {
+public abstract class BasePlanetObject implements PlanetObject, SerializableObject {
/** This is the planet model embedded in all objects derived from this
* class. */
@@ -41,6 +44,11 @@ public abstract class BasePlanetObject implements PlanetObject {
}
@Override
+ public void write(final OutputStream outputStream) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public int hashCode() {
return planetModel.hashCode();
}
@@ -51,6 +59,8 @@ public abstract class BasePlanetObject implements PlanetObject {
return false;
return planetModel.equals(((BasePlanetObject)o).planetModel);
}
+
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6b8f98db/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
index 93d4708..8a96fdf 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
@@ -15,7 +15,10 @@
* limitations under the License.
*/
package org.apache.lucene.spatial3d.geom;
-
+
+import java.io.InputStream;
+import java.io.IOException;
+
/**
* This class represents a degenerate point bounding box.
* It is not a simple GeoPoint because we must have the latitude and longitude.
@@ -39,6 +42,16 @@ class GeoDegeneratePoint extends GeoPoint implements GeoBBox, GeoCircle {
this.edgePoints = new GeoPoint[]{this};
}
+ /** Constructor for deserialization.
+ *@param planetModel is the planet model to use.
+ *@param inputStream is the input stream.
+ */
+ public GeoDegeneratePoint(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
+ super(planetModel, inputStream);
+ this.planetModel = planetModel;
+ this.edgePoints = new GeoPoint[]{this};
+ }
+
@Override
public PlanetModel getPlanetModel() {
return planetModel;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6b8f98db/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
index a63dd8f..de51a2b 100755
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
@@ -15,13 +15,17 @@
* limitations under the License.
*/
package org.apache.lucene.spatial3d.geom;
-
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
/**
* This class represents a point on the surface of a sphere or ellipsoid.
*
* @lucene.experimental
*/
-public class GeoPoint extends Vector {
+public class GeoPoint extends Vector implements SerializableObject {
// By making lazily-evaluated variables be "volatile", we guarantee atomicity when they
// are updated. This is necessary if we are using these classes in a multi-thread fashion,
@@ -73,6 +77,14 @@ public class GeoPoint extends Vector {
this(planetModel, Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon), lat, lon);
}
+ /** Construct a GeoPoint from a planet model and an input stream.
+ */
+ public GeoPoint(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
+ // Note: this relies on left-right parameter execution order!! Much code depends on that though and
+ // it is apparently in a java spec: https://stackoverflow.com/questions/2201688/order-of-execution-of-parameters-guarantees-in-java
+ this(planetModel, SerializableObject.readDouble(inputStream), SerializableObject.readDouble(inputStream));
+ }
+
/** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
* @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
* @param x is the unit x value.
@@ -115,6 +127,12 @@ public class GeoPoint extends Vector {
super(x, y, z);
}
+ @Override
+ public void write(final OutputStream outputStream) throws IOException {
+ SerializableObject.writeDouble(outputStream, getLatitude());
+ SerializableObject.writeDouble(outputStream, getLongitude());
+ }
+
/** Compute an arc distance between two points.
* Note: this is an angular distance, and not a surface distance, and is therefore independent of planet model.
* For surface distance, see {@link PlanetModel#surfaceDistance(GeoPoint, GeoPoint)}
@@ -190,4 +208,6 @@ public class GeoPoint extends Vector {
}
return "[lat="+getLatitude()+", lon="+getLongitude()+"("+super.toString()+")]";
}
+
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6b8f98db/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetObject.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetObject.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetObject.java
index 05ed7b1..836bf4c 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetObject.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetObject.java
@@ -26,4 +26,5 @@ public interface PlanetObject {
/** Returns the {@link PlanetModel} provided when this shape was created. */
PlanetModel getPlanetModel();
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6b8f98db/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SerializableObject.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SerializableObject.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SerializableObject.java
new file mode 100644
index 0000000..618ebaf
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SerializableObject.java
@@ -0,0 +1,200 @@
+/*
+ * 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.lucene.spatial3d.geom;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Indicates that a geo3d object can be serialized and deserialized.
+ *
+ * @lucene.experimental
+ */
+public interface SerializableObject {
+
+ /** Serialize to output stream.
+ * @param outputStream is the output stream to write to.
+ */
+ void write(OutputStream outputStream) throws IOException;
+
+ /** Write an object to a stream.
+ * @param outputStream is the output stream.
+ * @param object is the object to write.
+ */
+ static void writeObject(final OutputStream outputStream, final SerializableObject object) throws IOException {
+ writeString(outputStream, object.getClass().getName());
+ object.write(outputStream);
+ }
+
+ /** Read an object from a stream (for objects that need a PlanetModel).
+ * @param planetModel is the planet model to use to deserialize the object.
+ * @param inputStream is the input stream.
+ * @return the deserialized object.
+ */
+ static SerializableObject readObject(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
+ // Read the class name
+ final String className = readString(inputStream);
+ try {
+ // Look for the class
+ final Class<?> clazz = Class.forName(className);
+ // Look for the right constructor
+ final Constructor<?> c = clazz.getDeclaredConstructor(PlanetModel.class, InputStream.class);
+ // Invoke it
+ final Object object = c.newInstance(planetModel, inputStream);
+ // check whether caste will work
+ if (!(object instanceof SerializableObject)) {
+ throw new IOException("Object "+className+" does not implement SerializableObject");
+ }
+ return (SerializableObject)object;
+ } catch (ClassNotFoundException e) {
+ throw new IOException("Can't find class "+className+" for deserialization: "+e.getMessage(), e);
+ } catch (InstantiationException e) {
+ throw new IOException("Instantiation exception for class "+className+": "+e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new IOException("Illegal access creating class "+className+": "+e.getMessage(), e);
+ } catch (NoSuchMethodException e) {
+ throw new IOException("No such method exception for class "+className+": "+e.getMessage(), e);
+ } catch (InvocationTargetException e) {
+ throw new IOException("Exception instantiating class "+className+": "+e.getMessage(), e);
+ }
+ }
+
+ /** Read an object from a stream (for objects that do not need a PlanetModel).
+ * @param inputStream is the input stream.
+ * @return the deserialized object.
+ */
+ static SerializableObject readObject(final InputStream inputStream) throws IOException {
+ // Read the class name
+ final String className = readString(inputStream);
+ try {
+ // Look for the class
+ final Class<?> clazz = Class.forName(className);
+ // Look for the right constructor
+ final Constructor<?> c = clazz.getDeclaredConstructor(InputStream.class);
+ // Invoke it
+ final Object object = c.newInstance(inputStream);
+ // check whether caste will work
+ if (!(object instanceof SerializableObject)) {
+ throw new IOException("Object "+className+" does not implement SerializableObject");
+ }
+ return (SerializableObject)object;
+ } catch (ClassNotFoundException e) {
+ throw new IOException("Can't find class "+className+" for deserialization: "+e.getMessage(), e);
+ } catch (InstantiationException e) {
+ throw new IOException("Instantiation exception for class "+className+": "+e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new IOException("Illegal access creating class "+className+": "+e.getMessage(), e);
+ } catch (NoSuchMethodException e) {
+ throw new IOException("No such method exception for class "+className+": "+e.getMessage(), e);
+ } catch (InvocationTargetException e) {
+ throw new IOException("Exception instantiating class "+className+": "+e.getMessage(), e);
+ }
+ }
+
+ /** Write a string to a stream.
+ * @param outputStream is the output stream.
+ * @param value is the string to write.
+ */
+ static void writeString(final OutputStream outputStream, final String value) throws IOException {
+ final byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
+ writeInt(outputStream, bytes.length);
+ outputStream.write(bytes);
+ }
+
+ /** Read a string from a stream.
+ * @param inputStream is the stream to read from.
+ * @return the string that was read.
+ */
+ static String readString(final InputStream inputStream) throws IOException {
+ int stringLength = readInt(inputStream);
+ int stringOffset = 0;
+ final byte[] bytes = new byte[stringLength];
+ while (stringLength > 0) {
+ final int amt = inputStream.read(bytes, stringOffset, stringLength);
+ if (amt == -1) {
+ throw new IOException("Unexpected end of input stream");
+ }
+ stringOffset += amt;
+ stringLength -= amt;
+ }
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+
+ /** Write a double to a stream.
+ * @param outputStream is the output stream.
+ * @param value is the value to write.
+ */
+ static void writeDouble(final OutputStream outputStream, final double value) throws IOException {
+ writeLong(outputStream, Double.doubleToLongBits(value));
+ }
+
+ /** Read a double from a stream.
+ * @param inputStream is the input stream.
+ * @return the double value read from the stream.
+ */
+ static double readDouble(final InputStream inputStream) throws IOException {
+ return Double.longBitsToDouble(readLong(inputStream));
+ }
+
+ /** Write a long to a stream.
+ * @param outputStream is the output stream.
+ * @param value is the value to write.
+ */
+ static void writeLong(final OutputStream outputStream, final long value) throws IOException {
+ writeInt(outputStream, (int)value);
+ writeInt(outputStream, (int)(value >> 32));
+ }
+
+ /** Read a long from a stream.
+ * @param inputStream is the input stream.
+ * @return the long value read from the stream.
+ */
+ static long readLong(final InputStream inputStream) throws IOException {
+ final long lower = ((long)(readInt(inputStream))) & 0x00000000ffffffffL;
+ final long upper = (((long)(readInt(inputStream))) << 32) & 0xffffffff00000000L;
+ return lower + upper;
+ }
+
+ /** Write an int to a stream.
+ * @param outputStream is the output stream.
+ * @param value is the value to write.
+ */
+ static void writeInt(final OutputStream outputStream, final int value) throws IOException {
+ outputStream.write(value);
+ outputStream.write(value >> 8);
+ outputStream.write(value >> 16);
+ outputStream.write(value >> 24);
+ }
+
+ /** Read an int from a stream.
+ * @param inputStream is the input stream.
+ * @return the value read from the stream.
+ */
+ static int readInt(final InputStream inputStream) throws IOException {
+ final int l1 = (inputStream.read()) & 0x000000ff;
+ final int l2 = (inputStream.read() << 8) & 0x0000ff00;
+ final int l3 = (inputStream.read() << 16) & 0x00ff0000;
+ final int l4 = (inputStream.read() << 24) & 0xff000000;
+ return l1 + l2 + l3 + l4;
+ }
+
+}