diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AppearanceModelImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AppearanceModelImpl.java index 250d2878a465daa5cf91d48140e8d997a8ae8c4e..6a678f22858f390a5efd6492641f0e9cd2cd9216 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AppearanceModelImpl.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AppearanceModelImpl.java @@ -49,7 +49,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.gephi.appearance.api.AppearanceModel; -import org.gephi.appearance.api.AttributeFunction; import org.gephi.appearance.api.Function; import org.gephi.appearance.api.Interpolator; import org.gephi.appearance.spi.PartitionTransformer; @@ -59,11 +58,20 @@ import org.gephi.appearance.spi.Transformer; import org.gephi.appearance.spi.TransformerUI; import org.gephi.graph.api.AttributeUtils; import org.gephi.graph.api.Column; +import org.gephi.graph.api.ColumnObserver; +import org.gephi.graph.api.DirectedGraph; +import org.gephi.graph.api.Edge; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; import org.gephi.graph.api.Index; import org.gephi.graph.api.GraphController; import org.gephi.graph.api.GraphModel; +import org.gephi.graph.api.GraphObserver; +import org.gephi.graph.api.Node; +import org.gephi.graph.api.Table; import org.gephi.project.api.Workspace; import org.openide.util.Lookup; +import org.openide.util.NbBundle; /** * @@ -75,19 +83,29 @@ public class AppearanceModelImpl implements AppearanceModel { private final GraphModel graphModel; private final Interpolator defaultInterpolator; private boolean localScale = false; + // Transformers + private final List nodeTransformers; + private final List edgeTransformers; + // Transformer UIS + private final Map transformerUIs; //Functions private final Object functionLock; - private List nodeFunctions; - private List edgeFunctions; + // + private final FunctionsModel functionsMain; + private final Map functions = new HashMap(); public AppearanceModelImpl(Workspace workspace) { this.workspace = workspace; this.graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace); this.defaultInterpolator = Interpolator.LINEAR; this.functionLock = new Object(); + this.transformerUIs = initTransformerUIs(); + this.nodeTransformers = initNodeTransformers(); + this.edgeTransformers = initEdgeTransformers(); //Functions - refreshFunctions(); + functionsMain = new FunctionsModel(graphModel.getGraph()); + refreshFunctions(graphModel.getGraph()); } @Override @@ -101,125 +119,405 @@ public class AppearanceModelImpl implements AppearanceModel { } @Override - public Function[] getNodeFunctions() { - refreshFunctions(); - return nodeFunctions.toArray(new Function[0]); + public Function[] getNodeFunctions(Graph graph) { + return refreshFunctions(graph).getNodeFunctions(); } @Override - public Function[] getEdgeFunctions() { - refreshFunctions(); - return edgeFunctions.toArray(new Function[0]); + public Function[] getEdgeFunctions(Graph graph) { + return refreshFunctions(graph).getEdgeFunctions(); } - private void refreshFunctions() { + private FunctionsModel refreshFunctions(Graph graph) { synchronized (functionLock) { - //Index UIs - Map uis = new HashMap(); - for (TransformerUI ui : Lookup.getDefault().lookupAll(TransformerUI.class)) { - Class transformerClass = ui.getTransformerClass(); - if (transformerClass == null) { - throw new NullPointerException("Transformer class can' be null"); + FunctionsModel m; + if (graph.getView().isMainView()) { + m = functionsMain; + } else { + m = functions.get(graph); + if (m == null) { + m = new FunctionsModel(graph); + functions.put(graph, m); } - if (uis.containsKey(transformerClass)) { - throw new RuntimeException("A Transformer can't be attach to multiple TransformerUI"); + } + + //Check and detroy old + for (Iterator> it = functions.entrySet().iterator(); + it.hasNext();) { + Map.Entry entry = it.next(); + if (entry.getKey().getView().isDestroyed()) { + it.remove(); } - uis.put(transformerClass, ui); } + return m; + } + } - //Index existing funcs - Set attributeNodeFunctions = new HashSet(); - Set attributeEdgeFunctions = new HashSet(); - if (nodeFunctions != null) { - for (Function f : nodeFunctions) { - if (f.isAttribute()) { - attributeNodeFunctions.add(((AttributeFunction) f).getColumn()); + private class NodeFunctionsModel extends ElementFunctionsModel { + + public NodeFunctionsModel(Graph graph) { + super(graph); + } + + @Override + public Iterable getElements() { + return graph.getNodes(); + } + + @Override + public Table getTable() { + return graph.getModel().getNodeTable(); + } + + @Override + public Index getIndex(boolean localScale) { + return localScale ? graph.getModel().getNodeIndex(graph.getView()) : graph.getModel().getNodeIndex(); + } + + @Override + public List getTransformers() { + return nodeTransformers; + } + + @Override + public String getIdPrefix() { + return "node"; + } + + @Override + public void refreshGraphFunctions() { + if (!rankings.containsKey(getId("degree"))) { + rankings.put(getId("degree"), new DegreeRankingImpl(graph, defaultInterpolator)); + } + if (graph.isDirected()) { + if (!rankings.containsKey(getId("indegree"))) { + DirectedGraph directedGraph = (DirectedGraph) graph; + rankings.put(getId("indegree"), new InDegreeRankingImpl(directedGraph, defaultInterpolator)); + rankings.put(getId("outdegree"), new OutDegreeRankingImpl(directedGraph, defaultInterpolator)); + } + } else { + rankings.remove(getId("indegree")); + rankings.remove(getId("outdegree")); + } + + // Degree functions + for (Transformer t : getRankingTransformers()) { + String degreeId = getId(t, "degree"); + RankingImpl degreeRanking = rankings.get(getId("degree")); + if (!graphFunctions.containsKey(degreeId)) { + String name = NbBundle.getMessage(AppearanceModelImpl.class, "NodeGraphFunction.Degree.name"); + graphFunctions.put(degreeId, new GraphFunctionImpl(degreeId, name, graph, t, getTransformerUI(t), degreeRanking)); + } + degreeRanking.refresh(); + + String indegreeId = getId(t, "indegree"); + String outdegreeId = getId(t, "outdegree"); + + RankingImpl indegreeRanking = rankings.get(getId("indegree")); + RankingImpl outdegreeRanking = rankings.get(getId("outdegree")); + if (indegreeRanking != null && outdegreeRanking != null) { + if (!graphFunctions.containsKey(indegreeId)) { + String inDegreeName = NbBundle.getMessage(AppearanceModelImpl.class, "NodeGraphFunction.InDegree.name"); + String outDegreeName = NbBundle.getMessage(AppearanceModelImpl.class, "NodeGraphFunction.OutDegree.name"); + graphFunctions.put(indegreeId, new GraphFunctionImpl(indegreeId, inDegreeName, graph, t, getTransformerUI(t), indegreeRanking)); + graphFunctions.put(outdegreeId, new GraphFunctionImpl(outdegreeId, outDegreeName, graph, t, getTransformerUI(t), outdegreeRanking)); } + indegreeRanking.refresh(); + outdegreeRanking.refresh(); + } else { + graphFunctions.remove(indegreeId); + graphFunctions.remove(outdegreeId); + } + } + } + } + + private class EdgeFunctionsModel extends ElementFunctionsModel { + + public EdgeFunctionsModel(Graph graph) { + super(graph); + } + + @Override + public Iterable getElements() { + return graph.getEdges(); + } + + @Override + public Table getTable() { + return graph.getModel().getNodeTable(); + } + + @Override + public Index getIndex(boolean localScale) { + return localScale ? graph.getModel().getEdgeIndex(graph.getView()) : graph.getModel().getEdgeIndex(); + } + + @Override + public List getTransformers() { + return edgeTransformers; + } + + @Override + public String getIdPrefix() { + return "edge"; + } + + @Override + public void refreshGraphFunctions() { + if (!rankings.containsKey(getId("weight"))) { + rankings.put(getId("weight"), new EdgeWeightRankingImpl(graph, defaultInterpolator)); + } + if (graph.getModel().isMultiGraph()) { + if (!partitions.containsKey(getId("type"))) { + partitions.put(getId("type"), new EdgeTypePartitionImpl(graph)); + } + } else { + partitions.remove(getId("type")); + } + + // Weight function + for (Transformer t : getRankingTransformers()) { + String weightId = getId(t, "weight"); + RankingImpl ranking = rankings.get(getId("weight")); + if (!graphFunctions.containsKey(weightId)) { + String name = NbBundle.getMessage(AppearanceModelImpl.class, "EdgeGraphFunction.Weight.name"); + graphFunctions.put(weightId, new GraphFunctionImpl(weightId, name, graph, t, getTransformerUI(t), ranking)); } + ranking.refresh(); } - if (edgeFunctions != null) { - for (Function f : edgeFunctions) { - if (f.isAttribute()) { - attributeEdgeFunctions.add(((AttributeFunction) f).getColumn()); + + // Type Function + for (Transformer t : getPartitionTransformers()) { + String typeId = getId(t, "type"); + PartitionImpl partition = partitions.get(getId("type")); + if (partition != null) { + if (!graphFunctions.containsKey(typeId)) { + String name = NbBundle.getMessage(AppearanceModelImpl.class, "EdgeGraphFunction.Type.name"); + graphFunctions.put(typeId, new GraphFunctionImpl(typeId, name, graph, t, getTransformerUI(t), partition)); } + //Refresh + } else { + graphFunctions.remove(typeId); } } + } + } - //Simple transformers - if (nodeFunctions == null) { - nodeFunctions = new ArrayList(); - edgeFunctions = new ArrayList(); + private class FunctionsModel { - for (Transformer transformer : Lookup.getDefault().lookupAll(Transformer.class)) { - if (transformer instanceof SimpleTransformer) { - if (transformer.isNode()) { - nodeFunctions.add(new FunctionImpl(this, null, transformer, uis.get(transformer.getClass()))); - } - if (transformer.isEdge()) { - edgeFunctions.add(new FunctionImpl(this, null, transformer, uis.get(transformer.getClass()))); - } + protected final Graph graph; + protected final NodeFunctionsModel nodeFunctionsModel; + protected final EdgeFunctionsModel edgeFunctionsModel; + + public FunctionsModel(Graph graph) { + this.graph = graph; + this.nodeFunctionsModel = new NodeFunctionsModel(graph); + this.edgeFunctionsModel = new EdgeFunctionsModel(graph); + } + + public Function[] getNodeFunctions() { + return getFunctions(nodeFunctionsModel).toArray(new Function[0]); + } + + public Function[] getEdgeFunctions() { + return getFunctions(nodeFunctionsModel).toArray(new Function[0]); + } + + private List getFunctions(ElementFunctionsModel model) { + model.refreshFunctions(); + List functions = new ArrayList(); + functions.addAll(model.simpleFunctions.values()); + functions.addAll(model.graphFunctions.values()); + functions.addAll(model.attributeFunctions.values()); + return functions; + } + } + + private abstract class ElementFunctionsModel { + + protected final Graph graph; + protected final GraphObserver graphObserver; + protected final Map columnObservers; + protected final Map simpleFunctions; + protected final Map graphFunctions; + protected final Map attributeFunctions; + protected final Map partitions; + protected final Map rankings; + + protected ElementFunctionsModel(Graph graph) { + this.graph = graph; + simpleFunctions = new HashMap(); + graphFunctions = new HashMap(); + attributeFunctions = new HashMap(); + columnObservers = new HashMap(); + graphObserver = graph.getModel().createGraphObserver(graph, false); + partitions = new HashMap(); + rankings = new HashMap(); + + // Init simple + initSimpleFunctions(); + } + + public abstract Iterable getElements(); + + public abstract Table getTable(); + + public abstract Index getIndex(boolean localScale); + + public abstract List getTransformers(); + + public abstract String getIdPrefix(); + + public abstract void refreshGraphFunctions(); + + protected void refreshFunctions() { + graph.readLock(); + boolean graphHasChanged = graphObserver.isNew() || graphObserver.hasGraphChanged(); + if (graphHasChanged) { + refreshGraphFunctions(); + } + refreshAttributeFunctions(graphHasChanged); + graph.readUnlock(); + } + + private void refreshAttributeFunctions(boolean graphHasChanged) { + Set columns = new HashSet(); + for (Column column : getTable()) { + if (!column.isProperty() && column.isIndexed()) { + columns.add(column); + } + } + + //Clean + for (Iterator> itr = columnObservers.entrySet().iterator(); itr.hasNext();) { + Map.Entry entry = itr.next(); + if (columns.contains(entry.getKey())) { + rankings.remove(getId(entry.getKey())); + partitions.remove(getId(entry.getKey())); + for (Transformer t : getTransformers()) { + attributeFunctions.remove(getId(t, entry.getKey())); } + itr.remove(); } } - //Atts - Set foundNodeColumns = new HashSet(); - Set foundEdgeColumns = new HashSet(); - for (Transformer transformer : Lookup.getDefault().lookupAll(Transformer.class)) { - if (transformer instanceof RankingTransformer || transformer instanceof PartitionTransformer) { - if (transformer.isNode()) { - for (Column col : graphModel.getNodeTable()) { - if (!col.isProperty()) { - Index index = localScale ? graphModel.getNodeIndex(graphModel.getVisibleView()) : graphModel.getNodeIndex(); - if (transformer instanceof RankingTransformer && isRanking(col) && !attributeNodeFunctions.contains(col)) { - nodeFunctions.add(new FunctionImpl(this, col, transformer, uis.get(transformer.getClass()), new RankingImpl(col, index, defaultInterpolator))); - } else if (transformer instanceof PartitionTransformer && isPartition(col) && !attributeNodeFunctions.contains(col)) { - nodeFunctions.add(new FunctionImpl(this, col, transformer, uis.get(transformer.getClass()), new PartitionImpl(col, index))); - } - foundNodeColumns.add(col); - } + + //Get columns to be refreshed + List toRefreshColumns = new ArrayList(); + for (Column column : columns) { + if (!columnObservers.containsKey(column)) { + columnObservers.put(column, column.createColumnObserver()); + toRefreshColumns.add(column); + } else if (columnObservers.get(column).hasColumnChanged() || graphHasChanged) { + toRefreshColumns.add(column); + } + } + + //Refresh ranking and partitions + for (Column column : toRefreshColumns) { + RankingImpl ranking = rankings.get(getId(column)); + PartitionImpl partition = partitions.get(getId(column)); + if (ranking == null && partition == null) { + if (isPartition(graph, column)) { + partition = new AttributePartitionImpl(column, getIndex(false)); + partitions.put(getId(column), partition); + } else { + ranking = new AttributeRankingImpl(column, getIndex(localScale), defaultInterpolator); + rankings.put(getId(column), ranking); + } + } + if (ranking != null) { + ranking.refresh(); + } + if (partition != null) { + //Refresh + } + } + + //Ranking functions + for (Transformer t : getRankingTransformers()) { + for (Column col : toRefreshColumns) { + RankingImpl ranking = rankings.get(getId(col)); + if (ranking != null) { + String id = getId(t, col); + if (!attributeFunctions.containsKey(id)) { + attributeFunctions.put(id, new AttributeFunctionImpl(id, graph, col, t, getTransformerUI(t), ranking)); } } - if (transformer.isEdge()) { - for (Column col : graphModel.getEdgeTable()) { - if (!col.isProperty() && col.isNumber()) { - Index index = localScale ? graphModel.getEdgeIndex(graphModel.getVisibleView()) : graphModel.getEdgeIndex(); - if (transformer instanceof RankingTransformer && isRanking(col) && !attributeEdgeFunctions.contains(col)) { - edgeFunctions.add(new FunctionImpl(this, col, transformer, uis.get(transformer.getClass()), new RankingImpl(col, index, defaultInterpolator))); - } else if (transformer instanceof PartitionTransformer && isPartition(col) && !attributeEdgeFunctions.contains(col)) { - edgeFunctions.add(new FunctionImpl(this, col, transformer, uis.get(transformer.getClass()), new PartitionImpl(col, index))); - } - foundEdgeColumns.add(col); - } + } + } + + //Partition functions + for (Transformer t : getPartitionTransformers()) { + for (Column col : toRefreshColumns) { + PartitionImpl partition = partitions.get(getId(col)); + if (partition != null) { + String id = getId(t, col); + if (!attributeFunctions.containsKey(id)) { + attributeFunctions.put(id, new AttributeFunctionImpl(id, graph, col, t, getTransformerUI(t), partition)); } } } } - attributeNodeFunctions.removeAll(foundNodeColumns); - attributeEdgeFunctions.removeAll(foundEdgeColumns); - - //Remove - for (Iterator nodeItr = nodeFunctions.iterator(); nodeItr.hasNext();) { - Function f = nodeItr.next(); - if (f.isAttribute() && attributeNodeFunctions.contains(((AttributeFunction) f).getColumn())) { - nodeItr.remove(); + } + + private void initSimpleFunctions() { + for (Transformer transformer : getTransformers()) { + if (transformer instanceof SimpleTransformer) { + String id = getId(transformer, "simple"); + simpleFunctions.put(id, new SimpleFunctionImpl(id, graph, transformer, getTransformerUI(transformer))); } } - for (Iterator edgeItr = edgeFunctions.iterator(); edgeItr.hasNext();) { - Function f = edgeItr.next(); - if (f.isAttribute() && attributeEdgeFunctions.contains(((AttributeFunction) f).getColumn())) { - edgeItr.remove(); + } + + protected TransformerUI getTransformerUI(Transformer transformer) { + return transformerUIs.get(transformer.getClass()); + } + + protected List getRankingTransformers() { + List res = new ArrayList(); + for (Transformer t : getTransformers()) { + if (t instanceof RankingTransformer) { + res.add(t); + } + } + return res; + } + + protected List getPartitionTransformers() { + List res = new ArrayList(); + for (Transformer t : getTransformers()) { + if (t instanceof PartitionTransformer) { + res.add(t); } } + return res; + } + + protected String getId(Transformer transformer, Column column) { + return getIdPrefix() + "_" + transformer.getClass().getSimpleName() + "_column_" + column.getId(); + } + + protected String getId(Transformer transformer, String suffix) { + return getIdPrefix() + "_" + transformer.getClass().getSimpleName() + "_" + suffix; + } + + protected String getId(Column column) { + return getIdPrefix() + "_column_" + column.getId(); + } + + protected String getId(String suffix) { + return getIdPrefix() + "_" + suffix; } } - private boolean isPartition(Column column) { + private boolean isPartition(Graph graph, Column column) { Index index; if (AttributeUtils.isNodeColumn(column)) { - index = localScale ? graphModel.getNodeIndex(graphModel.getVisibleView()) : graphModel.getNodeIndex(); + index = graphModel.getNodeIndex(graph.getView()); } else { - index = localScale ? graphModel.getEdgeIndex(graphModel.getVisibleView()) : graphModel.getEdgeIndex(); + index = graphModel.getEdgeIndex(graph.getView()); } int valueCount = index.countValues(column); int elementCount = index.countElements(column); @@ -230,28 +528,24 @@ public class AppearanceModelImpl implements AppearanceModel { if (ratio < 0.6) { return true; } - } else { - if (ratio < 0.1) { - return true; - } - } - } else { - if (ratio < 0.8) { + } else if (ratio < 0.1) { return true; } + } else if (ratio < 0.8) { + return true; } return false; } - private boolean isRanking(Column column) { + private boolean isRanking(Graph graph, Column column) { if (column.isNumber()) { Index index; if (AttributeUtils.isNodeColumn(column)) { - index = localScale ? graphModel.getNodeIndex(graphModel.getVisibleView()) : graphModel.getNodeIndex(); + index = localScale ? graphModel.getNodeIndex(graph.getView()) : graphModel.getNodeIndex(); } else { - index = localScale ? graphModel.getEdgeIndex(graphModel.getVisibleView()) : graphModel.getEdgeIndex(); + index = localScale ? graphModel.getEdgeIndex(graph.getView()) : graphModel.getEdgeIndex(); } - if (index.countValues(column) > 0 && !isPartition(column)) { + if (index.countValues(column) > 0 && !isPartition(graph, column)) { return true; } } @@ -265,4 +559,41 @@ public class AppearanceModelImpl implements AppearanceModel { protected GraphModel getGraphModel() { return graphModel; } + + private Map initTransformerUIs() { + //Index UIs + Map uis = new HashMap(); + + for (TransformerUI ui : Lookup.getDefault().lookupAll(TransformerUI.class)) { + Class transformerClass = ui.getTransformerClass(); + if (transformerClass == null) { + throw new NullPointerException("Transformer class can' be null"); + } + if (uis.containsKey(transformerClass)) { + throw new RuntimeException("A Transformer can't be attach to multiple TransformerUI"); + } + uis.put(transformerClass, ui); + } + return uis; + } + + private List initNodeTransformers() { + List res = new ArrayList(); + for (Transformer transformer : Lookup.getDefault().lookupAll(Transformer.class)) { + if (transformer.isNode()) { + res.add(transformer); + } + } + return res; + } + + private List initEdgeTransformers() { + List res = new ArrayList(); + for (Transformer transformer : Lookup.getDefault().lookupAll(Transformer.class)) { + if (transformer.isEdge()) { + res.add(transformer); + } + } + return res; + } } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeFunctionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeFunctionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..f121cc6e3af46a093fe195faefcb284a8f05283a --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeFunctionImpl.java @@ -0,0 +1,51 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.AttributeFunction; +import org.gephi.appearance.api.Partition; +import org.gephi.appearance.api.PartitionFunction; +import org.gephi.appearance.api.Ranking; +import org.gephi.appearance.api.RankingFunction; +import org.gephi.appearance.spi.Transformer; +import org.gephi.appearance.spi.TransformerUI; +import org.gephi.graph.api.Column; +import org.gephi.graph.api.Graph; + +/** + * + * @author mbastian + */ +public class AttributeFunctionImpl extends FunctionImpl implements RankingFunction, PartitionFunction, AttributeFunction { + + public AttributeFunctionImpl(String id, Graph graph, Column column, Transformer transformer, TransformerUI transformerUI, RankingImpl ranking) { + super(id, null, graph, column, transformer, transformerUI, null, ranking); + } + + public AttributeFunctionImpl(String id, Graph graph, Column column, Transformer transformer, TransformerUI transformerUI, PartitionImpl partition) { + super(id, null, graph, column, transformer, transformerUI, partition, null); + } + + @Override + public Column getColumn() { + return column; + } + + @Override + public Partition getPartition() { + return partition; + } + + @Override + public Ranking getRanking() { + return ranking; + } + + @Override + public String toString() { + return column.getTitle(); + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributePartitionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributePartitionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..9910a8bc351a736a0f7b17c38fb23143eddb0e88 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributePartitionImpl.java @@ -0,0 +1,120 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import org.gephi.graph.api.Column; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Index; + +/** + * + * @author mbastian + */ +public class AttributePartitionImpl extends PartitionImpl { + + protected final Index index; + protected final Column column; + + public AttributePartitionImpl(Column column, Index index) { + super(); + this.column = column; + this.index = index; + } + + @Override + public Object getValue(Element element) { + return element.getAttribute(column); + } + + @Override + public Iterable getValues() { + return index.values(column); + } + + @Override + public int getElementCount() { + return index.countElements(column); + } + + @Override + public int count(Object value) { + return index.count(column, value); + } + + @Override + public float percentage(Object value) { + int count = index.count(column, value); + return (float) count / index.countElements(column); + } + + @Override + public int size() { + return index.countValues(column); + } + + @Override + public Column getColumn() { + return column; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 23 * hash + (this.column != null ? this.column.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final AttributePartitionImpl other = (AttributePartitionImpl) obj; + if (this.column != other.column && (this.column == null || !this.column.equals(other.column))) { + return false; + } + return true; + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeRankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeRankingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..330c716c4a342bc2c0dea07ee374696d1d327dd2 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/AttributeRankingImpl.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.Interpolator; +import org.gephi.graph.api.Column; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Index; + +/** + * + * @author mbastian + */ +public class AttributeRankingImpl extends RankingImpl { + + protected final Index index; + protected final Column column; + + public AttributeRankingImpl(Column column, Index index, Interpolator interpolator) { + super(interpolator); + this.column = column; + this.index = index; + } + + @Override + protected void refresh() { + min = index.getMinValue(column); + max = index.getMaxValue(column); + } + + @Override + public Number getValue(Element element) { + return (Number) element.getAttribute(column); + } + + @Override + public int hashCode() { + int hash = 3; + hash = 67 * hash + (this.column != null ? this.column.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final AttributeRankingImpl other = (AttributeRankingImpl) obj; + if (this.column != other.column && (this.column == null || !this.column.equals(other.column))) { + return false; + } + return true; + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/DegreeRankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/DegreeRankingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a32ed8f5d2973278733ab07a64b1f7ecaba9d316 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/DegreeRankingImpl.java @@ -0,0 +1,81 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.Interpolator; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; +import org.gephi.graph.api.Node; + +/** + * + * @author mbastian + */ +public class DegreeRankingImpl extends RankingImpl { + + private final Graph graph; + + public DegreeRankingImpl(Graph graph, Interpolator interpolator) { + super(interpolator); + this.graph = graph; + } + + @Override + public Number getValue(Element element) { + return graph.getDegree((Node) element); + } + + @Override + protected void refresh() { + if (graph.getNodeCount() > 0) { + int minV = Integer.MAX_VALUE; + int maxV = Integer.MIN_VALUE; + for (Node n : graph.getNodes()) { + int degree = graph.getDegree(n); + minV = Math.min(degree, minV); + maxV = Math.max(degree, maxV); + } + min = minV; + max = maxV; + } + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeTypePartitionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeTypePartitionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a8834ecb7cd3515dd95bcb00bae69848c1955a34 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeTypePartitionImpl.java @@ -0,0 +1,101 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import java.util.Arrays; +import org.gephi.graph.api.Column; +import org.gephi.graph.api.Edge; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; +import org.gephi.graph.api.GraphModel; + +/** + * + * @author mbastian + */ +public class EdgeTypePartitionImpl extends PartitionImpl { + + protected final Graph graph; + protected final GraphModel model; + + public EdgeTypePartitionImpl(Graph graph) { + super(); + this.graph = graph; + this.model = graph.getModel(); + } + + @Override + public Iterable getValues() { + return Arrays.asList(model.getEdgeTypeLabels()); + } + + @Override + public Object getValue(Element element) { + return ((Edge) element).getTypeLabel(); + } + + @Override + public int getElementCount() { + return graph.getEdgeCount(); + } + + @Override + public int count(Object value) { + return graph.getEdgeCount(model.getEdgeType(value)); + } + + @Override + public float percentage(Object value) { + int count = count(value); + return (float) count / graph.getEdgeCount(); + } + + @Override + public int size() { + return model.getEdgeTypeCount(); + } + + @Override + public Column getColumn() { + return null; + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeWeightRankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeWeightRankingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..d023b6a41b07e48527f18603e91bdf00b3aaf788 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/EdgeWeightRankingImpl.java @@ -0,0 +1,81 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.Interpolator; +import org.gephi.graph.api.Edge; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; + +/** + * + * @author mbastian + */ +public class EdgeWeightRankingImpl extends RankingImpl { + + private final Graph graph; + + public EdgeWeightRankingImpl(Graph graph, Interpolator interpolator) { + super(interpolator); + this.graph = graph; + } + + @Override + public Number getValue(Element element) { + return ((Edge) element).getWeight(); + } + + @Override + protected void refresh() { + if (graph.getEdgeCount() > 0) { + double minV = Double.MAX_VALUE; + double maxV = Double.MIN_VALUE; + for (Edge e : graph.getEdges()) { + double weight = e.getWeight(); + minV = Math.min(weight, minV); + maxV = Math.max(weight, maxV); + } + min = minV; + max = maxV; + } + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/FunctionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/FunctionImpl.java index 61aa14c26b5ca15dcb34d0673437d1c370e3ae81..5962347b54cb711eb6eff3cbe7bf2dbc321e8309 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/FunctionImpl.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/FunctionImpl.java @@ -41,11 +41,7 @@ */ package org.gephi.appearance; -import org.gephi.appearance.api.Partition; -import org.gephi.appearance.api.PartitionFunction; -import org.gephi.appearance.api.Ranking; -import org.gephi.appearance.api.RankingFunction; -import org.gephi.appearance.api.SimpleFunction; +import org.gephi.appearance.api.Function; import org.gephi.appearance.spi.PartitionTransformer; import org.gephi.appearance.spi.RankingTransformer; import org.gephi.appearance.spi.SimpleTransformer; @@ -53,35 +49,31 @@ import org.gephi.appearance.spi.Transformer; import org.gephi.appearance.spi.TransformerUI; import org.gephi.graph.api.Column; import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; /** * * @author mbastian */ -public class FunctionImpl implements RankingFunction, PartitionFunction, SimpleFunction { +public abstract class FunctionImpl implements Function { - protected final AppearanceModelImpl model; + protected final String id; + protected final String name; + protected final Graph graph; protected final Column column; protected final Transformer transformer; protected final TransformerUI transformerUI; protected final PartitionImpl partition; protected final RankingImpl ranking; - public FunctionImpl(AppearanceModelImpl model, Column column, Transformer transformer, TransformerUI transformerUI) { - this(model, column, transformer, transformerUI, null, null); - } - - public FunctionImpl(AppearanceModelImpl model, Column column, Transformer transformer, TransformerUI transformerUI, RankingImpl ranking) { - this(model, column, transformer, transformerUI, null, ranking); - } - - public FunctionImpl(AppearanceModelImpl model, Column column, Transformer transformer, TransformerUI transformerUI, PartitionImpl partition) { - this(model, column, transformer, transformerUI, partition, null); - } - - public FunctionImpl(AppearanceModelImpl model, Column column, Transformer transformer, TransformerUI transformerUI, PartitionImpl partition, RankingImpl ranking) { - this.model = model; + protected FunctionImpl(String id, String name, Graph graph, Column column, Transformer transformer, TransformerUI transformerUI, PartitionImpl partition, RankingImpl ranking) { + if (id == null) { + throw new NullPointerException("The id can't be null"); + } + this.id = id; + this.name = name; this.column = column; + this.graph = graph; try { this.transformer = transformer.getClass().newInstance(); } catch (Exception ex) { @@ -97,23 +89,14 @@ public class FunctionImpl implements RankingFunction, PartitionFunction, SimpleF if (isSimple()) { ((SimpleTransformer) transformer).transform(element); } else if (isRanking()) { - Number val = (Number) element.getAttribute(column); + Number val = ranking.getValue(element); ((RankingTransformer) transformer).transform(element, ranking, val); } else if (isPartition()) { - Object val = element.getAttribute(column); + Object val = partition.getValue(element); ((PartitionTransformer) transformer).transform(element, partition, val); } } - @Override - public Column getColumn() { - return column; - } - - public AppearanceModelImpl getModel() { - return model; - } - @Override public Transformer getTransformer() { return transformer; @@ -126,7 +109,7 @@ public class FunctionImpl implements RankingFunction, PartitionFunction, SimpleF @Override public boolean isSimple() { - return column == null; + return ranking == null && partition == null; } @Override @@ -145,39 +128,30 @@ public class FunctionImpl implements RankingFunction, PartitionFunction, SimpleF } @Override - public Partition getPartition() { - return partition; - } - - @Override - public Ranking getRanking() { - return ranking; + public Graph getGraph() { + return graph; } @Override public String toString() { - if (column != null) { - if (column.getTitle() != null) { - return column.getTitle(); - } else { - return column.getId(); - } + if (name != null) { + return name; } - return super.toString(); + return id; } @Override public int hashCode() { int hash = 5; - hash = 47 * hash + (this.column != null ? this.column.hashCode() : 0); - hash = 47 * hash + (this.transformer != null ? this.transformer.hashCode() : 0); - hash = 47 * hash + (this.partition != null ? this.partition.hashCode() : 0); - hash = 47 * hash + (this.ranking != null ? this.ranking.hashCode() : 0); + hash = 97 * hash + (this.id != null ? this.id.hashCode() : 0); return hash; } @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj == null) { return false; } @@ -185,16 +159,7 @@ public class FunctionImpl implements RankingFunction, PartitionFunction, SimpleF return false; } final FunctionImpl other = (FunctionImpl) obj; - if (this.column != other.column && (this.column == null || !this.column.equals(other.column))) { - return false; - } - if (this.transformer != other.transformer && (this.transformer == null || !this.transformer.equals(other.transformer))) { - return false; - } - if (this.partition != other.partition && (this.partition == null || !this.partition.equals(other.partition))) { - return false; - } - if (this.ranking != other.ranking && (this.ranking == null || !this.ranking.equals(other.ranking))) { + if ((this.id == null) ? (other.id != null) : !this.id.equals(other.id)) { return false; } return true; diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/GraphFunctionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/GraphFunctionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6e394453fb8af60ea215b37dc1302ad15c4a1ec2 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/GraphFunctionImpl.java @@ -0,0 +1,40 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.GraphFunction; +import org.gephi.appearance.api.Partition; +import org.gephi.appearance.api.PartitionFunction; +import org.gephi.appearance.api.Ranking; +import org.gephi.appearance.api.RankingFunction; +import org.gephi.appearance.spi.Transformer; +import org.gephi.appearance.spi.TransformerUI; +import org.gephi.graph.api.Graph; + +/** + * + * @author mbastian + */ +public class GraphFunctionImpl extends FunctionImpl implements GraphFunction, RankingFunction, PartitionFunction { + + public GraphFunctionImpl(String id, String name, Graph graph, Transformer transformer, TransformerUI transformerUI, RankingImpl ranking) { + super(id, name, graph, null, transformer, transformerUI, null, ranking); + } + + public GraphFunctionImpl(String id, String name, Graph graph, Transformer transformer, TransformerUI transformerUI, PartitionImpl partition) { + super(id, name, graph, null, transformer, transformerUI, partition, null); + } + + @Override + public PartitionImpl getPartition() { + return partition; + } + + @Override + public RankingImpl getRanking() { + return ranking; + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/InDegreeRankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/InDegreeRankingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ecf78bf732ac6bc0355bb06cf8674a9e74466328 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/InDegreeRankingImpl.java @@ -0,0 +1,81 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.Interpolator; +import org.gephi.graph.api.DirectedGraph; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Node; + +/** + * + * @author mbastian + */ +public class InDegreeRankingImpl extends RankingImpl { + + private final DirectedGraph graph; + + public InDegreeRankingImpl(DirectedGraph graph, Interpolator interpolator) { + super(interpolator); + this.graph = graph; + } + + @Override + public Number getValue(Element element) { + return graph.getInDegree((Node) element); + } + + @Override + protected void refresh() { + if (graph.getNodeCount() > 0) { + int minV = Integer.MAX_VALUE; + int maxV = Integer.MIN_VALUE; + for (Node n : graph.getNodes()) { + int degree = graph.getInDegree(n); + minV = Math.min(degree, minV); + maxV = Math.max(degree, maxV); + } + min = minV; + max = maxV; + } + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/OutDegreeRankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/OutDegreeRankingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..82dab8122bb75419ccbf01f1f9db5148771c6be7 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/OutDegreeRankingImpl.java @@ -0,0 +1,81 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.Interpolator; +import org.gephi.graph.api.DirectedGraph; +import org.gephi.graph.api.Element; +import org.gephi.graph.api.Node; + +/** + * + * @author mbastian + */ +public class OutDegreeRankingImpl extends RankingImpl { + + private final DirectedGraph graph; + + public OutDegreeRankingImpl(DirectedGraph graph, Interpolator interpolator) { + super(interpolator); + this.graph = graph; + } + + @Override + public Number getValue(Element element) { + return graph.getOutDegree((Node) element); + } + + @Override + protected void refresh() { + if (graph.getNodeCount() > 0) { + int minV = Integer.MAX_VALUE; + int maxV = Integer.MIN_VALUE; + for (Node n : graph.getNodes()) { + int degree = graph.getOutDegree(n); + minV = Math.min(degree, minV); + maxV = Math.max(degree, maxV); + } + min = minV; + max = maxV; + } + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/PartitionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/PartitionImpl.java index f4e60a43bd5a25ed8f1b386d3050eee9dc1d893f..9de5419a4cac96c3e400e7adce9a63f934f00dea 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/PartitionImpl.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/PartitionImpl.java @@ -45,40 +45,19 @@ import java.awt.Color; import java.util.HashMap; import java.util.Map; import org.gephi.appearance.api.Partition; -import org.gephi.graph.api.Column; -import org.gephi.graph.api.Index; /** * * @author mbastian */ -public class PartitionImpl implements Partition { +public abstract class PartitionImpl implements Partition { - private final Index index; - private final Column column; - private final Map colorMap; + protected final Map colorMap; - public PartitionImpl(Column column, Index index) { - this.column = column; - this.index = index; + protected PartitionImpl() { this.colorMap = new HashMap(); } - @Override - public Iterable getValues() { - return index.values(column); - } - - @Override - public int getElementCount() { - return index.countElements(column); - } - - @Override - public int count(Object value) { - return index.count(column, value); - } - @Override public Color getColor(Object value) { return colorMap.get(value); @@ -89,41 +68,4 @@ public class PartitionImpl implements Partition { colorMap.put(value, color); } - @Override - public float percentage(Object value) { - int count = index.count(column, value); - return (float) count / index.countElements(column); - } - - @Override - public int size() { - return index.countValues(column); - } - - @Override - public Column getColumn() { - return column; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 23 * hash + (this.column != null ? this.column.hashCode() : 0); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final PartitionImpl other = (PartitionImpl) obj; - if (this.column != other.column && (this.column == null || !this.column.equals(other.column))) { - return false; - } - return true; - } } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/RankingImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/RankingImpl.java index 697788ae45e76b9bec948c6c549ce174c8595141..952483193f174c4ed24893b41a08c4db9a6c7249 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/RankingImpl.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/RankingImpl.java @@ -43,33 +43,31 @@ package org.gephi.appearance; import org.gephi.appearance.api.Interpolator; import org.gephi.appearance.api.Ranking; -import org.gephi.graph.api.Column; -import org.gephi.graph.api.Index; /** * * @author mbastian */ -public class RankingImpl implements Ranking { +public abstract class RankingImpl implements Ranking { - private final Index index; - private final Column column; - private Interpolator interpolator; + protected Interpolator interpolator; + protected Number min; + protected Number max; - public RankingImpl(Column column, Index index, Interpolator interpolator) { - this.column = column; - this.index = index; + protected RankingImpl(Interpolator interpolator) { this.interpolator = interpolator; } + protected abstract void refresh(); + @Override public Number getMinValue() { - return index.getMinValue(column); + return min; } @Override public Number getMaxValue() { - return index.getMaxValue(column); + return max; } @Override @@ -84,29 +82,7 @@ public class RankingImpl implements Ranking { @Override public float normalize(Number value) { - float normalizedValue = (float) (value.doubleValue() - getMinValue().doubleValue()) / (float) (getMaxValue().doubleValue() - getMinValue().doubleValue()); + float normalizedValue = (float) (value.doubleValue() - min.doubleValue()) / (float) (max.doubleValue() - min.doubleValue()); return interpolator.interpolate(normalizedValue); } - - @Override - public int hashCode() { - int hash = 3; - hash = 67 * hash + (this.column != null ? this.column.hashCode() : 0); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final RankingImpl other = (RankingImpl) obj; - if (this.column != other.column && (this.column == null || !this.column.equals(other.column))) { - return false; - } - return true; - } } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/SimpleFunctionImpl.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/SimpleFunctionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..1bf1a92ca599af2530b66fe06429de646163f5e9 --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/SimpleFunctionImpl.java @@ -0,0 +1,22 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.gephi.appearance; + +import org.gephi.appearance.api.SimpleFunction; +import org.gephi.appearance.spi.Transformer; +import org.gephi.appearance.spi.TransformerUI; +import org.gephi.graph.api.Graph; + +/** + * + * @author mbastian + */ +public class SimpleFunctionImpl extends FunctionImpl implements SimpleFunction { + + public SimpleFunctionImpl(String id, Graph graph, Transformer transformer, TransformerUI transformerUI) { + super(id, null, graph, null, transformer, transformerUI, null, null); + } +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/AppearanceModel.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/AppearanceModel.java index 8e1d48d3044648ae1a09ce8fda85f1762a70a258..492e1f7cafd45fadac2ac21b386f54d99ed07b92 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/AppearanceModel.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/AppearanceModel.java @@ -41,6 +41,7 @@ */ package org.gephi.appearance.api; +import org.gephi.graph.api.Graph; import org.gephi.project.api.Workspace; /** @@ -57,18 +58,16 @@ public interface AppearanceModel { public Workspace getWorkspace(); /** - * Returns - * true if rankings are using the currently visible graph as a - * scale. If - * false the complete graph is used to determine minimum and - * maximum values, the ranking scale. + * Returns true if rankings are using the currently visible + * graph as a scale. If false the complete graph is used to + * determine minimum and maximum values, the ranking scale. * * @return true if using a local scale, false if * global scale */ public boolean isLocalScale(); - public Function[] getNodeFunctions(); + public Function[] getNodeFunctions(Graph graph); - public Function[] getEdgeFunctions(); + public Function[] getEdgeFunctions(Graph graph); } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Function.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Function.java index 977945b26d2294c71b26bdccdbc393e16e09ac9e..50f186e1e3f85d077711ae91de4f574a32b6d97b 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Function.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Function.java @@ -44,6 +44,7 @@ package org.gephi.appearance.api; import org.gephi.appearance.spi.Transformer; import org.gephi.appearance.spi.TransformerUI; import org.gephi.graph.api.Element; +import org.gephi.graph.api.Graph; /** * @@ -64,4 +65,6 @@ public interface Function { public boolean isRanking(); public boolean isPartition(); + + public Graph getGraph(); } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/GraphFunction.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/GraphFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..144fd06d1865287001e16fcdf6bc05b251490a0e --- /dev/null +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/GraphFunction.java @@ -0,0 +1,50 @@ +/* + Copyright 2008-2013 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2013 Gephi Consortium. + */ +package org.gephi.appearance.api; + +/** + * + * @author mbastian + */ +public interface GraphFunction extends Function { + +} diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Interpolator.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Interpolator.java index 8e0bb3161a4b86b8cd36c4e396c0b26a9bc14028..ff22f7a6c1cf32477ab80537112ca908a6362e78 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Interpolator.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Interpolator.java @@ -52,9 +52,7 @@ import java.awt.geom.Point2D; public abstract class Interpolator { /** - * Linear interpolation - * x = interpolate(x) - * + * Linear interpolation x = interpolate(x) */ public static final Interpolator LINEAR = new Interpolator() { @Override diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Partition.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Partition.java index 99b64fd0e70c60548342100ac05ab58f561a9266..3e35def6595b82dfb35ef161967697d8fa976d57 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Partition.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Partition.java @@ -43,6 +43,7 @@ package org.gephi.appearance.api; import java.awt.Color; import org.gephi.graph.api.Column; +import org.gephi.graph.api.Element; /** * @@ -56,6 +57,8 @@ public interface Partition { public int count(Object value); + public Object getValue(Element element); + public Color getColor(Object value); public void setColor(Object value, Color color); diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/PartitionFunction.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/PartitionFunction.java index 962b072742851d518563a0279401eaef2cb66939..27b133d18f7abb1fa09c70a881e770b6e08504d1 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/PartitionFunction.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/PartitionFunction.java @@ -45,7 +45,7 @@ package org.gephi.appearance.api; * * @author mbastian */ -public interface PartitionFunction extends AttributeFunction { +public interface PartitionFunction extends Function { public Partition getPartition(); } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Ranking.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Ranking.java index 02a776eec56408bde1758e7f71261438717488d5..a5922f4b31bceacc3078c8ea8f9c4ddc9e2df353 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Ranking.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/Ranking.java @@ -41,6 +41,8 @@ */ package org.gephi.appearance.api; +import org.gephi.graph.api.Element; + /** * * @author mbastian @@ -55,5 +57,7 @@ public interface Ranking { public void setInterpolator(Interpolator interpolator); + public Number getValue(Element element); + public float normalize(Number value); } diff --git a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/RankingFunction.java b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/RankingFunction.java index 9bcd4e2067800845deee9244e639ee32978b1e53..5ed05b93978a4b8addb59aa2987bfc0fbd6d714b 100644 --- a/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/RankingFunction.java +++ b/modules/AppearanceAPI/src/main/java/org/gephi/appearance/api/RankingFunction.java @@ -45,7 +45,7 @@ package org.gephi.appearance.api; * * @author mbastian */ -public interface RankingFunction extends AttributeFunction { +public interface RankingFunction extends Function { public Ranking getRanking(); } diff --git a/modules/AppearanceAPI/src/main/resources/org/gephi/appearance/Bundle.properties b/modules/AppearanceAPI/src/main/resources/org/gephi/appearance/Bundle.properties new file mode 100644 index 0000000000000000000000000000000000000000..5303b17e4de2434f19a9219eb1d454107a81d461 --- /dev/null +++ b/modules/AppearanceAPI/src/main/resources/org/gephi/appearance/Bundle.properties @@ -0,0 +1,5 @@ +NodeGraphFunction.Degree.name = Degree +NodeGraphFunction.InDegree.name = In-Degree +NodeGraphFunction.OutDegree.name = Out-Degree +EdgeGraphFunction.Weight.name = Weight +EdgeGraphFunction.Type.name = Type diff --git a/modules/DesktopAppearance/src/main/java/org/gephi/desktop/appearance/AppearanceUIModel.java b/modules/DesktopAppearance/src/main/java/org/gephi/desktop/appearance/AppearanceUIModel.java index db5e0766d6bbe9c2b2a4113f9aaaa529a5b0440e..2a7425319e7a75d415a960509692459fc7b47fc3 100644 --- a/modules/DesktopAppearance/src/main/java/org/gephi/desktop/appearance/AppearanceUIModel.java +++ b/modules/DesktopAppearance/src/main/java/org/gephi/desktop/appearance/AppearanceUIModel.java @@ -56,6 +56,9 @@ import org.gephi.appearance.spi.Transformer; import org.gephi.appearance.spi.TransformerCategory; import org.gephi.appearance.spi.TransformerUI; import static org.gephi.desktop.appearance.AppearanceUIController.ELEMENT_CLASSES; +import org.gephi.graph.api.Graph; +import org.gephi.graph.api.GraphController; +import org.openide.util.Lookup; /** * @@ -65,6 +68,7 @@ public class AppearanceUIModel { protected final AppearanceUIController controller; protected final AppearanceModel appearanceModel; + protected final GraphController graphController; protected final Map> selectedTransformerUI; protected final Map> selectedFunction; protected final Map selectedCategory; @@ -75,6 +79,7 @@ public class AppearanceUIModel { public AppearanceUIModel(AppearanceUIController controller, AppearanceModel model) { this.controller = controller; this.appearanceModel = model; + this.graphController = Lookup.getDefault().lookup(GraphController.class); //Init maps selectedCategory = new HashMap(); @@ -90,8 +95,9 @@ public class AppearanceUIModel { } private void initSelectedTransformerUIs(String elementClass) { + Graph graph = graphController.getGraphModel(appearanceModel.getWorkspace()).getGraph(); Map newMap = new HashMap(); - for (Function func : elementClass.equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions() : appearanceModel.getEdgeFunctions()) { + for (Function func : elementClass.equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions(graph) : appearanceModel.getEdgeFunctions(graph)) { TransformerUI ui = func.getUI(); if (ui != null) { TransformerCategory cat = ui.getCategory(); @@ -111,7 +117,8 @@ public class AppearanceUIModel { private void refreshSelectedFunctions(String elementClass) { Set functionSet = new HashSet(); - for (Function func : elementClass.equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions() : appearanceModel.getEdgeFunctions()) { + Graph graph = graphController.getGraphModel(appearanceModel.getWorkspace()).getGraph(); + for (Function func : elementClass.equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions(graph) : appearanceModel.getEdgeFunctions(graph)) { TransformerUI ui = func.getUI(); if (ui != null) { functionSet.add(func); @@ -127,9 +134,10 @@ public class AppearanceUIModel { } public boolean refreshSelectedFunction() { + Graph graph = graphController.getGraphModel(appearanceModel.getWorkspace()).getGraph(); Function sFunction = getSelectedFunction(); if (sFunction != null && sFunction.isAttribute()) { - for (Function func : getSelectedElementClass().equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions() : appearanceModel.getEdgeFunctions()) { + for (Function func : getSelectedElementClass().equals(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions(graph) : appearanceModel.getEdgeFunctions(graph)) { if (func.equals(sFunction)) { return false; } @@ -170,8 +178,9 @@ public class AppearanceUIModel { } public Collection getFunctions() { + Graph graph = graphController.getGraphModel(appearanceModel.getWorkspace()).getGraph(); List functions = new ArrayList(); - for (Function func : selectedElementClass.equalsIgnoreCase(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions() : appearanceModel.getEdgeFunctions()) { + for (Function func : selectedElementClass.equalsIgnoreCase(AppearanceUIController.NODE_ELEMENT) ? appearanceModel.getNodeFunctions(graph) : appearanceModel.getEdgeFunctions(graph)) { TransformerUI ui = func.getUI(); if (ui != null && ui.getDisplayName().equals(getSelectedTransformerUI().getDisplayName())) { if (ui.getCategory().equals(selectedCategory.get(selectedElementClass))) {