/*
 * Copyright 2007 Ralf Joachim
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.exolab.castor.builder.types;

import org.exolab.castor.xml.schema.Facet;
import org.exolab.javasource.JSourceCode;

/**
 * A base class for types which support the length, whiteSpace and pattern facets.
 * 
 * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
 * @version $Revision: 6662 $ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $
 * @since 1.1
 */
public abstract class AbstractLengthFacet extends AbstractWhiteSpaceFacet {
    //--------------------------------------------------------------------------

    /** The length facet. */
    private int _length = 0;
    
    /** The max length facet. */
    private int _maxLength = -1;
    
    /** The min length facet. */
    private int _minLength = 0;
    
    //--------------------------------------------------------------------------

    /**
     * No-arg constructor. By default only 'collapse' is supported for the whiteSpace facet.
     */
    protected AbstractLengthFacet() {
        super(true);
    }
    
    /**
     * Construct a new AbstractXSLengthFacet optionally allowing the whiteSpace facet to be set
     * to 'replace' and 'preserve' values in addition to 'collaps'.
     *
     * @param whiteSpaceCollapseOnly If set to true only 'collapse' is allowed for the whiteSpace
     *        facet. If set to false 'collaps', 'replace' and 'preserve' values are allowed for
     *        whiteSpace facet.
     */
    protected AbstractLengthFacet(final boolean whiteSpaceCollapseOnly) {
        super(whiteSpaceCollapseOnly);
    }
    
    //--------------------------------------------------------------------------

    /**
     * Returns true if a length has been set.
     * 
     * @return True if a length has been set.
     */
    public final boolean hasLength() {
        return (_length > 0);
    }

    /**
     * Returns the length that this type must have.
     * 
     * @return The length that this type must have.
     */
    public final int getLength() {
        return _length;
    }

    /**
     * Sets the length of this type. While setting the length, the maxLength
     * and minLength are also set up to this length.
     *
     * @param length The length to set.
     */
    public final void setLength(final int length) {
        _length = length;
        
        setMaxLength(length);
        setMinLength(length);
    }

    /**
     * Returns true if a maximum length has been set.
     * 
     * @return True if a maximum length has been set.
     */
    public final boolean hasMaxLength() {
        return (_maxLength >= 0);
    }

    /**
     * Returns the maximum length occurances of this type can be. A negative value denotes
     * no maximum length.
     * 
     * @return The maximum length facet.
     */
    public final int getMaxLength() {
        return _maxLength;
    }

    /**
     * Sets the maximum length of this type. To remove the max length facet,
     * use a negative value.
     *
     * @param maxLength The maximum length for occurances of this type.
     */
    public final void setMaxLength(final int maxLength) {
        _maxLength = maxLength;
    }

    /**
     * Returns true if a minimum length has been set.
     * 
     * @return True if a minimum length has been set.
     */
    public final boolean hasMinLength() {
        return (_minLength > 0);
    }

    /**
     * Returns the minimum length occurances of this type can be.
     * 
     * @return The minimum length facet.
     */
    public final int getMinLength() {
        return _minLength;
    }

    /**
     * Sets the minimum length of this XSString.
     * 
     * @param minLength The minimum length for occurances of this type.
     */
    public final void setMinLength(final int minLength) {
        _minLength = minLength;
    }

    //--------------------------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    protected final void setFacet(final Facet facet) {
        super.setFacet(facet);
        setLengthFacet(facet);
    }
    
    /**
     * Transfer given facet if it is one of length, maxLength or minLength.
     *
     * @param facet The facet to transfer.
     */
    protected final void setLengthFacet(final Facet facet) {
        String name = facet.getName();
        if (Facet.LENGTH.equals(name)) {
            setLength(facet.toInt());
        } else if (Facet.MAX_LENGTH.equals(name)) {
            setMaxLength(facet.toInt());
        } else if (Facet.MIN_LENGTH.equals(name)) {
            setMinLength(facet.toInt());
        }
    }

    /**
     * Generate the source code for length, maxLength or minLength facets validation.
     *
     * @param jsc The JSourceCode to fill in.
     * @param validatorName The name of the TypeValidator that the patterns should be added to.
     */
    protected final void codeLengthFacet(final JSourceCode jsc, final String validatorName) {
        if (hasLength()) {
            jsc.add("{0}.setLength({1});", validatorName, Integer.toString(getLength()));
        } else {
            if (hasMaxLength()) {
                jsc.add("{0}.setMaxLength({1});", validatorName, Integer.toString(getMaxLength()));
            }
            if (hasMinLength()) {
                jsc.add("{0}.setMinLength({1});", validatorName, Integer.toString(getMinLength()));
            }
        }
    }

    //--------------------------------------------------------------------------
}
