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.api.ldap.model.schema.syntaxCheckers;
021
022
023import java.util.regex.Pattern;
024
025import org.apache.directory.api.i18n.I18n;
026import org.apache.directory.api.ldap.model.constants.SchemaConstants;
027import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
028import org.apache.directory.api.util.Strings;
029
030
031/**
032 * A SyntaxChecker which verifies that a name is valid for an ObjectClass
033 * or an AttributeType<br><br>
034 * <pre>
035 * &lt;m-name&gt; = &lt;keystring&gt; <br>
036 * &lt;keystring&gt; = &lt;leadkeychar&gt; *&lt;keychar&gt;<br>
037 * &lt;leadkeychar&gt; = &lt;ALPHA&gt;<br>
038 * &lt;keychar&gt; = &lt;ALPHA&gt; / &lt;DIGIT&gt; / &lt;HYPHEN&gt; / &lt;SEMI&gt;<br>
039 * &lt;ALPHA&gt;   = %x41-5A / %x61-7A   ; "A"-"Z" / "a"-"z"<br>
040 * &lt;DIGIT&gt;   = %x30 / &lt;LDIGIT       ; "0"-"9"<br>
041 * &lt;LDIGIT&gt;  = %x31-39             ; "1"-"9"<br>
042 * &lt;HYPHEN&gt;  = %x2D ; hyphen ("-")<br>
043 * &lt;SEMI&gt;    = %x3B ; semicolon (";")<br>
044 * </pre>
045 * 
046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047 */
048@SuppressWarnings("serial")
049public final class ObjectNameSyntaxChecker extends SyntaxChecker
050{
051    private static final String REGEXP = "^([a-zA-Z][a-zA-Z0-9-;]*)$";
052
053    private static final Pattern PATTERN = Pattern.compile( REGEXP );
054    
055    /**
056     * A static instance of ObjectNameSyntaxChecker
057     */
058    public static final ObjectNameSyntaxChecker INSTANCE = 
059        new ObjectNameSyntaxChecker( SchemaConstants.OBJECT_NAME_SYNTAX );
060    
061    /**
062     * A static Builder for this class
063     */
064    public static final class Builder extends SCBuilder<ObjectNameSyntaxChecker>
065    {
066        /**
067         * The Builder constructor
068         */
069        private Builder()
070        {
071            super( SchemaConstants.OBJECT_NAME_SYNTAX );
072        }
073        
074        
075        /**
076         * Create a new instance of ObjectNameSyntaxChecker
077         * @return A new instance of ObjectNameSyntaxChecker
078         */
079        @Override
080        public ObjectNameSyntaxChecker build()
081        {
082            return new ObjectNameSyntaxChecker( oid );
083        }
084    }
085
086    
087    /**
088     * Creates a new instance of ObjectNameSyntaxChecker.
089     * 
090     * @param oid The OID to use for this SyntaxChecker
091     */
092    private ObjectNameSyntaxChecker( String oid )
093    {
094        super( oid );
095    }
096
097    
098    /**
099     * @return An instance of the Builder for this class
100     */
101    public static Builder builder()
102    {
103        return new Builder();
104    }
105
106
107    /**
108     * {@inheritDoc}
109     */
110    @Override
111    public boolean isValidSyntax( Object value )
112    {
113        String strValue;
114
115        if ( value == null )
116        {
117            if ( LOG.isDebugEnabled() )
118            {
119                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, "null" ) );
120            }
121            
122            return false;
123        }
124
125        if ( value instanceof String )
126        {
127            strValue = ( String ) value;
128        }
129        else if ( value instanceof byte[] )
130        {
131            strValue = Strings.utf8ToString( ( byte[] ) value );
132        }
133        else
134        {
135            strValue = value.toString();
136        }
137
138        if ( strValue.length() == 0 )
139        {
140            if ( LOG.isDebugEnabled() )
141            {
142                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
143            }
144            
145            return false;
146        }
147
148        // Search for the '$' separator
149        boolean result = PATTERN.matcher( strValue ).matches();
150
151        if ( LOG.isDebugEnabled() )
152        {
153            if ( result )
154            {
155                LOG.debug( I18n.msg( I18n.MSG_04489_SYNTAX_VALID, value ) );
156            }
157            else
158            {
159                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
160            }
161        }
162
163        return result;
164    }
165}