package org.opengis.filter.identity; import java.util.Date; /** * Union type class for the {@code Version} Union type in FES 2.0. * <p> * The union is actually captured as a union inside a single long field. * * @invariant {@code #getVersionAction() != null || #getIndex() != null || #getDateTime() != null} */ public final class Version { /** * The VersionAction attribute may also be the strings FIRST, LATEST, PREVIOUS, NEXT and ALL. */ public enum Action { /** Select the first version of a resource. */ FIRST, /** Select the most recent version of a resource. */ LAST, /** Select the previous version of a resource relative to the version specified using the rid attribute. */ NEXT, /** Select the next version of a resource relative to the version specified using the rid attribute. */ PREVIOUS, /** Select all available version of a resource. */ ALL; public static Action lookup(int ordinal) { for (Action action : Action.values()) { if (action.ordinal() == ordinal) { return action; } } return null; // not found } } static final long UNION_MASK = 0x0FFFFFFFFFFFFFFFl; static final long UNION_INTEGER = 0x1000000000000000l; static final long UNION_DATE = 0x2000000000000000l; static final long UNION_ACTION = 0x4000000000000000l; /** * The union is represented as * <ul> * <li>UNION_INTEGER | <code>int</code></li> * <li>UNION_DATE | <code>date.getTime()</code></li> * <li>UNION_ACTION | <code>action.ordinal()</code></li> * </ul> */ final long union; /** * The {@link #isEmpty() empty} Version constructor. */ public Version() { this.union = 0; } private Version(long union){ this.union = union; } public static Version valueOf(long union){ //TODO: some validity check? return new Version(union); } public Version(final Action action) { if (action == null) { throw new IllegalArgumentException("action can't be null"); } this.union = UNION_ACTION | action.ordinal(); } public Version(final Integer index) { if (index == null) { throw new IllegalArgumentException("index can't be null"); } this.union = UNION_INTEGER | (long) index; } public Version(final Date dateTime) { if (dateTime == null) { throw new IllegalArgumentException("dateTime can't be null"); } this.union = UNION_DATE | (dateTime.getTime()); } public boolean isEmpty(){ return union == 0; } public boolean isVersionAction() { return (UNION_ACTION & union) > 0; } /** * Access to the union memento; this may be stored as an encoding of the * Version in memory sensitive settings where the over head of an object * is not desired. * <p> * To restore please use <code>new Version( union )</code> * * @return memento holding the contents of a Version object */ public long union(){ return union; } /** * Version requested using a predefined constant. * <p> * The versionAction attribute may also be the strings FIRST, LATEST, PREVIOUS, NEXT and ALL. The token FIRST shall select the first version of a * resource. The token LATEST shall select the most recent version of a resource. The PREVIOUS and NEXT tokens shall select the previous or next * version of a resource relative to the version specified using the rid attribute. The token ALL shall select all available version of a * resource. * * @return Version requested using a predefined constant. */ public Action getVersionAction() { if ((UNION_ACTION & union) > 0) { int ordinal = (int) (union & UNION_MASK); Action action = Action.lookup(ordinal); return action; } return null; } /** * Version index requested. * * @return true if the Version is supplied by an index */ public boolean isIndex() { return (UNION_INTEGER & union) > 0; } /** * Version requested as defined by an index (from 1 through to the latest). * <p> * The version attribute may be an integer N indicating that the Nth version of the resource shall be selected. The first version of a resource * shall be numbered 1. If N exceeds the number of versions available, the latest version of the resource shall be selected. * * @return index of version requested (from 1 through to the latest) */ public Integer getIndex() { if ((UNION_INTEGER & union) > 0) { int index = (int) (union & UNION_MASK); return index; } return null; } public boolean isDateTime() { return (UNION_DATE & union) > 0; } /** * Version requested as the closest to the provided date. * <p> * The version attribute may also be date indicating that the version of the resource closest to the specified date shall be selected. * * @return date of version requested */ public Date getDateTime() { if ((UNION_DATE & union) > 0) { long time = (union & UNION_MASK); return new Date(time); } return null; } @Override public boolean equals(Object o) { if (!(o instanceof Version)) { return false; } Version v = (Version) o; return union == v.union; } @Override public int hashCode() { return 17 * (int) union; } }