Skip to content

Commit 078b712

Browse files
author
Jake Kenneally
committed
still a work in progress
1 parent 48b0a7f commit 078b712

File tree

10 files changed

+526
-22
lines changed

10 files changed

+526
-22
lines changed

geomesa-core/src/main/scala/org/locationtech/geomesa/core/index/IndexEntry.scala

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.locationtech.geomesa.core.index
22

33
import java.nio.ByteBuffer
4-
54
import com.typesafe.scalalogging.slf4j.Logging
65
import com.vividsolutions.jts.geom.Geometry
76
import org.apache.accumulo.core.data.{Key, Value}
@@ -13,7 +12,6 @@ import org.locationtech.geomesa.core.data.{DATA_CQ, SimpleFeatureEncoder}
1312
import org.locationtech.geomesa.utils.geohash.{GeoHash, GeohashUtils}
1413
import org.locationtech.geomesa.utils.text.WKBUtils
1514
import org.opengis.feature.simple.SimpleFeature
16-
1715
import scala.collection.JavaConversions._
1816

1917
object IndexEntry {
@@ -55,15 +53,30 @@ object IndexEntry {
5553
val encodedDtg = entry.dt.map(dtg => ByteBuffer.allocate(8).putLong(dtg.getMillis).array()).getOrElse(Array[Byte]())
5654

5755
new Value(
58-
ByteBuffer.allocate(4).putInt(encodedId.length).array() ++ encodedId ++
59-
ByteBuffer.allocate(4).putInt(encodedGeom.length).array() ++ encodedGeom ++
60-
encodedDtg)
56+
ByteBuffer.allocate(4).putInt(encodedId.length).array() ++ encodedId ++
57+
ByteBuffer.allocate(4).putInt(encodedGeom.length).array() ++ encodedGeom ++
58+
encodedDtg)
6159
}
6260

63-
def decodeIndexValue(v: Value): DecodedIndexValue = {
64-
val buf = v.get()
65-
val idLength = ByteBuffer.wrap(buf, 0, 4).getInt
66-
val (idPortion, geomDatePortion) = buf.drop(4).splitAt(idLength)
61+
// the metadata CQ consists of the feature's:
62+
// 1. ID
63+
// 2. WKB-encoded geometry
64+
// 3. start-date/time
65+
def encodeIndexCQMetadataKey(entry: SimpleFeature): Key = {
66+
val encodedId = entry.sid.getBytes
67+
val encodedGeom = WKBUtils.write(entry.geometry)
68+
val encodedDtg = entry.dt.map(dtg => ByteBuffer.allocate(8).putLong(dtg.getMillis).array()).getOrElse(Array[Byte]())
69+
val EMPTY_BYTES = Array.emptyByteArray
70+
val cqByteArray = ByteBuffer.allocate(4).putInt(encodedId.length).array() ++ encodedId ++
71+
ByteBuffer.allocate(4).putInt(encodedGeom.length).array() ++ encodedGeom ++
72+
encodedDtg
73+
74+
new Key(EMPTY_BYTES, EMPTY_BYTES, cqByteArray, EMPTY_BYTES, Long.MaxValue)
75+
}
76+
77+
def byteArrayToDecodedIndexValue(b: Array[Byte]): DecodedIndexValue = {
78+
val idLength = ByteBuffer.wrap(b, 0, 4).getInt
79+
val (idPortion, geomDatePortion) = b.drop(4).splitAt(idLength)
6780
val id = new String(idPortion)
6881
val geomLength = ByteBuffer.wrap(geomDatePortion, 0, 4).getInt
6982
if(geomLength < (geomDatePortion.length - 4)) {
@@ -74,7 +87,34 @@ object IndexEntry {
7487
}
7588
}
7689

90+
def byteArrayToDecodedMetadata(b: Array[Byte]): DecodedCQMetadata = {
91+
// This will need to conform to some decided CQ format ie: gh(x,y) ~ metadata
92+
// meta data being: id, geom, and time. below time is optional, may want to eliminate this choice
93+
val idLength = ByteBuffer.wrap(b, 0, 4).getInt
94+
val (idPortion, geomDatePortion) = b.drop(4).splitAt(idLength)
95+
val id = new String(idPortion)
96+
val geomLength = ByteBuffer.wrap(geomDatePortion, 0, 4).getInt
97+
if(geomLength < (geomDatePortion.length - 4)) {
98+
val (l,r) = geomDatePortion.drop(4).splitAt(geomLength)
99+
DecodedCQMetadata(id, WKBUtils.read(l), Some(ByteBuffer.wrap(r).getLong))
100+
} else {
101+
DecodedCQMetadata(id, WKBUtils.read(geomDatePortion.drop(4)), None)
102+
}
103+
}
104+
105+
def decodeIndexValue(v: Value): DecodedIndexValue = {
106+
val buf = v.get()
107+
byteArrayToDecodedIndexValue(buf)
108+
}
109+
77110
case class DecodedIndexValue(id: String, geom: Geometry, dtgMillis: Option[Long])
111+
112+
def decodeIndexCQMetadata(k: Key): DecodedCQMetadata = {
113+
val cqd = k.getColumnQualifierData.toArray
114+
byteArrayToDecodedMetadata(cqd)
115+
}
116+
117+
case class DecodedCQMetadata(id: String, geom: Geometry, dtgMillis: Option[Long])
78118
}
79119

80120
case class IndexEntryEncoder(rowf: TextFormatter,
@@ -144,7 +184,7 @@ object IndexEntryDecoder {
144184
}
145185
}
146186

147-
import org.locationtech.geomesa.core.index.IndexEntryDecoder._
187+
import IndexEntryDecoder._
148188

149189
case class IndexEntryDecoder(ghDecoder: GeohashDecoder, dtDecoder: Option[DateDecoder]) {
150190
def decode(key: Key) = {
@@ -154,3 +194,21 @@ case class IndexEntryDecoder(ghDecoder: GeohashDecoder, dtDecoder: Option[DateDe
154194
builder.buildFeature("")
155195
}
156196
}
197+
198+
object IndexCQMetadataDecoder {
199+
val metaBuilder = new ThreadLocal[SimpleFeatureBuilder] {
200+
override def initialValue(): SimpleFeatureBuilder = new SimpleFeatureBuilder(indexSFT)
201+
}
202+
}
203+
204+
import IndexCQMetadataDecoder._
205+
206+
case class IndexCQMetadataDecoder(ghDecoder: GeohashDecoder, dtDecoder: Option[DateDecoder]) {
207+
// are we grabbing the right stuff from the key?
208+
def decode(key: Key) = {
209+
val builder = metaBuilder.get
210+
builder.reset()
211+
builder.addAll(List(ghDecoder.decode(key).geom, dtDecoder.map(_.decode(key))))
212+
builder.buildFeature("")
213+
}
214+
}

geomesa-plugin/dev-scripts/run.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
if [ "$1" = "--debug" ]; then
2-
GEO_DEBUG="jpda"
3-
fi
41
pushd $CATALINA_HOME/bin
5-
./catalina.sh $GEO_DEBUG run
2+
./catalina.sh jpda run
63
popd
74

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
org.locationtech.geomesa.plugin.wms.CoverageFormatFactory
1+
org.locationtech.geomesa.plugin.wms.CoverageFormatFactory
2+
org.locationtech.geomesa.plugin.wcs.AccumuloCoverageFormatFactory

geomesa-plugin/src/main/resources/applicationContext.xml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</property>
3131
</bean>
3232

33-
<bean id="accumuloDataStorePanel" class="org.geoserver.web.data.resource.DataStorePanelInfo">
33+
<bean id="accumuloDataStorePanel" class="org.geoserver.web.data.resource.DataStorePanelInfo">
3434
<property name="id" value="accumuloDataStorePanel"/>
3535
<property name="factoryClass" value="org.locationtech.geomesa.core.data.AccumuloDataStoreFactory"/>
3636
<property name="iconBase" value="org.geoserver.web.GeoServerApplication"/>
@@ -39,16 +39,23 @@
3939
value="org.locationtech.geomesa.plugin.wfs.AccumuloDataStoreEditPanel"/>
4040
</bean>
4141

42-
<bean id="accumuloCoverageStorePanel"
43-
class="org.geoserver.web.data.resource.DataStorePanelInfo">
44-
<property name="id" value="accumulo"/>
42+
<bean id="coverageStorePanel" class="org.geoserver.web.data.resource.DataStorePanelInfo">
43+
<property name="id" value="coverageStorePanel"/>
4544
<property name="factoryClass" value="org.locationtech.geomesa.plugin.wms.CoverageFormat"/>
4645
<property name="iconBase" value="org.geoserver.web.GeoServerApplication"/>
4746
<property name="icon" value="img/icons/geosilk/database_raster.png"/>
4847
<property name="componentClass"
4948
value="org.locationtech.geomesa.plugin.wms.CoverageStoreEditPanel"/>
5049
</bean>
5150

51+
<bean id="accumuloCoverageStorePanel" class="org.geoserver.web.data.resource.DataStorePanelInfo">
52+
<property name="id" value="accumuloCoverageStorePanel"/>
53+
<property name="factoryClass" value="org.locationtech.geomesa.plugin.wcs.AccumuloCoverageFormat"/>
54+
<property name="iconBase" value="org.geoserver.web.GeoServerApplication"/>
55+
<property name="icon" value="img/icons/geosilk/database_raster.png"/>
56+
<property name="componentClass" value="org.locationtech.geomesa.plugin.wcs.AccumuloCoverageStoreEditPanel"/>
57+
</bean>
58+
5259
<bean id="geomesaProcessFactory" class="org.locationtech.geomesa.plugin.wps.GeomesaProcessFactory">
5360
<constructor-arg index="0" value="Geomesa Processes"/>
5461
<constructor-arg index="1" value="geomesa"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!--
2+
~ Copyright 2014 Commonwealth Computer Research, Inc.
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<html xmlns:wicket="http://wicket.apache.org/">
18+
<body>
19+
<wicket:panel>
20+
<fieldset>
21+
<legend>
22+
<span>
23+
<wicket:message key="connectionParameters">
24+
Connection Parameters
25+
</wicket:message>
26+
</span>
27+
</legend>
28+
<div>
29+
<span wicket:id="instanceId"></span>
30+
</div>
31+
<div>
32+
<span wicket:id="zookeepers"></span>
33+
</div>
34+
<div>
35+
<span wicket:id="user"></span>
36+
</div>
37+
<div>
38+
<span wicket:id="password"></span>
39+
</div>
40+
<div>
41+
<span wicket:id="authTokens"></span>
42+
</div>
43+
<div>
44+
<span wicket:id="tableName"></span>
45+
</div>
46+
<div>
47+
<span wicket:id="columnFamily"></span>
48+
</div>
49+
<div>
50+
<span wicket:id="columnQualifier"></span>
51+
</div>
52+
<div>
53+
<span wicket:id="resolution"></span>
54+
</div>
55+
</fieldset>
56+
</wicket:panel>
57+
</body>
58+
</html>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.locationtech.geomesa.plugin.wcs
2+
3+
import java.io.File
4+
5+
import org.geotools.coverage.grid.io.AbstractGridFormat
6+
import org.geotools.coverage.grid.io.AbstractGridFormat._
7+
import org.geotools.factory.Hints
8+
import org.geotools.parameter.{DefaultParameterDescriptorGroup, ParameterGroup}
9+
import org.opengis.coverage.grid.Format
10+
import org.opengis.parameter.GeneralParameterDescriptor
11+
12+
class AccumuloCoverageFormat extends AbstractGridFormat() with Format {
13+
mInfo = new java.util.HashMap[String, String]()
14+
mInfo.put("name", "New Accumulo Coverage Format")
15+
mInfo.put("description", "Serve tile imagery from Accumulo tables with a specific format")
16+
mInfo.put("vendor", "CCRI")
17+
mInfo.put("docURL", "http://www.ccri.com")
18+
mInfo.put("version", "2.0")
19+
val parameterDescriptors =
20+
Array[GeneralParameterDescriptor](READ_GRIDGEOMETRY2D, TIME)
21+
22+
val defaultParameterGroup = new DefaultParameterDescriptorGroup(mInfo, parameterDescriptors)
23+
24+
readParameters = new ParameterGroup(defaultParameterGroup)
25+
writeParameters = null
26+
27+
override def getReader(source: AnyRef) = getReader(source, null)
28+
override def getReader(source: AnyRef, hints: Hints) = source match {
29+
case file: File => new AccumuloCoverageReader(file.getPath, hints)
30+
case path: String => new AccumuloCoverageReader(path, hints)
31+
case unk => throw new Exception(s"unexpected data type for reader source: ${Option(unk).map(_.getClass.getName).getOrElse("null")}")
32+
}
33+
override def accepts(input: AnyRef) = true
34+
override def accepts(source: AnyRef, hints: Hints) = true
35+
override def getWriter(destination: AnyRef) = throw new UnsupportedOperationException("Unsupported")
36+
override def getWriter(destination: AnyRef, hints: Hints) = throw new UnsupportedOperationException("Unsupported")
37+
override def getDefaultImageIOWriteParameters = throw new UnsupportedOperationException("Unsupported")
38+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2013 Commonwealth Computer Research, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.locationtech.geomesa.plugin.wcs
18+
19+
import java.awt.RenderingHints
20+
import java.util.Collections
21+
22+
import org.geotools.coverage.grid.io.{AbstractGridFormat, GridFormatFactorySpi}
23+
24+
class AccumuloCoverageFormatFactory extends GridFormatFactorySpi {
25+
def isAvailable = true
26+
27+
def createFormat(): AbstractGridFormat = new AccumuloCoverageFormat
28+
29+
def getImplementationHints: java.util.Map[RenderingHints.Key, _] = Collections.emptyMap()
30+
31+
}

0 commit comments

Comments
 (0)