/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;

import java.util.Locale;

/**
 * Enumeration of axis types.
 *
 * <p>The most commonly used values are
 * <code>COLUMNS</code> (the first axis of a 2-dimensional query),
 * <code>ROWS</code> (the second axis of a 2-dimensional query) and
 * <code>FILTER</code> (also known as the slicer axis, denoted by a
 * <code>WHERE</code> clause in an MDX statement).
 *
 * @author jhyde
 * @since Oct 23, 2006
 */
public interface Axis {

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#FILTER}.
     */
    Standard FILTER = Standard.FILTER;

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#COLUMNS}.
     */
    Standard COLUMNS = Standard.COLUMNS;

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#ROWS}.
     */
    Standard ROWS = Standard.ROWS;

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#PAGES}.
     */
    Standard PAGES = Standard.PAGES;

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#CHAPTERS}.
     */
    Standard SECTIONS = Standard.SECTIONS;

    /**
     * Abbreviation for {@link org.olap4j.Axis.Standard#FILTER}.
     */
    Standard CHAPTERS = Standard.CHAPTERS;

    /**
     * Returns the name of this axis, e.g. "COLUMNS", "FILTER", "AXIS(17)".
     *
     * @return Name of the axis
     */
    String name();

    /**
     * Returns whether this is the filter (slicer) axis.
     *
     * @return whether this is the filter axis
     */
    boolean isFilter();


    /**
     * Returns the ordinal which is to be used for retrieving this axis from
     * the {@link org.olap4j.CellSet#getAxes()}, or retrieving its
     * coordinate from {@link Cell#getCoordinateList()}.
     *
     * <p>For example:
     * <ul>
     * <li>-1 {@link org.olap4j.Axis.Standard#FILTER FILTER}</li>
     * <li>0 {@link org.olap4j.Axis.Standard#COLUMNS COLUMNS}</li>
     * <li>1 {@link org.olap4j.Axis.Standard#ROWS ROWS}</li>
     * <li>2 {@link org.olap4j.Axis.Standard#PAGES PAGES}</li>
     * <li>3 {@link org.olap4j.Axis.Standard#CHAPTERS CHAPTERS}</li>
     * <li>4 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
     * <li>5 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
     * <li>6 AXES(6)</li>
     * <li>123 AXES(123)</li>
     * </ul>
     *
     * @return ordinal of this axis
     */
    int axisOrdinal();

    /**
     * Returns localized name for this Axis.
     *
     * <p>Examples: "FILTER", "ROWS", "COLUMNS", "AXIS(10)".
     *
     * @param locale Locale for which to give the name
     * @return localized name for this Axis
     */
    String getCaption(Locale locale);

    /**
     * Enumeration of standard, named axes descriptors.
     */
    public enum Standard implements Axis {
        /**
         * Filter axis, also known as the slicer axis, and represented by the
         * WHERE clause of an MDX query.
         */
        FILTER,

        /** COLUMNS axis, also known as X axis and AXIS(0). */
        COLUMNS,

        /** ROWS axis, also known as Y axis and AXIS(1). */
        ROWS,

        /** PAGES axis, also known as AXIS(2). */
        PAGES,

        /** CHAPTERS axis, also known as AXIS(3). */
        CHAPTERS,

        /** SECTIONS axis, also known as AXIS(4). */
        SECTIONS;

        public int axisOrdinal() {
            return ordinal() - 1;
        }

        public boolean isFilter() {
            return this == FILTER;
        }

        public String getCaption(Locale locale) {
            // TODO: localize
            return name();
        }
    }

    /**
     * Container class for various Axis factory methods.
     */
    class Factory {
        private static final Standard[] STANDARD_VALUES = Standard.values();

        /**
         * Returns the axis with a given ordinal.
         *
         * <p>For example, {@code forOrdinal(0)} returns the COLUMNS axis;
         * {@code forOrdinal(-1)} returns the SLICER axis;
         * {@code forOrdinal(100)} returns AXIS(100).
         *
         * @param ordinal Axis ordinal
         * @return Axis whose ordinal is as given
         */
        public static Axis forOrdinal(final int ordinal) {
            if (ordinal < -1) {
                throw new IllegalArgumentException(
                    "Axis ordinal must be -1 or higher");
            }
            if (ordinal + 1 < STANDARD_VALUES.length) {
                return STANDARD_VALUES[ordinal + 1];
            }
            return new Axis() {
                public String toString() {
                    return name();
                }

                public String name() {
                    return "AXIS(" + ordinal + ")";
                }

                public boolean isFilter() {
                    return false;
                }

                public int axisOrdinal() {
                    return ordinal;
                }

                public String getCaption(Locale locale) {
                    // TODO: localize
                    return name();
                }
            };
        }
    }
}

// End Axis.java
