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 * http://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 }
108
109
110 /**
111 * Creates a Syntax object using a unique OID.
112 *
113 * @param oid the OID for this syntax
114 * @param description the description for this syntax
115 * @param isHumanReadable true if this syntax is human readable
116 */
117 public LdapSyntax( String oid, String description, boolean isHumanReadable )
118 {
119 super( SchemaObjectType.LDAP_SYNTAX, oid );
120 this.description = description;
121 this.isHumanReadable = isHumanReadable;
122 this.hasHumanReadableFlag = true;
123 }
124
125
126 /**
127 * Gets whether or not the Syntax is human readable.
128 *
129 * @return true if the syntax can be interpreted by humans, false otherwise
130 */
131 public boolean isHumanReadable()
132 {
133 if ( hasHumanReadableFlag )
134 {
135 return isHumanReadable;
136 }
137 else
138 {
139 List<String> values = getExtension( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT );
140
141 if ( ( values == null ) || values.isEmpty() )
142 {
143 // Default to String if the flag is not set
144 return true;
145 }
146 else
147 {
148 String value = values.get( 0 );
149 hasHumanReadableFlag = true;
150
151 if ( "FALSE".equalsIgnoreCase( value ) )
152 {
153 isHumanReadable = true;
154 return true;
155 }
156 else
157 {
158 isHumanReadable = false;
159 return false;
160 }
161 }
162 }
163 }
164
165
166 /**
167 * Sets the human readable flag value.
168 *
169 * @param humanReadable the human readable flag value to set
170 */
171 public void setHumanReadable( boolean humanReadable )
172 {
173 if ( locked )
174 {
175 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
176 }
177
178 if ( !isReadOnly )
179 {
180 this.isHumanReadable = humanReadable;
181 this.hasHumanReadableFlag = true;
182 }
183 }
184
185
186 /**
187 * Gets the SyntaxChecker used to validate values in accordance with this
188 * Syntax.
189 *
190 * @return the SyntaxChecker
191 */
192 public SyntaxChecker getSyntaxChecker()
193 {
194 return syntaxChecker;
195 }
196
197
198 /**
199 * Sets the associated SyntaxChecker
200 *
201 * @param syntaxChecker The associated SyntaxChecker
202 */
203 public void setSyntaxChecker( SyntaxChecker syntaxChecker )
204 {
205 if ( locked )
206 {
207 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
208 }
209
210 if ( !isReadOnly )
211 {
212 this.syntaxChecker = syntaxChecker;
213 }
214 }
215
216
217 /**
218 * Update the associated SyntaxChecker, even if the SchemaObject is readOnly
219 *
220 * @param newSyntaxChecker The associated SyntaxChecker
221 */
222 public void updateSyntaxChecker( SyntaxChecker newSyntaxChecker )
223 {
224 if ( locked )
225 {
226 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
227 }
228
229 this.syntaxChecker = newSyntaxChecker;
230 }
231
232
233 /**
234 * {@inheritDoc}
235 */
236 @Override
237 public String toString()
238 {
239 return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
240 }
241
242
243 /**
244 * {@inheritDoc}
245 */
246 @Override
247 public LdapSyntax copy()
248 {
249 LdapSyntax copy = new LdapSyntax( oid );
250
251 // Copy the SchemaObject common data
252 copy.copy( this );
253
254 // Copy the HR flag
255 copy.isHumanReadable = isHumanReadable;
256
257 // Copy the HR presence flag
258 copy.hasHumanReadableFlag = hasHumanReadableFlag;
259
260 // All the references to other Registries object are set to null.
261 copy.syntaxChecker = null;
262
263 return copy;
264 }
265
266
267 /**
268 * {@inheritDoc}
269 */
270 @Override
271 public boolean equals( Object o )
272 {
273 if ( !super.equals( o ) )
274 {
275 return false;
276 }
277
278 if ( !( o instanceof LdapSyntax ) )
279 {
280 return false;
281 }
282
283 LdapSyntax that = ( LdapSyntax ) o;
284
285 // IsHR
286 if ( isHumanReadable != that.isHumanReadable )
287 {
288 return false;
289 }
290
291 // Check the SyntaxChecker (not a equals)
292 if ( syntaxChecker != null )
293 {
294 if ( that.syntaxChecker == null )
295 {
296 return false;
297 }
298
299 return syntaxChecker.getOid().equals( that.syntaxChecker.getOid() );
300 }
301 else
302 {
303 return that.syntaxChecker == null;
304 }
305 }
306
307
308 /**
309 * {@inheritDoc}
310 */
311 @Override
312 public void clear()
313 {
314 // Clear the common elements
315 super.clear();
316
317 // Clear the references
318 syntaxChecker = null;
319 }
320 }