package net.gcdc.asn1.uper; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import net.gcdc.asn1.datatypes.FixedSize; import net.gcdc.asn1.datatypes.SizeRange; import net.gcdc.asn1.uper.SimpleTypeResolver.Unknown; class SeqOfCoder implements Decoder, Encoder { @Override public boolean canEncode(T obj, Annotation[] extraAnnotations) { return obj instanceof List; } @Override public void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) throws Asn1EncodingException { Class type = obj.getClass(); UperEncoder.logger.debug(String.format("SEQUENCE OF %s",obj.getClass().getName())); AnnotationStore annotations = new AnnotationStore(type.getAnnotations(), extraAnnotations); List list = (List) obj; final FixedSize fixedSize = annotations.getAnnotation(FixedSize.class); //CG pass annotations too each field encoding Annotation[] annotationArray = new Annotation[] {}; if (annotations != null & annotations.getAnnotations() != null && !annotations.getAnnotations().isEmpty()) { ArrayList fieldAnnotations = new ArrayList(); fieldAnnotations.addAll(annotations.getAnnotations()); annotationArray = new Annotation[fieldAnnotations.size()]; for (int i = 0; i< fieldAnnotations.size();i++){ annotationArray[i] = fieldAnnotations.get(i); } } SizeRange sizeRange = annotations.getAnnotation(SizeRange.class); if (fixedSize != null) sizeRange = new SizeRange() { @Override public Class annotationType() { return SizeRange.class; } @Override public int minValue() { return fixedSize.value(); } @Override public int maxValue() { return fixedSize.value(); } @Override public boolean hasExtensionMarker() { return false; } }; if (sizeRange == null) { int position1 = bitbuffer.position(); try { UperEncoder.encodeLengthDeterminant(bitbuffer, list.size()); } catch (Asn1EncodingException e) { throw new Asn1EncodingException(" number of elements ", e); } UperEncoder.logger.debug(String.format("unbound size %d, encoded as %s", list.size(), bitbuffer.toBooleanStringFromPosition(position1))); UperEncoder.logger.debug(String.format(" all elems of Seq Of: %s", list )); for (Object elem : list) { try { UperEncoder.encode2(bitbuffer, elem, annotationArray); } catch (Asn1EncodingException e) { throw new Asn1EncodingException(" element " + elem.toString(), e); } } return; } boolean outsideOfRange = list.size() < sizeRange.minValue() || sizeRange.maxValue() < list.size(); if (outsideOfRange && !sizeRange.hasExtensionMarker()) { throw new IllegalArgumentException( "Out-of-range size for " + obj.getClass() + ", expected " + sizeRange.minValue() + ".." + sizeRange.maxValue() + ", got " + list.size()); } if (sizeRange.hasExtensionMarker()) { bitbuffer.put(outsideOfRange); UperEncoder.logger.debug(String.format("With Extension Marker, %s of range (%d <= %d <= %d)", (outsideOfRange ? "outside" : "inside"), sizeRange.minValue(), list.size(), sizeRange.maxValue())); if (outsideOfRange) { throw new UnsupportedOperationException( "Sequence-of size range extensions are not implemented yet, range " + sizeRange.minValue() + ".." + sizeRange.maxValue() + ", requested size " + list.size()); } } UperEncoder.logger.debug(String.format("seq-of of constrained size %d, encoding size...", list.size())); UperEncoder.encodeConstrainedInt(bitbuffer, list.size(), sizeRange.minValue(), sizeRange.maxValue()); UperEncoder.logger.debug(String.format(" all elems of Seq Of: %s", list)); for (Object elem : list) { UperEncoder.encode2(bitbuffer, elem, new Annotation[] {}); } } @Override public boolean canDecode(Class classOfT, Annotation[] extraAnnotations) { return List.class.isAssignableFrom(classOfT); } @SuppressWarnings("unchecked") @Override public T decode(BitBuffer bitbuffer, Class classOfT,Field field, Annotation[] extraAnnotations) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); UperEncoder.logger.debug(String.format("SEQUENCE OF for %s", classOfT)); FixedSize fixedSize = annotations.getAnnotation(FixedSize.class); SizeRange sizeRange = annotations.getAnnotation(SizeRange.class); //CG pass annotations from the sequence to each element encoding Annotation[] annotationArray = new Annotation[] {}; if (annotations != null && annotations.getAnnotations() != null && !annotations.getAnnotations().isEmpty()){ annotationArray = new Annotation[annotations.getAnnotations().size()]; Iterator it = annotations.getAnnotations().iterator(); int i = 0; while (it.hasNext()) { annotationArray[i] = it.next(); i++; } } long size = (fixedSize != null) ? fixedSize.value() : (sizeRange != null) ? UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.intRangeFromSizeRange(sizeRange)) : UperEncoder.decodeLengthDeterminant(bitbuffer); Collection coll = new ArrayList((int) size); Class classOfElements; Class[] typeArgs = SimpleTypeResolver.resolveRawArguments(List.class, classOfT); classOfElements = typeArgs[0]; if (classOfElements == null || classOfElements == Unknown.class) { try { ParameterizedType elementType = (ParameterizedType) field.getGenericType(); classOfElements = (Class) elementType.getActualTypeArguments()[0]; } catch (SecurityException e) { throw new IllegalArgumentException("Can't resolve type of elements for " + classOfT.getName()); } } for (int i = 0; i < size; i++) { coll.add(UperEncoder.decodeAny(bitbuffer, classOfElements,field, annotationArray)); } T result = null; try { result = UperEncoder.instantiate(classOfT, coll); } catch (Exception e) { result = (T) coll; } return result; } @Override public T getDefault(Class classOfT, Annotation[] extraAnnotations) { throw new IllegalArgumentException("Default Sequence not yet implemented"); } }