001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.entry;
021
022 import javax.naming.NamingException;
023
024 import org.apache.directory.shared.ldap.schema.SyntaxChecker;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027
028
029 /**
030 * A wrapper around byte[] values in entries.
031 *
032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
033 * @version $Rev$, $Date$
034 */
035 public abstract class AbstractValue<T> implements Value<T>
036 {
037 /** logger for reporting errors that might not be handled properly upstream */
038 private static final Logger LOG = LoggerFactory.getLogger( AbstractValue.class );
039
040
041 /** the wrapped binary value */
042 protected T wrapped;
043
044 /** the canonical representation of the wrapped value */
045 protected T normalizedValue;
046
047 /** A flag set when the value has been normalized */
048 protected boolean normalized;
049
050 /** cached results of the isValid() method call */
051 protected Boolean valid;
052
053 /** A flag set if the normalized data is different from the wrapped data */
054 protected transient boolean same;
055
056 /**
057 * Reset the value
058 */
059 public void clear()
060 {
061 wrapped = null;
062 normalized = false;
063 normalizedValue = null;
064 valid = null;
065 }
066
067
068 /**
069 * {@inheritDoc}
070 */
071 public Value<T> clone()
072 {
073 try
074 {
075 return (Value<T>)super.clone();
076 }
077 catch ( CloneNotSupportedException cnse )
078 {
079 // Do nothing
080 return null;
081 }
082 }
083
084
085 /**
086 * Gets a reference to the wrapped binary value.
087 *
088 * Warning ! The value is not copied !!!
089 *
090 * @return a direct handle on the binary value that is wrapped
091 */
092 public T getReference()
093 {
094 return wrapped;
095 }
096
097
098 /**
099 * Gets a copy of the wrapped binary value.
100 *
101 * @return a copy of the binary value that is wrapped
102 */
103 public T get()
104 {
105 // Just call the specific Client copy method.
106 return getCopy();
107 }
108
109
110 /**
111 * Gets the normalized (canonical) representation for the wrapped value.
112 * If the wrapped value is null, null is returned, otherwise the normalized
113 * form is returned. If the normalized Value is null, then the wrapped
114 * value is returned
115 *
116 * @return gets the normalized value
117 */
118 public T getNormalizedValue()
119 {
120 if ( isNull() )
121 {
122 return null;
123 }
124
125 if ( normalizedValue == null )
126 {
127 return getCopy();
128 }
129
130 return getNormalizedValueCopy();
131 }
132
133
134 /**
135 * Gets a reference to the the normalized (canonical) representation
136 * for the wrapped value.
137 *
138 * @return gets a reference to the normalized value
139 */
140 public T getNormalizedValueReference()
141 {
142 if ( isNull() )
143 {
144 return null;
145 }
146
147 if ( normalizedValue == null )
148 {
149 return wrapped;
150 }
151
152 return normalizedValue;
153
154 }
155
156
157 /**
158 * Check if the contained value is null or not
159 *
160 * @return <code>true</code> if the inner value is null.
161 */
162 public final boolean isNull()
163 {
164 return wrapped == null;
165 }
166
167
168 /**
169 * @return Tells if the wrapped value and the normalized value are the same
170 */
171 public final boolean isSame()
172 {
173 return same;
174 }
175
176
177 /**
178 * Check if the Valid flag is set or not. This flag is set by a call
179 * to the isValid( SyntaxChecker ) method for client values. It is overridden
180 * for server values.
181 *
182 * if the flag is not set, returns <code>false</code>
183 *
184 * @see ServerValue#isValid()
185 */
186 public boolean isValid()
187 {
188 if ( valid != null )
189 {
190 return valid;
191 }
192
193 return false;
194 }
195
196
197 /**
198 * Uses the syntaxChecker associated with the attributeType to check if the
199 * value is valid. Repeated calls to this method do not attempt to re-check
200 * the syntax of the wrapped value every time if the wrapped value does not
201 * change. Syntax checks only result on the first check, and when the wrapped
202 * value changes.
203 *
204 * @see ServerValue#isValid()
205 */
206 public final boolean isValid( SyntaxChecker syntaxChecker ) throws NamingException
207 {
208 if ( valid != null )
209 {
210 return valid;
211 }
212
213 if ( syntaxChecker == null )
214 {
215 String message = "Cannot validate " + toString() + " with a null SyntaxChecker";
216 LOG.error( message );
217 throw new NamingException( message );
218 }
219
220 valid = syntaxChecker.isValidSyntax( getReference() );
221 return valid;
222 }
223
224
225 /**
226 * Normalize the value. In order to use this method, the Value
227 * must be schema aware.
228 *
229 * @exception NamingException If the value cannot be normalized
230 */
231 public void normalize() throws NamingException
232 {
233 normalized = true;
234 normalizedValue = wrapped;
235 }
236
237
238 /**
239 * Sets this value's wrapped value to a copy of the src array.
240 *
241 * @param wrapped the byte array to use as the wrapped value
242 */
243 public abstract void set( T wrapped );
244
245
246 /**
247 * Tells if the value has already be normalized or not.
248 *
249 * @return <code>true</code> if the value has already been normalized.
250 */
251 public final boolean isNormalized()
252 {
253 return normalized;
254 }
255
256
257 /**
258 * Set the normalized flag.
259 *
260 * @param the value : true or false
261 */
262 public final void setNormalized( boolean normalized )
263 {
264 this.normalized = normalized;
265 }
266 }