All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.exist.xquery.Cardinality Maven / Gradle / Ivy

/*
 * Copyright (C) 2014, Evolved Binary Ltd
 *
 * This file was originally ported from FusionDB to eXist-db by
 * Evolved Binary, for the benefit of the eXist-db Open Source community.
 * Only the ported code as it appears in this file, at the time that
 * it was contributed to eXist-db, was re-licensed under The GNU
 * Lesser General Public License v2.1 only for use in eXist-db.
 *
 * This license grant applies only to a snapshot of the code as it
 * appeared when ported, it does not offer or infer any rights to either
 * updates of this source code or access to the original source code.
 *
 * The GNU Lesser General Public License v2.1 only license follows.
 *
 * ---------------------------------------------------------------------
 *
 * Copyright (C) 2014, Evolved Binary Ltd
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; version 2.1.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.exist.xquery;

import static org.exist.xquery.Cardinality.InternalValue.*;

/**
 * Defines XPath Occurrence Indicators
 * (*,?,+), and additionally defines {@link #EMPTY_SEQUENCE}, and {@link #EXACTLY_ONE} for convenience.
 *
 * @author Adam Retter
 */
public enum Cardinality {

    EMPTY_SEQUENCE(ZERO),

    //TODO(AR) can we eliminate this?
    EXACTLY_ONE(ONE),

    //TODO(AR) eliminate this in favour of probably ONE_OR_MORE
    _MANY(MANY),

    /**
     * indicator '?'
     */
    ZERO_OR_ONE((byte)(ZERO | ONE)),

    /**
     * indicator '+'
     */
    ONE_OR_MORE((byte)(ONE | MANY)),

    /**
     * indicator '*'
     */
    ZERO_OR_MORE((byte)(ZERO | ONE | MANY));


    private final byte val;

    Cardinality(final byte val) {
        this.val = val;
    }

    /**
     * The cardinality represents a sequence of at least one value.
     *
     * @return true if the cardinality represents a sequence of at least one value, or false otherwise.
     */
    public boolean atLeastOne() {
        return (val & ZERO) == 0;
    }

    /**
     * The cardinality represents a sequence of at most one value.
     *
     * @return true if the cardinality represents a sequence of at most one value, or false otherwise.
     */
    public boolean atMostOne() {
        return (val & MANY) == 0;
    }

    /**
     * Tests whether this Cardinality is a sub-cardinality or equal
     * of {@code other}.
     *
     * @param other the other cardinality
     *
     * @return true if this is a sub-cardinality or equal cardinality of {@code other}.
     */
    public boolean isSubCardinalityOrEqualOf(final Cardinality other) {
        return (val | other.val) == other.val;
    }

    /**
     * Tests whether this Cardinality is a super-cardinality or equal
     * of {@code other}.
     *
     * @param other the other cardinality
     *
     * @return true if this is a super-cardinality or equal cardinality of {@code other}.
     */
    public boolean isSuperCardinalityOrEqualOf(final Cardinality other) {
        return (val & other.val) == other.val;
    }

    /**
     * Given two cardinalities, return a cardinality that is capable of
     * representing both,
     * i.e.: {@code a.isSubCardinalityOrEqualOf(max(a, b)) && b.isSubCardinalityOrEqualOf(max(a, b)) && b.max(a, b))}
     *
     * @param a the first cardinality
     * @param b the second cardinality
     *
     * @return the super cardinality
     */
    public static Cardinality superCardinalityOf(final Cardinality a, final Cardinality b) {
        final byte max = (byte)(a.val | b.val);
        for (final Cardinality cardinality : Cardinality.values()) {
            if (cardinality.val == max) {
                return cardinality;
            }
        }
        throw new IllegalStateException();
    }

    /**
     * Get an XQuery notation representation of the cardinality.
     *
     * @return the XQuery notation
     */
    public String toXQueryCardinalityString() {
        switch (this) {
            case EMPTY_SEQUENCE:
                return "empty-sequence()";

            case EXACTLY_ONE:
                return "";

            case ZERO_OR_ONE:
                return "?";

            case _MANY:
            case ONE_OR_MORE:
                return "+";

            case ZERO_OR_MORE:
                return "*";

            default:
                // impossible
                throw new IllegalArgumentException("Unknown cardinality: " + name());
        }
    }

    /**
     * Get a human pronounceable description of the cardinality.
     *
     * @return a pronounceable description
     */
    public String getHumanDescription() {
        switch (this) {
            case EMPTY_SEQUENCE:
                return "empty";
            case EXACTLY_ONE:
                return "exactly one";
            case ZERO_OR_ONE:
                return "zero or one";

            case _MANY:
            case ONE_OR_MORE:
                return "one or more";

            case ZERO_OR_MORE:
                return "zero or more";
            default:
                // impossible
                throw new IllegalArgumentException("Unknown cardinality: " + name());
        }
    }

    /**
     * Get the Cardinality from an integer representation.
     *
     * @param intValue integer representation of cardinality
     *
     * @return the cardinality
     *
     * @deprecated You should not pass cardinality as integer values,
     *     this is for backwards compatibility with eXist-db
     */
    @Deprecated
    public static Cardinality fromInt(final int intValue) {
        for (final Cardinality cardinality : Cardinality.values()) {
            if (cardinality.val == intValue) {
                return cardinality;
            }
        }
        throw new IllegalArgumentException("No know cardinality for intValue: " + intValue);
    }

    static class InternalValue {
        static final byte ZERO = 1;
        static final byte ONE = 2;
        static final byte MANY = 4;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy