www.pudn.com > cryptix-asn1-0.1.11.zip > Set.java
/* $Id: Set.java,v 1.6 2001/05/30 18:15:42 raif Exp $ * * Copyright (C) 1997-2001 The Cryptix Foundation Limited. All rights reserved. * * Use, modification, copying and distribution of this software is subject to * the terms and conditions of the Cryptix General Licence. You should have * received a copy of the Cryptix General Licence along with this library; if * not, you can download a copy from http://www.cryptix.org/ */ package cryptix.asn1.lang; import cryptix.asn1.io.ASNReader; import cryptix.asn1.io.ASNWriter; import cryptix.asn1.io.ElementNotFoundException; import cryptix.asn1.io.EncodingException; import org.apache.log4j.Category; import java.io.EOFException; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; /** * The basic implementation of the ASN.1 SET type.* * The value of such type is a (shallow) copy of the components of the SETE. It * is returned as a java.util.ArrayList, and is supposed to hold the * concrete values of the constituants of the SET. Access to those constituants * is provided by an implementation of the cryptix.asn1.lang.IIterativeType * interface --which should return a java.util.Iterator instance.
* * @version $Revision: 1.6 $ * @author Raif S. Naffah */ public abstract class Set extends CompoundType { // Constants and vars // ....................................................................... static Category cat = Category.getInstance(Set.class.getName()); // Constructor(s) // ....................................................................... public Set(Tag tag) { super("", tag); } public Set(String name, Tag tag) { super(name, tag); } /** * Constructs a new instance of a SET type, given a designated Tag and a * designated initial value. * * @param name the name of this instance. * @param tag the designated Tag value. * @param value the designated initial value. * @exception ClassCastException if the designated value is not an ArrayList. */ public Set(String name, Tag tag, Object value) { super(name, tag); if (value != null) if (value instanceof ArrayList) value(value); else throw new ClassCastException(); } // Redefinition of methods in superclass Type // ....................................................................... /** * Decodes a SET from an input stream. * * @param is the ASN.1 stream to read from. * @exception IOException if an exception occurs during the operation. */ public void decode(ASNReader is) throws IOException { String cn = this.getClass().getName(); cat.debug("==> "+cn+".decode()"); this.reset(); is.mark(Integer.MAX_VALUE); ASNReader local = is.decodeStructure(this); if (local == null) { cat.warn(cn+" not found. Backtracking..."); is.reset(); throw new ElementNotFoundException(cn); } Iterator it; IType t; int found; loop: while (true) { for (it = this.iterator(), found = 0; it.hasNext(); ) { t = (Type) it.next(); if (t.isBlank()) { try { local.mark(Integer.MAX_VALUE); cat.info("Looking for "+t.getClass().getName()); t.decode(local); cat.info("Found "+t.getClass().getName()); found++; } catch (EOFException x) { cat.info("Exhausted the input stream. Breaking..."); break loop; } catch (ElementNotFoundException x) { cat.warn(String.valueOf(x)+". Backtracking..."); if (!t.isOptional()) local.reset(); } } } if (found == 0) break loop; } it = this.iterator(); while (it.hasNext()) { t = (Type) it.next(); if (t.isBlank() && !t.isOptional()) { // throw new ASNException("After completely parsing "+cn // +" (SET), a non optional type ("+t.getClass().getName() // +") was found missing"); cat.error("After completely parsing "+cn +" (SET), a non optional type ("+t.getClass().getName() +") was found missing"); throw new ElementNotFoundException(cn); } } cat.debug("<== "+cn+".decode()"); } /** * Resets the current value of this instance to its initial state. */ public void reset() { for (Iterator it = this.iterator(); it.hasNext(); ) ((IType) it.next()).reset(); } /** * Returns the current value of this instance. For a SET, this is * effectively a deep copy of the components' contents. * * @return the current value of this instance. */ public Object value() { return cloneComponents(); } /** * Sets the current value of this instance to the designated one. For a * SET, this operation consists of iterating through the elements of * the designated value, and assigning the similar element (with the same * tag) in this instance's components, the value of the element from value. * * @param value the new value to assign to this instance. */ public void value(Object value) { String cn = this.getClass().getName(); cat.debug("==> "+cn+".value("+String.valueOf(value)+")"); this.reset(); if (value instanceof IType) value = ((IType) value).value(); Iterator src; if (value instanceof ArrayList) src = ((ArrayList) value).iterator(); else src = ((ArrayList) ((Any) value).value()).iterator(); Iterator dst = this.iterator(); while (src.hasNext() && dst.hasNext()) { IType ts = (IType) src.next(); IType td = (IType) dst.next(); // what checks should we make? remember that any term may be an ANY // (with a null tag)? cat.info("Assigning value from "+ts.getClass().getName()+" to "+td.getClass().getName()); if (ts instanceof IIterativeType) td.value(ts); else td.value(ts.value()); } cat.debug("<== "+cn+".value()"); } /** * Returns true if the value of this instance is not set. * * @return true if this instance's value is not set. */ public boolean isBlank() { boolean result = true; for (Iterator it = this.iterator(); it.hasNext(); ) { IType t = (IType) it.next(); if (!t.isBlank()) { result = false; break; } } return result; } // IIterativeType interface implementation // ....................................................................... /** * Returns a ListIterator instance capable of iterating over the types in * this SET's components/fields. * * @return a java.util.ListIterator over the types in the components of * this SET. */ public ListIterator iterator() { return components.listIterator(); } // other instance methods // ....................................................................... /** * Initialises the components of this instance. */ protected void initInternal() { super.initInternal(); value = null; } // java.lang.Object overloaded methods // ....................................................................... /** * Returns a string representation of this instance. * * @return a string representation of this instance. */ public String toString() { String cn = this.getClass().getName(); String ls = System.getProperty("line.separator"); StringBuffer sb = new StringBuffer(ls); sb.append("-- Begin ").append(cn).append(" (SET)").append(ls); int i = 1; for (Iterator it = this.iterator(); it.hasNext(); ) { IType t = (IType) it.next(); sb.append("-- field #").append(i++) .append(" (").append(t.getClass().getName()).append("): ") .append(String.valueOf(t)).append(ls); } sb.append("-- End ").append(cn).append(" (SET)"); return sb.toString(); } }