/* * Copyright (c) 2007-2008, Dennis M. Sosnoski. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following * disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of * JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jibx.schema.codegen; import org.apache.log4j.Logger; import org.jibx.schema.SchemaUtils; import org.jibx.schema.elements.AnnotatedBase; import org.jibx.schema.elements.SchemaBase; /** * Information for a reference to a global definition. The reference may be replaced with an inlined copy of the * definition during code generation. */ public class ReferenceItem extends Item { /** Logger for class. */ private static final Logger s_logger = Logger.getLogger(GroupItem.class.getName()); /** Referenced type structure definition. */ private final DefinitionItem m_definition; /** * Copy constructor. * * @param original * @param ref reference (for overrides to copy; null if none) * @param parent */ private ReferenceItem(ReferenceItem original, Item ref, GroupItem parent) { super(original, ref, parent); m_definition = original.m_definition; } /** * Internal constructor for direct reference. * * @param comp schema component * @param parent containing structure (null if a top-level structure) * @param def referenced definition */ /*package*/ ReferenceItem(AnnotatedBase comp, GroupItem parent, DefinitionItem def) { super(comp, parent); m_definition = def; def.countReference(); } /** * Internal constructor for converting group to reference. This is used when an embedded group is converted to a * separate definition, as needed for class reuse. * * @param group * @param def */ /*package*/ ReferenceItem(GroupItem group, DefinitionItem def) { super(group, null, group.getParent()); m_definition = def; def.countReference(); } /** * Get the referenced structure. * * @return reference */ public DefinitionItem getDefinition() { return m_definition; } /** * Inline the referenced structure. This replaces the reference with a deep copy of the definition, copying the * reference name and optional/repeated information over to the definition. * * @return replacement group */ public Item inlineReference() { Item item; AnnotatedBase comp = m_definition.getSchemaComponent(); // Is there any reason for this? It looks like it should work ok without. // int type = comp.type(); // if (m_definition.getChildCount() == 1 && // (type == SchemaBase.ELEMENT_TYPE || type == SchemaBase.ATTRIBUTE_TYPE)) { // // // inlining attribute or element just substitutes the definition for the reference // item = m_definition.getFirstChild().copy(this, getParent()); // if (s_logger.isDebugEnabled()) { // s_logger.debug("Inlining reference to " + SchemaUtils.describeComponent(comp) + // " using direct substitution"); // } // // } else { // inlining anything else creates a new group from the definition item = new GroupItem(this); if (s_logger.isDebugEnabled()) { s_logger.debug("Inlining reference to " + SchemaUtils.describeComponent(comp) + " as new group"); } // } getParent().replaceChild(this, item); return item; } /** * Copy the item under a different parent. * * @param ref reference (for overrides to copy; null if none) * @param parent * @return copy */ protected Item copy(Item ref, GroupItem parent) { return new ReferenceItem(this, ref, parent); } /** * Classify the content of this item as attribute, element, and/or character data content. */ protected void classifyContent() { // handle basic classification for this component super.classifyContent(); // assume the characteristics of the referenced definition m_definition.classifyContent(); if (m_definition.isAttributePresent()) { forceAttributePresent(); } if (m_definition.isElementPresent()) { forceElementPresent(); } if (m_definition.isContentPresent()) { forceContentPresent(); } } /** * Build a description of the reference. * * @param depth current nesting depth * @return description */ public String describe(int depth) { StringBuffer buff = new StringBuffer(depth + 50); buff.append(leadString(depth)); buff.append("reference to "); if (m_definition.isInline()) { buff.append("inlined "); } buff.append(SchemaUtils.describeComponent(m_definition.getSchemaComponent())); buff.append(" with value name "); buff.append(getName()); buff.append(": "); buff.append(SchemaUtils.describeComponent(getSchemaComponent())); buff.append('\n'); return buff.toString(); } }