From: jwat Date: Thu, 4 Oct 2012 11:10:38 +0000 (+0900) Subject: * Add size restricted 'INTEGER' and 'ENUMERATED' types which contain a Long value. X-Git-Url: http://git.osdn.net/view?p=bm-asn1%2Fbm-asn1.git;a=commitdiff_plain;h=f732458a3fe40c8880ff279acc75f4b37402edef * Add size restricted 'INTEGER' and 'ENUMERATED' types which contain a Long value. * 'INTEGER' and 'ENUMERATED' types which contain a BigInteger value renamed to 'BigINTEGER' and 'BigENUMERATED'. * Some bugs were fixed. --- diff --git a/jp/bitmeister/asn1/annotation/ASN1Enumeration.java b/jp/bitmeister/asn1/annotation/ASN1Enumeration.java index 08cd10e..643a65c 100644 --- a/jp/bitmeister/asn1/annotation/ASN1Enumeration.java +++ b/jp/bitmeister/asn1/annotation/ASN1Enumeration.java @@ -20,6 +20,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -28,14 +30,15 @@ import jp.bitmeister.asn1.type.builtin.INTEGER; * *

* If a field annotated as {@code @ASN1Enumeration} is present in a definition - * of a sub-class of {@code INTEGER} or {@code ENUMERATED}, value that can be - * contained in the type is limited to values of {@code @ASN1Enumeration} - * fields. An {@code @ASN1Enumeration} field must be a {@code public} - * {@code static} {@code final} field and the type shall be {@code int}, - * {@code long} or {@code BigInteger}. Each value of {@code @ASN1Enumeration} - * fields appearing in definition of a type must be distinct from the others. A - * sub-class of {@code ENUMERATED} must have at least one - * {@code @ASN1Enumeration} field. + * of a sub-class of {@code INTEGER}, {@code ENUMERATED}, {@code BigINTEGER} or + * {@code BigENUMERATED}, value that can be contained in the type is limited to + * values of {@code @ASN1Enumeration} fields. An {@code @ASN1Enumeration} field + * must be a {@code public} {@code static} {@code final} field and the type + * shall be {@code int}, {@code long} or {@code BigInteger} (only for + * {@code BigINTEGER} or {@code BigENUMERATED}). Each value of + * {@code @ASN1Enumeration} fields appearing in definition of a type must be + * distinct from the others. A sub-class of {@code ENUMERATED} or + * {@code BigENUMERATED} must have at least one {@code @ASN1Enumeration} field. *

*

* For example, following ASN.1 definition : @@ -66,6 +69,8 @@ import jp.bitmeister.asn1.type.builtin.INTEGER; * * @see INTEGER * @see ENUMERATED + * @see BigINTEGER + * @see BigENUMERATED */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) diff --git a/jp/bitmeister/asn1/codec/ber/BerDecoder.java b/jp/bitmeister/asn1/codec/ber/BerDecoder.java index 567e8a9..e0ad79a 100644 --- a/jp/bitmeister/asn1/codec/ber/BerDecoder.java +++ b/jp/bitmeister/asn1/codec/ber/BerDecoder.java @@ -42,6 +42,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -207,9 +209,21 @@ public class BerDecoder implements ASN1Decoder, * * @see * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type - * .IntegerType) + * .builtin.INTEGER) */ public Void visit(INTEGER data) throws ASN1DecodingException { + data.set(new BigInteger(readStream(readLength())).longValue()); + return null; + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .IntegerType) + */ + public Void visit(BigINTEGER data) throws ASN1DecodingException { data.set(new BigInteger(readStream(readLength()))); return null; } @@ -219,12 +233,24 @@ public class BerDecoder implements ASN1Decoder, * * @see * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type - * .EnumeratedType) + * .builtin.ENUMERATED) */ public Void visit(ENUMERATED data) throws ASN1DecodingException { visit((INTEGER) data); return null; } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .EnumeratedType) + */ + public Void visit(BigENUMERATED data) throws ASN1DecodingException { + visit((BigINTEGER) data); + return null; + } /* * (non-Javadoc) diff --git a/jp/bitmeister/asn1/codec/ber/BerEncoder.java b/jp/bitmeister/asn1/codec/ber/BerEncoder.java index e3e3186..6866f18 100644 --- a/jp/bitmeister/asn1/codec/ber/BerEncoder.java +++ b/jp/bitmeister/asn1/codec/ber/BerEncoder.java @@ -39,6 +39,8 @@ import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; import jp.bitmeister.asn1.type.builtin.CHOICE; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; import jp.bitmeister.asn1.type.builtin.NULL; @@ -155,6 +157,13 @@ public class BerEncoder implements ASN1Encoder, return newPrimitiveOctets(data.value() ? (byte) 0xff : (byte) 0x00); } + /* (non-Javadoc) + * @see jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type.builtin.INTEGER) + */ + public EncodedOctets visit(INTEGER data) throws ASN1EncodingException { + return newPrimitiveOctets(BigInteger.valueOf(data.value()).toByteArray()); + } + /* * (non-Javadoc) * @@ -162,9 +171,16 @@ public class BerEncoder implements ASN1Encoder, * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type * .builtin.INTEGER) */ - public EncodedOctets visit(INTEGER data) { + public EncodedOctets visit(BigINTEGER data) { return newPrimitiveOctets(data.value().toByteArray()); } + + /* (non-Javadoc) + * @see jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type.builtin.ENUMERATED) + */ + public EncodedOctets visit(ENUMERATED data) throws ASN1EncodingException { + return visit((INTEGER)data); + } /* * (non-Javadoc) @@ -173,10 +189,10 @@ public class BerEncoder implements ASN1Encoder, * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type * .builtin.ENUMERATED) */ - public EncodedOctets visit(ENUMERATED data) { - return visit((INTEGER) data); + public EncodedOctets visit(BigENUMERATED data) { + return visit((BigINTEGER) data); } - + /* * (non-Javadoc) * diff --git a/jp/bitmeister/asn1/codec/xer/XerDecoder.java b/jp/bitmeister/asn1/codec/xer/XerDecoder.java index 4991e50..33fcdaf 100644 --- a/jp/bitmeister/asn1/codec/xer/XerDecoder.java +++ b/jp/bitmeister/asn1/codec/xer/XerDecoder.java @@ -41,6 +41,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -549,6 +551,43 @@ public class XerDecoder implements ASN1Decoder, */ @Override public void characters(String characters) { + data.set(Long.valueOf(characters)); + } + + }; + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .builtin.BigINTEGER) + */ + public DataDecoder visit(final BigINTEGER data) { + return new DataDecoder() { + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement + * (java.lang.String) + */ + @Override + void startChildElement(String qName) { + data.set(qName); + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters + * (java.lang.String) + */ + @Override + public void characters(String characters) { data.set(new BigInteger(characters)); } @@ -708,7 +747,7 @@ public class XerDecoder implements ASN1Decoder, }; } - + /* * (non-Javadoc) * @@ -719,6 +758,17 @@ public class XerDecoder implements ASN1Decoder, public DataDecoder visit(ENUMERATED data) { return visit((INTEGER) data); } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .builtin.BigENUMERATED) + */ + public DataDecoder visit(BigENUMERATED data) { + return visit((BigINTEGER) data); + } /* * (non-Javadoc) @@ -978,6 +1028,7 @@ public class XerDecoder implements ASN1Decoder, void startElement(String qName) { if (BOOLEAN.class.isAssignableFrom(data.componentType()) || ENUMERATED.class.isAssignableFrom(data.componentType()) + || BigENUMERATED.class.isAssignableFrom(data.componentType()) || CHOICE.class.isAssignableFrom(data.componentType())) { useXmlValueList = true; } diff --git a/jp/bitmeister/asn1/codec/xer/XerEncoder.java b/jp/bitmeister/asn1/codec/xer/XerEncoder.java index 19ca50e..3f9b158 100644 --- a/jp/bitmeister/asn1/codec/xer/XerEncoder.java +++ b/jp/bitmeister/asn1/codec/xer/XerEncoder.java @@ -36,6 +36,7 @@ import jp.bitmeister.asn1.exception.ASN1EncodingException; import jp.bitmeister.asn1.processor.ASN1Visitor; import jp.bitmeister.asn1.type.ASN1Module; import jp.bitmeister.asn1.type.ASN1Type; +import jp.bitmeister.asn1.type.AbstractInteger; import jp.bitmeister.asn1.type.CollectionType; import jp.bitmeister.asn1.type.ConstructiveType; import jp.bitmeister.asn1.type.ElementSpecification; @@ -45,6 +46,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -215,13 +218,19 @@ public class XerEncoder implements ASN1Encoder, * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type * .builtin.INTEGER) */ - public String visit(INTEGER data) { - String numberId = data.identifier(); - if (numberId != null) { - return TAG_START + numberId + SINGLE_TAG_END; - } else { - return data.value().toString(); - } + public String visit(INTEGER data) throws ASN1EncodingException { + return encodeInteger(data); + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .builtin.BigINTEGER) + */ + public String visit(BigINTEGER data) { + return encodeInteger(data); } /* @@ -331,7 +340,18 @@ public class XerEncoder implements ASN1Encoder, * .builtin.ENUMERATED) */ public String visit(ENUMERATED data) { - return visit((INTEGER) data); + return encodeInteger(data); + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type + * .builtin.BigENUMERATED) + */ + public String visit(BigENUMERATED data) { + return encodeInteger(data); } /* @@ -451,6 +471,22 @@ public class XerEncoder implements ASN1Encoder, } /** + * Encodes an ASN.1 'INTEGER' or 'ENUMERATED' data. + * + * @param data + * The integer data. + * @return The XER representation of the data. + */ + private String encodeInteger(AbstractInteger data) { + String numberId = data.identifier(); + if (numberId != null) { + return TAG_START + numberId + SINGLE_TAG_END; + } else { + return data.value().toString(); + } + } + + /** * Encodes each element of the {@code ConstructiveType} data. * * @param data @@ -487,6 +523,7 @@ public class XerEncoder implements ASN1Encoder, builder = new StringBuilder(); if (BOOLEAN.class.isAssignableFrom(data.componentType()) || ENUMERATED.class.isAssignableFrom(data.componentType()) + || BigENUMERATED.class.isAssignableFrom(data.componentType()) || CHOICE.class.isAssignableFrom(data.componentType())) { for (ASN1Type e : data.collection()) { builder.append(e.accept(this)); diff --git a/jp/bitmeister/asn1/exception/ASN1DecodingException.java b/jp/bitmeister/asn1/exception/ASN1DecodingException.java index 9c598c7..2525f68 100644 --- a/jp/bitmeister/asn1/exception/ASN1DecodingException.java +++ b/jp/bitmeister/asn1/exception/ASN1DecodingException.java @@ -22,4 +22,21 @@ package jp.bitmeister.asn1.exception; */ @SuppressWarnings("serial") public class ASN1DecodingException extends ASN1Exception { + + /** + * Instantiate an {@code ASN1DecodingException}. + */ + public ASN1DecodingException() { + } + + /** + * Instantiate an {@code ASN1DecodingException} with specified error message. + * + * @param message + * The error message. + */ + public ASN1DecodingException(String message) { + super(message); + } + } diff --git a/jp/bitmeister/asn1/exception/ASN1EncodingException.java b/jp/bitmeister/asn1/exception/ASN1EncodingException.java index e2b42bb..56e6a80 100644 --- a/jp/bitmeister/asn1/exception/ASN1EncodingException.java +++ b/jp/bitmeister/asn1/exception/ASN1EncodingException.java @@ -22,4 +22,21 @@ package jp.bitmeister.asn1.exception; */ @SuppressWarnings("serial") public class ASN1EncodingException extends ASN1Exception { + + /** + * Instantiate an {@code ASN1EncodingException}. + */ + public ASN1EncodingException() { + } + + /** + * Instantiate an {@code ASN1EncodingException} with specified error message. + * + * @param message + * The error message. + */ + public ASN1EncodingException(String message) { + super(message); + } + } diff --git a/jp/bitmeister/asn1/exception/ASN1Exception.java b/jp/bitmeister/asn1/exception/ASN1Exception.java index a81806f..5598e98 100644 --- a/jp/bitmeister/asn1/exception/ASN1Exception.java +++ b/jp/bitmeister/asn1/exception/ASN1Exception.java @@ -26,6 +26,22 @@ import jp.bitmeister.asn1.type.ASN1Type; public class ASN1Exception extends Exception { protected DetailedMessage message; + + /** + * Instantiate an {@code ASN1Exception}. + */ + public ASN1Exception() { + } + + /** + * Instantiate an {@code ASN1Exception} with specified error message. + * + * @param message + * The error message. + */ + public ASN1Exception(String message) { + super(message); + } /** * Set detailed message of this exception. diff --git a/jp/bitmeister/asn1/exception/ASN1IllegalArgument.java b/jp/bitmeister/asn1/exception/ASN1IllegalArgument.java index d6d0372..ffcd0f0 100644 --- a/jp/bitmeister/asn1/exception/ASN1IllegalArgument.java +++ b/jp/bitmeister/asn1/exception/ASN1IllegalArgument.java @@ -22,4 +22,21 @@ package jp.bitmeister.asn1.exception; */ @SuppressWarnings("serial") public class ASN1IllegalArgument extends ASN1RuntimeException { + + /** + * Instantiate an {@code ASN1IllegalArgument}. + */ + public ASN1IllegalArgument() { + } + + /** + * Instantiate an {@code ASN1IllegalArgument} with specified error message. + * + * @param message + * The error message. + */ + public ASN1IllegalArgument(String message) { + super(message); + } + } diff --git a/jp/bitmeister/asn1/exception/ASN1IllegalDefinition.java b/jp/bitmeister/asn1/exception/ASN1IllegalDefinition.java index 82d53ee..0014005 100644 --- a/jp/bitmeister/asn1/exception/ASN1IllegalDefinition.java +++ b/jp/bitmeister/asn1/exception/ASN1IllegalDefinition.java @@ -22,4 +22,21 @@ package jp.bitmeister.asn1.exception; */ @SuppressWarnings("serial") public class ASN1IllegalDefinition extends ASN1RuntimeException { + + /** + * Instantiate an {@code ASN1IllegalDefinition}. + */ + public ASN1IllegalDefinition() { + } + + /** + * Instantiate an {@code ASN1IllegalDefinition} with specified error message. + * + * @param message + * The error message. + */ + public ASN1IllegalDefinition(String message) { + super(message); + } + } diff --git a/jp/bitmeister/asn1/exception/ASN1InvalidDataValue.java b/jp/bitmeister/asn1/exception/ASN1InvalidDataValue.java index b0a5805..856afc3 100644 --- a/jp/bitmeister/asn1/exception/ASN1InvalidDataValue.java +++ b/jp/bitmeister/asn1/exception/ASN1InvalidDataValue.java @@ -22,4 +22,21 @@ package jp.bitmeister.asn1.exception; */ @SuppressWarnings("serial") public class ASN1InvalidDataValue extends ASN1RuntimeException { + + /** + * Instantiate an {@code ASN1InvalidDataValue}. + */ + public ASN1InvalidDataValue() { + } + + /** + * Instantiate an {@code ASN1InvalidDataValue} with specified error message. + * + * @param message + * The error message. + */ + public ASN1InvalidDataValue(String message) { + super(message); + } + } diff --git a/jp/bitmeister/asn1/exception/ASN1RuntimeException.java b/jp/bitmeister/asn1/exception/ASN1RuntimeException.java index bda784b..6cb4f65 100644 --- a/jp/bitmeister/asn1/exception/ASN1RuntimeException.java +++ b/jp/bitmeister/asn1/exception/ASN1RuntimeException.java @@ -27,7 +27,23 @@ import jp.bitmeister.asn1.type.ASN1Type; public class ASN1RuntimeException extends RuntimeException { private DetailedMessage message; - + + /** + * Instantiate an {@code ASN1RuntimeException}. + */ + public ASN1RuntimeException() { + } + + /** + * Instantiate an {@code ASN1RuntimeException} with specified error message. + * + * @param message + * The error message. + */ + public ASN1RuntimeException(String message) { + super(message); + } + /** * Set detailed message of this exception. * diff --git a/jp/bitmeister/asn1/processor/ASN1StringBuilder.java b/jp/bitmeister/asn1/processor/ASN1StringBuilder.java index 74b0761..6b3273e 100644 --- a/jp/bitmeister/asn1/processor/ASN1StringBuilder.java +++ b/jp/bitmeister/asn1/processor/ASN1StringBuilder.java @@ -24,6 +24,7 @@ import jp.bitmeister.asn1.type.ASN1TagClass; import jp.bitmeister.asn1.type.ASN1TagMode; import jp.bitmeister.asn1.type.ASN1TagValue; import jp.bitmeister.asn1.type.ASN1Type; +import jp.bitmeister.asn1.type.AbstractInteger; import jp.bitmeister.asn1.type.CollectionType; import jp.bitmeister.asn1.type.ConstructiveType; import jp.bitmeister.asn1.type.ElementSpecification; @@ -35,6 +36,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -195,20 +198,40 @@ public class ASN1StringBuilder implements builder.append(data.value() ? "TRUE" : "FALSE"); return null; } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1 + * .type.builtin.INTEGER) + */ + public Void visit(INTEGER data) throws ASN1RuntimeException { + writeInteger((AbstractInteger) data); + return null; + } /* * (non-Javadoc) * * @see * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type - * .builtin.INTEGER) + * .builtin.BigINTEGER) */ - public Void visit(INTEGER data) { - String numberId = data.identifier(); - if (numberId != null) { - builder.append(numberId); - } - builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE); + public Void visit(BigINTEGER data) { + writeInteger((AbstractInteger)data); + return null; + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1 + * .type.builtin.ENUMERATED) + */ + public Void visit(ENUMERATED data) { + writeInteger((AbstractInteger) data); return null; } @@ -217,10 +240,10 @@ public class ASN1StringBuilder implements * * @see * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type - * .builtin.ENUMERATED) + * .builtin.BigENUMERATED) */ - public Void visit(ENUMERATED data) { - visit((INTEGER) data); + public Void visit(BigENUMERATED data) { + writeInteger((AbstractInteger)data); return null; } @@ -450,6 +473,18 @@ public class ASN1StringBuilder implements } /** + * Writes value and identifier of an ASN.1 'INTEGER' or 'ENUMERATED' value. + * @param data The integer data. + */ + private void writeInteger(AbstractInteger data) { + String numberId = data.identifier(); + if (numberId != null) { + builder.append(numberId); + } + builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE); + } + + /** * Writes descriptions of each element of {@code ConstructiveType}. * * @param data diff --git a/jp/bitmeister/asn1/processor/ASN1Visitor.java b/jp/bitmeister/asn1/processor/ASN1Visitor.java index b392d80..e1dec77 100644 --- a/jp/bitmeister/asn1/processor/ASN1Visitor.java +++ b/jp/bitmeister/asn1/processor/ASN1Visitor.java @@ -22,6 +22,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -49,7 +51,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(BOOLEAN data) throws E; @@ -60,9 +62,20 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(INTEGER data) throws E; + + /** + * Visits the {@code BigINTEGER} data. + * + * @param data + * The data to be visited. + * @return Result. + * @throws E + * When an error occurred in the {@code accept} method. + */ + public R visit(BigINTEGER data) throws E; /** * Visits the {@code BIT_STRING} data. @@ -71,7 +84,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(BIT_STRING data) throws E; @@ -82,7 +95,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(OCTET_STRING data) throws E; @@ -93,7 +106,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(NULL data) throws E; @@ -104,7 +117,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(OBJECT_IDENTIFIER data) throws E; @@ -115,7 +128,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(REAL data) throws E; @@ -126,18 +139,29 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(ENUMERATED data) throws E; /** + * Visits the {@code BigENUMERATED} data. + * + * @param data + * The data to be visited. + * @return Result. + * @throws E + * When an error occurred in the {@code accept} method. + */ + public R visit(BigENUMERATED data) throws E; + + /** * Visits the {@code RELATIVE_OID} data. * * @param data * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(RELATIVE_OID data) throws E; @@ -148,7 +172,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(ANY data) throws E; @@ -159,7 +183,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(CHOICE data) throws E; @@ -170,7 +194,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(SEQUENCE_OF data) throws E; @@ -181,7 +205,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(SEQUENCE data) throws E; @@ -192,7 +216,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(SET_OF data) throws E; @@ -203,7 +227,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(SET data) throws E; @@ -214,7 +238,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(StringType data) throws E; @@ -225,7 +249,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(TimeType data) throws E; @@ -236,7 +260,7 @@ public interface ASN1Visitor { * The data to be visited. * @return Result. * @throws E - * When an error occured in the {@code accept} method. + * When an error occurred in the {@code accept} method. */ public R visit(UnknownType data) throws E; diff --git a/jp/bitmeister/asn1/processor/ASN1VisitorAdaptor.java b/jp/bitmeister/asn1/processor/ASN1VisitorAdaptor.java index 06e3612..041b2a9 100644 --- a/jp/bitmeister/asn1/processor/ASN1VisitorAdaptor.java +++ b/jp/bitmeister/asn1/processor/ASN1VisitorAdaptor.java @@ -22,6 +22,8 @@ import jp.bitmeister.asn1.type.UnknownType; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.CHOICE; import jp.bitmeister.asn1.type.builtin.ENUMERATED; import jp.bitmeister.asn1.type.builtin.INTEGER; @@ -60,7 +62,7 @@ public class ASN1VisitorAdaptor implements ASN1Visitor implements ASN1Visitor implements ASN1Visitor implements ASN1Visitor type, String fieldName) { if (tagMode == ASN1TagMode.DEFAULT) { - if (tagDefault == ASN1TagDefault.IMPLICIT_TAGS) { + if (tagDefault == ASN1TagDefault.IMPLICIT_TAGS + || (tagDefault == ASN1TagDefault.AUTOMATIC_TAGS && canImplicitTagging(type))) { this.tagMode = ASN1TagMode.IMPLICIT; } else { this.tagMode = ASN1TagMode.EXPLICIT; diff --git a/jp/bitmeister/asn1/type/AbstractInteger.java b/jp/bitmeister/asn1/type/AbstractInteger.java new file mode 100644 index 0000000..6c79a87 --- /dev/null +++ b/jp/bitmeister/asn1/type/AbstractInteger.java @@ -0,0 +1,156 @@ +/* + * 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; + +import java.util.Map; +import java.util.Map.Entry; + +import jp.bitmeister.asn1.annotation.ASN1Enumeration; +import jp.bitmeister.asn1.exception.ASN1IllegalArgument; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; +import jp.bitmeister.asn1.type.builtin.INTEGER; + +/** + * The base class for ASN.1 'INTEGER' types. + * + *

+ * This class provides generic interfaces and common methods for classes that + * represents ASN.1 'INTEGER' type. + *

+ *

+ * A sub-class of {@code AbstractInteger} can contain one or more fields + * annotated as {@code @ASN1Enumeration}. If a sub-class of + * {@code AbstractInteger} contains {@code @ASN1Enumeration} fields, the value + * of the data must be same as one of the {@code @ASN1Enumeration} fields. + *

+ * + * @author WATANABE, Jun. + * + * @see ASN1Enumeration + * @see INTEGER + * @see BigINTEGER + */ +public abstract class AbstractInteger> extends + PrimitiveType implements ValueComparable> { + + /** + * 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 e : getNamedNumberMap().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; + } + + /* + * (non-Javadoc) + * + * @see jp.bitmeister.asn1.type.PrimitiveType#set(null) + */ + @Override + public void set(T value) { + if (isEnum()) { + Map map = getNamedNumberMap(); + if (!map.isEmpty() && !map.containsKey(value)) { + ASN1IllegalArgument ex = new ASN1IllegalArgument(); + ex.setMessage( + "Invalid value '" + + value + + "'. Value of a class that represents ASN.1 'ENUMERATED' must be same as one of enumerations.", + null, getClass(), null, null); + throw ex; + } + } + super.set(value); + } + + /** + * Returns an identifier related to the value of this data if the type has + * {@code @ASN1Enumeration} fields. + * + * @return An identifier related to the value. + */ + public String identifier() { + return getNamedNumberMap().get(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 abstract boolean isLongValue(); + + /** + * 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 abstract boolean isIntValue(); + + /** + * 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(); + } + + /* (non-Javadoc) + * @see jp.bitmeister.asn1.type.ValueComparable#compareTo(jp.bitmeister.asn1.type.ASN1Type) + */ + public int compareTo(AbstractInteger other) { + return value().compareTo(other.value()); + } + + /** + * Returns map of enumerations related to this type. + * + * @return The map of enumerations. + */ + protected abstract Map getNamedNumberMap(); + + /** + * Tests if base type of this data is ASN.1 'ENUMERATED'. + * + * @return {@code true} if base type of this data is ASN.1 'ENUMERATED'. + */ + protected abstract boolean isEnum(); + +} diff --git a/jp/bitmeister/asn1/type/BuiltInModule.java b/jp/bitmeister/asn1/type/BuiltInModule.java index dfdebfd..7631b8e 100644 --- a/jp/bitmeister/asn1/type/BuiltInModule.java +++ b/jp/bitmeister/asn1/type/BuiltInModule.java @@ -23,8 +23,8 @@ import jp.bitmeister.asn1.annotation.ASN1Tag; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.BOOLEAN; -import jp.bitmeister.asn1.type.builtin.ENUMERATED; -import jp.bitmeister.asn1.type.builtin.INTEGER; +import jp.bitmeister.asn1.type.builtin.BigENUMERATED; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.NULL; import jp.bitmeister.asn1.type.builtin.OBJECT_IDENTIFIER; import jp.bitmeister.asn1.type.builtin.OCTET_STRING; @@ -63,7 +63,7 @@ import jp.bitmeister.asn1.type.useful.VisibleString; @ASN1ModuleTags(ASN1TagDefault.AUTOMATIC_TAGS) @ASN1DefinedTypes({ BOOLEAN.class, // UNIVERSAL 1 - INTEGER.class, // UNIVERSAL 2 + BigINTEGER.class, // UNIVERSAL 2 BIT_STRING.class, // UNIVERSAL 3 OCTET_STRING.class, // UNIVERSAL 4 NULL.class, // UNIVERSAL 5 @@ -106,13 +106,13 @@ class BuiltInModule extends ASN1Module { * * @author WATANABE, Jun. * - * @see ENUMERATED - * @see INTEGER + * @see BigENUMERATED + * @see BigINTEGER */ @ASN1BuiltIn @ASN1Identifier("ENUMERATED(unknown)") @ASN1Tag(value = 10, tagClass = ASN1TagClass.UNIVERSAL, tagMode = ASN1TagMode.IMPLICIT) - public static class UnknownEnumerated extends INTEGER { + public static class UnknownEnumerated extends BigINTEGER { } /** diff --git a/jp/bitmeister/asn1/type/NamedNumberMap.java b/jp/bitmeister/asn1/type/NamedNumberMap.java new file mode 100644 index 0000000..f11b613 --- /dev/null +++ b/jp/bitmeister/asn1/type/NamedNumberMap.java @@ -0,0 +1,132 @@ +/* + * 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; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import jp.bitmeister.asn1.annotation.ASN1BuiltIn; +import jp.bitmeister.asn1.annotation.ASN1Enumeration; +import jp.bitmeister.asn1.annotation.ASN1Identifier; +import jp.bitmeister.asn1.exception.ASN1IllegalDefinition; +import jp.bitmeister.asn1.exception.ASN1RuntimeException; + +/** + * Contains values and identifiers of enumerations related to ASN.1 'INTEGER' and 'ENUMERATED' types. + * + * @author WATANABE, Jun. + * + * @see AbstractInteger + */ +public abstract class NamedNumberMap> { + + /** + * Map of maps of enumerations that related to key types. + */ + private Map>, Map> namedNumberMaps = new HashMap>, Map>(); + + /** + * Put an empty enumeration map to {@code namedNumberMaps}. + * + * @param type The key type. + */ + public void putEmptyMap(Class> type) { + namedNumberMaps.put(type, new HashMap()); + } + + /** + * Returns the map of enumerations related to the type. The {@code Map} maps + * value to identifier string. + * + * @param type + * the Type. + * @return The map of enumerations. + */ + public Map getNamedNumberMap(Class> type) { + Map map = namedNumberMaps.get(type); + if (map != null) { + return map; + } + map = new HashMap(); + 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; + } + T value = null; + try { + value = getKeyValue(f); + } + catch (ASN1RuntimeException ex) { + ex.setMessage(ex.getMessage(), ex.getCause(), 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); + throw ex; + } + map.put(value, fieldId); + } + @SuppressWarnings("unchecked") + Class> parent = (Class>)type.getSuperclass(); + if (parent.isAnnotationPresent(ASN1BuiltIn.class)) { + if (!type.getSuperclass().equals(AbstractInteger.class) && 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 (!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); + } + namedNumberMaps.put(type, map); + return map; + } + + /** + * Returns key value that defined by the enumeration field. + * + * @param f + * The enumeration field. + * @return The key value. + */ + public abstract T getKeyValue(Field f); + +} diff --git a/jp/bitmeister/asn1/type/ValueComparable.java b/jp/bitmeister/asn1/type/ValueComparable.java index 42c4e1f..ce73c71 100644 --- a/jp/bitmeister/asn1/type/ValueComparable.java +++ b/jp/bitmeister/asn1/type/ValueComparable.java @@ -15,6 +15,7 @@ */ package jp.bitmeister.asn1.type; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.INTEGER; import jp.bitmeister.asn1.type.builtin.REAL; @@ -22,17 +23,18 @@ import jp.bitmeister.asn1.type.builtin.REAL; * The interface for classes whose instance can be compared to other instance. * *

- * {@code INTEGER} and {@code REAL} implements this interface and their value - * shall be ordered by the natural ordering. {@code compareTo} method is used - * for compare the value to the other value. + * {@code INTEGER}, {@code BigINTEGER} and {@code REAL} implements this + * interface and their value shall be ordered by the natural ordering. + * {@code compareTo} method is used for compare the value to the other value. *

* * @author WATANABE, Jun. * * @see INTEGER + * @see BigINTEGER * @see REAL */ -public interface ValueComparable { +public interface ValueComparable { /** * Compares the value of this instance to the value of the other instance. @@ -42,6 +44,6 @@ public interface ValueComparable { * @return A negative integer, zero, or a positive integer as this value is * less than, equal to, or greater than the other value. */ - public int compareTo(ASN1Type other); + public int compareTo(T other); } diff --git a/jp/bitmeister/asn1/type/builtin/BigENUMERATED.java b/jp/bitmeister/asn1/type/builtin/BigENUMERATED.java new file mode 100644 index 0000000..805e202 --- /dev/null +++ b/jp/bitmeister/asn1/type/builtin/BigENUMERATED.java @@ -0,0 +1,98 @@ +/* + * 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.math.BigInteger; + +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.processor.ASN1Visitor; +import jp.bitmeister.asn1.type.ASN1TagClass; +import jp.bitmeister.asn1.type.ASN1TagMode; + +/** + * An implementation of ASN.1 'ENUMERATED' type that can contain + * arbitrary-precision integer value. + * + *

+ * This is the base class used for defining 'ENUMERATED' types which need to + * contain an arbitrary-precision value. A sub-class of {@code BigENUMERATED} + * must contain one or more fields annotated as {@code @ASN1Enumeration}. + *

+ * + * @author WATANABE, Jun. + * + * @see ASN1Enumeration + * @see ENUMERATED + */ +@ASN1BuiltIn +@ASN1Identifier("ENUMERATED") +@ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 10, tagMode = ASN1TagMode.IMPLICIT) +public abstract class BigENUMERATED extends BigINTEGER { + + /** + * Instantiates an empty {@code BigENUMERATED}. + */ + public BigENUMERATED() { + } + + /** + * Instantiates an {@code BigENUMERATED} and initialize it with the + * {@code BigInteger} value. + * + * @param value + * The value to be assigned. + */ + public BigENUMERATED(BigInteger value) { + super(value); + } + + /** + * Instantiates an {@code BigENUMERATED} and initialize it with the {@code long} + * value. + * + * @param value + * The value to be assigned. + */ + public BigENUMERATED(long value) { + super(value); + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.type.builtin.INTEGER#accept(jp.bitmeister.asn1.processor + * .ASN1Visitor) + */ + @Override + public R accept(ASN1Visitor visitor) throws E { + return visitor.visit(this); + } + + /* + * (non-Javadoc) + * + * @see jp.bitmeister.asn1.type.AbstractInteger#isEnum() + */ + @Override + protected boolean isEnum() { + return true; + } + +} diff --git a/jp/bitmeister/asn1/type/builtin/BigINTEGER.java b/jp/bitmeister/asn1/type/builtin/BigINTEGER.java new file mode 100644 index 0000000..31c5eaa --- /dev/null +++ b/jp/bitmeister/asn1/type/builtin/BigINTEGER.java @@ -0,0 +1,185 @@ +/* + * 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. + * + *

+ * 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. + *

+ * + * @author WATANABE, Jun. + * + * @see INTEGER + */ +@ASN1BuiltIn +@ASN1Identifier("INTEGER") +@ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 2, tagMode = ASN1TagMode.IMPLICIT) +public class BigINTEGER extends AbstractInteger { + + /** + * Contains the maps of enumerations for all of the sub-types of {@code BigINTEGER} + * and {@code BigENUMERATED}. + */ + private static final NamedNumberMap NAMED_NUMBER_MAPS = new NamedNumberMap() { + + /* (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 getNamedNumberMap() { + return NAMED_NUMBER_MAPS.getNamedNumberMap(getClass()); + } + + /* + * (non-Javadoc) + * + * @see + * jp.bitmeister.asn1.type.ASN1Type#accept(jp.bitmeister.asn1.processor. + * ASN1Visitor) + */ + @Override + public R accept(ASN1Visitor visitor) throws E { + return visitor.visit(this); + } + + /* + * (non-Javadoc) + * + * @see jp.bitmeister.asn1.type.AbstractInteger#isEnum() + */ + @Override + protected boolean isEnum() { + return false; + } + +} diff --git a/jp/bitmeister/asn1/type/builtin/CHOICE.java b/jp/bitmeister/asn1/type/builtin/CHOICE.java index ff539fd..097560a 100644 --- a/jp/bitmeister/asn1/type/builtin/CHOICE.java +++ b/jp/bitmeister/asn1/type/builtin/CHOICE.java @@ -49,8 +49,7 @@ public abstract class CHOICE extends SelectiveType { /** * Instantiates a {@code CHOICE} and initialize it with the parameter. The - * ASN.1 tag that assigned to the type of the data is used for select an - * alternative. + * ASN.1 type of the data is used for select an alternative. * * @param data * The data to be assigned. diff --git a/jp/bitmeister/asn1/type/builtin/ENUMERATED.java b/jp/bitmeister/asn1/type/builtin/ENUMERATED.java index abdb094..486d922 100644 --- a/jp/bitmeister/asn1/type/builtin/ENUMERATED.java +++ b/jp/bitmeister/asn1/type/builtin/ENUMERATED.java @@ -15,8 +15,6 @@ */ package jp.bitmeister.asn1.type.builtin; -import java.math.BigInteger; - import jp.bitmeister.asn1.annotation.ASN1BuiltIn; import jp.bitmeister.asn1.annotation.ASN1Enumeration; import jp.bitmeister.asn1.annotation.ASN1Tag; @@ -25,17 +23,21 @@ import jp.bitmeister.asn1.type.ASN1TagClass; import jp.bitmeister.asn1.type.ASN1TagMode; /** - * Represents ASN.1 'ENUMERATED' type. + * An implementation of ASN.1 'ENUMERATED' type that contains {@code Long} + * value. * *

- * This is the base class used for defining 'ENUMERATED' types. A sub-class of - * {@code ENUMERATED} must contain one or more fields annotated as - * {@code @ASN1Enumeration}. + * This is the base class used for defining 'ENUMERATED' types, and has a + * {@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 BigENUMERATED} type shall be used. A sub-class of {@code ENUMERATED} + * must contain one or more fields annotated as {@code @ASN1Enumeration}. *

* * @author WATANABE, Jun. * * @see ASN1Enumeration + * @see BigENUMERATED */ @ASN1BuiltIn @ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 10, tagMode = ASN1TagMode.IMPLICIT) @@ -48,17 +50,6 @@ public abstract class ENUMERATED extends INTEGER { } /** - * Instantiates an {@code ENUMERATED} and initialize it with the - * {@code BigInteger} value. - * - * @param value - * The value to be assigned. - */ - public ENUMERATED(BigInteger value) { - super(value); - } - - /** * Instantiates an {@code ENUMERATED} and initialize it with the {@code long} * value. * @@ -81,4 +72,14 @@ public abstract class ENUMERATED extends INTEGER { return visitor.visit(this); } + /* + * (non-Javadoc) + * + * @see jp.bitmeister.asn1.type.AbstractInteger#isEnum() + */ + @Override + protected boolean isEnum() { + return true; + } + } diff --git a/jp/bitmeister/asn1/type/builtin/INTEGER.java b/jp/bitmeister/asn1/type/builtin/INTEGER.java index e991ffe..def4b97 100644 --- a/jp/bitmeister/asn1/type/builtin/INTEGER.java +++ b/jp/bitmeister/asn1/type/builtin/INTEGER.java @@ -1,159 +1,65 @@ -/* - * 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.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. * *

* An instance of this class represents an 'INTEGER' type data, and has a - * {@link java.math.BigInteger} value. - *

- *

- * 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. *

* * @author WATANABE, Jun. * - * @see ASN1Enumeration + * @see BigINTEGER */ @ASN1BuiltIn @ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 2, tagMode = ASN1TagMode.IMPLICIT) -public class INTEGER extends PrimitiveType implements - ValueComparable { +public class INTEGER extends AbstractInteger { /** - * 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, Map> NAMED_NUMBER_MAPS = new HashMap, Map>(); - - static { - NAMED_NUMBER_MAPS.put(INTEGER.class, new HashMap()); - } + private static final NamedNumberMap NAMED_NUMBER_MAPS = new NamedNumberMap() { - /** - * 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 getNamedNumberMap( - Class type) { - if (NAMED_NUMBER_MAPS.containsKey(type)) { - return NAMED_NUMBER_MAPS.get(type); - } - Map map = new HashMap(); - 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); - throw ex; - } - map.put(value, fieldId); - } - Class parent = type.getSuperclass().asSubclass(INTEGER.class); - 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); + ASN1IllegalDefinition ex = new ASN1IllegalDefinition( + "An enumeration of INTEGER type must be an 'int' or a 'long' field."); 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); + return value; } - NAMED_NUMBER_MAPS.put(type, map); - return map; + + }; + + static { + NAMED_NUMBER_MAPS.putEmptyMap(INTEGER.class); } /** @@ -163,17 +69,6 @@ public class INTEGER extends PrimitiveType implements } /** - * 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. * @@ -184,125 +79,47 @@ public class INTEGER extends PrimitiveType implements 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 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); - } - - /** - * 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 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; + public Map getNamedNumberMap() { + return NAMED_NUMBER_MAPS.getNamedNumberMap(getClass()); } - /** - * 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 accept(ASN1Visitor 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; + return true; } - /** - * 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}. + /* (non-Javadoc) + * @see jp.bitmeister.asn1.type.AbstractInteger#isIntValue() */ + @Override 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(); - } - - /* - * (non-Javadoc) - * - * @see - * jp.bitmeister.asn1.type.ValueComparable#compareTo(jp.bitmeister.asn1. - * type.ASN1Type) - */ - public int compareTo(ASN1Type other) { - return value().compareTo(((INTEGER) other).value()); + 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 accept(ASN1Visitor visitor) throws E { - return visitor.visit(this); + protected boolean isEnum() { + return false; } } diff --git a/jp/bitmeister/asn1/type/builtin/REAL.java b/jp/bitmeister/asn1/type/builtin/REAL.java index 915fe46..1fa3b35 100644 --- a/jp/bitmeister/asn1/type/builtin/REAL.java +++ b/jp/bitmeister/asn1/type/builtin/REAL.java @@ -21,7 +21,6 @@ import jp.bitmeister.asn1.exception.ASN1IllegalArgument; 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; @@ -39,7 +38,7 @@ import jp.bitmeister.asn1.type.ValueComparable; */ @ASN1BuiltIn @ASN1Tag(tagClass = ASN1TagClass.UNIVERSAL, value = 9, tagMode = ASN1TagMode.IMPLICIT) -public class REAL extends PrimitiveType implements ValueComparable { +public class REAL extends PrimitiveType implements ValueComparable { private boolean isBinary = false; @@ -165,8 +164,8 @@ public class REAL extends PrimitiveType implements ValueComparable { * jp.bitmeister.asn1.type.ValueComparable#compareTo(jp.bitmeister.asn1. * type.ASN1Type) */ - public int compareTo(ASN1Type other) { - return value().compareTo(((REAL) other).value()); + public int compareTo(REAL other) { + return value().compareTo(other.value()); } /* diff --git a/jp/bitmeister/asn1/type/useful/EMBEDDED_PDV.java b/jp/bitmeister/asn1/type/useful/EMBEDDED_PDV.java index cc1ea4b..47e0f1d 100644 --- a/jp/bitmeister/asn1/type/useful/EMBEDDED_PDV.java +++ b/jp/bitmeister/asn1/type/useful/EMBEDDED_PDV.java @@ -26,7 +26,7 @@ import jp.bitmeister.asn1.type.ASN1TagClass; import jp.bitmeister.asn1.type.ASN1TagMode; import jp.bitmeister.asn1.type.ASN1Type; import jp.bitmeister.asn1.type.builtin.CHOICE; -import jp.bitmeister.asn1.type.builtin.INTEGER; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.NULL; import jp.bitmeister.asn1.type.builtin.OBJECT_IDENTIFIER; import jp.bitmeister.asn1.type.builtin.OCTET_STRING; @@ -126,7 +126,7 @@ public class EMBEDDED_PDV extends SEQUENCE { */ @ASN1Element(0) @ASN1Identifier("presentation-context-id") - public INTEGER presentation_context_id; + public BigINTEGER presentation_context_id; /** * 'transfer-syntax' field. @@ -150,7 +150,7 @@ public class EMBEDDED_PDV extends SEQUENCE { * @param transfer_syntax * 'transfer-syntax' field. */ - public ContextNegotiation(INTEGER presentation_context_id, + public ContextNegotiation(BigINTEGER presentation_context_id, OBJECT_IDENTIFIER transfer_syntax) { this.presentation_context_id = presentation_context_id; this.transfer_syntax = transfer_syntax; @@ -183,7 +183,7 @@ public class EMBEDDED_PDV extends SEQUENCE { */ @ASN1Alternative(2) @ASN1Identifier("presentation-context-id") - public INTEGER presentation_context_id; + public BigINTEGER presentation_context_id; /** * 'context-negotiation' field. diff --git a/jp/bitmeister/asn1/type/useful/EXTERNAL.java b/jp/bitmeister/asn1/type/useful/EXTERNAL.java index 9bc9b66..c80b488 100644 --- a/jp/bitmeister/asn1/type/useful/EXTERNAL.java +++ b/jp/bitmeister/asn1/type/useful/EXTERNAL.java @@ -27,7 +27,7 @@ import jp.bitmeister.asn1.type.ASN1Type; import jp.bitmeister.asn1.type.builtin.ANY; import jp.bitmeister.asn1.type.builtin.BIT_STRING; import jp.bitmeister.asn1.type.builtin.CHOICE; -import jp.bitmeister.asn1.type.builtin.INTEGER; +import jp.bitmeister.asn1.type.builtin.BigINTEGER; import jp.bitmeister.asn1.type.builtin.OBJECT_IDENTIFIER; import jp.bitmeister.asn1.type.builtin.OCTET_STRING; import jp.bitmeister.asn1.type.builtin.SEQUENCE; @@ -71,7 +71,7 @@ public class EXTERNAL extends SEQUENCE { */ @ASN1Element(value = 1, optional = true) @ASN1Identifier("indirect-reference") - public INTEGER indirect_reference; + public BigINTEGER indirect_reference; /** * 'data-value-descriptor' field. @@ -134,7 +134,7 @@ public class EXTERNAL extends SEQUENCE { } public EXTERNAL(OBJECT_IDENTIFIER direct_reference, - INTEGER indirect_reference, ObjectDescriptor data_value_descriptor, + BigINTEGER indirect_reference, ObjectDescriptor data_value_descriptor, Encoding encoding) { this.direct_reference = direct_reference; this.indirect_reference = indirect_reference;