понедельник, 27 июня 2011 г.

Добавление элементов в векторный слой с фильтрацией (gwt-openlayers)

Имеем WFS слой с некоторым атрибутом "class". Требуется показать на карте только те элементы, у которых значение class равно 1. Для этого запишем:
WFSProtocolOptions wfsProtocolOptions = new WFSProtocolOptions();
wfsProtocolOptions.setUrl("http://server:8080/geoserver/wfs");
wfsProtocolOptions.setFeatureType("main");
wfsProtocolOptions.setFeatureNameSpace("http://www.dev-city.ru/rptp");
wfsProtocolOptions.setGeometryName("geom");
wfsProtocolOptions.setVersion("1.1.0");
wfsProtocolOptions.setSrsName("EPSG:900913");
VectorOptions vectorOptions =  new VectorOptions();
vectorOptions.setProtocol(new WFSProtocol(wfsProtocolOptions));
FilterComparison filter = new FilterComparison();
filter.setType(FilterComparison.EQUAL_TO);
filter.setProperty("class");
filter.setValue(1);
vectorOptions.setStrategies(new Strategy[]{new BBoxStrategy(),
  new FilterStrategy(filter), new SaveStrategy()});
Vector layer = new Vector("слой WFS", vectorOptions);
К сожалению, в gwt-openlayers классы FilterComparison, FilterStrategy и SaveStrategy не реализованы. Но это исправимо:
package ru.rp.client.openlayers;
import org.gwtopenmaps.openlayers.client.filter.Filter;
import org.gwtopenmaps.openlayers.client.util.JSObject;

public class FilterComparison extends Filter {
    public static final short EQUAL_TO                 = 0;
    public static final short NOT_EQUAL_TO             = 1;
    public static final short LESS_THAN                = 2;
    public static final short GREATER_THAN             = 3;
    public static final short LESS_THAN_OR_EQUAL_TO    = 4;
    public static final short GREATER_THAN_OR_EQUAL_TO = 5;
    public static final short BETWEEN                  = 6;
    public static final short LIKE                     = 7;

    protected FilterComparison(JSObject filter) {
        super(filter);
    }

    public FilterComparison(){
  this(FilterComparisonImpl.create());
 }

    public void setType(short type) {
        FilterComparisonImpl.setType(this.getJSObject(), type);
    }

    public void setProperty(String property) {
        FilterComparisonImpl.setProperty(this.getJSObject(), property);
    }

    public void setValue(String value) {
        FilterComparisonImpl.setValue(this.getJSObject(), value);
    }

    public void setValue(short value) {
        FilterComparisonImpl.setValue(this.getJSObject(), value);
    }

    public void setValue(int value) {
        FilterComparisonImpl.setValue(this.getJSObject(), value);
    }

    public void setValue(float value) {
        FilterComparisonImpl.setValue(this.getJSObject(), value);
    }

}
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.util.JSObject;

public class FilterComparisonImpl {

    public native static JSObject create()/*-{
  return new $wnd.OpenLayers.Filter.Comparison();
 }-*/;

    public native static void setType(JSObject filter, short type)/*-{
        switch (type) {
            case 0: filter.type = $wnd.OpenLayers.Filter.Comparison.EQUAL_TO; break;
            case 1: filter.type = $wnd.OpenLayers.Filter.Comparison.NOT_EQUAL_TO; break;
            case 2: filter.type = $wnd.OpenLayers.Filter.Comparison.LESS_THAN; break;
            case 3: filter.type = $wnd.OpenLayers.Filter.Comparison.GREATER_THAN; break;
            case 4: filter.type = $wnd.OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO; break;
            case 5: filter.type = $wnd.OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO; break;
            case 6: filter.type = $wnd.OpenLayers.Filter.Comparison.BETWEEN; break;
            case 7: filter.type = $wnd.OpenLayers.Filter.Comparison.LIKE; break;
        }
    }-*/;

    public native static void setProperty(JSObject filter, String property)/*-{
        filter.property = property;
    }-*/;

    public native static void setValue(JSObject filter, String value)/*-{
        filter.value = value;
    }-*/;

    public native static void setValue(JSObject filter, short value)/*-{
        filter.value = value;
    }-*/;

    public native static void setValue(JSObject filter, int value)/*-{
        filter.value = value;
    }-*/;

    public native static void setValue(JSObject filter, float value)/*-{
        filter.value = value;
    }-*/;
}
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.filter.Filter;
import org.gwtopenmaps.openlayers.client.strategy.Strategy;
import org.gwtopenmaps.openlayers.client.util.JSObject;

public class FilterStrategy extends Strategy {

    protected FilterStrategy(JSObject strategy) {
        super(strategy);
    }

    public FilterStrategy(Filter filter){
  this(FilterStrategyImpl.create(filter.getJSObject()));
    }
}

package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.util.JSObject;

public class FilterStrategyImpl {

    public native static JSObject create(JSObject filter)/*-{
  return new $wnd.OpenLayers.Strategy.Filter({filter: filter});
 }-*/;

}
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.feature.VectorFeature;
import org.gwtopenmaps.openlayers.client.strategy.Strategy;
import org.gwtopenmaps.openlayers.client.util.JSObject;

public class SaveStrategy extends Strategy {

    protected SaveStrategy(JSObject strategy) {
        super(strategy);
    }

    public SaveStrategy(){
  this(SaveStrategyImpl.create());
 }

    public static void setVectorFeatureUpdateState(VectorFeature vectorFeature) {
        vectorFeature.setJSObject(SaveStrategyImpl.setVectorFeatureUpdateState(
        vectorFeature.getJSObject()));
    }

}
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.util.JSObject;

public class SaveStrategyImpl {

    public native static JSObject create()/*-{
  return new $wnd.OpenLayers.Strategy.Save();
 }-*/;

    public native static JSObject setVectorFeatureUpdateState(JSObject vector)/*-{
        if (vector.state == null)
            vector.state = $wnd.OpenLayers.State.UNKNOWN;
        vector.toState($wnd.OpenLayers.State.UPDATE);
        return vector;
    }-*/;
}
Создадим на javascript контролы добавления, редактирования и удаления точечных элементов:
        var draw = new OpenLayers.Control.DrawFeature(
            layer, OpenLayers.Handler.Point,
            {
                title: "Добавить объект",
                displayClass: "olControlDrawFeaturePoint",
                multi: false
            }
        );
        var edit = new OpenLayers.Control.ModifyFeature(layer, {
            title: "Редактировать объект",
            displayClass: "olControlModifyFeature",
            mode: OpenLayers.Control.DRAG
        });
        var del = new DeleteFeature(layer, {title: "Удалить объект"});
Эти контролы будут вставлены в панель OpenLayers.Control.Panel. Удаление и редактирование работает. Но при попытке добавления точки ничего не происходит. Если убрать new FilterStrategy(filter), то вставка будет работать.
Пришлось искать альтернативное решение, без использования FilterStrategy. Фильтрацию можно включить через стили слоя:
vectorOptions.setStyleMap(createStyleMap());
где
private StyleMap createStyleMap() {
        Style defaultStyle = new Style();
        Style selectStyle = new Style();
        Style temporaryStyle = new Style();
        // Здесь можно изменить стили
        ru.rp.client.openlayers.StyleMap styleMap =
            new ru.rp.client.openlayers.StyleMap(
                defaultStyle, selectStyle, temporaryStyle);
        styleMap.addRule(1); // Это и есть нужный фильтр
        return styleMap;
}
Для этого был создан класс:
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.Style;

public class StyleMap extends org.gwtopenmaps.openlayers.client.StyleMap {

    public StyleMap(Style defaultStyle, Style selectStyle, Style temporaryStyle) {
        super(defaultStyle, selectStyle, temporaryStyle);
    }

    public void addRule(int i) {
        StyleMapImpl.addRule(this.getJSObject(), i);
    }

}
package ru.rp.client.openlayers;

import org.gwtopenmaps.openlayers.client.util.JSObject;

public class StyleMapImpl {

    public static native void addRule(JSObject styleMap, int i)/*-{
        var rule = new $wnd.OpenLayers.Rule({
            filter: new $wnd.OpenLayers.Filter.Comparison({
                type: $wnd.OpenLayers.Filter.Comparison.EQUAL_TO,
                property: "class",
                value: i
                })
        });
        styleMap.styles["default"].addRules([rule]);
        styleMap.styles["temporary"].addRules([rule]);
        styleMap.styles["select"].addRules([rule]);
    }-*/;

}
Но это ещё не всё. При добавлении точки её атрибуты не заполнены и она не будет показана. Требуется перед добавлением точки добавить ей атрибут class с нужным значением:
layer.addVectorBeforeFeatureAddedListener(new VectorBeforeFeatureAddedListener() {
        public void onBeforeFeatureAdded(BeforeFeatureAddedEvent eventObject) {
            JSObject object = eventObject.getJSObject().getProperty("feature");
            VectorFeature vectorFeature = VectorFeature.narrowToVectorFeature(object);
            Attributes attributes = vectorFeature.getAttributes();
            if (attributes != null)
            if (attributes.getAttributeAsString("class") == null) {
                attributes.setAttribute("class", 1);
                vectorFeature.setAttributes(attributes);
            }
        }
    });
Всё! Теперь и слой фильтруется, и точки добавляются! Конечно, всё вышеизложенное можно применять сразу в openlayers (без использования gwt-openlayers).

Комментариев нет:

Отправить комментарий