org.shaman.rpg.editor.project.elements.JdomElements.java Source code

Java tutorial

Introduction

Here is the source code for org.shaman.rpg.editor.project.elements.JdomElements.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.shaman.rpg.editor.project.elements;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.openide.filesystems.FileAlreadyLockedException;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;

/**
 * Helper class for loading and saving {@link JdomGroup} and {@link JdomElement}.
 * @author Sebastian Wei
 */
public class JdomElements {
    private static final String FILENAME = ".elements";
    private static final String ROOT_NAME = "elements";
    private static final String ROOT_NAMESPACE = "game";
    private static final int AUTOSAVE_PERIOD = 1000; //wait 1 sec
    private static final Logger LOG = Logger.getLogger(Elements.class.getName());

    static final String ATTRIBUTE_ID = "id";
    static final Namespace NAMESPACE = Namespace.getNamespace(ROOT_NAMESPACE);

    volatile boolean hasChanges = false;

    private FileObject file;
    private Document doc;
    private JdomGroup root;
    private boolean autosave;
    private AutosaveThread autosaveThread;

    static void setAttributeNullCheck(org.jdom2.Element element, String attribute, String value) {
        if (value != null) {
            element.setAttribute(attribute, value);
        }
    }

    /**
     * <b>Do not use, an instance is provided in the project's lookup</b>.
     * @param projectRoot 
     */
    public JdomElements(FileObject projectRoot) {
        try {
            file = projectRoot.getFileObject(FILENAME);
            if (file == null) {
                file = projectRoot.createData(FILENAME);
                //set hidden flag
                //setHidden(FileUtil.toFile(file).toPath());
                root = newDoc();
                save();
            } else {
                //load
                SAXBuilder b = new SAXBuilder();
                try (InputStream in = file.getInputStream()) {
                    doc = b.build(in);
                } catch (JDOMException ex) {
                    Exceptions.printStackTrace(ex);
                    //create new file
                    root = newDoc();
                    save();
                    return;
                }
                //validate file
                org.jdom2.Element e = doc.getRootElement();
                if (!e.getName().equals(ROOT_NAME) || !e.getNamespaceURI().equals(ROOT_NAMESPACE)) {
                    //invalid root file -> corrupt file -> create new file
                    LOG.warning("corrupt elements file: invalid root node");
                    root = newDoc();
                    save();
                    return;
                }
                //create root group
                root = new JdomGroup(null, this, e, 0);
                root.load();
            }
        } catch (IOException e) {
            Exceptions.printStackTrace(e);
        }
    }

    @Deprecated
    private void setHidden(Path path) {
        try {
            Boolean hidden = (Boolean) Files.getAttribute(path, "dos:hidden", LinkOption.NOFOLLOW_LINKS);
            if (hidden != null && !hidden) {
                Files.setAttribute(path, "dos:hidden", Boolean.TRUE, LinkOption.NOFOLLOW_LINKS);
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private JdomGroup newDoc() {
        //create new file
        org.jdom2.Element e = new org.jdom2.Element(ROOT_NAME);
        e.setNamespace(NAMESPACE);
        //e.setAttribute("xmlns", ROOT_NAMESPACE);
        doc = new Document(e);
        JdomGroup r = new JdomGroup(null, this, e, 0);
        return r;
    }

    public JdomGroup getRoot() {
        return root;
    }

    public synchronized void save() {
        root.update();
        XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
        try (OutputStream stream = file.getOutputStream()) {
            out.output(doc, stream);
        } catch (FileAlreadyLockedException ex) {
            Exceptions.printStackTrace(ex);
            return;
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
            return;
        }

        //debug
        LOG.fine("elements saved");
        //      try {
        //         for (String line : file.asLines()) {
        //            System.out.println(line);
        //         }
        //      } catch (IOException ex) {
        //         Exceptions.printStackTrace(ex);
        //      }
    }

    public synchronized void setAutosave(boolean autosave) {
        if (this.autosave == autosave) {
            return; //no changes
        }
        this.autosave = autosave;
        if (autosave) {
            //start autosave thread
            autosaveThread = new AutosaveThread();
            autosaveThread.start();
        } else {
            //stop autosave thread
            if (autosaveThread != null) {
                autosaveThread.interrupt();
                autosaveThread = null;
            }
        }
    }

    public boolean isAutosave() {
        return autosave;
    }

    private class AutosaveThread extends Thread {

        @Override
        public void run() {
            while (true) {
                if (Thread.interrupted()) {
                    break; //autosave turned off
                }
                if (hasChanges) {
                    hasChanges = false;
                    save();
                }
                if (Thread.interrupted()) {
                    break; //autosave turned off
                }
                try {
                    Thread.sleep(AUTOSAVE_PERIOD);
                } catch (InterruptedException ex) {
                    break; //autosave turned off
                }
            }
            LOG.info("autosave thread turned off");
        }

    }
}