org.locationtech.udig.processingtoolbox.tools.SplitByFeaturesDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.locationtech.udig.processingtoolbox.tools.SplitByFeaturesDialog.java

Source

/*
 * uDig - User Friendly Desktop Internet GIS client
 * (C) MangoSystem - www.mangosystem.com 
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
 * License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
 */
package org.locationtech.udig.processingtoolbox.tools;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PlatformUI;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.process.spatialstatistics.core.StringHelper;
import org.geotools.process.spatialstatistics.storage.NamePolicy;
import org.geotools.process.spatialstatistics.storage.ShapeExportOperation;
import org.geotools.process.spatialstatistics.transformation.ClipWithGeometryFeatureCollection;
import org.geotools.util.logging.Logging;
import org.locationtech.udig.processingtoolbox.ToolboxPlugin;
import org.locationtech.udig.processingtoolbox.ToolboxView;
import org.locationtech.udig.processingtoolbox.internal.Messages;
import org.locationtech.udig.processingtoolbox.internal.ui.OutputDataWidget;
import org.locationtech.udig.processingtoolbox.internal.ui.OutputDataWidget.FileDataType;
import org.locationtech.udig.processingtoolbox.styler.MapUtils;
import org.locationtech.udig.processingtoolbox.styler.MapUtils.FieldType;
import org.locationtech.udig.processingtoolbox.styler.MapUtils.VectorLayerType;
import org.locationtech.udig.project.IMap;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.PropertyName;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.operation.union.CascadedPolygonUnion;

/**
 * Splits the features creates a subset of multiple output features.
 * 
 * @author MapPlus
 */
public class SplitByFeaturesDialog extends AbstractGeoProcessingDialog implements IRunnableWithProgress {
    protected static final Logger LOGGER = Logging.getLogger(SplitByFeaturesDialog.class);

    private Combo cboInputFeatures, cboSplitFeatures, cboSplitField, cboNamePolicy;

    private Button chkPrefix;

    private Table uniqueTable;

    private NamePolicy namePolicy = NamePolicy.NORMAL;

    private SimpleFeatureCollection inputFeatures, splitFeatures;

    private String prefix = null;

    public SplitByFeaturesDialog(Shell parentShell, IMap map) {
        super(parentShell, map);

        setShellStyle(SWT.CLOSE | SWT.MIN | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL | SWT.RESIZE);

        this.windowTitle = Messages.SplitByFeaturesDialog_title;
        this.windowDesc = Messages.SplitByFeaturesDialog_description;
        this.windowSize = new Point(650, 600);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite area = (Composite) super.createDialogArea(parent);

        Composite container = new Composite(area, SWT.BORDER);
        container.setLayout(new GridLayout(2, false));
        container.setLayoutData(new GridData(GridData.FILL_BOTH));

        // input features
        uiBuilder.createLabel(container, Messages.SplitByAttributesDialog_InputFeatures, null, 2);
        cboInputFeatures = uiBuilder.createCombo(container, 2);
        cboInputFeatures.addModifyListener(modifyListener);

        // split features
        uiBuilder.createLabel(container, Messages.SplitByFeaturesDialog_SplitFeatures, null, 2);
        cboSplitFeatures = uiBuilder.createCombo(container, 2);
        cboSplitFeatures.addModifyListener(modifyListener);

        // split field
        uiBuilder.createLabel(container, Messages.SplitByAttributesDialog_SplitField, null, 1);
        cboSplitField = uiBuilder.createCombo(container, 1);
        cboSplitField.addModifyListener(modifyListener);

        chkPrefix = uiBuilder.createCheckbox(container, Messages.SplitByAttributesDialog_UsePrefix, null, 2);
        chkPrefix.setSelection(true);
        chkPrefix.addSelectionListener(selectionListener);

        // output layers
        Group grpTable = uiBuilder.createGroup(container, Messages.SplitByAttributesDialog_OutputLayers, false, 2);
        grpTable.setLayout(new GridLayout(4, false));

        String[] columns = new String[] { Messages.SplitByAttributesDialog_OutputName,
                Messages.SplitByAttributesDialog_FieldValue, Messages.SplitByAttributesDialog_Count };
        uniqueTable = uiBuilder.createEditableTable(grpTable, columns, 4, 1);

        // 4. name policy
        uiBuilder.createLabel(container, Messages.SplitByAttributesDialog_NamePolicy, null, 1);
        cboNamePolicy = uiBuilder.createCombo(container, 2);
        cboNamePolicy.addModifyListener(modifyListener);
        setComboItems(cboNamePolicy, NamePolicy.class);
        cboNamePolicy.select(0);

        locationView = new OutputDataWidget(FileDataType.FOLDER, SWT.OPEN);
        locationView.create(container, SWT.BORDER, 2, 1);
        locationView.setFolder(ToolboxView.getWorkspace()); // default location

        // load layers
        fillLayers(map, cboInputFeatures, VectorLayerType.ALL);
        fillLayers(map, cboSplitFeatures, VectorLayerType.POLYGON);

        area.pack(true);
        return area;
    }

    SelectionListener selectionListener = new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent event) {
            Widget widget = event.widget;
            if (widget.equals(chkPrefix)) {
                updatePrefix();
            }
        }
    };

    ModifyListener modifyListener = new ModifyListener() {
        @Override
        public void modifyText(ModifyEvent e) {
            Widget widget = e.widget;
            if (invalidWidgetValue(widget)) {
                return;
            }

            if (widget.equals(cboInputFeatures)) {
                inputFeatures = MapUtils.getFeatures(map, cboInputFeatures.getText());
                prefix = cboInputFeatures.getText();
                updatePrefix();
            } else if (widget.equals(cboSplitFeatures)) {
                splitFeatures = MapUtils.getFeatures(map, cboSplitFeatures.getText());
                if (splitFeatures != null) {
                    fillFields(cboSplitField, splitFeatures.getSchema(), FieldType.ALL);
                    uniqueTable.removeAll();
                }
            } else if (widget.equals(cboSplitField)) {
                BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(), new Runnable() {
                    @Override
                    public void run() {
                        buildTables(cboSplitField.getText());
                    }
                });
            } else if (widget.equals(cboNamePolicy)) {
                namePolicy = NamePolicy.valueOf(cboNamePolicy.getText());
            }
        }
    };

    @SuppressWarnings("unchecked")
    private void updatePrefix() {
        for (TableItem item : uniqueTable.getItems()) {
            Entry<Object, Integer> entrySet = (Entry<Object, Integer>) item.getData();
            String fieldName = entrySet.getKey().toString();
            if (chkPrefix.getSelection() && !StringHelper.isNullOrEmpty(prefix)) {
                fieldName = prefix + "_" + entrySet.getKey().toString(); //$NON-NLS-1$
            }
            item.setText(new String[] { fieldName, entrySet.getKey().toString(), entrySet.getValue().toString() });
        }
    }

    private void buildTables(String attributeName) {
        SortedMap<Object, Integer> valueCountsMap = new TreeMap<Object, Integer>();
        SimpleFeatureIterator featureIter = splitFeatures.features();
        try {
            while (featureIter.hasNext()) {
                final SimpleFeature feature = featureIter.next();
                Object value = feature.getAttribute(attributeName);
                if (value == null) {
                    value = "Null_Value"; //$NON-NLS-1$
                }

                if (valueCountsMap.containsKey(value)) {
                    final int cnt = valueCountsMap.get(value);
                    valueCountsMap.put(value, Integer.valueOf(cnt + 1));
                } else {
                    valueCountsMap.put(value, Integer.valueOf(1));
                }
            }
        } finally {
            featureIter.close();
        }

        uniqueTable.removeAll();
        for (Entry<Object, Integer> entrySet : valueCountsMap.entrySet()) {
            TableItem item = new TableItem(uniqueTable, SWT.NONE);
            String fieldName = entrySet.getKey().toString();
            if (this.chkPrefix.getSelection() && !StringHelper.isNullOrEmpty(prefix)) {
                fieldName = prefix + "_" + entrySet.getKey().toString(); //$NON-NLS-1$
            }

            item.setText(new String[] { fieldName, entrySet.getKey().toString(), entrySet.getValue().toString() });
            item.setData(entrySet);
            item.setChecked(true);
        }
    }

    @Override
    protected void okPressed() {
        if (inputFeatures == null || splitFeatures == null || !existCheckedItem(uniqueTable)) {
            openInformation(getShell(), Messages.SplitByAttributesDialog_Warning);
            return;
        }

        try {
            PlatformUI.getWorkbench().getProgressService().run(false, true, this);
            openInformation(getShell(), Messages.General_Completed);
            super.okPressed();
        } catch (InvocationTargetException e) {
            MessageDialog.openError(getShell(), Messages.General_Error, e.getMessage());
        } catch (InterruptedException e) {
            MessageDialog.openInformation(getShell(), Messages.General_Cancelled, e.getMessage());
        }
    }

    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
        monitor.beginTask(String.format(Messages.Task_Executing, windowTitle), uniqueTable.getItems().length + 1);
        try {
            monitor.worked(increment);

            final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
            PropertyName uniqueField = ff.property(cboSplitField.getText());

            ShapeExportOperation process = new ShapeExportOperation();
            process.setOutputDataStore(locationView.getDataStore());
            process.setNamePolicy(namePolicy);

            for (TableItem item : uniqueTable.getItems()) {
                monitor.subTask(String.format(Messages.Task_Executing, item.getText()));
                if (monitor.isCanceled()) {
                    break;
                }

                if (item.getChecked()) {
                    String layerName = item.getText();
                    final String value = item.getText(1);
                    Filter filter = ff.equal(uniqueField, ff.literal(value), true);
                    if (value.equals("Null_Value")) { //$NON-NLS-1$
                        filter = ff.isNull(uniqueField);
                    }

                    Geometry clipGeometry = unionGeometry(splitFeatures.subCollection(filter));
                    process.setOutputTypeName(layerName);
                    SimpleFeatureSource outputSfs = process
                            .execute(new ClipWithGeometryFeatureCollection(inputFeatures, clipGeometry));
                    if (outputSfs == null) {
                        ToolboxPlugin.log(windowTitle + " : Failed to export : " + layerName); //$NON-NLS-1$
                    }
                }

                monitor.worked(increment);
                Thread.sleep(100);
            }
        } catch (Exception e) {
            ToolboxPlugin.log(e.getMessage());
            throw new InvocationTargetException(e.getCause(), e.getMessage());
        } finally {
            monitor.done();
        }
    }

    private Geometry unionGeometry(SimpleFeatureCollection inutFeatures) {
        List<Geometry> geometries = new ArrayList<Geometry>();
        SimpleFeatureIterator featureIter = inutFeatures.features();
        try {
            while (featureIter.hasNext()) {
                SimpleFeature feature = featureIter.next();
                Geometry geometry = (Geometry) feature.getDefaultGeometry();
                if (geometry == null || geometry.isEmpty()) {
                    continue;
                }
                geometries.add(geometry);
            }
        } finally {
            featureIter.close();
        }

        CascadedPolygonUnion unionOp = new CascadedPolygonUnion(geometries);
        return unionOp.union();
    }
}