-/*
- * Copyright 2011 BitMeister Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
package jp.bitmeister.asn1.type.builtin;
import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.math.BigInteger;
-import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
import jp.bitmeister.asn1.annotation.ASN1BuiltIn;
-import jp.bitmeister.asn1.annotation.ASN1Enumeration;
-import jp.bitmeister.asn1.annotation.ASN1Identifier;
import jp.bitmeister.asn1.annotation.ASN1Tag;
-import jp.bitmeister.asn1.exception.ASN1IllegalArgument;
import jp.bitmeister.asn1.exception.ASN1IllegalDefinition;
import jp.bitmeister.asn1.exception.ASN1RuntimeException;
import jp.bitmeister.asn1.processor.ASN1Visitor;
import jp.bitmeister.asn1.type.ASN1TagClass;
import jp.bitmeister.asn1.type.ASN1TagMode;
-import jp.bitmeister.asn1.type.ASN1Type;
-import jp.bitmeister.asn1.type.PrimitiveType;
-import jp.bitmeister.asn1.type.ValueComparable;
+import jp.bitmeister.asn1.type.AbstractInteger;
+import jp.bitmeister.asn1.type.NamedNumberMap;
/**
- * Represents ASN.1 'INTEGER' type.
+ * An implementation of ASN.1 'INTEGER' type that contains {@code Long} value.
*
* <p>
* An instance of this class represents an 'INTEGER' type data, and has a
- * {@link java.math.BigInteger} value.
- * </p>
- * <p>
- * A sub-class of {@code INTEGER} can contain one or more fields annotated as
- * {@code @ASN1Enumeration}. If a sub-class of {@code INTEGER} contains
- * {@code @ASN1Enumeration} fields, the value of the data must be same as one of
- * the {@code @ASN1Enumeration} fields.
+ * {@link java.lang.Long} value. If the data needs to contain value which is
+ * bigger than {@code Long.MAX_VALUE} or smaller than {@code Long.MIN_VALUE},
+ * {@code BigINTEGER} type shall be used.
* </p>
*
* @author WATANABE, Jun. <jwat at bitmeister.jp>
*
- * @see ASN1Enumeration
+ * @see BigINTEGER
*/
@ASN1BuiltIn
@ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 2, tagMode = ASN1TagMode.IMPLICIT)
-public class INTEGER extends PrimitiveType<BigInteger> implements
- ValueComparable {
+public class INTEGER extends AbstractInteger<Long> {
/**
- * Contains the maps of enumerations for all of the sub-types of 'INTEGER'
- * and 'ENUMERATED'.
+ * Contains the maps of enumerations for all of the sub-types of {@code INTEGER}
+ * and {@code ENUMERATED}.
*/
- private static final Map<Class<? extends INTEGER>, Map<BigInteger, String>> NAMED_NUMBER_MAPS = new HashMap<Class<? extends INTEGER>, Map<BigInteger, String>>();
-
- static {
- NAMED_NUMBER_MAPS.put(INTEGER.class, new HashMap<BigInteger, String>());
- }
+ private static final NamedNumberMap<Long> NAMED_NUMBER_MAPS = new NamedNumberMap<Long>() {
- /**
- * Returns the map of enumerations for the type. The {@code Map} maps value
- * to identifier.
- *
- * @param type
- * The type.
- * @return The map of enumerations.
- */
- private static Map<BigInteger, String> getNamedNumberMap(
- Class<? extends INTEGER> type) {
- if (NAMED_NUMBER_MAPS.containsKey(type)) {
- return NAMED_NUMBER_MAPS.get(type);
- }
- Map<BigInteger, String> map = new HashMap<BigInteger, String>();
- for (Field f : type.getDeclaredFields()) {
- if (!f.isAnnotationPresent(ASN1Enumeration.class)) {
- continue;
- }
- final int modifier = Modifier.PUBLIC | Modifier.STATIC
- | Modifier.FINAL;
- ASN1Identifier id = f.getAnnotation(ASN1Identifier.class);
- String fieldId = id != null ? id.value() : f.getName();
- if ((f.getModifiers() & modifier) != modifier) {
- ASN1IllegalDefinition ex = new ASN1IllegalDefinition();
- ex.setMessage(
- "An enumeration must be a public static final field.",
- null, type, fieldId, null);
- throw ex;
- }
- BigInteger value;
- if (f.getType() == BigInteger.class) {
- try {
- value = (BigInteger) f.get(null);
- } catch (Exception e) {
- ASN1RuntimeException ex = new ASN1RuntimeException();
- ex.setMessage("Failed to retreave the BigInteger value.",
- e, type, fieldId, null);
- throw ex;
- }
- } else if (f.getType() == int.class || f.getType() == long.class) {
+ @Override
+ public Long getKeyValue(Field f) {
+ Long value;
+ if (f.getType() == int.class || f.getType() == long.class) {
try {
- value = BigInteger.valueOf(f.getLong(null));
+ value = f.getLong(null);
} catch (Exception e) {
- ASN1RuntimeException ex = new ASN1RuntimeException();
- ex.setMessage("Failed to convert the value to BigInteger.",
- e, type, fieldId, null);
+ ASN1RuntimeException ex = new ASN1RuntimeException(
+ "Failed to retreave the Long value.");
throw ex;
}
} else {
- ASN1IllegalDefinition ex = new ASN1IllegalDefinition();
- ex.setMessage(
- "An enumeration must be an 'int', 'long' or 'BigInteger' field.",
- null, type, fieldId, null);
- throw ex;
- }
- if (map.containsKey(value)) {
- ASN1IllegalDefinition ex = new ASN1IllegalDefinition();
- ex.setMessage(
- "Each number of enumerations shall be distinct from all other enumerations in the type.",
- null, type, fieldId, null);
+ ASN1IllegalDefinition ex = new ASN1IllegalDefinition(
+ "An enumeration of INTEGER type must be an 'int' or a 'long' field.");
throw ex;
}
- map.put(value, fieldId);
+ return value;
}
- @SuppressWarnings("unchecked")
- Class<? extends INTEGER> parent = (Class<? extends INTEGER>) type
- .getSuperclass();
- if (parent == ENUMERATED.class) {
- if (map.isEmpty()) {
- ASN1IllegalDefinition ex = new ASN1IllegalDefinition();
- ex.setMessage(
- "ENUMERATED type shall have at least one enumeration item.",
- null, type, null, null);
- throw ex;
- }
- } else if (parent != INTEGER.class) {
- if (!map.isEmpty()) {
- ASN1IllegalDefinition ex = new ASN1IllegalDefinition();
- ex.setMessage(
- "A class that does not extend 'INTEGER' or 'ENUMERATED' directly, can not have own enumerations.",
- null, type, null, null);
- throw ex;
- }
- map = getNamedNumberMap(parent);
- }
- NAMED_NUMBER_MAPS.put(type, map);
- return map;
+
+ };
+
+ static {
+ NAMED_NUMBER_MAPS.putEmptyMap(INTEGER.class);
}
/**
}
/**
- * Instantiates an {@code INTEGER} and initialize it with the
- * {@code BigInteger} value.
- *
- * @param value
- * The value to be assigned.
- */
- public INTEGER(BigInteger value) {
- set(value);
- }
-
- /**
* Instantiates an {@code INTEGER} and initialize it with the {@code long}
* value.
*
set(value);
}
- /*
- * (non-Javadoc)
- *
- * @see jp.bitmeister.asn1.type.PrimitiveType#set(null)
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.AbstractInteger#getNamedNumberMap()
*/
@Override
- public void set(BigInteger value) {
- Map<BigInteger, String> map = getNamedNumberMap(getClass());
- if (!map.isEmpty() && !map.containsKey(value)) {
- ASN1IllegalArgument ex = new ASN1IllegalArgument();
- ex.setMessage(
- "Invalid value '"
- + value
- + "'. If a class has enumerations, the value must be same as one of them.",
- null, getClass(), null, null);
- throw ex;
- }
- super.set(value);
+ public Map<Long, String> getNamedNumberMap() {
+ return NAMED_NUMBER_MAPS.getNamedNumberMap(getClass());
}
- /**
- * Sets the {@code long} value to this data.
- *
- * @param value
- * The value to be assigned.
- */
- public void set(long value) {
- set(BigInteger.valueOf(value));
- }
-
- /**
- * Sets the value specified by the name of number to this data.
- *
- * @param nameOfNumber
- * The name of number.
- */
- public void set(String nameOfNumber) {
- for (Entry<BigInteger, String> e: getNamedNumberMap(getClass()).entrySet()) {
- if (e.getValue().equals(nameOfNumber)) {
- set(e.getKey());
- return;
- }
- }
- ASN1IllegalArgument e = new ASN1IllegalArgument();
- e.setMessage("The name '" + nameOfNumber + "' is not defined in this type.", null, getClass(), null, null);
- throw e;
- }
-
- /**
- * Returns an identifier related to the value of this data if the type has
- * {@code @ASN1Enumeration} fields.
- *
- * @return An identifier related to the value.
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.ASN1Type#accept(jp.bitmeister.asn1.processor.ASN1Visitor)
*/
- public String identifier() {
- return getNamedNumberMap(getClass()).get(value());
+ @Override
+ public <R, E extends Throwable> R accept(ASN1Visitor<R, E> visitor)
+ throws E {
+ return visitor.visit(this);
}
- /**
- * Tests if the value of this data is in the range of {@code long} value.
- *
- * @return {@code true} when the value of this data is in the range of
- * {@code long}.
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.AbstractInteger#isLongValue()
*/
+ @Override
public boolean isLongValue() {
- return value().compareTo(BigInteger.valueOf(Long.MIN_VALUE)) >= 0
- && value().compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0;
- }
-
- /**
- * Tests if the value of this data is in the range of {@code int} value.
- *
- * @return {@code true} when the value of this data is in the range of
- * {@code int}.
- */
- public boolean isIntValue() {
- return value().compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) >= 0
- && value().compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) <= 0;
- }
-
- /**
- * Returns a {@code long} value that converted from the value of this data.
- *
- * @return A {@code long} value.
- */
- public long longValue() {
- return value().longValue();
- }
-
- /**
- * Returns an {@code int} value that converted from the value of this data.
- *
- * @return An {@code int} value.
- */
- public int intValue() {
- return value().intValue();
+ return true;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * jp.bitmeister.asn1.type.ValueComparable#compareTo(jp.bitmeister.asn1.
- * type.ASN1Type)
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.AbstractInteger#isIntValue()
*/
@Override
- public int compareTo(ASN1Type other) {
- return value().compareTo(((INTEGER) other).value());
+ public boolean isIntValue() {
+ return Integer.MIN_VALUE <= value() && value() <= Integer.MAX_VALUE;
}
-
+
/*
* (non-Javadoc)
*
- * @see
- * jp.bitmeister.asn1.type.ASN1Type#accept(jp.bitmeister.asn1.processor.
- * ASN1Visitor)
+ * @see jp.bitmeister.asn1.type.AbstractInteger#isEnum()
*/
@Override
- public <R, E extends Throwable> R accept(ASN1Visitor<R, E> visitor) throws E {
- return visitor.visit(this);
+ protected boolean isEnum() {
+ return false;
}
}