| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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.apache.jackrabbit.oak.api; |
| |
| import java.math.BigDecimal; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.jcr.PropertyType; |
| |
| import org.jetbrains.annotations.NotNull; |
| |
| /** |
| * Instances of this class map Java types to {@link PropertyType property types}. |
| * Passing an instance of this class to {@link PropertyState#getValue(Type)} determines |
| * the return type of that method. |
| * @param <T> |
| */ |
| public final class Type<T> implements Comparable<Type<?>> { |
| |
| private static final Map<String, Type<?>> TYPES = new HashMap<String, Type<?>>(); |
| |
| private static <T> Type<T> create(int tag, boolean array, String string) { |
| Type<T> type = new Type<T>(tag, array, string); |
| TYPES.put(string, type); |
| return type; |
| } |
| |
| /** Map {@code String} to {@link PropertyType#STRING} */ |
| public static final Type<String> STRING = |
| create(PropertyType.STRING, false, "STRING"); |
| |
| /** Map {@code Blob} to {@link PropertyType#BINARY} */ |
| public static final Type<Blob> BINARY = |
| create(PropertyType.BINARY, false, "BINARY"); |
| |
| /** Map {@code Long} to {@link PropertyType#LONG} */ |
| public static final Type<Long> LONG = |
| create(PropertyType.LONG, false, "LONG"); |
| |
| /** Map {@code Double} to {@link PropertyType#DOUBLE} */ |
| public static final Type<Double> DOUBLE = |
| create(PropertyType.DOUBLE, false, "DOUBLE"); |
| |
| /** Map {@code String} to {@link PropertyType#DATE} */ |
| public static final Type<String> DATE = |
| create(PropertyType.DATE, false, "DATE"); |
| |
| /** Map {@code Boolean} to {@link PropertyType#BOOLEAN} */ |
| public static final Type<Boolean> BOOLEAN = |
| create(PropertyType.BOOLEAN, false, "BOOLEAN"); |
| |
| /** Map {@code String} to {@link PropertyType#STRING} */ |
| public static final Type<String> NAME = |
| create(PropertyType.NAME, false, "NAME"); |
| |
| /** Map {@code String} to {@link PropertyType#PATH} */ |
| public static final Type<String> PATH = |
| create(PropertyType.PATH, false, "PATH"); |
| |
| /** Map {@code String} to {@link PropertyType#REFERENCE} */ |
| public static final Type<String> REFERENCE = |
| create(PropertyType.REFERENCE, false, "REFERENCE"); |
| |
| /** Map {@code String} to {@link PropertyType#WEAKREFERENCE} */ |
| public static final Type<String> WEAKREFERENCE = |
| create(PropertyType.WEAKREFERENCE, false, "WEAKREFERENCE"); |
| |
| /** Map {@code String} to {@link PropertyType#URI} */ |
| public static final Type<String> URI = |
| create(PropertyType.URI, false, "URI"); |
| |
| /** Map {@code BigDecimal} to {@link PropertyType#DECIMAL} */ |
| public static final Type<BigDecimal> DECIMAL = |
| create(PropertyType.DECIMAL, false, "DECIMAL"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#STRING} */ |
| public static final Type<Iterable<String>> STRINGS = |
| create(PropertyType.STRING, true, "STRINGS"); |
| |
| /** Map {@code Iterable<Blob>} to array of {@link PropertyType#BINARY} */ |
| public static final Type<Iterable<Blob>> BINARIES = |
| create(PropertyType.BINARY, true, "BINARIES"); |
| |
| /** Map {@code Iterable<Long>} to array of {@link PropertyType#LONG} */ |
| public static final Type<Iterable<Long>> LONGS = |
| create(PropertyType.LONG, true, "LONGS"); |
| |
| /** Map {@code Iterable<Double>} to array of {@link PropertyType#DOUBLE} */ |
| public static final Type<Iterable<Double>> DOUBLES = |
| create(PropertyType.DOUBLE, true, "DOUBLES"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#DATE} */ |
| public static final Type<Iterable<String>> DATES = |
| create(PropertyType.DATE, true, "DATES"); |
| |
| /** Map {@code Iterable<Boolean>} to array of {@link PropertyType#BOOLEAN} */ |
| public static final Type<Iterable<Boolean>> BOOLEANS = |
| create(PropertyType.BOOLEAN, true, "BOOLEANS"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#NAME} */ |
| public static final Type<Iterable<String>> NAMES = |
| create(PropertyType.NAME, true, "NAMES"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#PATH} */ |
| public static final Type<Iterable<String>> PATHS = |
| create(PropertyType.PATH, true, "PATHS"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#REFERENCE} */ |
| public static final Type<Iterable<String>> REFERENCES = |
| create(PropertyType.REFERENCE, true, "REFERENCES"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#WEAKREFERENCE} */ |
| public static final Type<Iterable<String>> WEAKREFERENCES = |
| create(PropertyType.WEAKREFERENCE, true, "WEAKREFERENCES"); |
| |
| /** Map {@code Iterable<String>} to array of {@link PropertyType#URI} */ |
| public static final Type<Iterable<String>> URIS = |
| create(PropertyType.URI, true, "URIS"); |
| |
| /** Map {@code Iterable<BigDecimal>} to array of {@link PropertyType#DECIMAL} */ |
| public static final Type<Iterable<BigDecimal>> DECIMALS = |
| create(PropertyType.DECIMAL, true, "DECIMALS"); |
| |
| /** The special "undefined" type, never encountered in normal values */ |
| public static final Type<Void> UNDEFINED = |
| create(PropertyType.UNDEFINED, false, "UNDEFINED"); |
| |
| /** Multi-valued "undefined" type, never encountered in normal values */ |
| public static final Type<Iterable<Void>> UNDEFINEDS = |
| create(PropertyType.UNDEFINED, true, "UNDEFINEDS"); |
| |
| private final int tag; |
| |
| private final boolean array; |
| |
| private final String string; |
| |
| private Type(int tag, boolean array, String string) { |
| this.tag = tag; |
| this.array = array; |
| this.string = string; |
| } |
| |
| /** |
| * Corresponding type tag as defined in {@link PropertyType}. |
| * @return type tag |
| */ |
| public int tag() { |
| return tag; |
| } |
| |
| /** |
| * Determine whether this is an array type |
| * @return {@code true} if and only if this is an array type |
| */ |
| public boolean isArray() { |
| return array; |
| } |
| |
| /** |
| * Corresponding {@code Type} for a given type tag and array flag. |
| * @param tag type tag as defined in {@link PropertyType}. |
| * @param array whether this is an array or not |
| * @return {@code Type} instance |
| * @throws IllegalArgumentException if tag is not valid as per definition in {@link PropertyType}. |
| */ |
| public static Type<?> fromTag(int tag, boolean array) { |
| switch (tag) { |
| case PropertyType.STRING: return array ? STRINGS : STRING; |
| case PropertyType.BINARY: return array ? BINARIES : BINARY; |
| case PropertyType.LONG: return array ? LONGS : LONG; |
| case PropertyType.DOUBLE: return array ? DOUBLES : DOUBLE; |
| case PropertyType.DATE: return array ? DATES: DATE; |
| case PropertyType.BOOLEAN: return array ? BOOLEANS: BOOLEAN; |
| case PropertyType.NAME: return array ? NAMES : NAME; |
| case PropertyType.PATH: return array ? PATHS: PATH; |
| case PropertyType.REFERENCE: return array ? REFERENCES : REFERENCE; |
| case PropertyType.WEAKREFERENCE: return array ? WEAKREFERENCES : WEAKREFERENCE; |
| case PropertyType.URI: return array ? URIS: URI; |
| case PropertyType.DECIMAL: return array ? DECIMALS : DECIMAL; |
| case PropertyType.UNDEFINED: return array ? UNDEFINEDS : UNDEFINED; |
| default: throw new IllegalArgumentException("Invalid type tag: " + tag); |
| } |
| } |
| |
| /** |
| * Returns the {@code Type} with the given string representation. |
| * |
| * @param string type string |
| * @return matching type |
| */ |
| public static Type<?> fromString(String string) { |
| Type<?> type = TYPES.get(string); |
| if (type == null) { |
| throw new IllegalArgumentException("Invalid type name: " + string); |
| } |
| return type; |
| } |
| |
| /** |
| * Determine the base type of array types |
| * @return base type |
| * @throws IllegalStateException if {@code isArray} is false. |
| */ |
| public Type<?> getBaseType() { |
| checkState(isArray(), "Not an array"); |
| return fromTag(tag, false); |
| } |
| |
| /** |
| * Determine the array type which has this type as base type |
| * @return array type with this type as base type |
| * @throws IllegalStateException if {@code isArray} is true. |
| */ |
| public Type<?> getArrayType() { |
| checkState(!isArray(), "Not a simply type"); |
| return fromTag(tag, true); |
| } |
| |
| //--------------------------------------------------------< Comparable >-- |
| |
| @Override |
| public int compareTo(@NotNull Type<?> that) { |
| if (tag < that.tag) { |
| return -1; |
| } |
| |
| if (tag > that.tag) { |
| return 1; |
| } |
| |
| if (!array && that.array) { |
| return -1; |
| } |
| |
| if (array && !that.array) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| //------------------------------------------------------------< Object >-- |
| |
| @Override |
| public String toString() { |
| return string; |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = 1; |
| |
| result = result + 31 * tag; |
| result = result + 31 * hashCode(array); |
| |
| return result; |
| } |
| |
| private int hashCode(boolean value) { |
| return value ? 1231 : 1237; |
| } |
| |
| private void checkState(boolean condition, String message) { |
| if (!condition) { |
| throw new IllegalStateException(message); |
| } |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| return this == other; |
| } |
| |
| } |