001/** 002 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 003 * This file is part of the LDP4j Project: 004 * http://www.ldp4j.org/ 005 * 006 * Center for Open Middleware 007 * http://www.centeropenmiddleware.com/ 008 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 009 * Copyright (C) 2014 Center for Open Middleware. 010 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 011 * Licensed under the Apache License, Version 2.0 (the "License"); 012 * you may not use this file except in compliance with the License. 013 * You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, software 018 * distributed under the License is distributed on an "AS IS" BASIS, 019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 020 * See the License for the specific language governing permissions and 021 * limitations under the License. 022 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 023 * Artifact : org.ldp4j.framework:ldp4j-application-api:0.1.0 024 * Bundle : ldp4j-application-api-0.1.0.jar 025 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 026 */ 027package org.ldp4j.application.vocabulary; 028 029 030/** 031 * A term implementation that enforces the creation of immutable terms defined 032 * for an {@code AbstractImmutableVocabulary}, which behave as {@code Enum} constants. 033 * 034 * @version 1.0 035 * @since 1.0.0 036 * @author Miguel Esteban Gutiérrez 037 * @see AbstractImmutableVocabulary 038 */ 039public class ImmutableTerm implements Term { 040 041 private static final long serialVersionUID = 6842492155071877731L; 042 043 private static final int HASH_CODE_SALT = 19; 044 private final int ordinal; 045 private final String name; 046 private final AbstractImmutableVocabulary<? extends ImmutableTerm> vocabulary; 047 private final String entityName; 048 049 public ImmutableTerm(AbstractImmutableVocabulary<? extends ImmutableTerm> vocabulary, String entityName) { 050 this.vocabulary = vocabulary; 051 this.entityName = entityName; 052 this.name = TermUtils.toTermName(entityName); 053 this.ordinal = vocabulary.reserveTermName(this.name); 054 vocabulary.registerTerm(this); 055 } 056 057 /** 058 * {@inheritDoc} 059 */ 060 @Override 061 public final int ordinal() { 062 return ordinal; 063 } 064 065 /** 066 * {@inheritDoc} 067 */ 068 @Override 069 public final String name() { 070 return name; 071 } 072 073 /** 074 * {@inheritDoc} 075 */ 076 @Override 077 public final String entityName() { 078 return entityName; 079 } 080 081 /** 082 * {@inheritDoc} 083 */ 084 @Override 085 public final String qualifiedEntityName() { 086 return vocabulary.getNamespace() + entityName; 087 } 088 089 /** 090 * {@inheritDoc} 091 */ 092 @Override 093 public final Vocabulary<? extends ImmutableTerm> getDeclaringVocabulary() { 094 return vocabulary; 095 } 096 097 /** 098 * {@inheritDoc} <br/> 099 * This method may be overridden, though it typically isn't necessary or 100 * desirable. An term type should override this method when a more specific 101 * value types are supported. 102 */ 103 @Override 104 public <V> V as(Class<? extends V> valueClass) { 105 try { 106 return TypeAdapter.adapt(this, valueClass); 107 } catch (CannotAdaptClassesException e) { 108 throw new UnsupportedOperationException("Class '"+getClass().getCanonicalName()+" cannot be transformed to '"+valueClass.getCanonicalName()+"'",e); 109 } 110 } 111 112 /** 113 * Returns true if the specified object is equal to this term constant. 114 * 115 * @param other 116 * the object to be compared for equality with this object. 117 * @return true if the specified object is equal to this term constant. 118 */ 119 @Override 120 public final boolean equals(Object other) { 121 return this == other; 122 } 123 124 /** 125 * Returns a hash code for this term constant. 126 * 127 * @return a hash code for this term constant. 128 */ 129 @Override 130 public final int hashCode() { 131 return super.hashCode()*HASH_CODE_SALT; 132 } 133 134 /** 135 * Throws CloneNotSupportedException. This guarantees that terms are never 136 * cloned, which is necessary to preserve their "singleton" status. 137 * 138 * @return (never returns) 139 */ 140 @Override 141 protected final Object clone() throws CloneNotSupportedException { 142 super.clone(); 143 throw new CloneNotSupportedException(); 144 } 145 146 /** 147 * Returns the qualified entity name of this term constant. 148 * This method may be overridden, though it typically isn't necessary or 149 * desirable. An term type should override this method when a more 150 * "programmer-friendly" string form exists. 151 * 152 * @return the name of this term constant 153 */ 154 @Override 155 public String toString() { 156 return qualifiedEntityName(); 157 } 158 159 /** 160 * Compares this term with the specified object for order. Returns a 161 * negative integer, zero, or a positive integer as this object is less 162 * than, equal to, or greater than the specified object. 163 * 164 * Term constants are only comparable to other term constants of the same 165 * vocabulary. The natural order implemented by this method is the order in 166 * which the constants are declared. 167 */ 168 @Override 169 public int compareTo(Term other) { 170 ImmutableTerm self = this; 171 // TODO: This is too strict, replace by an ordering based on namespace, vocabulary identity, and then on the ordering within the namespace 172 if (self.getClass() != other.getClass() && // optimization 173 self.getDeclaringVocabulary() != other.getDeclaringVocabulary()) { 174 throw new ClassCastException(); 175 } 176 return self.ordinal - other.ordinal(); 177 } 178 179}