graphstream / gs-core

Graphstream core
http://graphstream-project.org/
Other
398 stars 109 forks source link

ConcurrentModificationException in StyleRenderer #359

Open papperwing opened 3 years ago

papperwing commented 3 years ago

Hi, I am getting ConcurrentModificationException in StyleRenderer and I am not sure where is the problem.

I have several other problems related to my project, not sure if they are bugs, to share them here. I tried to register in the sympa, but did not find how to ask the question. Could I list them in the next issue?

Exception:

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1445)
    at java.util.HashMap$ValueIterator.next(HashMap.java:1474)
    at org.graphstream.ui.graphicGraph.StyleGroup$BulkIterator.next(StyleGroup.java:815)
    at org.graphstream.ui.graphicGraph.StyleGroup$BulkIterator.next(StyleGroup.java:1)
    at java.lang.Iterable.forEach(Iterable.java:74)
    at org.graphstream.ui.swing.renderer.StyleRenderer.render(StyleRenderer.java:92)
    at org.graphstream.ui.swing.renderer.StyleRenderer.render(StyleRenderer.java:67)
    at org.graphstream.ui.swing.SwingGraphRenderer.lambda$render$4(SwingGraphRenderer.java:242)
    at java.lang.Iterable.forEach(Iterable.java:75)
    at org.graphstream.ui.swing.SwingGraphRenderer.lambda$render$5(SwingGraphRenderer.java:240)
    at java.lang.Iterable.forEach(Iterable.java:75)
    at org.graphstream.ui.swing.SwingGraphRenderer.render(SwingGraphRenderer.java:239)
    at org.graphstream.ui.swing.SwingGraphRenderer.render(SwingGraphRenderer.java:96)
    at org.graphstream.ui.swing_viewer.DefaultView.render(DefaultView.java:252)
    at org.graphstream.ui.swing_viewer.DefaultView.paintComponent(DefaultView.java:180)
    at javax.swing.JComponent.paint(JComponent.java:1056)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
    at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Piece of code working with graphstream:

public class Main {

    protected String lcStylesheet = "node{fill-color: black;} node.community{fill-color: red;}";

    public static void main(String[] args) {
        Main main = new Main();
        SwingUtilities.invokeLater(main::display);
    }

    private void display(){
        System.setProperty("org.graphstream.ui", "swing");
        Random seed = new Random();

        TransactionFile sourceData = getData("./data/box-interactions-2020_07_01-filtered_empty_File_Mail.csv");
        final Graph sourceGraph1 = prepareGraph(sourceData);
        sourceGraph1.setAttribute("ui.stylesheet", lcStylesheet);
        Viewer viewer1 = new SwingViewer(sourceGraph1, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
        viewer1.addView(new DefaultView(viewer1,"viewer1",new SwingGraphRenderer()));
        ViewerPipe viewerPipe = viewer1.newViewerPipe();
        MutableBoolean stopCondition = new MutableBoolean(true);
        viewerPipe.addViewerListener(new ZoomListener(viewer1.getView("viewer1").getCamera(), stopCondition));
        viewerPipe.addSink(sourceGraph1);
        new Thread(()-> {while(stopCondition.isValue())viewerPipe.pump();}).start();
        viewer1.enableAutoLayout(new SpringBox(false,seed));

        final Graph sourceGraph2 = prepareGraph(sourceData);
        Viewer viewer2 = new SwingViewer(sourceGraph2, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
        viewer2.enableAutoLayout(new SpringBox(false, seed));
        ViewPanel viewPanel1 = new DefaultView(viewer1,"panel1",new SwingGraphRenderer());
        viewPanel1.setPreferredSize(new Dimension(750,350));
        ViewPanel viewPanel2 = new DefaultView(viewer2,"panel2",new SwingGraphRenderer());
        viewPanel2.setPreferredSize(new Dimension(750,350));

        JPanel panel1 = new JPanel();
        panel1.setBackground(Color.gray);
        panel1.setLayout(new BorderLayout());
        panel1.setPreferredSize(new Dimension(750,350));
        panel1.add(viewPanel1,BorderLayout.CENTER);

        JPanel panel2 = new JPanel();
        panel1.setBackground(Color.blue);
        panel2.setLayout(new BorderLayout());
        panel2.setPreferredSize(new Dimension(750,350));
        panel2.add(viewPanel2, BorderLayout.CENTER);

        JPanel graphPanel = new JPanel();
        graphPanel.setPreferredSize(new Dimension(1600, 600));
        graphPanel.setLayout(new BorderLayout(5,5));
        graphPanel.add(panel1,BorderLayout.WEST);
        graphPanel.add(panel2, BorderLayout.EAST);

        JComboBox<Transaction> lCCommunitiesNames = new JComboBox<>();
        lCCommunitiesNames.setPreferredSize(new Dimension(795,30));
        lCCommunitiesNames.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent itemEvent) {
                if(itemEvent.getStateChange() == ItemEvent.SELECTED){
                    Transaction community = (Transaction) itemEvent.getItem();

                    new GraphMapper().map(sourceGraph1,community);
                }
            }
        });
        JPanel lCComboPanel = new JPanel();
        lCComboPanel.setLayout(new BorderLayout());
        lCComboPanel.add(lCCommunitiesNames,BorderLayout.CENTER);

        JComboBox<Transaction> minoltaCommunitiesNames = new JComboBox<>();
        minoltaCommunitiesNames.setPreferredSize(new Dimension(795,30));
        JPanel minoltaComboPanel = new JPanel();
        minoltaComboPanel.setLayout(new BorderLayout());
        minoltaComboPanel.add(minoltaCommunitiesNames, BorderLayout.CENTER);

        JPanel selectorPanel = new JPanel();
        selectorPanel.setLayout(new BorderLayout(5,5));
        graphPanel.setPreferredSize(new Dimension(1600, 100));
        selectorPanel.add(lCComboPanel,BorderLayout.WEST);
        selectorPanel.add(minoltaCommunitiesNames, BorderLayout.EAST);

        JPanel buttonPanel = new JPanel();
        graphPanel.setPreferredSize(new Dimension(1600, 100));

        JFrame f=new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setSize(new Dimension(1600,900));
        f.setLayout(new BorderLayout(50,10));
        f.add(buttonPanel, BorderLayout.NORTH);
        f.add(graphPanel,BorderLayout.CENTER);
        f.add(selectorPanel,BorderLayout.SOUTH);
        f.setVisible(true);

        populate(sourceData,sourceGraph1,lCCommunitiesNames,sourceGraph2,minoltaCommunitiesNames);

    }

    private Graph prepareGraph(TransactionFile graphData){
        Graph graph = GraphMapper.map(graphData);
        return graph;
    }

    private TransactionFile getData(String path) {
        List<String> types = Arrays.asList("Edit", "Uploaded", "Created");
        TransactionFile graphData = GraphLoader.getUserUserTransactionFile(path, 1, types);
        return graphData;
    }

    private void populate(
            TransactionFile inputData,
            final Graph LC,
            JComboBox<Transaction> lCCommunitiesNames,
            final Graph minolta,
            JComboBox<Transaction> minoltaCommunitiesNames
        ){
        Map<String,Object> parameters = new HashMap<>();
        parameters.put(ParameterName.coreSize.toString(), 10);
        parameters.put(ParameterName.similarityThreshold.toString(), 0.2);

        Runnable lcRun = new Runnable() {
            @Override
            public void run() {
                Operator dbLinkClustering = new DBLinkClustering(0.8);
                TransactionFile vertexPartitioning = dbLinkClustering.apply(inputData, parameters);
                for (Transaction community: vertexPartitioning.getTransactions()){
                    lCCommunitiesNames.addItem(community);
                }

            }
        };

        Thread lcThread = new Thread(lcRun);
        lcThread.start();

        /*Runnable MinoltaRun = new Runnable() {
            @Override
            public void run() {
                Operator linkClustering = new DBLinkClustering(0.8);
                Map<String,Object> parameters = new HashMap<>();
                parameters.put(ParameterName.coreSize.toString(), 10);
                parameters.put(ParameterName.similarityThreshold.toString(), 0.8);
                TransactionFile result = linkClustering.apply(getData(path),parameters);

            }
        };

        Thread minoltaThread = new Thread(MinoltaRun);
        minoltaThread.start();*/

    }
}

Mutable boolean:

public class MutableBoolean {
    boolean value;

    public MutableBoolean(boolean value) {
        this.value = value;
    }

    public boolean isValue() {
        return value;
    }

    public void setValue(boolean value) {
        this.value = value;
    }
}

Zoom Listener:

public class ZoomListener implements ViewerListener {

    Camera view;
    MutableBoolean loop;

    public ZoomListener(Camera view, MutableBoolean loop) {
        this.view = view;
        this.loop = loop;
    }

    @Override
    public void viewClosed(String s) {
        loop.setValue(false);
    }

    @Override
    public void buttonPushed(String s) {
        System.out.println("Pushed:" + s);
        if (s.equals("+")) {
            view.setViewPercent(view.getViewPercent() * 0.5);
            System.out.println("+");
        }

        if (s.equals("-")) {
            view.setViewPercent(view.getViewPercent() / 0.5);
            System.out.println("-");
        }
    }

    @Override
    public void buttonReleased(String s) {

    }

    @Override
    public void mouseOver(String s) {

    }

    @Override
    public void mouseLeft(String s) {

    }
}

GraphMapper#map

public static Graph map(TransactionFile neighbourList, String name) {
        Graph result = new DefaultGraph(name);
        result.setAutoCreate(true);
        result.setStrict(false);
        neighbourList.stream().forEach((t) -> {Node node = result.addNode(t.getAttributes().get("source").toString());
        node.setAttribute("ui.label", t.getAttributes().get("source").toString());});
        neighbourList.stream().forEach((t) -> {
            String source = (String) ((AdamissObjectImpl) t.getAttributes().get("source")).getData();
            for (AdamissObject o : t.getData()) {
                String target = (String) ((AdamissObjectImpl) o).getData();
                if (!source.equals(target)) result.addEdge(source + "->" + target, source, target);
            }
        });

        return result;
    }