/****************************************************************************** * Copyright (c) 2016 Oracle * 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 and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire.modeling.xml.schema; import static org.eclipse.sapphire.modeling.util.MiscUtil.normalizeToEmptyString; import javax.xml.namespace.QName; import org.w3c.dom.NodeList; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class XmlContentModelReference extends XmlContentModel { private QName contentModelName; protected XmlContentModelReference( final XmlDocumentSchema schema, final QName contentModelName, final int minOccur, final int maxOccur ) { super( schema, minOccur, maxOccur ); this.contentModelName = contentModelName; } public QName getContentModelName() { return this.contentModelName; } public XmlContentModel getContentModel() { final QName contentModelName = getContentModelName(); if( contentModelName == null ) { return null; } else { final String namespace = contentModelName.getNamespaceURI(); final String localName = contentModelName.getLocalPart(); if( namespace.equals( normalizeToEmptyString( this.schema.getNamespace() ) ) ) { return this.schema.getContentModel( localName ); } else { final String importedSchemaLocation = this.schema.getSchemaLocation( namespace ); final XmlDocumentSchema importedSchema = XmlDocumentSchemasCache.getSchema( importedSchemaLocation ); return importedSchema.getContentModel( localName ); } } } @Override public XmlContentModel findChildElementContentModel( final QName childElementName ) { final XmlContentModel contentModel = getContentModel(); if( contentModel != null ) { return contentModel.findChildElementContentModel( childElementName ); } return null; } @Override protected InsertionPosition findInsertionPosition( final NodeList nodeList, final int nodeListLength, final QName qname, final Position position ) { final InsertionPosition result = new InsertionPosition(); final XmlContentModel contentModel = getContentModel(); if( contentModel == null ) { return result; } for( int i = 0; ; i++ ) { final int startingPosition = position.listIndex; final InsertionPosition localResult = contentModel.findInsertionPosition( nodeList, nodeListLength, qname, position ); if( position.listIndex == startingPosition ) { i++; if( this.maxOccur != -1 && i > this.maxOccur ) { localResult.grade = InsertionPosition.G1_EXCEEDS_MAX_OCCUR; } else if( i <= this.minOccur ) { localResult.grade = InsertionPosition.G4_MEETS_OCCUR_REQUIREMENT; } else { localResult.grade = InsertionPosition.G2_OK_TO_INSERT; } result.merge( localResult ); break; } else { result.merge( localResult ); } } return result; } @Override protected void toString( final StringBuilder buf, final String indent ) { buf.append( indent ); buf.append( "content-model-ref [" ); //$NON-NLS-1$ buf.append( this.minOccur ); buf.append( ':' ); buf.append( this.maxOccur ); buf.append( "]\n" ); //$NON-NLS-1$ buf.append( indent ); buf.append( "{\n" ); //$NON-NLS-1$ buf.append( indent ); buf.append( " ref = " ); //$NON-NLS-1$ buf.append( this.contentModelName ); buf.append( '\n' ); buf.append( indent ); buf.append( '}' ); } public static final class Factory extends XmlContentModel.Factory { private QName contentModelName; public QName getContentModelName() { return this.contentModelName; } public void setContentModelName( final QName contentModelName ) { this.contentModelName = contentModelName; } public void setContentModelName( final String contentModelName ) { this.contentModelName = new QName( contentModelName ); } @Override public XmlContentModel create( final XmlDocumentSchema schema ) { return new XmlContentModelReference( schema, this.contentModelName, this.minOccur, this.maxOccur ); } } }