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.Chars; 027import org.apache.directory.api.util.Strings; 028 029 030/** 031 * A SyntaxChecker which verifies that a value is a valid Java primitive short or 032 * the Short wrapper. Essentially this constrains the min and max values of 033 * the Integer. 034 * <p> 035 * From RFC 4517 : 036 * 037 * <pre> 038 * Integer = ( HYPHEN LDIGIT *DIGIT ) | number 039 * 040 * From RFC 4512 : 041 * number = DIGIT | ( LDIGIT 1*DIGIT ) 042 * DIGIT = %x30 | LDIGIT ; "0"-"9" 043 * LDIGIT = %x31-39 ; "1"-"9" 044 * HYPHEN = %x2D ; hyphen ("-") 045 * </pre> 046 * 047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 048 */ 049@SuppressWarnings("serial") 050public final class JavaByteSyntaxChecker extends SyntaxChecker 051{ 052 /** 053 * A static instance of JavaByteSyntaxChecker 054 */ 055 public static final JavaByteSyntaxChecker INSTANCE = new JavaByteSyntaxChecker( SchemaConstants.JAVA_BYTE_SYNTAX ); 056 057 /** 058 * A static Builder for this class 059 */ 060 public static final class Builder extends SCBuilder<JavaByteSyntaxChecker> 061 { 062 /** 063 * The Builder constructor 064 */ 065 private Builder() 066 { 067 super( SchemaConstants.JAVA_BYTE_SYNTAX ); 068 } 069 070 071 /** 072 * Create a new instance of JavaByteSyntaxChecker 073 * @return A new instance of JavaByteSyntaxChecker 074 */ 075 @Override 076 public JavaByteSyntaxChecker build() 077 { 078 return new JavaByteSyntaxChecker( oid ); 079 } 080 } 081 082 083 /** 084 * Creates a new instance of JavaByteSyntaxChecker. 085 * 086 * @param oid The OID to use for this SyntaxChecker 087 */ 088 private JavaByteSyntaxChecker( String oid ) 089 { 090 super( oid ); 091 } 092 093 094 /** 095 * @return An instance of the Builder for this class 096 */ 097 public static Builder builder() 098 { 099 return new Builder(); 100 } 101 102 103 /** 104 * {@inheritDoc} 105 */ 106 @Override 107 public boolean isValidSyntax( Object value ) 108 { 109 String strValue; 110 111 if ( value == null ) 112 { 113 if ( LOG.isDebugEnabled() ) 114 { 115 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, "null" ) ); 116 } 117 118 return false; 119 } 120 121 if ( value instanceof String ) 122 { 123 strValue = ( String ) value; 124 } 125 else if ( value instanceof byte[] ) 126 { 127 strValue = Strings.utf8ToString( ( byte[] ) value ); 128 } 129 else 130 { 131 strValue = value.toString(); 132 } 133 134 if ( strValue.length() == 0 ) 135 { 136 if ( LOG.isDebugEnabled() ) 137 { 138 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 139 } 140 141 return false; 142 } 143 144 // The first char must be either a '-' or in [0..9]. 145 // If it's a '0', then there should be any other char after 146 int pos = 0; 147 char c = strValue.charAt( pos ); 148 149 if ( c == '-' ) 150 { 151 pos = 1; 152 } 153 else if ( !Chars.isDigit( c ) ) 154 { 155 if ( LOG.isDebugEnabled() ) 156 { 157 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 158 } 159 160 return false; 161 } 162 else if ( c == '0' ) 163 { 164 boolean result = strValue.length() <= 1; 165 166 if ( LOG.isDebugEnabled() ) 167 { 168 if ( result ) 169 { 170 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 171 } 172 else 173 { 174 LOG.debug( I18n.msg( I18n.MSG_04489_SYNTAX_VALID, value ) ); 175 } 176 } 177 178 return result; 179 } 180 181 // We must have at least a digit which is not '0' 182 if ( !Chars.isDigit( strValue, pos ) || Strings.isCharASCII( strValue, pos, '0' ) ) 183 { 184 if ( LOG.isDebugEnabled() ) 185 { 186 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 187 } 188 189 return false; 190 } 191 else 192 { 193 pos++; 194 } 195 196 while ( Chars.isDigit( strValue, pos ) ) 197 { 198 pos++; 199 } 200 201 if ( pos != strValue.length() ) 202 { 203 if ( LOG.isDebugEnabled() ) 204 { 205 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 206 } 207 208 return false; 209 } 210 211 // Should get a NumberFormatException for Byte values out of range 212 try 213 { 214 Byte.valueOf( strValue ); 215 216 if ( LOG.isDebugEnabled() ) 217 { 218 LOG.debug( I18n.msg( I18n.MSG_04489_SYNTAX_VALID, value ) ); 219 } 220 221 return true; 222 } 223 catch ( NumberFormatException e ) 224 { 225 if ( LOG.isDebugEnabled() ) 226 { 227 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) ); 228 } 229 230 return false; 231 } 232 } 233}