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 */ 020package org.apache.directory.shared.ldap.model.schema; 021 022 023import java.util.List; 024 025import org.apache.directory.shared.i18n.I18n; 026import org.apache.directory.shared.ldap.model.exception.LdapException; 027import org.apache.directory.shared.ldap.model.schema.registries.Registries; 028import org.apache.directory.shared.ldap.model.schema.syntaxCheckers.OctetStringSyntaxChecker; 029 030 031/** 032 * A syntax definition. Each attribute stored in a directory has a defined 033 * syntax (i.e. data type) which constrains the structure and format of its 034 * values. The description of each syntax specifies how attribute or assertion 035 * values conforming to the syntax are normally represented when transferred in 036 * LDAP operations. This representation is referred to as the LDAP-specific 037 * encoding to distinguish it from other methods of encoding attribute values. 038 * <p> 039 * According to ldapbis [MODELS]: 040 * </p> 041 * 042 * <pre> 043 * 4.1.5. LDAP Syntaxes 044 * 045 * LDAP Syntaxes of (attribute and assertion) values are described in 046 * terms of ASN.1 [X.680] and, optionally, have an octet string encoding 047 * known as the LDAP-specific encoding. Commonly, the LDAP-specific 048 * encoding is constrained to string of Universal Character Set (UCS) 049 * [ISO10646] characters in UTF-8 [UTF-8] form. 050 * 051 * Each LDAP syntax is identified by an object identifier (OID). 052 * 053 * LDAP syntax definitions are written according to the ABNF: 054 * 055 * SyntaxDescription = LPAREN WSP 056 * numericoid ; object identifier 057 * [ SP "DESC" SP qdstring ] ; description 058 * extensions WSP RPAREN ; extensions 059 * 060 * where: 061 * [numericoid] is object identifier assigned to this LDAP syntax; 062 * DESC [qdstring] is a short descriptive string; and 063 * [extensions] describe extensions. 064 * </pre> 065 * 066 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html"> RFC2252 Section 4.3.3</a> 067 * @see <a href= 068 * "http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-09.txt"> 069 * ldapbis [MODELS]</a> 070 * @see DescriptionUtils#getDescription(Syntax) 071 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 072 */ 073// super.hashCode is final 074@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode") 075public class LdapSyntax extends AbstractSchemaObject 076{ 077 /** the human readable flag */ 078 protected boolean isHumanReadable = false; 079 080 /** The associated SyntaxChecker */ 081 protected SyntaxChecker syntaxChecker; 082 083 084 /** 085 * Creates a Syntax object using a unique OID. 086 * 087 * @param oid the OID for this Syntax 088 */ 089 public LdapSyntax( String oid ) 090 { 091 super( SchemaObjectType.LDAP_SYNTAX, oid ); 092 } 093 094 095 /** 096 * Creates a Syntax object using a unique OID. 097 * 098 * @param oid the OID for this syntax 099 * @param description the description for this syntax 100 */ 101 public LdapSyntax( String oid, String description ) 102 { 103 super( SchemaObjectType.LDAP_SYNTAX, oid ); 104 this.description = description; 105 } 106 107 108 /** 109 * Creates a Syntax object using a unique OID. 110 * 111 * @param oid the OID for this syntax 112 * @param description the description for this syntax 113 * @param isHumanReadable true if this syntax is human readable 114 */ 115 public LdapSyntax( String oid, String description, boolean isHumanReadable ) 116 { 117 super( SchemaObjectType.LDAP_SYNTAX, oid ); 118 this.description = description; 119 this.isHumanReadable = isHumanReadable; 120 } 121 122 123 /** 124 * Gets whether or not the Syntax is human readable. 125 * 126 * @return true if the syntax can be interpreted by humans, false otherwise 127 */ 128 public boolean isHumanReadable() 129 { 130 return isHumanReadable; 131 } 132 133 134 /** 135 * Sets the human readable flag value. 136 * 137 * @param humanReadable the human readable flag value to set 138 */ 139 public void setHumanReadable( boolean humanReadable ) 140 { 141 if ( locked ) 142 { 143 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 144 } 145 146 if ( !isReadOnly ) 147 { 148 this.isHumanReadable = humanReadable; 149 } 150 } 151 152 153 /** 154 * Gets the SyntaxChecker used to validate values in accordance with this 155 * Syntax. 156 * 157 * @return the SyntaxChecker 158 */ 159 public SyntaxChecker getSyntaxChecker() 160 { 161 return syntaxChecker; 162 } 163 164 165 /** 166 * Sets the associated SyntaxChecker 167 * 168 * @param syntaxChecker The associated SyntaxChecker 169 */ 170 public void setSyntaxChecker( SyntaxChecker syntaxChecker ) 171 { 172 if ( locked ) 173 { 174 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 175 } 176 177 if ( !isReadOnly ) 178 { 179 this.syntaxChecker = syntaxChecker; 180 } 181 } 182 183 184 /** 185 * Update the associated SyntaxChecker, even if the SchemaObject is readOnly 186 * 187 * @param newSyntaxChecker The associated SyntaxChecker 188 */ 189 public void updateSyntaxChecker( SyntaxChecker newSyntaxChecker ) 190 { 191 if ( locked ) 192 { 193 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 194 } 195 196 this.syntaxChecker = newSyntaxChecker; 197 } 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override 204 public String toString() 205 { 206 return objectType + " " + DescriptionUtils.getDescription( this ); 207 } 208 209 210 /** 211 * {@inheritDoc} 212 */ 213 public void addToRegistries( List<Throwable> errors, Registries registries ) throws LdapException 214 { 215 if ( registries != null ) 216 { 217 try 218 { 219 // Gets the associated SyntaxChecker 220 syntaxChecker = registries.getSyntaxCheckerRegistry().lookup( oid ); 221 } 222 catch ( LdapException ne ) 223 { 224 // No SyntaxChecker ? Associate the Syntax to a catch all SyntaxChecker 225 syntaxChecker = new OctetStringSyntaxChecker( oid ); 226 } 227 228 // Add the references for S : 229 // S -> SC 230 if ( syntaxChecker != null ) 231 { 232 registries.addReference( this, syntaxChecker ); 233 } 234 } 235 } 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 @SuppressWarnings("PMD.CollapsibleIfStatements") 242 // Used because of comments 243 public void removeFromRegistries( List<Throwable> errors, Registries registries ) throws LdapException 244 { 245 if ( registries != null ) 246 { 247 /** 248 * Remove the Syntax references (using and usedBy) : 249 * S -> SC 250 */ 251 if ( syntaxChecker != null ) 252 { 253 registries.delReference( this, syntaxChecker ); 254 } 255 } 256 } 257 258 259 /** 260 * {@inheritDoc} 261 */ 262 public LdapSyntax copy() 263 { 264 LdapSyntax copy = new LdapSyntax( oid ); 265 266 // Copy the SchemaObject common data 267 copy.copy( this ); 268 269 // Copy the HR flag 270 copy.isHumanReadable = isHumanReadable; 271 272 // All the references to other Registries object are set to null. 273 copy.syntaxChecker = null; 274 275 return copy; 276 } 277 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override 283 public boolean equals( Object o ) 284 { 285 if ( !super.equals( o ) ) 286 { 287 return false; 288 } 289 290 if ( !( o instanceof LdapSyntax ) ) 291 { 292 return false; 293 } 294 295 LdapSyntax that = ( LdapSyntax ) o; 296 297 // IsHR 298 if ( isHumanReadable != that.isHumanReadable ) 299 { 300 return false; 301 } 302 303 // Check the SyntaxChecker (not a equals) 304 if ( syntaxChecker != null ) 305 { 306 if ( that.syntaxChecker == null ) 307 { 308 return false; 309 } 310 311 return syntaxChecker.getOid().equals( that.syntaxChecker.getOid() ); 312 } 313 else 314 { 315 return that.syntaxChecker == null; 316 } 317 } 318 319 320 /** 321 * {@inheritDoc} 322 */ 323 public void clear() 324 { 325 // Clear the common elements 326 super.clear(); 327 328 // Clear the references 329 syntaxChecker = null; 330 } 331}