NestedGroupCentroidAssignment { public double findCentroidForLevel( final AnalyticItemWrapper<T> item, final AssociationNotification<T> associationNotification) throws IOException { final GroupHolder group = new GroupHolder(); group.setGroupID(item.getGroupID()); double currentDistance = Double.NaN; int currentLevel = item.getZoomLevel(); boolean atEndLevel = false; while (!atEndLevel) { final boolean reachedEndLevel = currentLevel == endZoomLevel; atEndLevel = reachedEndLevel; final List<AnalyticItemWrapper<T>> centroids = (currentLevel == endZoomLevel) ? centroidManager.getCentroidsForGroup(group.getGroupID()) : centroidManager.getCentroidsForGroup(parentBatchID, group.getGroupID()); if (centroids.size() == 0) { throw new IOException("Cannot find group " + group.getGroupID()); } currentDistance = associationdFunction.compute(item, centroids, new AssociationNotification<T>() { @Override public void notify(final CentroidPairing<T> pairing) { group.setGroupID(pairing.getCentroid().getID()); if (reachedEndLevel) { associationNotification.notify(pairing); } } }); currentLevel = centroids.get(0).getZoomLevel() + 1; } return currentDistance; } NestedGroupCentroidAssignment(
      final CentroidManager<T> centroidManager,
      final int endZoomLevel,
      final String parentBatchID,
      final DistanceFn<T> distanceFunction);  NestedGroupCentroidAssignment(
      final JobContext context,
      final Class<?> scope,
      final Logger logger); static void setZoomLevel(
      final Configuration config,
      final Class<?> scope,
      final int zoomLevel); static void setParentBatchID(
      final Configuration config,
      final Class<?> scope,
      final String parentID); static Collection<ParameterEnum<?>> getParameters(); List<AnalyticItemWrapper<T>> getCentroidsForGroup(final String groupID); String getGroupForLevel(final AnalyticItemWrapper<T> item); double findCentroidForLevel(
      final AnalyticItemWrapper<T> item,
      final AssociationNotification<T> associationNotification); static void setParameters(
      final Configuration config,
      final Class<?> scope,
      final PropertyManagement runTimeProperties);  }
@Test public void test() throws IOException { final SimpleFeatureType ftype = AnalyticFeature.createGeometryFeatureAdapter( "centroid", new String[] {"extra1"}, BasicFeatureTypes.DEFAULT_NAMESPACE, ClusteringUtils.CLUSTERING_CRS).getFeatureType(); final GeometryFactory factory = new GeometryFactory(); final String grp1 = "g1"; final String grp2 = "g2"; final SimpleFeature level1b1G1Feature = AnalyticFeature.createGeometryFeature( ftype, "b1", "level1b1G1Feature", "fred", grp1, 20.30203, factory.createPoint(new Coordinate(02.5, 0.25)), new String[] {"extra1"}, new double[] {0.022}, 1, 1, 0); final Index index = new SpatialDimensionalityTypeProvider().createIndex(new SpatialOptions()); final FeatureDataAdapter adapter = new FeatureDataAdapter(ftype); adapter.init(index); final String namespace = "test_" + getClass().getName() + "_" + name.getMethodName(); final StoreFactoryFamilySpi storeFamily = new MemoryStoreFactoryFamily(); final StoreFactoryOptions opts = storeFamily.getDataStoreFactory().createOptionsInstance(); opts.setGeoWaveNamespace(namespace); final DataStorePluginOptions storePluginOptions = new DataStorePluginOptions(opts); final DataStore dataStore = storeFamily.getDataStoreFactory().createStore(opts); final IndexStore indexStore = storeFamily.getIndexStoreFactory().createStore(opts); final PersistentAdapterStore adapterStore = storeFamily.getAdapterStoreFactory().createStore(opts); ingest(dataStore, adapter, index, level1b1G1Feature); final SimpleFeature level1b1G2Feature = AnalyticFeature.createGeometryFeature( ftype, "b1", "level1b1G2Feature", "flood", grp2, 20.30203, factory.createPoint(new Coordinate(02.03, 0.2)), new String[] {"extra1"}, new double[] {0.022}, 1, 1, 0); ingest(dataStore, adapter, index, level1b1G2Feature); final SimpleFeature level2b1G1Feature = AnalyticFeature.createGeometryFeature( ftype, "b1", "level2b1G1Feature", "flou", level1b1G1Feature.getID(), 20.30203, factory.createPoint(new Coordinate(02.5, 0.25)), new String[] {"extra1"}, new double[] {0.022}, 2, 1, 0); ingest(dataStore, adapter, index, level2b1G1Feature); final SimpleFeature level2b1G2Feature = AnalyticFeature.createGeometryFeature( ftype, "b1", "level2b1G2Feature", "flapper", level1b1G2Feature.getID(), 20.30203, factory.createPoint(new Coordinate(02.03, 0.2)), new String[] {"extra1"}, new double[] {0.022}, 2, 1, 0); ingest(dataStore, adapter, index, level2b1G2Feature); final SimpleFeature level2B2G1Feature = AnalyticFeature.createGeometryFeature( ftype, "b2", "level2B2G1Feature", "flapper", level1b1G1Feature.getID(), 20.30203, factory.createPoint(new Coordinate(02.63, 0.25)), new String[] {"extra1"}, new double[] {0.022}, 2, 1, 0); ingest(dataStore, adapter, index, level2B2G1Feature); final SimpleFeatureItemWrapperFactory wrapperFactory = new SimpleFeatureItemWrapperFactory(); final CentroidManagerGeoWave<SimpleFeature> mananger = new CentroidManagerGeoWave<>( dataStore, indexStore, adapterStore, new SimpleFeatureItemWrapperFactory(), adapter.getTypeName(), storePluginOptions.createInternalAdapterStore().getAdapterId(adapter.getTypeName()), index.getName(), "b1", 1); final List<CentroidPairing<SimpleFeature>> capturedPairing = new ArrayList<>(); final AssociationNotification<SimpleFeature> assoc = new AssociationNotification<SimpleFeature>() { @Override public void notify(final CentroidPairing<SimpleFeature> pairing) { capturedPairing.add(pairing); } }; final FeatureCentroidDistanceFn distanceFn = new FeatureCentroidDistanceFn(); final NestedGroupCentroidAssignment<SimpleFeature> assigmentB1 = new NestedGroupCentroidAssignment<>(mananger, 1, "b1", distanceFn); assigmentB1.findCentroidForLevel(wrapperFactory.create(level1b1G1Feature), assoc); assertEquals(1, capturedPairing.size()); assertEquals(level1b1G1Feature.getID(), capturedPairing.get(0).getCentroid().getID()); capturedPairing.clear(); final NestedGroupCentroidAssignment<SimpleFeature> assigmentB1L2G1 = new NestedGroupCentroidAssignment<>(mananger, 2, "b1", distanceFn); assigmentB1L2G1.findCentroidForLevel(wrapperFactory.create(level1b1G1Feature), assoc); assertEquals(1, capturedPairing.size()); assertEquals(level2b1G1Feature.getID(), capturedPairing.get(0).getCentroid().getID()); capturedPairing.clear(); final NestedGroupCentroidAssignment<SimpleFeature> assigmentB1L2G2 = new NestedGroupCentroidAssignment<>(mananger, 2, "b1", distanceFn); assigmentB1L2G2.findCentroidForLevel(wrapperFactory.create(level1b1G2Feature), assoc); assertEquals(1, capturedPairing.size()); assertEquals(level2b1G2Feature.getID(), capturedPairing.get(0).getCentroid().getID()); capturedPairing.clear(); final CentroidManagerGeoWave<SimpleFeature> mananger2 = new CentroidManagerGeoWave<>( dataStore, indexStore, adapterStore, new SimpleFeatureItemWrapperFactory(), adapter.getTypeName(), storePluginOptions.createInternalAdapterStore().getAdapterId(adapter.getTypeName()), index.getName(), "b2", 2); final NestedGroupCentroidAssignment<SimpleFeature> assigmentB2L2 = new NestedGroupCentroidAssignment<>(mananger2, 2, "b1", distanceFn); assigmentB2L2.findCentroidForLevel(wrapperFactory.create(level1b1G1Feature), assoc); assertEquals(1, capturedPairing.size()); assertEquals(level2B2G1Feature.getID(), capturedPairing.get(0).getCentroid().getID()); capturedPairing.clear(); }