/* * 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.wrapper.aggregation.strategy; import de.fub.agg2graph.agg.IMergeHandler; import de.fub.agg2graph.agg.ITraceDistance; 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.processes.AggregationProcess; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.AggregationStrategy; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.DescriptorFactory; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.MergeHandler; import de.fub.maps.project.aggregator.pipeline.wrapper.interfaces.TraceDistance; import de.fub.maps.project.aggregator.xml.ProcessDescriptor; import de.fub.maps.project.aggregator.xml.Property; import de.fub.maps.project.aggregator.xml.PropertySection; import de.fub.maps.project.aggregator.xml.PropertySet; import de.fub.maps.project.models.Aggregator; import de.fub.utilsmodule.node.property.NodeProperty; 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 org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; /** * * @author Serdar */ @NbBundle.Messages({ "GpxmergeMatchIterativeMergeStrategy_Name=Gpx Merge Match Iterative Merge Strategy", "GpxmergeMatchIterativeMergeStrategy_Description=The standard aggregation strategy implementation", "GpxmergeMatchIterativeMergeStrategy_Settings_Name=Gpx Merge Match Iterative Merge Strategy Settings", "GpxmergeMatchIterativeMergeStrategy_Settings_Description=All parameters to configure the GpxmergeMatchIterativeMergeStrategy.", "GpxmergeMatchIterativeMergeStrategy_MaxLookahead_Name=Max Lookahead", "GpxmergeMatchIterativeMergeStrategy_MaxLookahead_Description=No description available", "GpxmergeMatchIterativeMergeStrategy_MaxPathDifference_Name=Max Path Difference", "GpxmergeMatchIterativeMergeStrategy_MaxPathDifference_Description=No description available", "GpxmergeMatchIterativeMergeStrategy_MaxInitDistance_Name=Max Init Distance", "GpxmergeMatchIterativeMergeStrategy_MaxInitDistance_Description=No description available", "GpxmergeMatchIterativeMergeStrategy_MergaHandler_Type_Name=MergeHandler Instance Type", "GpxmergeMatchIterativeMergeStrategy_MergeHandler_Type_Description=The instance that is responsible for merging the data points", "GpxmergeMatchIterativeMergeStrategy_TraceDistance_Type_Name=TraceDistance Instance Type", "GpxmergeMatchIterativeMergeStrategy_TraceDistance_Type_Description=The instance which is responsible for tracing the distance of a segment." }) @ServiceProvider(service = AggregationStrategy.class) public class GpxmergeMatchIterativeMergeStrategy extends de.fub.agg2graph.agg.strategy.GpxmergeMatchIterativeMergeStrategy implements AggregationStrategy { private static final Logger LOG = Logger.getLogger(GpxmergeMatchIterativeMergeStrategy.class.getName()); private static final String PROP_NAME_MAX_LOOKAHEAD = "GpxmergeMatchIterativeMergeStrategy.max.lookahead"; private static final String PROP_NAME_MAX_PATHDIFFERENCE = "GpxmergeMatchIterativeMergeStrategy.max.pathdifference"; private static final String PROP_NAME_MAX_INITDISTANCE = "GpxmergeMatchIterativeMergeStrategy.max.initDistance"; private static final String PROP_NAME_BASE_MERGEHANDLER_TYPE = "GpxmergeMatchIterativeMergeStrategy.base.mergehandler.type"; private static final String PROP_NAME_TRACE_DISTANCE_TYPE = "GpxmergeMatchIterativeMergeStrategy.trace.distance.type"; protected PropertySection propertySection = null; protected Aggregator aggregator; protected Node nodeDelegate = null; public GpxmergeMatchIterativeMergeStrategy() { } @Override public void setTraceDistance(ITraceDistance traceDistance) { this.traceDistance = traceDistance; } @Override public void setBaseMergeHandler(IMergeHandler baseMergeHandler) { this.baseMergeHandler = baseMergeHandler; } @Override public void setAggregator(Aggregator aggregator) { this.aggregator = aggregator; if (aggregator != null) { setAggContainer(aggregator.getAggContainer()); } reInit(); } @Override public Aggregator getAggregator() { return this.aggregator; } @Override public Node getNodeDelegate() { if (nodeDelegate == null) { nodeDelegate = new StrategyNode(GpxmergeMatchIterativeMergeStrategy.this); } return nodeDelegate; } @Override public PropertySection getPropertySection() { if (propertySection == null) { if (getAggregator() != null) { OUTERLOOP: for (ProcessDescriptor descriptor : getAggregator().getAggregatorDescriptor().getPipeline().getList()) { if (descriptor != null && AggregationProcess.class.getName().equals(descriptor.getJavaType())) { for (PropertySection section : descriptor.getProperties().getSections()) { if (GpxmergeMatchIterativeMergeStrategy.class.getName().equals(section.getId())) { propertySection = section; break OUTERLOOP; } } } } } if (propertySection == null) { propertySection = createDefaultDescriptor(); } } return propertySection; } protected PropertySection createDefaultDescriptor() { PropertySet propertySet = new PropertySet( Bundle.GpxmergeMatchIterativeMergeStrategy_Settings_Name(), Bundle.GpxmergeMatchIterativeMergeStrategy_Settings_Description()); propertySet.setId(GpxmergeMatchIterativeMergeStrategy.class.getName()); Property property = new Property(); property.setName(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxLookahead_Name()); property.setDescription(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxLookahead_Description()); property.setId(PROP_NAME_MAX_LOOKAHEAD); property.setJavaType(Integer.class.getName()); property.setValue(MessageFormat.format("{0}", getMaxLookahead()).replaceAll("[^0-9]", "")); propertySet.getProperties().add(property); property = new Property(); property.setName(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxPathDifference_Name()); property.setDescription(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxPathDifference_Description()); property.setId(PROP_NAME_MAX_PATHDIFFERENCE); property.setJavaType(Double.class.getName()); property.setValue(MessageFormat.format("{0}", getMaxLookahead()).replaceAll("\\,", ".")); propertySet.getProperties().add(property); property = new Property(); property.setName(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxInitDistance_Name()); property.setDescription(Bundle.GpxmergeMatchIterativeMergeStrategy_MaxInitDistance_Description()); property.setId(PROP_NAME_MAX_INITDISTANCE); property.setJavaType(Double.class.getName()); property.setValue(MessageFormat.format("{0}", getMaxLookahead()).replaceAll("\\,", ".")); propertySet.getProperties().add(property); property = new Property(); property.setName(Bundle.GpxmergeMatchIterativeMergeStrategy_MergaHandler_Type_Name()); property.setDescription(Bundle.GpxmergeMatchIterativeMergeStrategy_MergeHandler_Type_Description()); property.setId(PROP_NAME_BASE_MERGEHANDLER_TYPE); property.setJavaType(String.class.getName()); property.setValue(IterativeClosestPointsMerge.class.getName()); propertySet.getProperties().add(property); property = new Property(); property.setName(Bundle.GpxmergeMatchIterativeMergeStrategy_TraceDistance_Type_Name()); property.setDescription(Bundle.GpxmergeMatchIterativeMergeStrategy_TraceDistance_Type_Description()); property.setId(PROP_NAME_TRACE_DISTANCE_TYPE); property.setJavaType(String.class.getName()); property.setValue(GpxmergeTraceDistance.class.getName()); propertySet.getProperties().add(property); PropertySection section = new PropertySection( Bundle.GpxmergeMatchIterativeMergeStrategy_Settings_Name(), Bundle.GpxmergeMatchIterativeMergeStrategy_Settings_Description()); section.setId(GpxmergeMatchIterativeMergeStrategy.class.getName()); section.getPropertySet().add(propertySet); MergeHandler handler; try { handler = MergeHandler.Factory.find(IterativeClosestPointsMerge.class.getName()); if (handler != null) { PropertySet desc = handler.getPropertySet(); if (desc != null) { section.getPropertySet().add(desc); } } } catch (DescriptorFactory.InstanceNotFountException ex) { LOG.log(Level.SEVERE, ex.getMessage(), ex); } TraceDistance traceHandler; try { traceHandler = TraceDistance.Factory.find(GpxmergeTraceDistance.class.getName()); if (traceHandler != null) { PropertySet desc = traceHandler.getPropertySet(); if (desc != null) { section.getPropertySet().add(desc); } } } catch (DescriptorFactory.InstanceNotFountException ex) { LOG.log(Level.SEVERE, ex.getMessage(), ex); } return section; } protected void reInit() { propertySection = null; propertySection = getPropertySection(); if (propertySection != null) { List<PropertySet> propertySets = propertySection.getPropertySet(); for (PropertySet propertySet : propertySets) { if (Bundle.GpxmergeMatchIterativeMergeStrategy_Settings_Name().equals(propertySet.getName())) { for (Property property : propertySet.getProperties()) { if (property.getValue() != null) { if (PROP_NAME_MAX_LOOKAHEAD.equals(property.getId())) { setMaxLookahead(Integer.parseInt(property.getValue())); } else if (PROP_NAME_MAX_PATHDIFFERENCE.equals(property.getId())) { setMaxPathDifference(Double.parseDouble(property.getValue())); } else if (PROP_NAME_MAX_INITDISTANCE.equals(property.getId())) { setMaxInitDistance(Double.parseDouble(property.getValue())); } else if (PROP_NAME_BASE_MERGEHANDLER_TYPE.equals(property.getId())) { // create the specified base MergeHandler MergeHandler mHandler = null; try { mHandler = MergeHandler.Factory.find(property.getValue(), aggregator); } catch (DescriptorFactory.InstanceNotFountException ex) { try { mHandler = MergeHandler.Factory.getDefault(); mHandler.setAggregator(aggregator); } catch (DescriptorFactory.InstanceNotFountException ex1) { Exceptions.printStackTrace(ex1); } } baseMergeHandler = mHandler; } else if (PROP_NAME_TRACE_DISTANCE_TYPE.equals(property.getId())) { // create the specified base TraceDistance instance TraceDistance tDistance = null; try { tDistance = TraceDistance.Factory.find(property.getValue(), aggregator); } catch (DescriptorFactory.InstanceNotFountException ex) { try { tDistance = TraceDistance.Factory.getDefault(); tDistance.setAggregator(aggregator); } catch (DescriptorFactory.InstanceNotFountException ex1) { Exceptions.printStackTrace(ex1); } } traceDistance = tDistance; } } } } } } } private static class StrategyNode extends AbstractNode { private static final Logger LOG = Logger.getLogger(StrategyNode.class.getName()); private final GpxmergeMatchIterativeMergeStrategy strategy; public StrategyNode(GpxmergeMatchIterativeMergeStrategy strategy) { super(Children.LEAF); this.strategy = strategy; } @Override protected Sheet createSheet() { Sheet sheet = Sheet.createDefault(); if (strategy != null) { final PropertySection propertySection = strategy.getPropertySection(); if (propertySection != null) { for (final de.fub.maps.project.aggregator.xml.PropertySet propertySet : propertySection.getPropertySet()) { if (GpxmergeMatchIterativeMergeStrategy.class.getName().equals(propertySet.getId())) { Sheet.Set set = Sheet.createPropertiesSet(); sheet.put(set); set.setName(propertySet.getId()); set.setDisplayName(propertySet.getName()); set.setShortDescription(propertySet.getDescription()); List<de.fub.maps.project.aggregator.xml.Property> properties = propertySet.getProperties(); for (final de.fub.maps.project.aggregator.xml.Property property : properties) { if (GpxmergeMatchIterativeMergeStrategy.PROP_NAME_MAX_LOOKAHEAD.equals(property.getId())) { set.put(new NodeProperty(property)); } else if (GpxmergeMatchIterativeMergeStrategy.PROP_NAME_MAX_PATHDIFFERENCE.equals(property.getId())) { set.put(new NodeProperty(property)); } else if (GpxmergeMatchIterativeMergeStrategy.PROP_NAME_MAX_INITDISTANCE.equals(property.getId())) { set.put(new NodeProperty(property)); } else if (GpxmergeMatchIterativeMergeStrategy.PROP_NAME_BASE_MERGEHANDLER_TYPE.equals(property.getId())) { ClassProperty classProperty = new MergeHandlerProperty(propertySection, property); set.put(classProperty); } else if (GpxmergeMatchIterativeMergeStrategy.PROP_NAME_TRACE_DISTANCE_TYPE.equals(property.getId())) { ClassProperty classProperty = new TractDistanceProperty(propertySection, property); set.put(classProperty); } } } } IMergeHandler baseMergeHandler1 = strategy.getBaseMergeHandler(); if (baseMergeHandler1 instanceof MergeHandler) { MergeHandler mergeHandler = (MergeHandler) baseMergeHandler1; PropertySet[] propertySets = mergeHandler.getNodeDelegate().getPropertySets(); for (Node.PropertySet propertySet : propertySets) { Sheet.Set set = convertToSet(propertySet); sheet.put(set); } } ITraceDistance traceDist = strategy.getTraceDist(); if (traceDist instanceof TraceDistance) { TraceDistance traceDistance = (TraceDistance) traceDist; Node.PropertySet[] propertySets = traceDistance.getNodeDelegate().getPropertySets(); for (Node.PropertySet propertySet : propertySets) { Sheet.Set set = convertToSet(propertySet); sheet.put(set); } } } } return sheet; } private Sheet.Set convertToSet(Node.PropertySet propertySet) { Sheet.Set set = Sheet.createPropertiesSet(); set.setName(propertySet.getName()); set.setDisplayName(propertySet.getDisplayName()); set.setShortDescription(propertySet.getShortDescription()); for (Node.Property<?> property : propertySet.getProperties()) { set.put(property); } return set; } private class TractDistanceProperty extends ClassProperty { private final PropertySection propertySection; private final de.fub.maps.project.aggregator.xml.Property property; private ClassWrapper wrapper = strategy.getTraceDist() != null ? new ClassWrapper(strategy.getTraceDist().getClass()) : new ClassWrapper(TraceDistance.class); public TractDistanceProperty(PropertySection propertySection, de.fub.maps.project.aggregator.xml.Property property) { super(property.getId(), property.getName(), property.getDescription(), TraceDistance.class); this.propertySection = propertySection; this.property = property; } @Override public ClassWrapper getValue() throws IllegalAccessException, InvocationTargetException { return wrapper; } @Override @SuppressWarnings(value = "unchecked") public void setValue(ClassWrapper val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (strategy.getAggregator().getAggregatorState() != Aggregator.AggregatorState.RUNNING) { if (val == null) { throw new IllegalArgumentException("null is not a valid argument."); } else if (wrapper == null || !val.getQualifiedName().equals(wrapper.getQualifiedName())) { // only if there is a change proceed. List<de.fub.maps.project.aggregator.xml.PropertySet> propertySets = propertySection.getPropertySet(); ClassWrapper oldValue = getValue(); wrapper = val; int index = -1; if (oldValue != null) { ArrayList<de.fub.maps.project.aggregator.xml.PropertySet> copyList = new ArrayList<de.fub.maps.project.aggregator.xml.PropertySet>(propertySets); // look for the associated propertySet for the old value for (de.fub.maps.project.aggregator.xml.PropertySet propertySet : copyList) { index++; if (propertySet.getId().equals(oldValue.getQualifiedName())) { // remove the associated propertySet LOG.info(MessageFormat.format("{0} removed: {1}", propertySet.getId(), propertySets.remove(propertySet))); // break; } } } // create the respective TraceInstance and update the PropertySet // in the property Set list try { TraceDistance traceDistance = TraceDistance.Factory.find(val.getQualifiedName()); if (traceDistance != null) { // set the ne TraceDistance instance name. property.setValue(val.getQualifiedName()); strategy.setTraceDistance(traceDistance); if (index < 0 || index >= propertySets.size()) { propertySets.add(traceDistance.getPropertySet()); } else { propertySets.add(traceDistance.getPropertySet()); } } } catch (DescriptorFactory.InstanceNotFountException ex) { LOG.log(Level.SEVERE, ex.getMessage(), ex); } } } } } private class MergeHandlerProperty extends ClassProperty { private final de.fub.maps.project.aggregator.xml.Property property; private final PropertySection section; private ClassWrapper wrapper; public MergeHandlerProperty(PropertySection propertySection, de.fub.maps.project.aggregator.xml.Property property) { super(property.getId(), property.getName(), property.getDescription(), MergeHandler.class); this.property = property; this.section = propertySection; wrapper = strategy.getBaseMergeHandler() != null ? new ClassWrapper(strategy.getBaseMergeHandler().getClass()) : new ClassWrapper(MergeHandler.class); } @Override public ClassWrapper getValue() throws IllegalAccessException, InvocationTargetException { return wrapper; } @Override public void setValue(ClassWrapper val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (strategy.getAggregator().getAggregatorState() != Aggregator.AggregatorState.RUNNING) { if (val == null) { throw new IllegalArgumentException("null is not a valid argument."); } else if (wrapper == null || !val.getQualifiedName().equals(wrapper.getQualifiedName())) { ClassWrapper oldValue = this.wrapper; wrapper = val; int index = -1; if (oldValue != null) { for (de.fub.maps.project.aggregator.xml.PropertySet propertySet : section.getPropertySet()) { index++; if (oldValue.getQualifiedName().equals(propertySet.getId())) { LOG.info(MessageFormat.format("PropertySet: {0} removed: {1}", propertySet.getId(), section.getPropertySet().remove(propertySet))); break; } } } try { MergeHandler mergeHandler = MergeHandler.Factory.find(val.getQualifiedName()); if (mergeHandler != null) { strategy.setBaseMergeHandler(mergeHandler); property.setValue(val.getQualifiedName()); if (index < 0 || index >= section.getPropertySet().size()) { section.getPropertySet().add(mergeHandler.getPropertySet()); } else { section.getPropertySet().add(index, mergeHandler.getPropertySet()); } } } catch (DescriptorFactory.InstanceNotFountException ex) { LOG.log(Level.SEVERE, ex.getMessage(), ex); } } } } } } }