org.sintef.thingml.ThingMLPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.sintef.thingml.ThingMLPanel.java

Source

/**
 * Copyright (C) 2014 SINTEF <franck.fleurey@sintef.no>
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sintef.thingml;

import jsyntaxpane.components.Markers;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.sintef.thingml.constraints.ThingMLHelpers;
import org.sintef.thingml.resource.thingml.IThingmlTextDiagnostic;
import org.sintef.thingml.resource.thingml.mopp.ThingmlResource;
import org.sintef.thingml.resource.thingml.mopp.ThingmlResourceFactory;
import org.thingml.compilers.*;
import org.thingml.compilers.checker.Checker;
import org.thingml.compilers.checker.EMFWrapper;
import org.thingml.compilers.checker.ErrorWrapper;
import org.thingml.compilers.configuration.CfgExternalConnectorCompiler;
import org.thingml.compilers.registry.ThingMLCompilerRegistry;
import org.thingml.compilers.spi.NetworkPlugin;
import org.thingml.compilers.spi.SerializationPlugin;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import javax.swing.text.EditorKit;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.util.*;
import java.util.Timer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by bmori on 26.05.2015.
 */
//FIXME: A lot of duplication, which should be avoided
public class ThingMLPanel extends JPanel {

    private static ServiceLoader<NetworkPlugin> plugins = ServiceLoader.load(NetworkPlugin.class);
    private static Set<NetworkPlugin> loadedPlugins;
    private static ServiceLoader<SerializationPlugin> serPlugins = ServiceLoader.load(SerializationPlugin.class);
    private static Set<SerializationPlugin> loadedSerPlugins;

    static {
        loadedPlugins = new HashSet<>();
        plugins.reload();
        Iterator<NetworkPlugin> it = plugins.iterator();
        while (it.hasNext()) {
            NetworkPlugin p = it.next();
            loadedPlugins.add(p);
        }
        loadedSerPlugins = new HashSet<>();
        serPlugins.reload();
        Iterator<SerializationPlugin> sit = serPlugins.iterator();
        while (sit.hasNext()) {
            SerializationPlugin sp = sit.next();
            loadedSerPlugins.add(sp);
        }
    }

    File targetFile = null;
    JEditorPane codeEditor = new JEditorPane();
    Boolean ArduinoPlugin = false;
    ObservableString transferBuf = null;

    Checker checker = new Checker("Generic") {//FIXME: if we are in _arduino instantiate the arduino checker, etc
        @Override
        public void do_check(Configuration cfg) {
            do_generic_check(cfg);
        }
    };

    public ThingMLPanel() {
        this(false, null);
    }

    public ThingMLPanel(Boolean ArduinoPlugin, final ObservableString transferBuf) {
        try {
            this.setLayout(new BorderLayout());
            jsyntaxpane.DefaultSyntaxKit.initKit();
            jsyntaxpane.DefaultSyntaxKit.registerContentType("text/thingml",
                    Class.forName("org.sintef.thingml.ThingMLJSyntaxKit").getName());
            JScrollPane scrPane = new JScrollPane(codeEditor);
            codeEditor.setContentType("text/thingml; charset=UTF-8");

            Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
            reg.getExtensionToFactoryMap().put("thingml", new ThingmlResourceFactory());

            //codeEditor.setBackground(Color.LIGHT_GRAY)

            JMenuBar menubar = new JMenuBar();
            JInternalFrame menuframe = new JInternalFrame();

            menuframe.setSize(getWidth(), getHeight());
            menuframe.setJMenuBar(menubar);

            menuframe.setLayout(new BorderLayout());
            menuframe.add(scrPane, BorderLayout.CENTER);

            if (!ArduinoPlugin) {
                try {
                    this.transferBuf = transferBuf;
                    EditorKit editorKit = codeEditor.getEditorKit();
                    JToolBar toolPane = new JToolBar();
                    ((ThingMLJSyntaxKit) editorKit).addToolBarActions(codeEditor, toolPane);
                    menuframe.add(toolPane, BorderLayout.NORTH);
                } catch (Exception e) {
                    if (ThingMLApp.debug)
                        e.printStackTrace();
                }
            }

            menuframe.setVisible(true);
            ((BasicInternalFrameUI) menuframe.getUI()).setNorthPane(null);
            menuframe.setBorder(BorderFactory.createEmptyBorder());
            add(menuframe, BorderLayout.CENTER);

            if (!ArduinoPlugin) {//FIXME: Nicolas, avoid code duplication
                final ThingMLCompilerRegistry registry = ThingMLCompilerRegistry.getInstance();

                JMenu newCompilersMenu = new JMenu("Compile to");
                for (final String id : registry.getCompilerIds()) {
                    JMenuItem item = new JMenuItem(id);
                    ThingMLCompiler c = registry.createCompilerInstanceByName(id);
                    if (c.getConnectorCompilers().size() > 0) {
                        JMenu compilerMenu = new JMenu(c.getID());
                        newCompilersMenu.add(compilerMenu);
                        compilerMenu.add(item);
                        for (final Map.Entry<String, CfgExternalConnectorCompiler> connectorCompiler : c
                                .getConnectorCompilers().entrySet()) {
                            JMenuItem connectorMenu = new JMenuItem(connectorCompiler.getKey());
                            compilerMenu.add(connectorMenu);
                            connectorMenu.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    ThingMLModel thingmlModel = ThingMLCompiler.loadModel(targetFile);
                                    for (Configuration cfg : ThingMLHelpers.allConfigurations(thingmlModel)) {
                                        final ThingMLCompiler compiler = registry.createCompilerInstanceByName(id);
                                        for (NetworkPlugin np : loadedPlugins) {
                                            if (np.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addNetworkPlugin(np);
                                            }
                                        }
                                        for (SerializationPlugin sp : loadedSerPlugins) {
                                            if (sp.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addSerializationPlugin(sp);
                                            }
                                        }
                                        compiler.setOutputDirectory(new File(System.getProperty("java.io.tmpdir")
                                                + "/ThingML_temp/" + cfg.getName()));
                                        compiler.compileConnector(connectorCompiler.getKey(), cfg);
                                    }
                                }
                            });
                        }
                    } else {
                        newCompilersMenu.add(item);
                    }

                    item.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            System.out.println("Input file : " + targetFile);
                            if (targetFile == null)
                                return;
                            try {
                                ThingMLModel thingmlModel = ThingMLCompiler.loadModel(targetFile);
                                if (thingmlModel != null) {
                                    for (Configuration cfg : ThingMLHelpers.allConfigurations(thingmlModel)) {
                                        final ThingMLCompiler compiler = registry.createCompilerInstanceByName(id);
                                        for (NetworkPlugin np : loadedPlugins) {
                                            if (np.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addNetworkPlugin(np);
                                            }
                                        }
                                        for (SerializationPlugin sp : loadedSerPlugins) {
                                            if (sp.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addSerializationPlugin(sp);
                                            }
                                        }
                                        compiler.setOutputDirectory(new File(System.getProperty("java.io.tmpdir")
                                                + "/ThingML_temp/" + cfg.getName()));
                                        compiler.compile(cfg);
                                    }
                                }
                            } catch (Exception ex) {
                                if (ThingMLApp.debug)
                                    ex.printStackTrace();
                            }
                        }
                    });
                    c = null;
                }

                menubar.add(newCompilersMenu);
            } else {

                final ThingMLCompilerRegistry registry = ThingMLCompilerRegistry.getInstance();

                JMenu newCompilersMenu = new JMenu("Compile to");
                for (final String id : registry.getCompilerIds()) {
                    if (id.compareToIgnoreCase("arduino") == 0) {
                        JMenuItem item = new JMenuItem(id);
                        ThingMLCompiler c = registry.createCompilerInstanceByName(id);
                        if (c.getConnectorCompilers().size() > 0) {
                            JMenu compilerMenu = new JMenu(c.getID());
                            newCompilersMenu.add(compilerMenu);
                            compilerMenu.add(item);
                            for (final Map.Entry<String, CfgExternalConnectorCompiler> connectorCompiler : c
                                    .getConnectorCompilers().entrySet()) {
                                JMenuItem connectorMenu = new JMenuItem(connectorCompiler.getKey());
                                compilerMenu.add(connectorMenu);
                                connectorMenu.addActionListener(new ActionListener() {
                                    @Override
                                    public void actionPerformed(ActionEvent e) {
                                        ThingMLModel thingmlModel = ThingMLCompiler.loadModel(targetFile);
                                        for (Configuration cfg : ThingMLHelpers.allConfigurations(thingmlModel)) {
                                            final ThingMLCompiler compiler = registry
                                                    .createCompilerInstanceByName(id);
                                            for (NetworkPlugin np : loadedPlugins) {
                                                if (np.getTargetedLanguages().contains(compiler.getID())) {
                                                    compiler.addNetworkPlugin(np);
                                                }
                                            }
                                            for (SerializationPlugin sp : loadedSerPlugins) {
                                                if (sp.getTargetedLanguages().contains(compiler.getID())) {
                                                    compiler.addSerializationPlugin(sp);
                                                }
                                            }
                                            compiler.setOutputDirectory(
                                                    new File(System.getProperty("java.io.tmpdir") + "/ThingML_temp/"
                                                            + cfg.getName()));
                                            compiler.compileConnector(connectorCompiler.getKey(), cfg);
                                        }
                                    }
                                });
                            }
                        } else {
                            newCompilersMenu.add(item);
                        }

                        item.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                System.out.println("Input file : " + targetFile);
                                if (targetFile == null)
                                    return;
                                try {
                                    ThingMLModel thingmlModel = ThingMLCompiler.loadModel(targetFile);
                                    for (Configuration cfg : ThingMLHelpers.allConfigurations(thingmlModel)) {
                                        final ThingMLCompiler compiler = registry.createCompilerInstanceByName(id);
                                        for (NetworkPlugin np : loadedPlugins) {
                                            if (np.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addNetworkPlugin(np);
                                            }
                                        }
                                        for (SerializationPlugin sp : loadedSerPlugins) {
                                            if (sp.getTargetedLanguages().contains(compiler.getID())) {
                                                compiler.addSerializationPlugin(sp);
                                            }
                                        }

                                        File myFileBuf = new File(System.getProperty("java.io.tmpdir")
                                                + "/ThingML_temp/" + cfg.getName());
                                        compiler.setOutputDirectory(myFileBuf);
                                        compiler.compile(cfg);

                                        final InputStream input = new FileInputStream(myFileBuf.getAbsolutePath()
                                                + "/" + cfg.getName() + "/" + cfg.getName() + ".pde");

                                        //System.out.println("tmp file: " + myFileBuf.getAbsolutePath() + "/" + cfg.getName() + "/" + cfg.getName() + ".pde");

                                        //final InputStream input = new FileInputStream(myFileBuf);
                                        String result = null;
                                        try {
                                            if (input != null) {
                                                result = org.apache.commons.io.IOUtils.toString(input);
                                                input.close();
                                                transferBuf.setString(result);
                                                transferBuf.hasChanged();
                                                transferBuf.notifyObservers();
                                            } else {
                                                //System.out.println("WHY");
                                            }
                                        } catch (Exception exce) {
                                            if (ThingMLApp.debug)
                                                System.out.println("OH REALLY?");
                                        }

                                    }
                                } catch (Exception ex) {
                                    if (ThingMLApp.debug)
                                        ex.printStackTrace();
                                }
                            }
                        });
                        c = null;
                    }
                }

                menubar.add(newCompilersMenu);
            }

            codeEditor.getDocument().addDocumentListener(new DocumentListener() {
                public void removeUpdate(DocumentEvent e) {
                    lastUpdate.set(System.currentTimeMillis());
                    checkNeeded.set(true);
                }

                public void insertUpdate(DocumentEvent e) {
                    lastUpdate.set(System.currentTimeMillis());
                    checkNeeded.set(true);
                }

                public void changedUpdate(DocumentEvent e) {
                    lastUpdate.set(System.currentTimeMillis());
                    checkNeeded.set(true);
                }
            });

            java.util.Timer timer = new Timer();
            timer.scheduleAtFixedRate(new SeamlessNotification(), 250, 250);

        } catch (Exception e) {
            if (ThingMLApp.debug)
                e.printStackTrace();
        }
    }

    public int getIndex(int line, int column) {
        try {
            int lineStart = codeEditor.getDocument().getDefaultRootElement().getElement(line - 1).getStartOffset();
            return lineStart + column;
        } catch (Exception e) {
            return 0;
        }
    }

    public int getNextIndex(int offset) {
        if (codeEditor.getDocument().getEndPosition().getOffset() > (offset + 1)) {
            return offset + 1;
        } else {
            return 0;
        }
    }

    public void loadText(String content, File tfile) {
        targetFile = tfile;
        codeEditor.setText(content);
    }

    AtomicBoolean checkNeeded = new AtomicBoolean(false);
    AtomicLong lastUpdate = new AtomicLong(System.currentTimeMillis());

    class SeamlessNotification extends TimerTask {

        @Override
        public void run() {
            if (checkNeeded.get() && System.currentTimeMillis() - lastUpdate.get() > 500) {
                if (codeEditor.getDocument().getLength() > 1) {
                    try {
                        updateMarkers(
                                codeEditor.getDocument().getText(0, codeEditor.getDocument().getLength() - 1));
                        checkNeeded.set(false);
                    } catch (Exception e) {
                        if (ThingMLApp.debug)
                            e.printStackTrace();
                    }
                }
            }
        }

        private void updateMarkers(String content) {
            try {

                Resource resource = null;

                if (targetFile != null) {
                    resource = new ThingmlResource(URI.createFileURI(targetFile.getAbsolutePath()));
                } else
                    resource = new ThingmlResource(URI.createURI("http://thingml.org"));

                ThingMLCompiler.resource = (ThingmlResource) resource;

                // It does not really work without a resourceSet
                ResourceSet rset = new ResourceSetImpl();
                rset.getResources().add(resource);

                // This is the text from the editor
                InputStream stream = new ByteArrayInputStream(codeEditor.getText().getBytes());
                resource.load(stream, null);
                org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(resource);

                Markers.removeMarkers(codeEditor);
                resource.getErrors().clear();
                resource.getWarnings().clear();
                checker.Errors.clear();
                checker.Warnings.clear();
                checker.Notices.clear();

                ThingMLModel model = (ThingMLModel) resource.getContents().get(0);
                checker.do_generic_check(model);
                checker.printErrors();
                checker.printWarnings();
                /*for (Configuration cfg : model.allConfigurations()) {
                System.out.println("Checking configuration " + cfg.getName());
                checker.do_generic_check(cfg);
                checker.printErrors();
                checker.printWarnings();
                }*/

                if (resource.getErrors().isEmpty())
                    org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(resource);
                else
                    for (Resource.Diagnostic error : resource.getErrors()) {
                        Markers.SimpleMarker marker = new Markers.SimpleMarker(new Color(255, 0, 0, 100));
                        if (error instanceof IThingmlTextDiagnostic) {
                            IThingmlTextDiagnostic e = (IThingmlTextDiagnostic) error;
                            Markers.markText(codeEditor, e.getCharStart(), e.getCharEnd() + 1, marker);
                        } else {
                            int offset = getIndex(error.getLine(), error.getColumn());
                            Markers.markText(codeEditor, offset, getNextIndex(offset), marker);
                        }
                    }
                for (Resource.Diagnostic error : resource.getWarnings()) {
                    Markers.SimpleMarker marker = new Markers.SimpleMarker(new Color(255, 155, 0, 100));
                    int offset = getIndex(error.getLine(), error.getColumn());
                    Markers.markText(codeEditor, offset, getNextIndex(offset), marker);
                }

                if (targetFile != null) {
                    FileWriter fileWriter = new FileWriter(targetFile);
                    fileWriter.write(codeEditor.getText());
                    fileWriter.close();
                }
            } catch (Exception e) {
                if (ThingMLApp.debug)
                    e.printStackTrace();
            }
        }
    }
}