Package org.eclipse.sapphire.modeling.xml

Source Code of org.eclipse.sapphire.modeling.xml.RootXmlResource

/******************************************************************************
* Copyright (c) 2014 Oracle and Accenture
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    Konstantin Komissarchik - initial implementation
*    Kamesh Sampath - [355457] Improve DTD doctype specification in XML binding
*    Kamesh Sampath - [355751] General improvement of XML root binding API
******************************************************************************/

package org.eclipse.sapphire.modeling.xml;

import static org.eclipse.sapphire.modeling.xml.XmlUtil.createDefaultElementName;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.xml.namespace.QName;

import org.eclipse.sapphire.Element;
import org.eclipse.sapphire.ElementType;
import org.eclipse.sapphire.LoggingService;
import org.eclipse.sapphire.Sapphire;
import org.eclipse.sapphire.modeling.CorruptedResourceException;
import org.eclipse.sapphire.modeling.ResourceStoreException;
import org.eclipse.sapphire.modeling.localization.LocalizationService;
import org.eclipse.sapphire.modeling.xml.annotations.CustomXmlRootBinding;
import org.eclipse.sapphire.modeling.xml.annotations.XmlBinding;
import org.eclipse.sapphire.modeling.xml.annotations.XmlDocumentType;
import org.eclipse.sapphire.modeling.xml.annotations.XmlSchema;
import org.eclipse.sapphire.modeling.xml.annotations.XmlSchemas;
import org.eclipse.sapphire.modeling.xml.internal.DocumentTypeRootElementController;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
* @author <a href="mailto:kamesh.sampath@accenture.com">Kamesh Sampath</a>
*/

public class RootXmlResource extends XmlResource
{
    private static final String PI_XML_TARGET = "xml";
    private static final String PI_XML_DATA = "version=\"1.0\" encoding=\"UTF-8\"";

    private final XmlResourceStore store;
    private final Document document;
    private RootElementController rootElementController;
    private XmlElement rootXmlElement;

    public RootXmlResource()
    {
        this( new XmlResourceStore() );
    }
   
    public RootXmlResource( final XmlResourceStore store )
    {
        super( null );
       
        this.store = store;
        this.document = store.getDomDocument();
    }
   
    public XmlResourceStore store()
    {
        return this.store;
    }
   
    @Override
    public void init( final Element modelElement )
    {
        super.init( modelElement );

        final ElementType modelElementType = modelElement.type();
       
        final CustomXmlRootBinding customXmlRootBindingAnnotation = modelElementType.getAnnotation( CustomXmlRootBinding.class );
       
        if( customXmlRootBindingAnnotation != null )
        {
            try
            {
                this.rootElementController = customXmlRootBindingAnnotation.value().newInstance();
            }
            catch( Exception e )
            {
                Sapphire.service( LoggingService.class ).log( e );
            }
        }
       
        if( this.rootElementController == null )
        {
            final XmlBinding xmlBindingAnnotation = modelElementType.getAnnotation( XmlBinding.class );
   
            if( xmlBindingAnnotation != null && xmlBindingAnnotation.path().length() != 0 )
            {
                final XmlPath path = new XmlPath( xmlBindingAnnotation.path(), getXmlNamespaceResolver() );
                final QName qualifiedName = path.getSegment( 0 ).getQualifiedName();
                final String localName = qualifiedName.getLocalPart();
                final String prefix = qualifiedName.getPrefix();
                final String namespace = qualifiedName.getNamespaceURI();
               
                final XmlDocumentType xmlDocumentTypeAnnotation = modelElementType.getAnnotation( XmlDocumentType.class );
              
                if( xmlDocumentTypeAnnotation != null && xmlDocumentTypeAnnotation.systemId().length() != 0 )
                {
                    this.rootElementController = new DocumentTypeRootElementController( localName );
                }
                else
                {
                    final Map<String,String> schemas = new HashMap<String,String>();
                    final XmlSchemas xmlSchemasAnnotation = modelElementType.getAnnotation( XmlSchemas.class );
                   
                    if( xmlSchemasAnnotation != null )
                    {
                        for( XmlSchema xmlSchemaAnnotation : xmlSchemasAnnotation.value() )
                        {
                            final String xmlSchemaNamespace = xmlSchemaAnnotation.namespace().trim();
                            final String xmlSchemaLocation = xmlSchemaAnnotation.location().trim();
                           
                            if( xmlSchemaNamespace.length() != 0 && xmlSchemaLocation.length() != 0 )
                            {
                                schemas.put( xmlSchemaNamespace, xmlSchemaLocation );
                            }
                        }
                    }
                   
                    final XmlSchema xmlSchemaAnnotation = modelElementType.getAnnotation( XmlSchema.class );
                   
                    if( xmlSchemaAnnotation != null )
                    {
                        final String xmlSchemaNamespace = xmlSchemaAnnotation.namespace().trim();
                        final String xmlSchemaLocation = xmlSchemaAnnotation.location().trim();
                       
                        if( xmlSchemaNamespace.length() != 0 && xmlSchemaLocation.length() != 0 )
                        {
                            schemas.put( xmlSchemaNamespace, xmlSchemaLocation );
                        }
                    }
                   
                    this.rootElementController = new StandardRootElementController( namespace, prefix, localName, schemas );
                }
            }
        }
       
        if( this.rootElementController == null )
        {
            this.rootElementController = new StandardRootElementController( createDefaultElementName( modelElementType ) );
        }
       
        this.rootElementController.init( this );
       
        store().registerRootModelElement( modelElement );
    }
   
    public final Document getDomDocument()
    {
        return this.document;
    }
   
    @Override
    public XmlElement getXmlElement( final boolean createIfNecessary )
    {
        org.w3c.dom.Element root = this.document.getDocumentElement();
   
        if( this.document.getChildNodes().getLength() == 0 )
        {
            if( createIfNecessary )
            {
                fixMalformedDescriptor();
                root = this.document.getDocumentElement();
            }
        }
        else
        {
            final boolean isRootValid
                = ( root == null ? false : this.rootElementController.checkRootElement() );
           
            if( isRootValid == false )
            {
                root = null;
               
                if( createIfNecessary )
                {
                    if( validateCorruptedResourceRecovery() )
                    {
                        fixMalformedDescriptor();
                        root = this.document.getDocumentElement();
                    }
                    else
                    {
                        throw new CorruptedResourceException();
                    }
                }
            }
        }
       
        if( root == null )
        {
            this.rootXmlElement = null;
        }
        else if( this.rootXmlElement == null || root != this.rootXmlElement.getDomNode() )
        {
            this.rootXmlElement = new XmlElement( store(), root );
        }
       
        return this.rootXmlElement;
    }
   
    @Override
    public void save() throws ResourceStoreException
    {
        if( this.document.getChildNodes().getLength() == 0 )
        {
            fixMalformedDescriptor();
        }
       
        this.store.save();
    }

    @Override
    public <A> A adapt( final Class<A> adapterType )
    {
        A adapter = super.adapt( adapterType );
       
        if( adapter == null )
        {
            adapter = this.store.adapt( adapterType );
        }
       
        return adapter;
    }
   
    @Override
    public boolean isOutOfDate()
    {
        return this.store.isOutOfDate();
    }
   
    @Override
    public void dispose()
    {
        super.dispose();
        this.store.dispose();
    }

    @Override
    protected LocalizationService initLocalizationService( final Locale locale )
    {
        return this.store.getLocalizationService( locale );
    }

    private final void fixMalformedDescriptor()
    {
        // Remove all of the existing top-level nodes. Note that we have to copy the
        // items from the node list before removing any as removal seems to alter the
        // node list.
       
        final NodeList topLevelNodes = this.document.getChildNodes();
        final Node[] nodes = new Node[ topLevelNodes.getLength() ];
       
        for( int i = 0, n = nodes.length; i < n; i++ )
        {
            nodes[ i ] = topLevelNodes.item( i );
        }
       
        for( Node node : nodes )
        {
            this.document.removeChild( node );
        }
       
        // Add a new XML declaration and the root element.
       
        if( store().isXmlDeclarationNeeded() )
        {
            final ProcessingInstruction xmlDeclarationNode = this.document.createProcessingInstruction( PI_XML_TARGET, PI_XML_DATA );
            this.document.insertBefore( xmlDeclarationNode, null );
           
            final Text newLineTextNode = this.document.createTextNode( "\n" );
            this.document.insertBefore( newLineTextNode, null );
        }
       
        this.rootElementController.createRootElement();
    }
   
}
TOP

Related Classes of org.eclipse.sapphire.modeling.xml.RootXmlResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.