Skip to content

Commit

Permalink
[GEOS-3922] Expose feature type filtering option
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Jul 12, 2015
1 parent 922588a commit e5f5f1c
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 57 deletions.
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -231,7 +231,7 @@ public void handlePostModifyEvent(final CatalogPostModifyEvent event) throws Cat
PRE_MODIFY_EVENT.remove(); PRE_MODIFY_EVENT.remove();


if (tileLayerInfo == null && !(source instanceof WorkspaceInfo)) { if (tileLayerInfo == null && !(source instanceof WorkspaceInfo)) {
return;// no tile layer assiociated, no need to continue return;// no tile layer associated, no need to continue
} }
if (preModifyEvent == null) { if (preModifyEvent == null) {
throw new IllegalStateException( throw new IllegalStateException(
Expand All @@ -245,6 +245,14 @@ public void handlePostModifyEvent(final CatalogPostModifyEvent event) throws Cat
log.finer("Handling modify event for " + source); log.finer("Handling modify event for " + source);
if (source instanceof FeatureTypeInfo || source instanceof CoverageInfo if (source instanceof FeatureTypeInfo || source instanceof CoverageInfo
|| source instanceof WMSLayerInfo || source instanceof LayerGroupInfo) { || source instanceof WMSLayerInfo || source instanceof LayerGroupInfo) {
/*
* Handle changing the filter definition, this is the kind of change that affects the
* full output contents
*/
if (changedProperties.contains("cqlFilter") && source instanceof FeatureTypeInfo) {
mediator.truncate(((FeatureTypeInfo) source).prefixedName());
}

/* /*
* Handle the rename case. For LayerInfos it's actually the related ResourceInfo what * Handle the rename case. For LayerInfos it's actually the related ResourceInfo what
* gets renamed, at least until the data/publish split is implemented in GeoServer. For * gets renamed, at least until the data/publish split is implemented in GeoServer. For
Expand Down
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -26,7 +26,6 @@
import org.geoserver.catalog.MetadataMap; import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.NamespaceInfo; import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.PublishedInfo; import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo; import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.event.CatalogModifyEvent; import org.geoserver.catalog.event.CatalogModifyEvent;
Expand Down Expand Up @@ -63,7 +62,7 @@ public class CatalogLayerEventListenerTest {


private LayerInfo mockLayerInfo; private LayerInfo mockLayerInfo;


private ResourceInfo mockResourceInfo; private FeatureTypeInfo mockResourceInfo;


private NamespaceInfo mockNamespaceInfo; private NamespaceInfo mockNamespaceInfo;


Expand Down Expand Up @@ -204,6 +203,41 @@ public void setUp() throws Exception {
assertEquals(renamedPrefixedResouceName, savedInfo.getName()); assertEquals(renamedPrefixedResouceName, savedInfo.getName());
} }


@Test
public void testCqlFilterChanged() throws Exception {
// change the cql filter
String cqlFilter = "name LIKE 'Foo%'";
when(mockResourceInfo.getCqlFilter()).thenReturn(cqlFilter);

CatalogModifyEvent modifyEvent = mock(CatalogModifyEvent.class);
when(modifyEvent.getSource()).thenReturn(mockResourceInfo);
when(modifyEvent.getPropertyNames()).thenReturn(Arrays.asList("cqlFilter"));
when(modifyEvent.getOldValues()).thenReturn(Arrays.asList((Object) null));
when(modifyEvent.getNewValues()).thenReturn(Arrays.asList((Object) cqlFilter));

GeoServerTileLayerInfo info = TileLayerInfoUtil.loadOrCreate(mockLayerInfo,
GWCConfig.getOldDefaults());
GeoServerTileLayer tileLayer = mock(GeoServerTileLayer.class);
when(mockMediator.hasTileLayer(same(mockResourceInfo))).thenReturn(true);
when(tileLayer.getInfo()).thenReturn(info);
when(tileLayer.getLayerInfo()).thenReturn(mockLayerInfo);

when(mockMediator.getTileLayer(same(mockResourceInfo))).thenReturn(tileLayer);
String resourceName = mockResourceInfo.prefixedName();
when(mockMediator.getTileLayerByName(eq(resourceName))).thenReturn(tileLayer);

listener.handleModifyEvent(modifyEvent);

verify(mockMediator, times(1)).hasTileLayer(same(mockResourceInfo));

CatalogPostModifyEvent postModifyEvent = mock(CatalogPostModifyEvent.class);
when(postModifyEvent.getSource()).thenReturn(mockResourceInfo);

listener.handlePostModifyEvent(postModifyEvent);

verify(mockMediator).truncate(eq(resourceName));
}

@Test public void testLayerGroupInfoRenamed() throws Exception { @Test public void testLayerGroupInfoRenamed() throws Exception {
final String oldGroupName = LAYER_GROUP_NAME; final String oldGroupName = LAYER_GROUP_NAME;
final String renamedGroupName = LAYER_GROUP_NAME + "_Renamed"; final String renamedGroupName = LAYER_GROUP_NAME + "_Renamed";
Expand Down
31 changes: 14 additions & 17 deletions src/main/src/main/java/org/geoserver/catalog/FeatureTypeInfo.java
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -58,17 +58,7 @@ public interface FeatureTypeInfo extends ResourceInfo {
* @return A filter, or <code>null</code> if one not set. * @return A filter, or <code>null</code> if one not set.
* @uml.property name="filter" * @uml.property name="filter"
*/ */
Filter getFilter(); Filter filter();

/**
* Sets a filter which should be applied to all queries of the dataset
* represented by the feature type.
*
* @param filter
* A filter, can be <code>null</code>
* @uml.property name="filter"
*/
void setFilter(Filter filter);


/** /**
* A cap on the number of features that a query against this type can return. * A cap on the number of features that a query against this type can return.
Expand Down Expand Up @@ -167,6 +157,18 @@ public interface FeatureTypeInfo extends ResourceInfo {
*/ */
FeatureType getFeatureType() throws IOException; FeatureType getFeatureType() throws IOException;


/**
* Return the ECQL string used as default feature type filter
*
*/
String getCqlFilter();

/**
* Set the ECQL string used as default featue type filter
*
*/
void setCqlFilter(String cqlFilterString);

/** /**
* Returns the underlying feature source instance. * Returns the underlying feature source instance.
* <p> * <p>
Expand All @@ -191,9 +193,4 @@ public interface FeatureTypeInfo extends ResourceInfo {


void setCircularArcPresent(boolean arcsPresent); void setCircularArcPresent(boolean arcsPresent);


/**
* The live feature resource, an instance of of {@link FeatureResource}.
*/
//FeatureResource getResource(ProgressListener listener)
// throws IOException;
} }
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -1233,7 +1233,7 @@ public void clear( FeatureTypeInfo info ) {
try { try {
Method m = GS_VERSIONING_FS.getMethod( "create", VERSIONING_FS, Method m = GS_VERSIONING_FS.getMethod( "create", VERSIONING_FS,
SimpleFeatureType.class, Filter.class, CoordinateReferenceSystem.class, int.class ); SimpleFeatureType.class, Filter.class, CoordinateReferenceSystem.class, int.class );
return (FeatureSource) m.invoke(null, fs, schema, info.getFilter(), return (FeatureSource) m.invoke(null, fs, schema, info.filter(),
resultCRS, info.getProjectionPolicy().getCode()); resultCRS, info.getProjectionPolicy().getCode());
} }
catch( Exception e ) { catch( Exception e ) {
Expand All @@ -1260,7 +1260,7 @@ public void clear( FeatureTypeInfo info ) {
} }


//return a normal //return a normal
return GeoServerFeatureLocking.create(fs, schema, info.getFilter(), resultCRS, info return GeoServerFeatureLocking.create(fs, schema, info.filter(), resultCRS, info
.getProjectionPolicy().getCode(), getTolerance(info), info.getMetadata()); .getProjectionPolicy().getCode(), getTolerance(info), info.getMetadata());
} }
} }
Expand Down
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand All @@ -17,6 +17,8 @@
import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.StoreInfo;
import org.geotools.data.FeatureSource; import org.geotools.data.FeatureSource;
import org.geotools.factory.Hints; import org.geotools.factory.Hints;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.filter.text.ecql.ECQL;
import org.geotools.measure.Measure; import org.geotools.measure.Measure;
import org.opengis.feature.Feature; import org.opengis.feature.Feature;
import org.opengis.feature.type.FeatureType; import org.opengis.feature.type.FeatureType;
Expand All @@ -27,7 +29,9 @@
public class FeatureTypeInfoImpl extends ResourceInfoImpl implements public class FeatureTypeInfoImpl extends ResourceInfoImpl implements
FeatureTypeInfo { FeatureTypeInfo {


protected Filter filter; protected transient Filter filter;

protected String cqlFilter;


protected int maxFeatures; protected int maxFeatures;
protected int numDecimals; protected int numDecimals;
Expand Down Expand Up @@ -77,14 +81,21 @@ public void setAttributes(List<AttributeTypeInfo> attributes) {
this.attributes = attributes; this.attributes = attributes;
} }


public Filter getFilter() { /*
* The filter is computed by current cqlFilter
*/
public Filter filter() {
try {
if (filter == null && cqlFilter != null && !cqlFilter.isEmpty()) {
filter = ECQL.toFilter(cqlFilter);
}
} catch (CQLException e) {
throw new org.geoserver.platform.ServiceException(
"Failed to generate filter from ECQL string " + e.getMessage());
}
return filter; return filter;
} }


public void setFilter(Filter filter) {
this.filter = filter;
}

public int getMaxFeatures() { public int getMaxFeatures() {
return maxFeatures; return maxFeatures;
} }
Expand Down Expand Up @@ -163,13 +174,13 @@ public int hashCode() {
* not the implementation * not the implementation
*/ */
public boolean equals(Object obj) { public boolean equals(Object obj) {
if ( !(obj instanceof FeatureTypeInfo ) ) { if (!(obj instanceof FeatureTypeInfo)) {
return false; return false;
} }
if ( !super.equals( obj ) ) { if (!super.equals(obj)) {
return false; return false;
} }

final FeatureTypeInfo other = (FeatureTypeInfo) obj; final FeatureTypeInfo other = (FeatureTypeInfo) obj;
if (attributes == null) { if (attributes == null) {
if (other.getAttributes() != null) if (other.getAttributes() != null)
Expand All @@ -181,11 +192,6 @@ public boolean equals(Object obj) {
return false; return false;
} else if (!responseSRS.equals(other.getResponseSRS())) } else if (!responseSRS.equals(other.getResponseSRS()))
return false; return false;
if (filter == null) {
if (other.getFilter() != null)
return false;
} else if (!filter.equals(other.getFilter()))
return false;
if (circularArcPresent != other.isCircularArcPresent()) if (circularArcPresent != other.isCircularArcPresent())
return false; return false;
if (linearizationTolerance == null) { if (linearizationTolerance == null) {
Expand All @@ -197,10 +203,16 @@ public boolean equals(Object obj) {
return false; return false;
if (numDecimals != other.getNumDecimals()) if (numDecimals != other.getNumDecimals())
return false; return false;
if(overridingServiceSRS != other.isOverridingServiceSRS()) if (overridingServiceSRS != other.isOverridingServiceSRS())
return false; return false;
if (skipNumberMatched != other.getSkipNumberMatched()) if (skipNumberMatched != other.getSkipNumberMatched())
return false; return false;
if (cqlFilter == null) {
if (other.getCqlFilter() != null)
return false;
} else if (!cqlFilter.equals(other.getCqlFilter()))
return false;

return true; return true;
} }


Expand All @@ -213,6 +225,16 @@ public Measure getLinearizationTolerance() {
public void setLinearizationTolerance(Measure tolerance) { public void setLinearizationTolerance(Measure tolerance) {
this.linearizationTolerance = tolerance; this.linearizationTolerance = tolerance;
} }


@Override
public String getCqlFilter() {
return cqlFilter;
}

@Override
public void setCqlFilter(String cqlFilter) {
this.cqlFilter = cqlFilter;
this.filter = null;
}


} }
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans * (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -97,8 +97,8 @@ public FeatureType getFeatureType() throws IOException {
return delegate.getFeatureType(); return delegate.getFeatureType();
} }


public Filter getFilter() { public Filter filter() {
return delegate.getFilter(); return delegate.filter();
} }


public String getId() { public String getId() {
Expand Down Expand Up @@ -212,10 +212,6 @@ public void setEnabled(boolean enabled) {
delegate.setEnabled(enabled); delegate.setEnabled(enabled);
} }


public void setFilter(Filter filter) {
delegate.setFilter(filter);
}

public void setLatLonBoundingBox(ReferencedEnvelope box) { public void setLatLonBoundingBox(ReferencedEnvelope box) {
delegate.setLatLonBoundingBox(box); delegate.setLatLonBoundingBox(box);
} }
Expand Down Expand Up @@ -322,4 +318,15 @@ public boolean isCircularArcPresent() {
public void setCircularArcPresent(boolean enabled) { public void setCircularArcPresent(boolean enabled) {
delegate.setCircularArcPresent(enabled); delegate.setCircularArcPresent(enabled);
} }

@Override
public String getCqlFilter() {
return delegate.getCqlFilter();
}

@Override
public void setCqlFilter(String cqlFilter) {
delegate.setCqlFilter(cqlFilter);
}

} }
Expand Up @@ -47,8 +47,12 @@
</ul> </ul>
</fieldset> </fieldset>
</div> </div>
</wicket:fragment> </wicket:fragment>
<div wicket:id="reloadWarningDialog"></div> <div wicket:id="reloadWarningDialog"></div>

<label for="cqlFilter"><wicket:message key="cqlFilter">cqlFilter</wicket:message></label>
<textarea wicket:id="cqlFilter" style="margin-bottom:10px" class="field textarea" cols="40" rows="10"></textarea>

</wicket:panel> </wicket:panel>
</body> </body>
</html> </html>

0 comments on commit e5f5f1c

Please sign in to comment.