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 * https://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 */ 020package org.apache.directory.api.ldap.model.schema; 021 022 023import java.util.List; 024 025import org.apache.directory.api.i18n.I18n; 026import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants; 027 028 029/** 030 * A syntax definition. Each attribute stored in a directory has a defined 031 * syntax (i.e. data type) which constrains the structure and format of its 032 * values. The description of each syntax specifies how attribute or assertion 033 * values conforming to the syntax are normally represented when transferred in 034 * LDAP operations. This representation is referred to as the LDAP-specific 035 * encoding to distinguish it from other methods of encoding attribute values. 036 * <p> 037 * According to ldapbis [MODELS]: 038 * </p> 039 * 040 * <pre> 041 * 4.1.5. LDAP Syntaxes 042 * 043 * LDAP Syntaxes of (attribute and assertion) values are described in 044 * terms of ASN.1 [X.680] and, optionally, have an octet string encoding 045 * known as the LDAP-specific encoding. Commonly, the LDAP-specific 046 * encoding is constrained to string of Universal Character Set (UCS) 047 * [ISO10646] characters in UTF-8 [UTF-8] form. 048 * 049 * Each LDAP syntax is identified by an object identifier (OID). 050 * 051 * LDAP syntax definitions are written according to the ABNF: 052 * 053 * SyntaxDescription = LPAREN WSP 054 * numericoid ; object identifier 055 * [ SP "DESC" SP qdstring ] ; description 056 * extensions WSP RPAREN ; extensions 057 * 058 * where: 059 * [numericoid] is object identifier assigned to this LDAP syntax; 060 * DESC [qdstring] is a short descriptive string; and 061 * [extensions] describe extensions. 062 * </pre> 063 * 064 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html"> RFC2252 Section 4.3.3</a> 065 * @see <a href= 066 * "http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-09.txt"> 067 * ldapbis [MODELS]</a> 068 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 069 */ 070public class LdapSyntax extends AbstractSchemaObject 071{ 072 /** The mandatory serialVersionUID */ 073 public static final long serialVersionUID = 1L; 074 075 /** the human readable flag */ 076 protected boolean isHumanReadable = false; 077 078 /** A flag set to true if the Syntax has a X-NOT-HUMAN-READABLE extension */ 079 private boolean hasHumanReadableFlag = false; 080 081 /** The associated SyntaxChecker */ 082 protected SyntaxChecker syntaxChecker; 083 084 085 /** 086 * Creates a Syntax object using a unique OID. 087 * 088 * @param oid the OID for this Syntax 089 */ 090 public LdapSyntax( String oid ) 091 { 092 super( SchemaObjectType.LDAP_SYNTAX, oid ); 093 } 094 095 096 /** 097 * Creates a Syntax object using a unique OID. 098 * 099 * @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}