de.relaunch64.popelganda.database.CustomScripts.java Source code

Java tutorial

Introduction

Here is the source code for de.relaunch64.popelganda.database.CustomScripts.java

Source

/*
 * Relaunch64 - A Java cross-development IDE for C64 machine language coding.
 * Copyright (C) 2001-2015 by Daniel Ldecke (http://www.danielluedecke.de)
 * 
 * Homepage: http://www.popelganda.de
 * 
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 3 of 
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, see <http://www.gnu.org/licenses/>.
 * 
 * 
 * Dieses Programm ist freie Software. Sie knnen es unter den Bedingungen der GNU
 * General Public License, wie von der Free Software Foundation verffentlicht, weitergeben
 * und/oder modifizieren, entweder gem Version 3 der Lizenz oder (wenn Sie mchten)
 * jeder spteren Version.
 * 
 * Die Verffentlichung dieses Programms erfolgt in der Hoffnung, da es Ihnen von Nutzen sein 
 * wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder 
 * der VERWENDBARKEIT FR EINEN BESTIMMTEN ZWECK. Details finden Sie in der 
 * GNU General Public License.
 * 
 * Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm 
 * erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>.
 */

package de.relaunch64.popelganda.database;

import de.relaunch64.popelganda.assemblers.Assemblers;
import de.relaunch64.popelganda.util.ConstantsR64;
import de.relaunch64.popelganda.util.FileTools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.IllegalAddException;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

/**
 *
 * @author Daniel Ldecke
 */
public class CustomScripts {

    private Document scriptFile;
    private final File filepath;
    private static final String ELEMENT_SCRIPT = "Script";
    private static final String ATTR_NAME = "script_name";
    private static final String ROOT_NAME = "CustomScripts";

    public CustomScripts() {
        // first of all, create the empty documents
        scriptFile = new Document(new Element(ROOT_NAME));
        // create file path to script file
        filepath = FileTools.createFilePath("relaunch64-scripts.xml");
    }

    /**
     * Loads the scripts from an XML file
     */
    public void loadScripts() {
        // if file exists, go on...
        if (filepath != null && filepath.exists()) {
            try {
                SAXBuilder builder = new SAXBuilder();
                scriptFile = builder.build(filepath);
            } catch (JDOMException | IOException ex) {
                ConstantsR64.r64logger.log(Level.WARNING, ex.getLocalizedMessage());
            }
        }
    }

    /**
     * Saves the scripts to xml-file
     */
    public void saveScripts() {
        // if file exists, go on...
        if (filepath != null) {
            OutputStream dest = null;
            try {
                XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
                dest = new FileOutputStream(filepath);
                out.output(scriptFile, dest);
            } catch (IOException ex) {
                ConstantsR64.r64logger.log(Level.WARNING, ex.getLocalizedMessage());
            } finally {
                if (dest != null) {
                    try {
                        dest.close();
                    } catch (IOException ex) {
                        ConstantsR64.r64logger.log(Level.WARNING, ex.getLocalizedMessage());
                    }
                }
            }
        }
    }

    /**
     * Adds a new script.
     * 
     * @param name the name of the new script
     * @param content the content of the new script
     * @return {@code true} if script was successfully added.
     */
    public boolean addScript(String name, String content) {
        // check for valid values
        if (null == name || name.isEmpty() || null == content || content.isEmpty())
            return false;
        // check if element exists
        int pos = findScript(name);
        // script already exists, so update
        if (pos != -1) {
            // retrieve element
            Element el = retrieveElement(pos);
            // change content
            if (el != null) {
                el.setText(content);
            } else {
                return false;
            }
        }
        // script does not exist, so add
        else {
            // create new element
            Element el = new Element(ELEMENT_SCRIPT);
            // add attribute
            el.setAttribute(ATTR_NAME, name);
            // add content
            el.setText(content);
            // add to document
            scriptFile.getRootElement().addContent(el);
        }
        return true;
    }

    /**
     * Returns the content of the script with the name {@code name}.
     * 
     * @param name the name of the script which content should be fetched
     * @return the content of the script with the name {@code name}.
     */
    public String getScript(String name) {
        // check if element exists
        int pos = findScript(name);
        // script already exists, so update
        if (pos != -1) {
            // retrieve element
            Element el = retrieveElement(pos);
            // check for valid value
            if (el != null) {
                return el.getText();
            }
        }
        return null;
    }

    /**
     * Returns the script name from the script at the position {@code index}.
     * 
     * @param pos the index position of the script which name should be fetched
     * @return the script name from the script at the position {@code index}
     */
    public String getScriptName(int pos) {
        // retrieve element
        Element el = retrieveElement(pos);
        // check for valid value
        if (el != null) {
            return el.getAttributeValue(ATTR_NAME);
        }
        return null;
    }

    /**
     * Returns a string array with all names of available scripts.
     * @return all available script names, or {@code null} if no scripts yet exits
     */
    public String[] getScriptNames() {
        ArrayList<String> snames = new ArrayList<>();
        for (int i = 0; i < getCount(); i++) {
            String sn = getScriptName(i);
            if (sn != null && !sn.isEmpty() && !snames.contains(sn)) {
                snames.add(sn);
            }
        }
        if (snames.isEmpty())
            return null;
        return snames.toArray(new String[snames.size()]);
    }

    /**
     * Retrieves an element from the XML-database at the position {@code pos}.
     * 
     * @param pos the position of the XML-element that should be fetched
     * @return the {@code Element} at position {@code pos} or {@code null} if no
     * such element exists or {@code pos} is out of bounds.
     */
    private Element retrieveElement(int pos) {
        // check for valid values
        if (pos < 0)
            return null;
        // create a list of all elements from the given xml file
        try {
            List<Element> elementList = scriptFile.getRootElement().getChildren();
            // and return the requestet Element
            try {
                return elementList.get(pos);
            } catch (IndexOutOfBoundsException e) {
                return null;
            }
        } catch (IllegalStateException e) {
            return null;
        }
    }

    /**
     * Finds the script with the name {@code name} and returns its
     * data base index number.
     * 
     * @param name The name of the script that should be found.
     * @return The index number of the found script in the XML data base,
     * or -1 if no such script with the name {@code name} exists (or {@code name}
     * was {@code null} or empty).
     */
    public int findScript(String name) {
        if (null == name || name.trim().isEmpty())
            return -1;
        // trim spaces
        name = name.trim();
        // create a list of all author elements from the author xml file
        try {
            List<Element> scriptList = scriptFile.getRootElement().getChildren();
            // and an iterator for the loop below
            Iterator<Element> iterator = scriptList.iterator();
            // counter for the return value if a found synonym matches the parameter
            int cnt = 0;

            while (iterator.hasNext()) {
                Element script = iterator.next();
                // if synonym-index-word matches the parameter string, return the position
                if (name.equalsIgnoreCase(script.getAttributeValue(ATTR_NAME))) {
                    return cnt;
                }
                // else increase counter
                cnt++;
            }
            // if no author was found, return -1
            return -1;
        } catch (IllegalStateException e) {
            return -1;
        }
    }

    /**
     * Returns the number of edited scripts.
     * @return the number of edited scripts
     */
    public int getCount() {
        return scriptFile.getRootElement().getContentSize();
    }

    /**
     * Removes the script with the name {@code name}.
     * 
     * @param name the name of the script that should be removed.
     * @return {@code true} if removal was successful
     */
    public boolean removeScript(String name) {
        int index = findScript(name);
        return removeScript(index);
    }

    /**
     * Removes the script at the index {@code index}. Use {@link #findScript(java.lang.String) findScript()}
     * to find the index of a script by name.
     *  
     * @param index the index of the script that should be removed
     * @return {@code true} if removal was successful
     */
    public boolean removeScript(int index) {
        List<Element> children = scriptFile.getRootElement().getChildren();
        try {
            Element el = children.remove(index);
            if (el != null) {
                // reset document
                scriptFile = new Document(new Element(ROOT_NAME));
                // iterate and add remaining elements
                for (Element e : children)
                    addScript(e.getAttributeValue(ATTR_NAME), e.getText());
                return true;
            }
        } catch (UnsupportedOperationException | IndexOutOfBoundsException | IllegalAddException ex) {
            return false;
        }
        return false;
    }

    public String getCompilerHelp(Object scriptName) {
        // ret value
        String helpText = "";
        if (null == scriptName)
            return null;
        // iterate assemblers
        for (int i = 0; i < Assemblers.getCount(); i++) {
            // get file name
            String fn = Assemblers.byID(i).fileName();
            // get script...
            String script = getScript(scriptName.toString());
            // ... and scriptlines
            String[] scriptlines = script.split(System.lineSeparator());
            // check whether assembler is in current script
            for (String sl : scriptlines) {
                // if yes, proceed
                if (sl.contains(fn)) {
                    try {
                        // prepare command line
                        String file = sl.substring(0, sl.indexOf(fn) + fn.length()).trim();
                        String commandline = file + Assemblers.byID(i).getHelpCLI();
                        ProcessBuilder pb;
                        Process p;
                        // Start ProcessBuilder
                        pb = new ProcessBuilder(commandline.split(" "));
                        // set parent directory to sourcecode fie
                        pb = pb.directory(new File(file).getParentFile());
                        pb = pb.redirectInput(ProcessBuilder.Redirect.PIPE);
                        // start process
                        p = pb.start();
                        // create scanner to receive compiler messages
                        try (Scanner sc = new Scanner(p.getInputStream()).useDelimiter(System.lineSeparator())) {
                            // write output to string builder
                            while (sc.hasNextLine()) {
                                helpText = helpText + sc.nextLine() + System.lineSeparator();
                            }
                        }
                    } catch (IOException ex) {
                        return null;
                    }
                    return helpText;
                }
            }
        }
        return null;
    }
}