/**
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * Copyright (C)
 * <a href="http://www.inab.org">Spanish National Institute of Bioinformatics (INB)</a>
 * <a href="http://www.bsc.es">Barcelona Supercomputing Center (BSC)</a>
 * <a href="http://inb.bsc.es">Computational Node 6</a>
 */

package org.inb.biomoby.shared.message;

import java.io.Serializable;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import org.inb.biomoby.MobyMessageContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * This class is a substitution to ontology classes.
 * In case JAXBContext could not find an appropriate ontology class in a classpath,
 * a class is substituted by this one.
 *
 * @author Dmitry Repchevsky
 */

public class AnyMobyObject extends MobyObject implements Serializable
{
    public final String type;
    
    public AnyMobyObject(String type)
    {
        this.type = type;
    }

    public AnyMobyObject(String type, String id, String namespace)
    {
        super(id, namespace);
        
        this.type = type;
    }
    
    private AnyMobyObject(MobyObject mobyObject, String type)
    {
        super(mobyObject.getMobyId(), mobyObject.getNamespace());

        this.type = type;

        this.articleName = mobyObject.articleName;
        this.attributes  = mobyObject.attributes;
    }
    
    public String getType()
    {
        return type;
    }

    /**
     * Method makes public an access to internal properties
     *
     * @param articleName - an articleName for a property
     * @return anything (MobyObject, AnyMobyObject, primitives, ontology generated classes)
     */
    @Override
    public AbstractMobyObject getAttribute(String articleName)
    {
        return super.getAttribute(articleName);
    }

    @Override
    public List<AbstractMobyObject> getAttributes(String articleName)
    {
        return super.getAttributes(articleName);
    }

    Element marshal()
    {
        Element element;
        
        try
        {
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            builderFactory.setNamespaceAware(true);
            Document doc = builderFactory.newDocumentBuilder().newDocument();
            
            JAXBContext context = MobyMessageContext.getContext();

            Marshaller m = context.createMarshaller();
            m.marshal(this, doc);

            element = doc.getDocumentElement();

            String prefix = element.getPrefix();
            String qName = prefix == null ? type : prefix + ':' + type;
            
            doc.renameNode(element, element.getNamespaceURI(), qName);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            element = null;
        }

        return element;
    }
    
    static AnyMobyObject unmarshal(Element element)
    {
        AnyMobyObject anyMobyObject;
        
        String name = element.getLocalName();
        String namespace = element.getNamespaceURI();

        Document doc = element.getOwnerDocument();
        doc.renameNode(element, namespace, "Object");

        try
        {
            JAXBContext context = MobyMessageContext.getContext();
            Unmarshaller u = context.createUnmarshaller();

            MobyObject mobyObject = (MobyObject)u.unmarshal(element);

            anyMobyObject = new AnyMobyObject(mobyObject, name);
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            anyMobyObject = null;
        }
 
        return anyMobyObject;
    }
}
