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-2016 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.2.2 024 * Bundle : ldp4j-application-api-0.2.2.jar 025 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 026 */ 027package org.ldp4j.application.vocabulary; 028 029import java.util.Objects; 030 031 032/** 033 * A term implementation that enforces the creation of immutable terms defined 034 * for an {@code AbstractImmutableVocabulary}, which behave as {@code Enum} constants. 035 * 036 * @version 1.0 037 * @since 1.0.0 038 * @author Miguel Esteban Gutiérrez 039 * @see AbstractImmutableVocabulary 040 */ 041public class ImmutableTerm implements Term { 042 043 private static final long serialVersionUID = 6842492155071877731L; 044 045 private static final int HASH_CODE_SALT = 19; 046 private final int ordinal; 047 private final String name; 048 private final AbstractImmutableVocabulary<? extends ImmutableTerm> vocabulary; 049 private final String entityName; 050 051 /** 052 * Create a new term for a vocabulary and entity. 053 * 054 * @param vocabulary 055 * the vocabulary to which the term will belong to. 056 * @param entityName 057 * the entity name of the term. 058 * @throws NullPointerException 059 * if any of the vocabulary is {@code null}. 060 * @throws IllegalArgumentException 061 * if the entity name is not valid. 062 */ 063 public ImmutableTerm(AbstractImmutableVocabulary<? extends ImmutableTerm> vocabulary, String entityName) { 064 this.vocabulary = Objects.requireNonNull(vocabulary,"Vocabulary cannot be null"); 065 this.entityName = entityName; 066 this.name = TermUtils.toTermName(entityName); 067 this.ordinal = vocabulary.reserveTermName(this.name); 068 vocabulary.registerTerm(this); 069 } 070 071 /** 072 * {@inheritDoc} 073 */ 074 @Override 075 public final int ordinal() { 076 return ordinal; 077 } 078 079 /** 080 * {@inheritDoc} 081 */ 082 @Override 083 public final String name() { 084 return name; 085 } 086 087 /** 088 * {@inheritDoc} 089 */ 090 @Override 091 public final String entityName() { 092 return entityName; 093 } 094 095 /** 096 * {@inheritDoc} 097 */ 098 @Override 099 public final String qualifiedEntityName() { 100 return vocabulary.getNamespace() + entityName; 101 } 102 103 /** 104 * {@inheritDoc} 105 */ 106 @Override 107 public final Vocabulary getDeclaringVocabulary() { 108 return vocabulary; 109 } 110 111 /** 112 * {@inheritDoc} <br> 113 * This method may be overridden, though it typically isn't necessary or 114 * desirable. An term type should override this method when a more specific 115 * value types are supported. 116 */ 117 @Override 118 public <V> V as(Class<? extends V> valueClass) { 119 try { 120 return TypeAdapter.adapt(this, valueClass); 121 } catch (CannotAdaptClassesException e) { 122 throw new UnsupportedOperationException("Class '"+getClass().getCanonicalName()+" cannot be transformed to '"+valueClass.getCanonicalName()+"'",e); 123 } 124 } 125 126 /** 127 * Returns true if the specified object is equal to this term constant. 128 * 129 * @param other 130 * the object to be compared for equality with this object. 131 * @return true if the specified object is equal to this term constant. 132 */ 133 @Override 134 public final boolean equals(Object other) { 135 return this == other; 136 } 137 138 /** 139 * Returns a hash code for this term constant. 140 * 141 * @return a hash code for this term constant. 142 */ 143 @Override 144 public final int hashCode() { 145 return super.hashCode()*HASH_CODE_SALT; 146 } 147 148 /** 149 * Throws CloneNotSupportedException. This guarantees that terms are never 150 * cloned, which is necessary to preserve their "singleton" status. 151 * 152 * @return (never returns) 153 */ 154 @Override 155 protected final Object clone() throws CloneNotSupportedException { // NOSONAR 156 throw new CloneNotSupportedException(); 157 } 158 159 /** 160 * Returns the qualified entity name of this term constant. 161 * This method may be overridden, though it typically isn't necessary or 162 * desirable. An term type should override this method when a more 163 * "programmer-friendly" string form exists. 164 * 165 * @return the name of this term constant 166 */ 167 @Override 168 public String toString() { 169 return qualifiedEntityName(); 170 } 171 172 /** 173 * Compares this term with the specified object for order. Returns a 174 * negative integer, zero, or a positive integer as this object is less 175 * than, equal to, or greater than the specified object. 176 * 177 * Term constants are only comparable to other term constants of the same 178 * vocabulary. The natural order implemented by this method is the order in 179 * which the constants are declared. 180 */ 181 @Override 182 public int compareTo(Term other) { 183 ImmutableTerm self = this; 184 if(self.getDeclaringVocabulary() != other.getDeclaringVocabulary()) { 185 throw new ClassCastException(); 186 } 187 return self.ordinal - other.ordinal(); 188 } 189 190}