EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.value]

COVERAGE SUMMARY FOR SOURCE FILE [ValueGeometry.java]

nameclass, %method, %block, %line, %
ValueGeometry.java100% (2/2)97%  (32/33)93%  (254/272)88%  (56/64)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ValueGeometry100% (1/1)96%  (27/28)93%  (233/251)86%  (49/57)
set (PreparedStatement, int): void 0%   (0/1)0%   (0/6)0%   (0/2)
get (String): ValueGeometry 100% (1/1)69%  (9/13)50%  (2/4)
getGeometryNoCopy (): Geometry 100% (1/1)79%  (15/19)67%  (4/6)
get (String, int): ValueGeometry 100% (1/1)82%  (18/22)60%  (3/5)
ValueGeometry (byte [], Geometry): void 100% (1/1)100% (13/13)100% (5/5)
compareSecure (Value, CompareMode): int 100% (1/1)100% (9/9)100% (2/2)
convertTo (int): Value 100% (1/1)100% (9/9)100% (3/3)
convertToWKB (Geometry): byte [] 100% (1/1)100% (20/20)100% (4/4)
equals (Object): boolean 100% (1/1)100% (14/14)100% (1/1)
get (Geometry): ValueGeometry 100% (1/1)100% (11/11)100% (2/2)
get (byte []): ValueGeometry 100% (1/1)100% (8/8)100% (1/1)
getBytes (): byte [] 100% (1/1)100% (3/3)100% (1/1)
getBytesNoCopy (): byte [] 100% (1/1)100% (3/3)100% (1/1)
getDimensionCount (Geometry): int 100% (1/1)100% (14/14)100% (3/3)
getDisplaySize (): int 100% (1/1)100% (4/4)100% (1/1)
getEnvelopeUnion (ValueGeometry): Value 100% (1/1)100% (21/21)100% (4/4)
getFromGeometry (Object): ValueGeometry 100% (1/1)100% (4/4)100% (1/1)
getGeometry (): Geometry 100% (1/1)100% (5/5)100% (1/1)
getMemory (): int 100% (1/1)100% (8/8)100% (1/1)
getObject (): Object 100% (1/1)100% (3/3)100% (1/1)
getPrecision (): long 100% (1/1)100% (2/2)100% (1/1)
getSQL (): String 100% (1/1)100% (13/13)100% (1/1)
getString (): String 100% (1/1)100% (3/3)100% (1/1)
getType (): int 100% (1/1)100% (2/2)100% (1/1)
getWKB (): byte [] 100% (1/1)100% (3/3)100% (1/1)
getWKT (): String 100% (1/1)100% (8/8)100% (1/1)
hashCode (): int 100% (1/1)100% (3/3)100% (1/1)
intersectsBoundingBox (ValueGeometry): boolean 100% (1/1)100% (8/8)100% (1/1)
     
class ValueGeometry$ZVisitor100% (1/1)100% (5/5)100% (21/21)100% (7/7)
ValueGeometry$ZVisitor (): void 100% (1/1)100% (3/3)100% (1/1)
filter (CoordinateSequence, int): void 100% (1/1)100% (10/10)100% (3/3)
isDone (): boolean 100% (1/1)100% (3/3)100% (1/1)
isFoundZ (): boolean 100% (1/1)100% (3/3)100% (1/1)
isGeometryChanged (): boolean 100% (1/1)100% (2/2)100% (1/1)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.value;
7 
8import java.sql.PreparedStatement;
9import java.sql.SQLException;
10import java.util.Arrays;
11 
12import com.vividsolutions.jts.geom.CoordinateSequence;
13import com.vividsolutions.jts.geom.CoordinateSequenceFilter;
14import com.vividsolutions.jts.geom.PrecisionModel;
15import org.h2.message.DbException;
16import org.h2.util.StringUtils;
17import com.vividsolutions.jts.geom.Envelope;
18import com.vividsolutions.jts.geom.Geometry;
19import com.vividsolutions.jts.geom.GeometryFactory;
20import com.vividsolutions.jts.io.ParseException;
21import com.vividsolutions.jts.io.WKBReader;
22import com.vividsolutions.jts.io.WKBWriter;
23import com.vividsolutions.jts.io.WKTReader;
24import com.vividsolutions.jts.io.WKTWriter;
25 
26/**
27 * Implementation of the GEOMETRY data type.
28 *
29 * @author Thomas Mueller
30 * @author Noel Grandin
31 * @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
32 */
33public class ValueGeometry extends Value {
34 
35    /**
36     * As conversion from/to WKB cost a significant amount of CPU cycles, WKB
37     * are kept in ValueGeometry instance.
38     *
39     * We always calculate the WKB, because not all WKT values can be
40     * represented in WKB, but since we persist it in WKB format, it has to be
41     * valid in WKB
42     */
43    private final byte[] bytes;
44 
45    private final int hashCode;
46 
47    /**
48     * The value. Converted from WKB only on request as conversion from/to WKB
49     * cost a significant amount of CPU cycles.
50     */
51    private Geometry geometry;
52 
53    /**
54     * Create a new geometry objects.
55     *
56     * @param bytes the bytes (always known)
57     * @param geometry the geometry object (may be null)
58     */
59    private ValueGeometry(byte[] bytes, Geometry geometry) {
60        this.bytes = bytes;
61        this.geometry = geometry;
62        this.hashCode = Arrays.hashCode(bytes);
63    }
64 
65    /**
66     * Get or create a geometry value for the given geometry.
67     *
68     * @param o the geometry object (of type
69     *            com.vividsolutions.jts.geom.Geometry)
70     * @return the value
71     */
72    public static ValueGeometry getFromGeometry(Object o) {
73        return get((Geometry) o);
74    }
75 
76    private static ValueGeometry get(Geometry g) {
77        byte[] bytes = convertToWKB(g);
78        return (ValueGeometry) Value.cache(new ValueGeometry(bytes, g));
79    }
80 
81    private static byte[] convertToWKB(Geometry g) {
82        boolean includeSRID = g.getSRID() != 0;
83        int dimensionCount = getDimensionCount(g);
84        WKBWriter writer = new WKBWriter(dimensionCount, includeSRID);
85        return writer.write(g);
86    }
87 
88    private static int getDimensionCount(Geometry geometry) {
89        ZVisitor finder = new ZVisitor();
90        geometry.apply(finder);
91        return finder.isFoundZ() ? 3 : 2;
92    }
93 
94    /**
95     * Get or create a geometry value for the given geometry.
96     *
97     * @param s the WKT representation of the geometry
98     * @return the value
99     */
100    public static ValueGeometry get(String s) {
101        try {
102            Geometry g = new WKTReader().read(s);
103            return get(g);
104        } catch (ParseException ex) {
105            throw DbException.convert(ex);
106        }
107    }
108 
109    /**
110     * Get or create a geometry value for the given geometry.
111     *
112     * @param s the WKT representation of the geometry
113     * @param srid the srid of the object
114     * @return the value
115     */
116    public static ValueGeometry get(String s, int srid) {
117        try {
118            GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), srid);
119            Geometry g = new WKTReader(geometryFactory).read(s);
120            return get(g);
121        } catch (ParseException ex) {
122            throw DbException.convert(ex);
123        }
124    }
125 
126    /**
127     * Get or create a geometry value for the given geometry.
128     *
129     * @param bytes the WKB representation of the geometry
130     * @return the value
131     */
132    public static ValueGeometry get(byte[] bytes) {
133        return (ValueGeometry) Value.cache(new ValueGeometry(bytes, null));
134    }
135 
136    /**
137     * Get a copy of geometry object. Geometry object is mutable. The returned
138     * object is therefore copied before returning.
139     *
140     * @return a copy of the geometry object
141     */
142    public Geometry getGeometry() {
143        return (Geometry) getGeometryNoCopy().clone();
144    }
145 
146    public Geometry getGeometryNoCopy() {
147        if (geometry == null) {
148            try {
149                geometry = new WKBReader().read(bytes);
150            } catch (ParseException ex) {
151                throw DbException.convert(ex);
152            }
153        }
154        return geometry;
155    }
156 
157    /**
158     * Test if this geometry envelope intersects with the other geometry
159     * envelope.
160     *
161     * @param r the other geometry
162     * @return true if the two overlap
163     */
164    public boolean intersectsBoundingBox(ValueGeometry r) {
165        // the Geometry object caches the envelope
166        return getGeometryNoCopy().getEnvelopeInternal().intersects(
167                r.getGeometryNoCopy().getEnvelopeInternal());
168    }
169 
170    /**
171     * Get the union.
172     *
173     * @param r the other geometry
174     * @return the union of this geometry envelope and another geometry envelope
175     */
176    public Value getEnvelopeUnion(ValueGeometry r) {
177        GeometryFactory gf = new GeometryFactory();
178        Envelope mergedEnvelope = new Envelope(getGeometryNoCopy().getEnvelopeInternal());
179        mergedEnvelope.expandToInclude(r.getGeometryNoCopy().getEnvelopeInternal());
180        return get(gf.toGeometry(mergedEnvelope));
181    }
182 
183    @Override
184    public int getType() {
185        return Value.GEOMETRY;
186    }
187 
188    @Override
189    public String getSQL() {
190        // WKT does not hold Z or SRID with JTS 1.13. As getSQL is used to
191        // export database, it should contains all object attributes. Moreover
192        // using bytes is faster than converting WKB to Geometry then to WKT.
193        return "X'" + StringUtils.convertBytesToHex(getBytesNoCopy()) + "'::Geometry";
194    }
195 
196    @Override
197    protected int compareSecure(Value v, CompareMode mode) {
198        Geometry g = ((ValueGeometry) v).getGeometryNoCopy();
199        return getGeometryNoCopy().compareTo(g);
200    }
201 
202    @Override
203    public String getString() {
204        return getWKT();
205    }
206 
207    @Override
208    public long getPrecision() {
209        return 0;
210    }
211 
212    @Override
213    public int hashCode() {
214        return hashCode;
215    }
216 
217    @Override
218    public Object getObject() {
219        return getGeometry();
220    }
221 
222    @Override
223    public byte[] getBytes() {
224        return getWKB();
225    }
226 
227    @Override
228    public byte[] getBytesNoCopy() {
229        return getWKB();
230    }
231 
232    @Override
233    public void set(PreparedStatement prep, int parameterIndex)
234            throws SQLException {
235        prep.setObject(parameterIndex, getGeometryNoCopy());
236    }
237 
238    @Override
239    public int getDisplaySize() {
240        return getWKT().length();
241    }
242 
243    @Override
244    public int getMemory() {
245        return getWKB().length * 20 + 24;
246    }
247 
248    @Override
249    public boolean equals(Object other) {
250        // The JTS library only does half-way support for 3D coordinates, so
251        // their equals method only checks the first two coordinates.
252        return other instanceof ValueGeometry &&
253                Arrays.equals(getWKB(), ((ValueGeometry) other).getWKB());
254    }
255 
256    /**
257     * Get the value in Well-Known-Text format.
258     *
259     * @return the well-known-text
260     */
261    public String getWKT() {
262        return new WKTWriter(3).write(getGeometryNoCopy());
263    }
264 
265    /**
266     * Get the value in Well-Known-Binary format.
267     *
268     * @return the well-known-binary
269     */
270    public byte[] getWKB() {
271        return bytes;
272    }
273 
274    @Override
275    public Value convertTo(int targetType) {
276        if (targetType == Value.JAVA_OBJECT) {
277            return this;
278        }
279        return super.convertTo(targetType);
280    }
281 
282    /**
283     * A visitor that checks if there is a Z coordinate.
284     */
285    static class ZVisitor implements CoordinateSequenceFilter {
286        boolean foundZ;
287 
288        public boolean isFoundZ() {
289            return foundZ;
290        }
291 
292        @Override
293        public void filter(CoordinateSequence coordinateSequence, int i) {
294            if (!Double.isNaN(coordinateSequence.getOrdinate(i, 2))) {
295                foundZ = true;
296            }
297        }
298 
299        @Override
300        public boolean isDone() {
301            return foundZ;
302        }
303 
304        @Override
305        public boolean isGeometryChanged() {
306            return false;
307        }
308 
309    }
310 
311}

[all classes][org.h2.value]
EMMA 2.0.5312 (C) Vladimir Roubtsov