/*
 * Copyright (c) 2007, 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.custom;

import org.jibx.binding.util.StringArray;

/**
 * Base class for possible root customizations.
 * 
 * @author Dennis M. Sosnoski
 */
public abstract class SchemaRootBase extends NestingCustomBase
{
    /** Empty array used as return value when nothing else specified. */
    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    
    /** Enumeration of allowed attribute names */
    public static final StringArray s_allowedAttributes = new StringArray(new String[] { "generate-unused",
        "package", "prefer-inline", "prefer-inner-class", "strip-prefixes", "strip-suffixes" },
        NestingCustomBase.s_allowedAttributes);
    
    /** Fully-qualified package name. */
    private String m_package;
    
    /** Generate even unused global definitions. */
    private Boolean m_generateUnused;
    
    /** Prefer inline definitions (separate classes for all if <code>FALSE</code>). */
    private Boolean m_preferInline;
    
    /** Use inner classes for substructures (top-level classes for all if <code>FALSE</code>). */
    private Boolean m_useInner;
    
    /** Prefix strings to be stripped when converting names. */
    private String[] m_stripPrefixes;
    
    /** Suffix strings to be stripped when converting names. */
    private String[] m_stripSuffixes;
    
    /**
     * Constructor.
     * 
     * @param parent
     */
    public SchemaRootBase(SchemaRootBase parent) {
        super(parent);
    }
    
    /**
     * Get parent customization (which will either be <code>null</code>, or another instance of this class).
     *
     * @return parent, or <code>null</code> if none
     */
    public SchemaRootBase getRootParent() {
        return (SchemaRootBase)getParent();
    }
    
    /**
     * Check whether unused definitions should be included in code generation. The default is <code>true</code> if not
     * overridden at any level.
     *
     * @return generate unused flag
     */
    public boolean isGenerateUnused() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_generateUnused != null) {
                return root.m_generateUnused.booleanValue();
            } else {
                root = root.getRootParent();
            }
        }
        return true;
    }
    
    /**
     * Check whether inlining of components is preferred. The default is <code>true</code> if not overridden at any
     * level.
     *
     * @return inline components flag
     */
    public boolean isPreferInline() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_preferInline != null) {
                return root.m_preferInline.booleanValue();
            } else {
                root = root.getRootParent();
            }
        }
        return true;
    }
    
    /**
     * Check whether inner classes are preferred for components used only by one definition. The default is
     * <code>true</code> if not overridden at any level.
     *
     * @return inline components flag
     */
    public boolean isUseInner() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_useInner != null) {
                return root.m_useInner.booleanValue();
            } else {
                root = root.getRootParent();
            }
        }
        return true;
    }
    
    /**
     * Get the prefixes to be stripped when converting XML names.
     *
     * @return prefixes
     */
    public String[] getStripPrefixes() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_stripPrefixes != null) {
                return root.m_stripPrefixes;
            } else {
                root = root.getRootParent();
            }
        }
        return EMPTY_STRING_ARRAY;
    }
    
    /**
     * Get the suffixes to be stripped when converting XML names.
     *
     * @return suffixes
     */
    public String[] getStripSuffixes() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_stripSuffixes != null) {
                return root.m_stripSuffixes;
            } else {
                root = root.getRootParent();
            }
        }
        return EMPTY_STRING_ARRAY;
    }

    /**
     * Get fully-qualified package name. This is inherited by nested schemas if set at any level.
     *
     * @return package (<code>null</code> if none set)
     */
    public String getPackage() {
        SchemaRootBase root = this;
        while (root != null) {
            if (root.m_package != null) {
                return root.m_package;
            } else {
                root = root.getRootParent();
            }
        }
        return null;
    }
}