1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.api.ldap.model.schema;
21
22
23 import java.util.List;
24
25 import org.apache.directory.api.i18n.I18n;
26 import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
27
28
29 /**
30 * A syntax definition. Each attribute stored in a directory has a defined
31 * syntax (i.e. data type) which constrains the structure and format of its
32 * values. The description of each syntax specifies how attribute or assertion
33 * values conforming to the syntax are normally represented when transferred in
34 * LDAP operations. This representation is referred to as the LDAP-specific
35 * encoding to distinguish it from other methods of encoding attribute values.
36 * <p>
37 * According to ldapbis [MODELS]:
38 * </p>
39 *
40 * <pre>
41 * 4.1.5. LDAP Syntaxes
42 *
43 * LDAP Syntaxes of (attribute and assertion) values are described in
44 * terms of ASN.1 [X.680] and, optionally, have an octet string encoding
45 * known as the LDAP-specific encoding. Commonly, the LDAP-specific
46 * encoding is constrained to string of Universal Character Set (UCS)
47 * [ISO10646] characters in UTF-8 [UTF-8] form.
48 *
49 * Each LDAP syntax is identified by an object identifier (OID).
50 *
51 * LDAP syntax definitions are written according to the ABNF:
52 *
53 * SyntaxDescription = LPAREN WSP
54 * numericoid ; object identifier
55 * [ SP "DESC" SP qdstring ] ; description
56 * extensions WSP RPAREN ; extensions
57 *
58 * where:
59 * [numericoid] is object identifier assigned to this LDAP syntax;
60 * DESC [qdstring] is a short descriptive string; and
61 * [extensions] describe extensions.
62 * </pre>
63 *
64 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html"> RFC2252 Section 4.3.3</a>
65 * @see <a href=
66 * "http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-09.txt">
67 * ldapbis [MODELS]</a>
68 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
69 */
70 public class LdapSyntax extends AbstractSchemaObject
71 {
72 /** The mandatory serialVersionUID */
73 public static final long serialVersionUID = 1L;
74
75 /** the human readable flag */
76 protected boolean isHumanReadable = false;
77
78 /** A flag set to true if the Syntax has a X-NOT-HUMAN-READABLE extension */
79 private boolean hasHumanReadableFlag = false;
80
81 /** The associated SyntaxChecker */
82 protected SyntaxChecker syntaxChecker;
83
84
85 /**
86 * Creates a Syntax object using a unique OID.
87 *
88 * @param oid the OID for this Syntax
89 */
90 public LdapSyntax( String oid )
91 {
92 super( SchemaObjectType.LDAP_SYNTAX, oid );
93 }
94
95
96 /**
97 * Creates a Syntax object using a unique OID.
98 *
99 * @param oid the OID for this syntax
100 * @param description the description for this syntax
101 */
102 public LdapSyntax( String oid, String description )
103 {
104 super( SchemaObjectType.LDAP_SYNTAX, oid );
105 this.description = description;
106 this.hasHumanReadableFlag = false;
107 computeHashCode();
108 }
109
110
111 /**
112 * Creates a Syntax object using a unique OID.
113 *
114 * @param oid the OID for this syntax
115 * @param description the description for this syntax
116 * @param isHumanReadable true if this syntax is human readable
117 */
118 public LdapSyntax( String oid, String description, boolean isHumanReadable )
119 {
120 super( SchemaObjectType.LDAP_SYNTAX, oid );
121 this.description = description;
122 this.isHumanReadable = isHumanReadable;
123 this.hasHumanReadableFlag = true;
124 computeHashCode();
125 }
126
127
128 /**
129 * Gets whether or not the Syntax is human readable.
130 *
131 * @return true if the syntax can be interpreted by humans, false otherwise
132 */
133 public boolean isHumanReadable()
134 {
135 if ( hasHumanReadableFlag )
136 {
137 return isHumanReadable;
138 }
139 else
140 {
141 List<String> values = getExtension( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT );
142
143 if ( ( values == null ) || values.isEmpty() )
144 {
145 // Default to String if the flag is not set
146 return true;
147 }
148 else
149 {
150 String value = values.get( 0 );
151 hasHumanReadableFlag = true;
152
153 if ( "FALSE".equalsIgnoreCase( value ) )
154 {
155 isHumanReadable = true;
156 return true;
157 }
158 else
159 {
160 isHumanReadable = false;
161 return false;
162 }
163 }
164 }
165 }
166
167
168 /**
169 * Sets the human readable flag value.
170 *
171 * @param humanReadable the human readable flag value to set
172 */
173 public void setHumanReadable( boolean humanReadable )
174 {
175 if ( locked )
176 {
177 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
178 }
179
180 this.isHumanReadable = humanReadable;
181 this.hasHumanReadableFlag = true;
182 }
183
184
185 /**
186 * Gets the SyntaxChecker used to validate values in accordance with this
187 * Syntax.
188 *
189 * @return the SyntaxChecker
190 */
191 public SyntaxChecker getSyntaxChecker()
192 {
193 return syntaxChecker;
194 }
195
196
197 /**
198 * Sets the associated SyntaxChecker
199 *
200 * @param syntaxChecker The associated SyntaxChecker
201 */
202 public void setSyntaxChecker( SyntaxChecker syntaxChecker )
203 {
204 if ( locked )
205 {
206 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
207 }
208
209 this.syntaxChecker = syntaxChecker;
210 }
211
212
213 /**
214 * Update the associated SyntaxChecker, even if the SchemaObject is readOnly
215 *
216 * @param newSyntaxChecker The associated SyntaxChecker
217 */
218 public void updateSyntaxChecker( SyntaxChecker newSyntaxChecker )
219 {
220 if ( locked )
221 {
222 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
223 }
224
225 this.syntaxChecker = newSyntaxChecker;
226 }
227
228
229 /**
230 * {@inheritDoc}
231 */
232 @Override
233 public String toString()
234 {
235 return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
236 }
237
238
239 /**
240 * {@inheritDoc}
241 */
242 @Override
243 public LdapSyntax copy()
244 {
245 LdapSyntax copy = new LdapSyntax( oid );
246
247 // Copy the SchemaObject common data
248 copy.copy( this );
249
250 // Copy the HR flag
251 copy.isHumanReadable = isHumanReadable;
252
253 // Copy the HR presence flag
254 copy.hasHumanReadableFlag = hasHumanReadableFlag;
255
256 // All the references to other Registries object are set to null.
257 copy.syntaxChecker = null;
258
259 return copy;
260 }
261
262
263 /**
264 * @see Object#equals(Object)
265 */
266 @Override
267 public int hashCode()
268 {
269 int hash = h;
270
271 hash = hash * 17 + ( isHumanReadable ? 1 : 0 );
272
273 if ( syntaxChecker != null )
274 {
275 hash = hash * 17 + syntaxChecker.hashCode();
276 }
277
278 return hash;
279 }
280
281
282 /**
283 * {@inheritDoc}
284 */
285 @Override
286 public boolean equals( Object o )
287 {
288 if ( !super.equals( o ) )
289 {
290 return false;
291 }
292
293 if ( !( o instanceof LdapSyntax ) )
294 {
295 return false;
296 }
297
298 LdapSyntax that = ( LdapSyntax ) o;
299
300 // IsHR
301 if ( isHumanReadable != that.isHumanReadable )
302 {
303 return false;
304 }
305
306 // Check the SyntaxChecker (not a equals)
307 if ( syntaxChecker != null )
308 {
309 if ( that.syntaxChecker == null )
310 {
311 return false;
312 }
313
314 return syntaxChecker.getOid().equals( that.syntaxChecker.getOid() );
315 }
316 else
317 {
318 return that.syntaxChecker == null;
319 }
320 }
321
322
323 /**
324 * {@inheritDoc}
325 */
326 @Override
327 public void clear()
328 {
329 // Clear the common elements
330 super.clear();
331
332 // Clear the references
333 syntaxChecker = null;
334 }
335 }