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;
+  }
+
+}