@Override
    public void refreshGraphFunctions() {
      if (!rankings.containsKey(getIdStr(GraphFunction.EDGE_WEIGHT.getId()))) {
        rankings.put(getIdStr(GraphFunction.EDGE_WEIGHT.getId()), new EdgeWeightRankingImpl(graph));
      }
      if (graph.getModel().isMultiGraph()) {
        if (!partitions.containsKey(getIdStr(GraphFunction.EDGE_TYPE.getId()))) {
          partitions.put(
              getIdStr(GraphFunction.EDGE_TYPE.getId()), new EdgeTypePartitionImpl(graph));
        }
      } else {
        partitions.remove(getIdStr(GraphFunction.EDGE_TYPE.getId()));
      }

      // Weight function
      for (Transformer t : getRankingTransformers()) {
        String weightId = getId(t, GraphFunction.EDGE_WEIGHT.getId());
        RankingImpl ranking = rankings.get(getIdStr(GraphFunction.EDGE_WEIGHT.getId()));
        if (!graphFunctions.containsKey(weightId)) {
          String name =
              NbBundle.getMessage(AppearanceModelImpl.class, "EdgeGraphFunction.Weight.name");
          graphFunctions.put(
              weightId,
              new GraphFunctionImpl(
                  weightId,
                  name,
                  Edge.class,
                  graph,
                  t,
                  getTransformerUI(t),
                  ranking,
                  defaultInterpolator));
        }
        ranking.refresh();
      }

      // Type Function
      for (Transformer t : getPartitionTransformers()) {
        String typeId = getId(t, GraphFunction.EDGE_TYPE.getId());
        PartitionImpl partition = partitions.get(getIdStr(GraphFunction.EDGE_TYPE.getId()));
        if (partition != null) {
          if (!graphFunctions.containsKey(typeId)) {
            String name =
                NbBundle.getMessage(AppearanceModelImpl.class, "EdgeGraphFunction.Type.name");
            graphFunctions.put(
                typeId,
                new GraphFunctionImpl(
                    typeId, name, Edge.class, graph, t, getTransformerUI(t), partition));
          }
          partition.refresh();
        } else {
          graphFunctions.remove(typeId);
        }
      }
    }
    private void refreshAttributeFunctions(boolean graphHasChanged) {
      Set<Column> columns = new HashSet<Column>();
      for (Column column : getTable()) {
        if (!column.isProperty()) {
          columns.add(column);
        }
      }

      // Clean
      for (Iterator<Map.Entry<Column, ColumnObserver>> itr = columnObservers.entrySet().iterator();
          itr.hasNext(); ) {
        Map.Entry<Column, ColumnObserver> entry = itr.next();
        if (!columns.contains(entry.getKey()) || forcedColumnsRefresh.contains(entry.getKey())) {
          rankings.remove(getIdCol(entry.getKey()));
          partitions.remove(getIdCol(entry.getKey()));
          for (Transformer t : getTransformers()) {
            attributeFunctions.remove(getId(t, entry.getKey()));
          }
          itr.remove();
          if (!entry.getValue().isDestroyed()) {
            entry.getValue().destroy();
          }
        }
      }

      // Get columns to be refreshed
      Set<Column> toRefreshColumns = new HashSet<Column>(forcedColumnsRefresh);
      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);
        }
      }
      forcedColumnsRefresh.clear();

      // Refresh ranking and partitions
      for (Column column : toRefreshColumns) {
        RankingImpl ranking = rankings.get(getIdCol(column));
        PartitionImpl partition = partitions.get(getIdCol(column));
        if (ranking == null && partition == null) {
          String id = getIdCol(column);
          if (forcedPartition.contains(id)
              || (!forcedRanking.contains(id) && isPartition(graph, column))) {
            if (column.isIndexed()) {
              partition = new AttributePartitionImpl(column, getIndex(false));
            } else {
              partition = new AttributePartitionImpl(column, graph);
            }
            partitions.put(getIdCol(column), partition);
          }

          if (forcedRanking.contains(id) || isRanking(graph, column)) {
            if (column.isIndexed()) {
              ranking = new AttributeRankingImpl(column, getIndex(localScale));
            } else {
              ranking = new AttributeRankingImpl(column, graph);
            }
            rankings.put(getIdCol(column), ranking);
          }
        }
        if (ranking != null) {
          ranking.refresh();
        }
        if (partition != null) {
          partition.refresh();
        }
      }

      // Ranking functions
      for (Transformer t : getRankingTransformers()) {
        for (Column col : toRefreshColumns) {
          RankingImpl ranking = rankings.get(getIdCol(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, defaultInterpolator));
            }
          }
        }
      }

      // Partition functions
      for (Transformer t : getPartitionTransformers()) {
        for (Column col : toRefreshColumns) {
          PartitionImpl partition = partitions.get(getIdCol(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));
            }
          }
        }
      }
    }
    @Override
    public void refreshGraphFunctions() {
      if (!rankings.containsKey(getIdStr(GraphFunction.NODE_DEGREE.getId()))) {
        rankings.put(getIdStr(GraphFunction.NODE_DEGREE.getId()), new DegreeRankingImpl(graph));
      }
      if (graph.isDirected()) {
        if (!rankings.containsKey(getIdStr(GraphFunction.NODE_INDEGREE.getId()))) {
          DirectedGraph directedGraph = (DirectedGraph) graph;
          rankings.put(
              getIdStr(GraphFunction.NODE_INDEGREE.getId()),
              new InDegreeRankingImpl(directedGraph));
          rankings.put(
              getIdStr(GraphFunction.NODE_OUTDEGREE.getId()),
              new OutDegreeRankingImpl(directedGraph));
        }
      } else {
        rankings.remove(getIdStr(GraphFunction.NODE_INDEGREE.getId()));
        rankings.remove(getIdStr(GraphFunction.NODE_OUTDEGREE.getId()));
      }

      // Degree functions
      for (Transformer t : getRankingTransformers()) {
        String degreeId = getId(t, GraphFunction.NODE_DEGREE.getId());
        RankingImpl degreeRanking = rankings.get(getIdStr(GraphFunction.NODE_DEGREE.getId()));
        if (!graphFunctions.containsKey(degreeId)) {
          String name =
              NbBundle.getMessage(AppearanceModelImpl.class, "NodeGraphFunction.Degree.name");
          graphFunctions.put(
              degreeId,
              new GraphFunctionImpl(
                  degreeId,
                  name,
                  Node.class,
                  graph,
                  t,
                  getTransformerUI(t),
                  degreeRanking,
                  defaultInterpolator));
        }
        degreeRanking.refresh();

        String indegreeId = getId(t, GraphFunction.NODE_INDEGREE.getId());
        String outdegreeId = getId(t, GraphFunction.NODE_OUTDEGREE.getId());

        RankingImpl indegreeRanking = rankings.get(getIdStr(GraphFunction.NODE_INDEGREE.getId()));
        RankingImpl outdegreeRanking = rankings.get(getIdStr(GraphFunction.NODE_OUTDEGREE.getId()));
        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,
                    Node.class,
                    graph,
                    t,
                    getTransformerUI(t),
                    indegreeRanking,
                    defaultInterpolator));
            graphFunctions.put(
                outdegreeId,
                new GraphFunctionImpl(
                    outdegreeId,
                    outDegreeName,
                    Node.class,
                    graph,
                    t,
                    getTransformerUI(t),
                    outdegreeRanking,
                    defaultInterpolator));
          }
          indegreeRanking.refresh();
          outdegreeRanking.refresh();
        } else {
          graphFunctions.remove(indegreeId);
          graphFunctions.remove(outdegreeId);
        }
      }
    }