public void updateWorld() {
    // System.out.println("update world");
    cacheMarker++;

    GraphModel graphModel = controller.getModel();
    if (graphModel == null) {
      engine.worldUpdated(cacheMarker);
      return;
    }
    if (gm != null && gm != graphModel) {
      reset();
    }
    gm = graphModel;
    HierarchicalGraph graph;
    if (graphModel.isDirected()) {
      undirected = false;
      graph = graphModel.getHierarchicalDirectedGraphVisible();
    } else if (graphModel.isUndirected()) {
      undirected = true;
      graph = graphModel.getHierarchicalUndirectedGraphVisible();
    } else if (graphModel.isMixed()) {
      undirected = false;
      graph = graphModel.getHierarchicalMixedGraphVisible();
    } else {
      undirected = false;
      graph = graphModel.getHierarchicalDirectedGraphVisible();
    }

    if (dynamicModel == null) {
      DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
      dynamicModel = dynamicController.getModel();
    }

    graphView = graph.getView().getViewId();

    ModelClass[] object3dClasses = engine.getModelClasses();

    graph.readLock();

    ModelClass nodeClass = object3dClasses[AbstractEngine.CLASS_NODE];
    if (nodeClass.isEnabled()
        && (graph.getNodeVersion() > nodeVersion || modeManager.requireModeChange())) {
      updateNodes(graph);
      nodeClass.setCacheMarker(cacheMarker);
    }

    ModelClass edgeClass = object3dClasses[AbstractEngine.CLASS_EDGE];
    if (edgeClass.isEnabled()
        && (graph.getEdgeVersion() > edgeVersion || modeManager.requireModeChange())) {
      updateEdges(graph);
      updateMetaEdges(graph);
      edgeClass.setCacheMarker(cacheMarker);
      if (!undirected && vizConfig.isShowArrows()) {
        object3dClasses[AbstractEngine.CLASS_ARROW].setCacheMarker(cacheMarker);
      }
    }

    ModelClass potatoClass = object3dClasses[AbstractEngine.CLASS_POTATO];
    if (potatoClass.isEnabled()
        && (graph.getNodeVersion() > nodeVersion || modeManager.requireModeChange())) {
      updatePotatoes(graph);
      potatoClass.setCacheMarker(cacheMarker);
    }

    nodeVersion = graph.getNodeVersion();
    edgeVersion = graph.getEdgeVersion();

    graph.readUnlock();

    engine.worldUpdated(cacheMarker);
  }
  public boolean execute() {
    attributeModel = workspace.getLookup().lookup(AttributeModel.class);
    graphModel = workspace.getLookup().lookup(GraphModel.class);
    HierarchicalGraph graph = null;
    if (exportVisible) {
      graph = graphModel.getHierarchicalGraphVisible();
    } else {
      graph = graphModel.getHierarchicalGraph();
    }
    Progress.start(progress);
    graph.readLock();

    // Options
    if (normalize) {
      calculateMinMax(graph);
    }

    // Calculate progress units count
    int max = 0;
    if (exportHierarchy) {
      for (Node n : graph.getNodesTree()) {
        max++;
      }
      for (Edge e : graph.getEdgesTree()) {
        max++;
      }
    } else {
      max = graph.getNodeCount();
      for (Edge e : graph.getEdgesAndMetaEdges()) {
        max++;
      }
    }
    Progress.switchToDeterminate(progress, max);

    try {
      XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
      outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.FALSE);

      XMLStreamWriter xmlWriter = outputFactory.createXMLStreamWriter(writer);
      xmlWriter = new IndentingXMLStreamWriter(xmlWriter);

      xmlWriter.writeStartDocument("UTF-8", "1.0");
      xmlWriter.setPrefix("", GEXF_NAMESPACE);
      xmlWriter.writeStartElement(GEXF_NAMESPACE, GEXF);
      xmlWriter.writeNamespace("", GEXF_NAMESPACE);
      xmlWriter.writeAttribute(GEXF_VERSION, "1.1");

      if (exportColors || exportPosition || exportSize) {
        xmlWriter.writeNamespace(VIZ, VIZ_NAMESPACE);
      }
      xmlWriter.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
      xmlWriter.writeAttribute("xsi:schemaLocation", GEXF_NAMESPACE_LOCATION);

      if (exportDynamic) {
        DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
        dynamicModel = dynamicController != null ? dynamicController.getModel(workspace) : null;
        visibleInterval =
            dynamicModel == null
                ? null
                : exportVisible
                    ? dynamicModel.getVisibleInterval()
                    : new TimeInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
      }

      writeMeta(xmlWriter);
      writeGraph(xmlWriter, graph);

      xmlWriter.writeEndElement();
      xmlWriter.writeEndDocument();
      xmlWriter.close();

    } catch (Exception e) {
      graph.readUnlockAll();
      if (e instanceof RuntimeException) {
        throw (RuntimeException) e;
      }
      throw new RuntimeException(e);
    }

    graph.readUnlock();

    Progress.finish(progress);
    return !cancel;
  }