/* * Copyright 2013 Serdar. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.fub.maps.project.aggregator.pipeline.processes; import de.fub.agg2graph.agg.AggContainer; import de.fub.agg2graph.agg.AggNode; import de.fub.agg2graph.agg.IAggregationStrategy; import de.fub.agg2graph.agg.IMergeHandler; import de.fub.agg2graph.agg.PointGhostPointPair; import de.fub.agg2graph.agg.strategy.AbstractAggregationStrategy; import de.fub.agg2graph.structs.GPSPoint; import de.fub.agg2graph.structs.GPSSegment; import de.fub.agg2graph.structs.ILocation; import de.fub.agg2graphui.layers.AggContainerLayer; import de.fub.agg2graphui.layers.MatchingLayer; import de.fub.agg2graphui.layers.MergingLayer; import de.fub.maps.project.aggregator.factories.nodes.properties.ClassProperty; import de.fub.maps.project.aggregator.factories.nodes.properties.ClassWrapper; import de.fub.maps.project.aggregator.pipeline.AbstractAggregationProcess; import de.fub.maps.project.aggregator.pipeline.AggregationProcessNode; import de.fub.maps.project.aggregator.pipeline.wrapper.DefaultCachingStrategy; import de.fub.maps.project.aggregator.pipeline.wrapper.aggregation.strategy.DefaultAggregationStrategy; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.AggregationStrategy; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.CachingStrategy; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.DescriptorFactory; import de.fub.maps.project.aggregator.xml.AggregatorDescriptor; import de.fub.maps.project.aggregator.xml.ProcessDescriptor; import de.fub.maps.project.aggregator.xml.PropertySection; import de.fub.maps.project.api.process.ProcessPipeline; import de.fub.maps.project.api.statistics.StatisticProvider; import de.fub.maps.project.models.Aggregator; import java.awt.Component; import java.awt.Image; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; import org.netbeans.api.annotations.common.StaticResource; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Exceptions; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; /** * Process unit implementations, which handles the aggregation job of an * Aggregator instance. * * @author Serdar */ @ServiceProvider(service = AbstractAggregationProcess.class) public class AggregationProcess extends AbstractAggregationProcess<List<GPSSegment>, AggContainer> implements StatisticProvider { @StaticResource private static final String ICON_PATH = "de/fub/maps/project/aggregator/pipeline/processes/datasourceProcessIcon.png"; private static final Image IMAGE = ImageUtilities.loadImage(ICON_PATH); private static final Logger LOG = Logger.getLogger(AggregationProcess.class.getName()); private List<GPSSegment> inputList; private MergingLayer mergeLayer; private MatchingLayer matchingLayer; private AggContainerLayer aggregationLayer; private int totalAggNodeCount = 0; private int totalGPSPointCount = 0; private int totalPointGhostPointPairs = 0; private AggregationNode node; public AggregationProcess() { initLayers(); } @Override public void setProcessDescriptor(ProcessDescriptor processDescriptor) { super.setProcessDescriptor(processDescriptor); reInit(); } private void reInit() { node = null; if (getProcessDescriptor() != null) { AggregatorDescriptor aggregatorDescriptor = getAggregator().getAggregatorDescriptor(); if (aggregatorDescriptor != null) { if (aggregatorDescriptor.getAggregationStrategy() != null) { AggregationStrategy aggregationStrategy = null; try { aggregationStrategy = AggregationStrategy.Factory.find(aggregatorDescriptor.getAggregationStrategy(), getAggregator()); } catch (DescriptorFactory.InstanceNotFountException ex) { try { aggregationStrategy = AggregationStrategy.Factory.getDefault(); } catch (DescriptorFactory.InstanceNotFountException ex1) { Exceptions.printStackTrace(ex1); } } if (aggregationStrategy != null && getAggregator() != null && getAggregator().getAggContainer() != null) { getAggregator().getAggContainer().setAggregationStrategy(aggregationStrategy); } } if (aggregatorDescriptor.getTileCachingStrategy() != null) { CachingStrategy cachingStrategy = null; try { cachingStrategy = CachingStrategy.Factory.find(aggregatorDescriptor.getTileCachingStrategy(), getAggregator()); } catch (DescriptorFactory.InstanceNotFountException ex) { try { cachingStrategy = CachingStrategy.Factory.getDefault(); } catch (DescriptorFactory.InstanceNotFountException ex1) { Exceptions.printStackTrace(ex1); } } if (cachingStrategy != null && getAggregator() != null && getAggregator().getAggContainer() != null) { getAggregator().getAggContainer().setCachingStrategy(cachingStrategy); } } } } } private void initLayers() { mergeLayer = new MergingLayer(); matchingLayer = new MatchingLayer(); aggregationLayer = new AggContainerLayer(); getLayers().add(matchingLayer); getLayers().add(mergeLayer); getLayers().add(aggregationLayer); } @Override protected ProcessDescriptor createProcessDescriptor() { // for the default settings the call will be delegated to the default // AggregationStrategy instance DefaulAggregationStrategy ProcessDescriptor descriptor = new ProcessDescriptor(); descriptor.setJavaType(AggregationProcess.class.getName()); descriptor.setDescription(Bundle.CLT_AggregationProcess_Description()); descriptor.setDisplayName(Bundle.CLT_AggregationProcess_Name()); DefaultAggregationStrategy defaultAggregationStrategy = new DefaultAggregationStrategy(); defaultAggregationStrategy.setAggregator(getAggregator()); PropertySection propertySection = defaultAggregationStrategy.getPropertySection(); if (propertySection != null) { descriptor.getProperties().getSections().add(propertySection); } DefaultCachingStrategy defaultCachingStrategy = new DefaultCachingStrategy(); defaultCachingStrategy.setAggregator(getAggregator()); propertySection = defaultCachingStrategy.getPropertySection(); if (propertySection != null) { descriptor.getProperties().getSections().add(propertySection); } return descriptor; } @Override public Node getNodeDelegate() { if (node == null) { node = new AggregationNode(AggregationProcess.this); } return node; } @Override public void setInput(List<GPSSegment> input) { this.inputList = input; } @Override public AggContainer getResult() { synchronized (RUN_MUTEX) { this.inputList = null; return getAggregator().getAggContainer(); } } @Override protected void start() { totalAggNodeCount = 0; totalGPSPointCount = 0; totalPointGhostPointPairs = 0; if (inputList != null && getAggregator() != null && getAggregator().getAggContainer() != null) { LOG.log(Level.FINE, "Segment size: {0}", inputList.size()); ProgressHandle handle = ProgressHandleFactory.createHandle(getName()); handle.start(inputList.size()); try { aggregationLayer.clearRenderObjects(); mergeLayer.clearRenderObjects(); matchingLayer.clearRenderObjects(); AggContainer aggContainer = getAggregator().getAggContainer(); int counter = 0; LOG.log(Level.FINE, "clean segments: {0}", inputList.size()); for (GPSSegment inputSegment : inputList) { if (canceled.get()) { fireProcessCanceledEvent(); break; } aggContainer.addSegment(inputSegment, counter == 0); counter++; // update debug layers: matching, merging IAggregationStrategy aggregationStrategy = aggContainer.getAggregationStrategy(); if (aggregationStrategy instanceof AbstractAggregationStrategy) { AbstractAggregationStrategy abstractAggregationStrategy = (AbstractAggregationStrategy) aggregationStrategy; IMergeHandler mergeHandler = abstractAggregationStrategy.getMergeHandler(); if (mergeHandler != null) { List<AggNode> aggNodes = mergeHandler.getAggNodes(); if (aggNodes != null) { totalAggNodeCount += aggNodes.size(); matchingLayer.add(aggNodes); } List<GPSPoint> gpsPoints = mergeHandler.getGpsPoints(); if (gpsPoints != null) { totalGPSPointCount += gpsPoints.size(); matchingLayer.add(gpsPoints); } List<PointGhostPointPair> pointGhostPointPairs = mergeHandler.getPointGhostPointPairs(); if (pointGhostPointPairs != null) { for (PointGhostPointPair pgpp : pointGhostPointPairs) { List<ILocation> line = new ArrayList<ILocation>(2); line.add(new GPSPoint(pgpp.point)); line.add(new GPSPoint(pgpp.ghostPoint)); mergeLayer.add(line); totalPointGhostPointPairs++; } } } } fireProcessProgressEvent(new ProcessPipeline.ProcessEvent<AggregationProcess>(this, "Aggregation...", (int) ((100d / inputList.size()) * (counter)))); handle.progress(counter); LOG.log(Level.FINE, "Segment number: {0}", (counter)); } aggregationLayer.add(aggContainer); } finally { handle.finish(); } } } @NbBundle.Messages("CLT_AggregationProcess_Name=Aggregation") @Override public String getName() { if (getProcessDescriptor() != null) { return getProcessDescriptor().getDisplayName(); } return Bundle.CLT_AggregationProcess_Name(); } @NbBundle.Messages("CLT_AggregationProcess_Description=Aggregation process") @Override public String getDescription() { if (getProcessDescriptor() != null) { return getProcessDescriptor().getDescription(); } return Bundle.CLT_AggregationProcess_Description(); } @Override public Image getIcon() { return IMAGE; } @Override public JComponent getSettingsView() { return null; } @Override public List<StatisticSection> getStatisticData() throws StatisticNotAvailableException { List<StatisticSection> statisticSections = new ArrayList<StatisticProvider.StatisticSection>(); statisticSections.add(getPerformanceData()); StatisticSection section = new StatisticSection( "Aggregation Statistics", "Displays all statistics data which are computed during the aggregation."); statisticSections.add(section); section.getStatisticsItemList().add(new StatisticItem( "Total Aggregation Node Count", String.valueOf(totalAggNodeCount), "The total amount of aggreagtion nodes, which are created during this aggregation process.")); section.getStatisticsItemList().add(new StatisticItem( "Total GPS Point Count", String.valueOf(totalGPSPointCount), "The total amount of GPS Point that are added during the aggregation.")); section.getStatisticsItemList().add(new StatisticItem( "Total Count Point/GhostPoint Pairs ", String.valueOf(totalPointGhostPointPairs), "The total amount of paris of Point/Ghostpoint.")); return statisticSections; } @Override public boolean cancel() { canceled.set(true); return canceled.get(); } @Override public Component getVisualRepresentation() { return null; } @NbBundle.Messages({ "CLT_Property_Aggregator_Strategy_Class_Name=Aggregation Strategy", "CLT_Property_Aggregator_Strategy_Class_Description=The aggregation strategy that wil be used during aggregation.", "CLT_Property_TileCache_Strategy_Class_Name=Tilecache Strategy", "CLT_Property_TileCache_Strategy_Class_Description=The TileCache strategy which will be used during the aggregation." }) private static class AggregationNode extends AggregationProcessNode { private final AggregationProcess aggregationProcess; public AggregationNode(AggregationProcess process) { super(process); this.aggregationProcess = process; } @Override protected Sheet createSheet() { Sheet sheet = super.createSheet(); final Aggregator aggregator = aggregationProcess.getAggregator(); if (aggregator != null && aggregator.getAggContainer() != null && aggregator.getAggContainer().getAggregationStrategy() instanceof AggregationStrategy) { sheet = Sheet.createDefault(); PropertySet[] sets = sheet.toArray(); for (PropertySet set : sets) { sheet.remove(set.getName()); } AggregatorDescriptor aggregatorDescriptor = aggregator.getAggregatorDescriptor(); if (aggregatorDescriptor != null) { Sheet.Set nodeSet = Sheet.createPropertiesSet(); nodeSet.setName(AggregationProcess.class.getName()); nodeSet.setDisplayName(Bundle.CLT_AggregationProcess_Name()); nodeSet.setShortDescription(Bundle.CLT_AggregationProcess_Description()); sheet.put(nodeSet); if (aggregatorDescriptor.getAggregationStrategy() != null) { ClassProperty classProperty = new AggregationStrategyInstanceProperty(aggregator, aggregatorDescriptor); nodeSet.put(classProperty); } if (aggregatorDescriptor.getTileCachingStrategy() != null) { ClassProperty classProperty = new CachingStrategyProperty(aggregator, aggregatorDescriptor); nodeSet.put(classProperty); } } if (aggregator.getAggContainer().getAggregationStrategy() instanceof AggregationStrategy) { AggregationStrategy aggregationStrategy = (AggregationStrategy) aggregator.getAggContainer().getAggregationStrategy(); PropertySet[] propertySets = aggregationStrategy.getNodeDelegate().getPropertySets(); for (PropertySet propertySet : propertySets) { Sheet.Set set = convertToSet(propertySet); sheet.put(set); } } if (aggregator.getAggContainer().getCachingStrategy() instanceof CachingStrategy) { CachingStrategy cachingStrategy = (CachingStrategy) aggregator.getAggContainer().getCachingStrategy(); PropertySet[] propertySets = cachingStrategy.getNodeDelegate().getPropertySets(); for (PropertySet propertySet : propertySets) { Sheet.Set set = convertToSet(propertySet); sheet.put(set); } } } return sheet; } private Sheet.Set convertToSet(PropertySet propertySet) { Sheet.Set set = Sheet.createPropertiesSet(); set.setName(propertySet.getName()); set.setDisplayName(propertySet.getDisplayName()); set.setShortDescription(propertySet.getShortDescription()); for (Property<?> property : propertySet.getProperties()) { set.put(property); } return set; } private class AggregationStrategyInstanceProperty extends ClassProperty { private final Aggregator aggregator; private final AggregatorDescriptor property; private ClassWrapper wrapper = null; public AggregationStrategyInstanceProperty(Aggregator aggregator, AggregatorDescriptor property) { super(AggregationStrategy.class.getName(), Bundle.CLT_Property_Aggregator_Strategy_Class_Name(), Bundle.CLT_Property_Aggregator_Strategy_Class_Description(), AggregationStrategy.class); this.aggregator = aggregator; this.property = property; wrapper = aggregator.getAggContainer().getAggregationStrategy() != null ? new ClassWrapper(aggregator.getAggContainer().getAggregationStrategy().getClass()) : null; } @Override public ClassWrapper getValue() throws IllegalAccessException, InvocationTargetException { return wrapper; } @Override public void setValue(ClassWrapper val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { ClassWrapper oldValue = getValue(); if (val == null) { throw new IllegalArgumentException("null is not a valid value"); } else if (!val.getQualifiedName().equals(wrapper.getQualifiedName()) && oldValue != null) { wrapper = val; ProcessDescriptor processDescriptor = aggregationProcess.getProcessDescriptor(); if (processDescriptor != null) { List<PropertySection> sections = processDescriptor.getProperties().getSections(); int index = -1; for (PropertySection propertySection : new ArrayList<PropertySection>(sections)) { index++; if (oldValue.getQualifiedName().equals(propertySection.getId())) { LOG.info(MessageFormat.format("Strategy removed: {0}", sections.remove(propertySection))); } } AggregationStrategy aggregationStrategy; try { aggregationStrategy = AggregationStrategy.Factory.find(val.getQualifiedName(), aggregator); if (aggregationStrategy != null) { aggregator.getAggContainer().setAggregationStrategy(aggregationStrategy); if (index < 0 || index >= sections.size()) { sections.add(aggregationStrategy.getPropertySection()); } else { sections.add(index, aggregationStrategy.getPropertySection()); } } property.setAggregationStrategy(val.getQualifiedName()); } catch (DescriptorFactory.InstanceNotFountException ex) { Exceptions.printStackTrace(ex); } } } } } private class CachingStrategyProperty extends ClassProperty { private final AggregatorDescriptor property; private final Aggregator aggregator; private ClassWrapper wrapper; public CachingStrategyProperty(Aggregator aggregator, AggregatorDescriptor property) { super(CachingStrategy.class.getName(), Bundle.CLT_Property_TileCache_Strategy_Class_Name(), Bundle.CLT_Property_TileCache_Strategy_Class_Description(), CachingStrategy.class); this.aggregator = aggregator; this.property = property; this.wrapper = aggregator.getAggContainer().getCachingStrategy() != null ? new ClassWrapper(aggregator.getAggContainer().getCachingStrategy().getClass()) : null; } @Override public ClassWrapper getValue() throws IllegalAccessException, InvocationTargetException { return wrapper; } @Override public void setValue(ClassWrapper val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (val == null) { throw new IllegalArgumentException("null not a valid value"); } else if (!val.getQualifiedName().equals(wrapper.getQualifiedName())) { ClassWrapper oldValue = wrapper; wrapper = val; ProcessDescriptor processDescriptor = aggregationProcess.getProcessDescriptor(); if (processDescriptor != null) { List<PropertySection> sections = processDescriptor.getProperties().getSections(); int index = -1; for (PropertySection propertySection : new ArrayList<PropertySection>(sections)) { index++; if (oldValue.getQualifiedName().equals(propertySection.getId())) { LOG.info(MessageFormat.format("Caching strategy removed: {0}", sections.remove(propertySection))); } } CachingStrategy cachingStrategy; try { cachingStrategy = CachingStrategy.Factory.find(val.getQualifiedName(), aggregator); if (cachingStrategy != null) { aggregator.getAggContainer().setCachingStrategy(cachingStrategy); if (index < 0 || index >= sections.size()) { sections.add(cachingStrategy.getPropertySection()); } else { sections.add(index, cachingStrategy.getPropertySection()); } } property.setTileCachingStrategy(val.getQualifiedName()); } catch (DescriptorFactory.InstanceNotFountException ex) { Exceptions.printStackTrace(ex); } } } } } } }