Package org.gephi.io.processor.plugin

Source Code of org.gephi.io.processor.plugin.DynamicProcessor

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.io.processor.plugin;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeOrigin;
import org.gephi.data.attributes.api.AttributeRow;
import org.gephi.data.attributes.api.AttributeTable;
import org.gephi.data.attributes.api.AttributeType;
import org.gephi.data.attributes.api.AttributeValue;
import org.gephi.data.attributes.type.DynamicType;
import org.gephi.data.attributes.type.Interval;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.data.attributes.type.TypeConvertor;
import org.gephi.data.properties.PropertiesColumn;
import org.gephi.dynamic.DynamicUtilities;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphFactory;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.gephi.io.importer.api.EdgeDraft.EdgeType;
import org.gephi.io.importer.api.EdgeDraftGetter;
import org.gephi.io.importer.api.NodeDraftGetter;
import org.gephi.io.processor.spi.Processor;
import org.gephi.project.api.ProjectController;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;

/**
* Processor 'Time Frame' that uses its 'date' parameter to associate the content
* of the container to a particular point in time. It locates and modify existing
* elements by appending new time intervals. It also create dynamic attribute
* values, as well as a dynamic weight.
* @author Mathieu Bastian
*/
@ServiceProvider(service = Processor.class)
public class DynamicProcessor extends AbstractProcessor implements Processor {

    //Settings
    private boolean dateMode = true;
    private String date = "";
    private boolean labelmatching = true;
    //Variable
    private double point;

    public void process() {
        ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
        //Workspace
        if (workspace == null) {
            workspace = pc.getCurrentWorkspace();
            if (workspace == null) {
                //Append mode but no workspace
                workspace = pc.newWorkspace(pc.getCurrentProject());
                pc.openWorkspace(workspace);
            }
        }
        if (container.getSource() != null) {
            pc.setSource(workspace, container.getSource());
        }

        //Architecture
        GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();

        HierarchicalGraph graph = null;
        switch (container.getEdgeDefault()) {
            case DIRECTED:
                graph = graphModel.getHierarchicalDirectedGraph();
                break;
            case UNDIRECTED:
                graph = graphModel.getHierarchicalUndirectedGraph();
                break;
            case MIXED:
                graph = graphModel.getHierarchicalMixedGraph();
                break;
            default:
                graph = graphModel.getHierarchicalMixedGraph();
                break;
        }
        GraphFactory factory = graphModel.factory();

        //Attributes - Manually merge models with new dynamic cols
        attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel();
        AttributeTable nodeTable = container.getAttributeModel().getNodeTable();
        AttributeTable edgeTable = container.getAttributeModel().getEdgeTable();
        for (AttributeColumn column : nodeTable.getColumns()) {
            AttributeColumn existingCol = attributeModel.getNodeTable().getColumn(column.getTitle());
            if (existingCol == null) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    AttributeType dynamicType = TypeConvertor.getDynamicType(column.getType());
                    if (dynamicType != null && !column.getType().isDynamicType()) {
                        attributeModel.getNodeTable().addColumn(column.getId(), column.getTitle(), dynamicType, column.getOrigin(), null);
                    } else {
                        attributeModel.getNodeTable().addColumn(column.getId(), column.getTitle(), column.getType(), column.getOrigin(), column.getDefaultValue());
                    }
                }
            }

        }
        for (AttributeColumn column : edgeTable.getColumns()) {
            AttributeColumn existingCol = attributeModel.getEdgeTable().getColumn(column.getTitle());
            if (existingCol == null) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    AttributeType dynamicType = TypeConvertor.getDynamicType(column.getType());
                    if (dynamicType != null && !column.getType().isDynamicType()) {
                        attributeModel.getEdgeTable().addColumn(column.getId(), column.getTitle(), dynamicType, column.getOrigin(), null);
                    } else {
                        attributeModel.getEdgeTable().addColumn(column.getId(), column.getTitle(), column.getType(), column.getOrigin(), column.getDefaultValue());
                    }
                }
            } else if (PropertiesColumn.EDGE_WEIGHT.getId().equals(column.getId()) && !existingCol.getType().isDynamicType()) {
                attributeModel.getEdgeTable().replaceColumn(attributeModel.getEdgeTable().getColumn(PropertiesColumn.EDGE_WEIGHT.getIndex()), PropertiesColumn.EDGE_WEIGHT.getId(), PropertiesColumn.EDGE_WEIGHT.getTitle(), AttributeType.DYNAMIC_FLOAT, AttributeOrigin.PROPERTY, null);
            }
        }

        //Get Time Interval Column
        AttributeColumn nodeDynamicColumn = attributeModel.getNodeTable().getColumn(DynamicModel.TIMEINTERVAL_COLUMN);
        AttributeColumn edgeDynamicColumn = attributeModel.getEdgeTable().getColumn(DynamicModel.TIMEINTERVAL_COLUMN);
        if (nodeDynamicColumn == null) {
            nodeDynamicColumn = attributeModel.getNodeTable().addColumn(DynamicModel.TIMEINTERVAL_COLUMN, "Time Interval", AttributeType.TIME_INTERVAL, AttributeOrigin.PROPERTY, null);
        }
        if (edgeDynamicColumn == null) {
            edgeDynamicColumn = attributeModel.getEdgeTable().addColumn(DynamicModel.TIMEINTERVAL_COLUMN, "Time Interval", AttributeType.TIME_INTERVAL, AttributeOrigin.PROPERTY, null);
        }

        //Get Time stamp
        if (dateMode) {
            try {
                point = DynamicUtilities.getDoubleFromXMLDateString(date);
            } catch (Exception e) {
                throw new RuntimeException("The entered date can't be parsed");
            }
        } else {
            point = Double.parseDouble(date);
        }
        DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
        dynamicController.setTimeFormat(dateMode ? DynamicModel.TimeFormat.DATE : DynamicModel.TimeFormat.DOUBLE);

        //Index existing graph
        Map<String, Node> map = new HashMap<String, Node>();
        for (Node n : graph.getNodes()) {
            String id = n.getNodeData().getId();
            if (id != null && !labelmatching && !id.equalsIgnoreCase(String.valueOf(n.getId()))) {
                map.put(id, n);
            }
            if (n.getNodeData().getLabel() != null && !n.getNodeData().getLabel().isEmpty() && labelmatching) {
                map.put(n.getNodeData().getLabel(), n);
            }
        }

        //Create all nodes
        Set<Node> nodesInDraft = new HashSet<Node>();
        int newNodeCount = 0;
        for (NodeDraftGetter draftNode : container.getNodes()) {
            Node node = null;
            String id = draftNode.getId();
            String label = draftNode.getLabel();
            if (!draftNode.isAutoId() && id != null && map.get(id) != null && !labelmatching) {
                node = map.get(id);
            } else if (label != null && map.get(label) != null && labelmatching) {
                node = map.get(label);
            }

            TimeInterval timeInterval = null;
            if (node == null) {
                //Node is new
                node = factory.newNode(draftNode.isAutoId() ? null : draftNode.getId());
                flushToNode(draftNode, node);
                draftNode.setNode(node);
                newNodeCount++;
            } else {
                timeInterval = (TimeInterval) node.getNodeData().getAttributes().getValue(nodeDynamicColumn.getIndex());
                flushToNodeAttributes(draftNode, node);
                draftNode.setNode(node);
            }
            nodesInDraft.add(node);

            //Add Point
            node.getNodeData().getAttributes().setValue(nodeDynamicColumn.getIndex(), addPoint(timeInterval, point));
        }

        //Push nodes in data structure
        for (NodeDraftGetter draftNode : container.getNodes()) {
            Node n = draftNode.getNode();
            NodeDraftGetter[] parents = draftNode.getParents();
            if (parents != null) {
                for (int i = 0; i < parents.length; i++) {
                    Node parent = parents[i].getNode();
                    graph.addNode(n, parent);
                }
            } else {
                graph.addNode(n);
            }
        }

        //Remove point from all nodes not in draft
        for (Node node : graph.getNodes()) {
            if (!nodesInDraft.contains(node)) {
                TimeInterval timeInterval = (TimeInterval) node.getNodeData().getAttributes().getValue(nodeDynamicColumn.getIndex());
                node.getNodeData().getAttributes().setValue(nodeDynamicColumn.getIndex(), removePoint(timeInterval, point));
            }
        }

        //Create all edges and push to data structure
        Set<Edge> edgesInDraft = new HashSet<Edge>();
        int newEdgeCount = 0;
        for (EdgeDraftGetter draftEdge : container.getEdges()) {
            Node source = draftEdge.getSource().getNode();
            Node target = draftEdge.getTarget().getNode();
            Edge edge = graph.getEdge(source, target);
            TimeInterval timeInterval = null;
            if (edge == null) {
                //Edge is new
                switch (container.getEdgeDefault()) {
                    case DIRECTED:
                        edge = factory.newEdge(draftEdge.isAutoId() ? null : draftEdge.getId(), source, target, draftEdge.getWeight(), true);
                        break;
                    case UNDIRECTED:
                        edge = factory.newEdge(draftEdge.isAutoId() ? null : draftEdge.getId(), source, target, draftEdge.getWeight(), false);
                        break;
                    case MIXED:
                        edge = factory.newEdge(draftEdge.isAutoId() ? null : draftEdge.getId(), source, target, draftEdge.getWeight(), draftEdge.getType().equals(EdgeType.UNDIRECTED) ? false : true);
                        break;
                }
                newEdgeCount++;
                graph.addEdge(edge);
                flushToEdge(draftEdge, edge);
            } else {
                timeInterval = (TimeInterval) edge.getEdgeData().getAttributes().getValue(edgeDynamicColumn.getIndex());
                flushToEdgeAttributes(draftEdge, edge);
            }
            edgesInDraft.add(edge);

            //Add Point
            edge.getEdgeData().getAttributes().setValue(edgeDynamicColumn.getIndex(), addPoint(timeInterval, point));
        }

        //Remove point from all edges not in draft
        for (Edge edge : graph.getEdges()) {
            if (!edgesInDraft.contains(edge)) {
                TimeInterval timeInterval = (TimeInterval) edge.getEdgeData().getAttributes().getValue(edgeDynamicColumn.getIndex());
                edge.getEdgeData().getAttributes().setValue(edgeDynamicColumn.getIndex(), removePoint(timeInterval, point));
            }
        }

        System.out.println("# New Nodes loaded: " + newNodeCount + "\n# New Edges loaded: " + newEdgeCount);
        workspace = null;
    }

    @Override
    protected void flushToNodeAttributes(NodeDraftGetter nodeDraft, Node node) {
        if (node.getNodeData().getAttributes() != null) {
            AttributeRow row = (AttributeRow) node.getNodeData().getAttributes();
            for (int i = 0; i < row.countValues(); i++) {
                Object val = row.getValue(i);
                AttributeColumn col = row.getColumnAt(i);
                Object draftValue = nodeDraft.getAttributeRow().getValue(col.getId());
                if (col.getType().isDynamicType()) {
                    if (draftValue == null && val != null) {
                        removePoint(col.getType(), (DynamicType) val, point);
                    } else if (draftValue != null) {
                        DynamicType dynamicValue = addPoint(col.getType(), (DynamicType) val, draftValue, point);
                        row.setValue(col.getIndex(), dynamicValue);
                    }
                } else if (draftValue != null && !col.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    row.setValue(col.getIndex(), draftValue);
                }
            }
        }
    }

    @Override
    protected void flushToEdgeAttributes(EdgeDraftGetter edgeDraft, Edge edge) {
        if (edge.getEdgeData().getAttributes() != null) {
            AttributeRow row = (AttributeRow) edge.getEdgeData().getAttributes();
            for (int i = 0; i < row.countValues(); i++) {
                Object val = row.getValue(i);
                AttributeColumn col = row.getColumnAt(i);
                Object draftValue = edgeDraft.getAttributeRow().getValue(col);
                if (col.getId().equals(PropertiesColumn.EDGE_WEIGHT.getId())) {
                    draftValue = new Float(edgeDraft.getWeight());
                }
                if (col.getType().isDynamicType()) {
                    if (draftValue == null && val != null) {
                        removePoint(col.getType(), (DynamicType) val, point);
                    } else if (draftValue != null) {
                        DynamicType dynamicValue = addPoint(col.getType(), (DynamicType) val, draftValue, point);
                        row.setValue(col.getIndex(), dynamicValue);
                    }
                } else if (draftValue != null && !col.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    row.setValue(col.getIndex(), draftValue);
                }
            }
        }
    }

    private TimeInterval addPoint(TimeInterval source, double point) {
        if (source == null) {
            return new TimeInterval(point, Double.POSITIVE_INFINITY);
        }
        List<Interval<Double[]>> intervals = source.getIntervals(point, point);
        if (intervals.isEmpty()) {
            return new TimeInterval(source, point, Double.POSITIVE_INFINITY);
        }
        return source;
    }

    private DynamicType addPoint(AttributeType type, DynamicType source, Object value, double point) {
        if (source == null) {
            return DynamicUtilities.createDynamicObject(type, new Interval(point, Double.POSITIVE_INFINITY, value));
        }
        List<Interval<?>> intervals = source.getIntervals(point, point);
        if (intervals.isEmpty()) {
            return DynamicUtilities.createDynamicObject(type, source, new Interval(point, Double.POSITIVE_INFINITY, value));
        } else if (intervals.size() > 1) {
            throw new RuntimeException("DynamicProcessor doesn't support overlapping intervals.");
        } else {
            Interval<?> toRemove = intervals.get(0);
            if (!toRemove.getValue().equals(value)) {
                Interval toAdd = new Interval(toRemove.getLow(), point, toRemove.isLowExcluded(), true, toRemove.getValue());
                DynamicType updated = DynamicUtilities.createDynamicObject(type, source, toAdd, toRemove);
                toAdd = new Interval(point, Double.POSITIVE_INFINITY, value);
                updated = DynamicUtilities.createDynamicObject(type, updated, toAdd);
                return updated;
            }
        }
        return source;
    }

    private TimeInterval removePoint(TimeInterval source, double point) {
        if (source == null) {
            return null;
        }
        List<Interval<Double[]>> intervals = source.getIntervals(point, point);
        if (intervals.size() > 1) {
            throw new RuntimeException("DynamicProcessor doesn't support overlapping intervals.");
        } else if (!intervals.isEmpty()) {
            Interval<Double[]> toRemove = intervals.get(0);
            if (toRemove.getLow() >= point) {
                return source;
            }

            Double[] toAdd = new Double[]{toRemove.getLow(), point};

            return new TimeInterval(source, toAdd[0], toAdd[1], toRemove.isLowExcluded(), true, toRemove.getLow(), toRemove.getHigh(), toRemove.isLowExcluded(), toRemove.isHighExcluded());
        }
        return source;
    }

    private DynamicType removePoint(AttributeType type, DynamicType source, double point) {
        if (source == null) {
            return null;
        }
        List<Interval<?>> intervals = source.getIntervals(point, point);
        if (intervals.size() > 1) {
            throw new RuntimeException("DynamicProcessor doesn't support overlapping intervals.");
        } else if (!intervals.isEmpty()) {
            Interval<?> toRemove = intervals.get(0);
            if (toRemove.getLow() >= point) {
                return source;
            }

            Interval toAdd = new Interval(toRemove.getLow(), point, toRemove.isLowExcluded(), true, toRemove.getValue());
            return DynamicUtilities.createDynamicObject(type, source, toAdd, toRemove);
        }
        return source;
    }

    public String getDisplayName() {
        return NbBundle.getMessage(DynamicProcessor.class, "DynamicProcessor.displayName");
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public boolean isDateMode() {
        return dateMode;
    }

    public void setDateMode(boolean dateMode) {
        this.dateMode = dateMode;
    }

    public boolean isLabelmatching() {
        return labelmatching;
    }

    public void setLabelmatching(boolean labelmatching) {
        this.labelmatching = labelmatching;
    }
}
TOP

Related Classes of org.gephi.io.processor.plugin.DynamicProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.