/*
 * __NAME__.java
 *
 * Created on __DATE__
 */

package Templates.API_Support.Services_API;

import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import org.openide.ErrorManager;
import org.openide.cookies.InstanceCookie;
import org.openide.loaders.DataObject;
import org.openide.loaders.Environment;
import org.openide.loaders.XMLDataObject;
import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;

/** A processor for XML files of a certain DTD.
 * In this case it adds an InstanceCookie, making them handy for lookup
 * or for use in FolderInstance's etc.
 * You could alternatively add an ExecCookie to make the XML
 * files executable, etc. Just add the cookie to the lookup.
 *
 * @author __USER__
 */
public class XMLProcessor implements Environment.Provider {

    /** Public ID for some DTD. */
    public static final String MYSTUFF_DTD_ID = "-//Your Org//DTD Some Description 1.0//EN"; // NOI18N
    //                CHANGEME ^^^^^^^              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    // ---- MERGE THIS INTO YOUR LAYER with INDICATED CHANGES: ----
    /*
    <filesystem>
        <folder name="xml">
            <!-- This registers the DTD by public ID in case anyone asks for it: -->
            <folder name="entities">
                <!-- See Javadoc for EntityCatalog for exact naming scheme: -->
                <folder name="Your_Org">
                    <!-- INCLUDE YOUR DTD in the MODULE, e.g. NEXT to the LAYER: -->
                    <file name="DTD_Some_Description_1_0" url="some_description-1_0.dtd"/>
                </folder>
            </folder>
            <!-- And this registers the processor for that public ID: -->
            <folder name="lookups">
                <folder name="Your_Org">
                    <file name="DTD_Some_Description_1_0.instance">
                        <attr name="instanceClass" stringvalue="__PACKAGE_AND_NAME__"/>
                    </file>
                </folder>
            </folder>
        </folder>
    </filesystem>
     */

    // ---- NOW THE FOLLOWING .xml FILE: ----
    /*
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE quadcurve PUBLIC
              "-//Your Org//DTD Some Description 1.0//EN"
              "http://yourorg.org/dtds/some_description-1_0.dtd">
    <quadcurve x1="0" y1="0" x2="100" y2="100" ctrlx=".5" ctrly=".5"/>
     */
    // ---- SHOULD PRODUCE an INSTANCE of QuadCurve2D.Float ----

    public Lookup getEnvironment(DataObject obj) {
        if (obj instanceof XMLDataObject) {
            XMLDataObject xml = (XMLDataObject)obj;
            InstanceContent content = new InstanceContent();
            // If it is cheap to create the cookies, you can do so right away.
            content.add(new MySupport(xml));
            // If it is more expensive, you can delay it until requested
            // (see below for the convertor impl):
            // content.add(xml, new MyConvertor());
            return new AbstractLookup(content);
            // If you like, you can change the cookies (lookup content)
            // dynamically later on. Just keep track of the InstanceContent
            // and add/remove whenever you like.
        } else {
            // Should not happen.
            return Lookup.EMPTY;
        }
    }

    /** Now provide some implementation of the cookie (or use an existing support).
     * Here we create an instance of a Java object based on the XML document,
     * which is the most common use of processors.
     *
     * Note that the use of InstanceCookie.Of permits us to avoid loading the
     * implementation class until it is actually going to be used. Someone
     * asking this XML file if it provides an instance of Shape will get the
     * answer "yes" without QuadCurve2D.Float having been necessarily loaded.
     * More importantly, if someone asks whether it provides an instance of some
     * totally unrelated class, it will get a quick "no". If you don't care, just
     * implement plain InstanceCookie and delete instanceOf().
     */
    private static final class MySupport implements InstanceCookie.Of {

        private final XMLDataObject xml;
        public MySupport(XMLDataObject xml) {
            this.xml = xml;
        }

        public Class instanceClass() /*throws IOException, ClassNotFoundException*/ {
            // Indicate the class (or relevant superclass or interface) which you
            // will be making instances of.
            return java.awt.geom.QuadCurve2D.Float.class; // <-- CHANGEME
        }

        public String instanceName() {
            // Should be the same as instanceClass().getName():
            return "java.awt.geom.QuadCurve2D$Float"; // <-- CHANGEME
        }

        public boolean instanceOf(Class c) {
            // Check whether we are assignable to this class.
            // Note that we consider resolving Shape to be fine
            // (it is a general interface) but avoid resolving
            // the impl classes (they might never be needed).
            // CHANGEME:
            return c == java.awt.Shape.class ||
                   c.getName().equals("java.awt.geom.QuadCurve2D") ||
                   c.getName().equals("java.awt.geom.QuadCurve2D$Float");
        }

        public Object instanceCreate() throws IOException/*, ClassNotFoundException*/ {
            try {
                Document doc = xml.getDocument();
                Element el = doc.getDocumentElement();
                // Now actually make the object, based on the XML.
                // CHANGEME:
                try {
                    float x1 = Float.valueOf(el.getAttribute("x1")).floatValue(); // NOI18N
                    float x2 = Float.valueOf(el.getAttribute("x2")).floatValue(); // NOI18N
                    float y1 = Float.valueOf(el.getAttribute("y1")).floatValue(); // NOI18N
                    float y2 = Float.valueOf(el.getAttribute("y2")).floatValue(); // NOI18N
                    float ctrlx = Float.valueOf(el.getAttribute("ctrlx")).floatValue(); // NOI18N
                    float ctrly = Float.valueOf(el.getAttribute("ctrly")).floatValue(); // NOI18N
                    return new java.awt.geom.QuadCurve2D.Float(x1, y1, ctrlx, ctrly, x2, y2);
                } catch (NumberFormatException nfe) {
                    // Deal with any problems in the XML by throwing IOException, e.g.
                    IOException ioe = new IOException(nfe.toString());
                    ErrorManager.getDefault().annotate(ioe, nfe);
                    throw ioe;
                }
            } catch (SAXException saxe) {
                IOException ioe = new IOException(saxe.toString());
                ErrorManager.getDefault().annotate(ioe, saxe);
                throw ioe;
            }
        }

    }

    /** Example of a convertor for creating cookies lazily.
     * Only needed if it is too expensive to create the cookies directly
     * (most cookie implementations are cheap to construct so this is not
     * usually necessary).
     * If you only needed one, you could implement this directly on the processor
     * class.
     */
    /*
    private static final class MyConvertor implements InstanceContent.Convertor {

        public Object convert(Object o) {
            XMLDataObject xml = (XMLDataObject)o;
            return new MySupport(xml);
        }

        public Class type(Object o) {
            return MySupport.class;
            // or even better, avoid resolving MySupport until needed:
            // return InstanceCookie.Of.class;
        }

        public String id(Object o) {
            // Generally irrelevant in this context.
            return o.toString();
        }

        public String displayName(Object o) {
            // Again, irrelevant here.
            return o.toString();
        }

    }
    */

}
