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 org.apache.directory.api.i18n.I18n;
024import org.apache.directory.api.ldap.model.constants.SchemaConstants;
025import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
026import org.apache.directory.api.util.Strings;
027
028
029/**
030 * A SyntaxChecker which verifies that a value is a Printable String according to RFC 4517.
031 * <p>
032 * From RFC 4517 :
033 * <pre>
034 * PrintableString    = 1*PrintableCharacter
035 * PrintableCharacter = ALPHA | DIGIT | SQUOTE | LPAREN | RPAREN |
036 *                          PLUS | COMMA | HYPHEN | DOT | EQUALS |
037 *                          SLASH | COLON | QUESTION | SPACE
038 *                          
039 * SLASH   = %x2F                ; forward slash ("/")
040 * COLON   = %x3A                ; colon (":")
041 * QUESTION= %x3F                ; question mark ("?")
042 * </pre>
043 * From RFC 4512 :
044 * <pre>
045 * ALPHA   = %x41-5A | %x61-7A   ; "A"-"Z" / "a"-"z"
046 * DIGIT   = %x30 | LDIGIT       ; "0"-"9"
047 * LDIGIT  = %x31-39             ; "1"-"9"
048 * SQUOTE  = %x27                ; single quote ("'")
049 * LPAREN  = %x28                ; left paren ("(")
050 * RPAREN  = %x29                ; right paren (")")
051 * PLUS    = %x2B                ; plus sign ("+")
052 * COMMA   = %x2C                ; comma (",")
053 * HYPHEN  = %x2D                ; hyphen ("-")
054 * DOT     = %x2E                ; period (".")
055 * EQUALS  = %x3D                ; equals sign ("=")
056 * SPACE   = %x20                ; space (" ")
057 * </pre>
058 *
059 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
060 */
061@SuppressWarnings("serial")
062public final class PrintableStringSyntaxChecker extends SyntaxChecker
063{
064    /**
065     * A static instance of PrintableStringSyntaxChecker
066     */
067    public static final PrintableStringSyntaxChecker INSTANCE = 
068        new PrintableStringSyntaxChecker( SchemaConstants.PRINTABLE_STRING_SYNTAX );
069    
070    /**
071     * A static Builder for this class
072     */
073    public static final class Builder extends SCBuilder<PrintableStringSyntaxChecker>
074    {
075        /**
076         * The Builder constructor
077         */
078        private Builder()
079        {
080            super( SchemaConstants.PRINTABLE_STRING_SYNTAX );
081        }
082        
083        
084        /**
085         * Create a new instance of PrintableStringSyntaxChecker
086         * @return A new instance of PrintableStringSyntaxChecker
087         */
088        @Override
089        public PrintableStringSyntaxChecker build()
090        {
091            return new PrintableStringSyntaxChecker( oid );
092        }
093    }
094
095    
096    /**
097     * Creates a new instance of PrintableStringSyntaxChecker.
098     * 
099     * @param oid The OID to use for this SyntaxChecker
100     */
101    private PrintableStringSyntaxChecker( String oid )
102    {
103        super( oid );
104    }
105
106    
107    /**
108     * @return An instance of the Builder for this class
109     */
110    public static Builder builder()
111    {
112        return new Builder();
113    }
114
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public boolean isValidSyntax( Object value )
121    {
122        String strValue;
123
124        if ( value == null )
125        {
126            if ( LOG.isDebugEnabled() )
127            {
128                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, "null" ) );
129            }
130            
131            return false;
132        }
133
134        if ( value instanceof String )
135        {
136            strValue = ( String ) value;
137        }
138        else if ( value instanceof byte[] )
139        {
140            strValue = Strings.utf8ToString( ( byte[] ) value );
141        }
142        else
143        {
144            strValue = value.toString();
145        }
146
147        if ( strValue.length() == 0 )
148        {
149            if ( LOG.isDebugEnabled() )
150            {
151                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
152            }
153            
154            return false;
155        }
156
157        // We must have at least one char
158        if ( strValue.length() == 0 )
159        {
160            if ( LOG.isDebugEnabled() )
161            {
162                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
163            }
164            
165            return false;
166        }
167
168        boolean result = Strings.isPrintableString( strValue );
169
170        if ( LOG.isDebugEnabled() )
171        {
172            if ( result )
173            {
174                LOG.debug( I18n.msg( I18n.MSG_04489_SYNTAX_VALID, value ) );
175            }
176            else
177            {
178                LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
179            }
180        }
181
182        return result;
183    }
184}