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
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand Down Expand Up @@ -231,7 +231,7 @@ public void handlePostModifyEvent(final CatalogPostModifyEvent event) throws Cat
PRE_MODIFY_EVENT.remove();

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) {
throw new IllegalStateException(
Expand All @@ -245,6 +245,14 @@ public void handlePostModifyEvent(final CatalogPostModifyEvent event) throws Cat
log.finer("Handling modify event for " + source);
if (source instanceof FeatureTypeInfo || source instanceof CoverageInfo
|| 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
* 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
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand Down Expand Up @@ -26,7 +26,6 @@
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.event.CatalogModifyEvent;
Expand Down Expand Up @@ -63,7 +62,7 @@ public class CatalogLayerEventListenerTest {

private LayerInfo mockLayerInfo;

private ResourceInfo mockResourceInfo;
private FeatureTypeInfo mockResourceInfo;

private NamespaceInfo mockNamespaceInfo;

Expand Down Expand Up @@ -204,6 +203,41 @@ public void setUp() throws Exception {
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 {
final String oldGroupName = LAYER_GROUP_NAME;
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
* This code is licensed under the GPL 2.0 license, available at the root
* 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.
* @uml.property name="filter"
*/
Filter getFilter();

/**
* 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);
Filter filter();

/**
* 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;

/**
* 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.
* <p>
Expand All @@ -191,9 +193,4 @@ public interface FeatureTypeInfo extends ResourceInfo {

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
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand Down Expand Up @@ -1233,7 +1233,7 @@ public void clear( FeatureTypeInfo info ) {
try {
Method m = GS_VERSIONING_FS.getMethod( "create", VERSIONING_FS,
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());
}
catch( Exception e ) {
Expand All @@ -1260,7 +1260,7 @@ public void clear( FeatureTypeInfo info ) {
}

//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());
}
}
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
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand All @@ -17,6 +17,8 @@
import org.geoserver.catalog.StoreInfo;
import org.geotools.data.FeatureSource;
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.opengis.feature.Feature;
import org.opengis.feature.type.FeatureType;
Expand All @@ -27,7 +29,9 @@
public class FeatureTypeInfoImpl extends ResourceInfoImpl implements
FeatureTypeInfo {

protected Filter filter;
protected transient Filter filter;

protected String cqlFilter;

protected int maxFeatures;
protected int numDecimals;
Expand Down Expand Up @@ -77,14 +81,21 @@ public void setAttributes(List<AttributeTypeInfo> 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;
}

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

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

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

return true;
}

Expand All @@ -213,6 +225,16 @@ public Measure getLinearizationTolerance() {
public void setLinearizationTolerance(Measure 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
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand Down Expand Up @@ -97,8 +97,8 @@ public FeatureType getFeatureType() throws IOException {
return delegate.getFeatureType();
}

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

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

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

public void setLatLonBoundingBox(ReferencedEnvelope box) {
delegate.setLatLonBoundingBox(box);
}
Expand Down Expand Up @@ -322,4 +318,15 @@ public boolean isCircularArcPresent() {
public void setCircularArcPresent(boolean 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>
</fieldset>
</div>
</wicket:fragment>
</wicket:fragment>
<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>
</body>
</html>

0 comments on commit e5f5f1c

Please sign in to comment.