+/*
+ * Copyright 2011-2012 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.math.BigInteger;
+import java.util.Map;
+
+import jp.bitmeister.asn1.annotation.ASN1BuiltIn;
+import jp.bitmeister.asn1.annotation.ASN1Identifier;
+import jp.bitmeister.asn1.annotation.ASN1Tag;
+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.AbstractInteger;
+import jp.bitmeister.asn1.type.NamedNumberMap;
+
+/**
+ * An implementation of ASN.1 'INTEGER' type that can contain
+ * arbitrary-precision integer value.
+ *
+ * <p>
+ * An instance of this class represents an 'INTEGER' type data that needs to
+ * contain an arbitrary-precision value. It has a {@link java.math.BigInteger}
+ * value.
+ * </p>
+ *
+ * @author WATANABE, Jun. <jwat at bitmeister.jp>
+ *
+ * @see INTEGER
+ */
+@ASN1BuiltIn
+@ASN1Identifier("INTEGER")
+@ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 2, tagMode = ASN1TagMode.IMPLICIT)
+public class BigINTEGER extends AbstractInteger<BigInteger> {
+
+ /**
+ * Contains the maps of enumerations for all of the sub-types of {@code BigINTEGER}
+ * and {@code BigENUMERATED}.
+ */
+ private static final NamedNumberMap<BigInteger> NAMED_NUMBER_MAPS = new NamedNumberMap<BigInteger>() {
+
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.NamedNumberMap#getKeyValue(java.lang.reflect.Field)
+ */
+ @Override
+ public BigInteger getKeyValue(Field f) {
+ BigInteger value;
+ if (f.getType() == BigInteger.class) {
+ try {
+ value = (BigInteger) f.get(null);
+ } catch (Exception e) {
+ ASN1RuntimeException ex = new ASN1RuntimeException(
+ "Failed to retreave the BigInteger value.");
+ throw ex;
+ }
+ } else if (f.getType() == int.class || f.getType() == long.class) {
+ try {
+ value = BigInteger.valueOf(f.getLong(null));
+ } catch (Exception e) {
+ ASN1RuntimeException ex = new ASN1RuntimeException(
+ "Failed to convert the value to BigInteger.");
+ throw ex;
+ }
+ } else {
+ ASN1IllegalDefinition ex = new ASN1IllegalDefinition(
+ "An enumeration of BigINTEGER type must be an 'int', a 'long' or a 'BigInteger' field.");
+ throw ex;
+ }
+ return value;
+ }
+
+ };
+
+ static {
+ NAMED_NUMBER_MAPS.putEmptyMap(BigINTEGER.class);
+ }
+
+ /**
+ * Instantiates an empty {@code INTEGER}.
+ */
+ public BigINTEGER() {
+ }
+
+ /**
+ * Instantiates an {@code INTEGER} and initialize it with the
+ * {@code BigInteger} value.
+ *
+ * @param value
+ * The value to be assigned.
+ */
+ public BigINTEGER(BigInteger value) {
+ set(value);
+ }
+
+ /**
+ * Instantiates an {@code INTEGER} and initialize it with the {@code long}
+ * value.
+ *
+ * @param value
+ * The value to be assigned.
+ */
+ public BigINTEGER(long value) {
+ set(value);
+ }
+
+ /**
+ * Sets the {@code long} value to this data.
+ *
+ * @param value
+ * The value to be assigned.
+ */
+ public void set(long value) {
+ set(BigInteger.valueOf(value));
+ }
+
+ /**
+ * 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}.
+ */
+ 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;
+ }
+
+
+ /* (non-Javadoc)
+ * @see jp.bitmeister.asn1.type.AbstractInteger#getNamedNumberMap()
+ */
+ @Override
+ public Map<BigInteger, String> getNamedNumberMap() {
+ return NAMED_NUMBER_MAPS.getNamedNumberMap(getClass());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jp.bitmeister.asn1.type.ASN1Type#accept(jp.bitmeister.asn1.processor.
+ * ASN1Visitor)
+ */
+ @Override
+ public <R, E extends Throwable> R accept(ASN1Visitor<R, E> visitor) throws E {
+ return visitor.visit(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jp.bitmeister.asn1.type.AbstractInteger#isEnum()
+ */
+ @Override
+ protected boolean isEnum() {
+ return false;
+ }
+
+}