www.pudn.com > cryptix-asn1-0.1.11.zip > Choice.java


/* $Id: Choice.java,v 1.7 2001/05/26 07:10:24 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.BlankElementException; 
import cryptix.asn1.io.ElementNotFoundException; 
 
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 CHOICE type.

* * The CHOICE alternatives are grouped in a java.util.ArrayList, with * a provided implementation of the cryptix.asn1.lang.IIterativeType * interface to iterate over them. The value of a CHOICE is the first non-blank * type among those contained in its components.

* * @version $Revision: 1.7 $ * @author Raif S. Naffah */ public abstract class Choice extends Set { // Constants and vars // ....................................................................... static Category cat = Category.getInstance(Choice.class.getName()); // Constructor(s) // ....................................................................... public Choice(Tag tag) { super("", tag); } public Choice(String name, Tag tag) { super(name, tag); } /** * Constructs a new instance of a CHOICE type, given a designated Tag and a * designated default 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 IType. */ public Choice(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 CHOICE 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); IType t; boolean found = false; cat.info("Looking for a valid ASN.1 alternative for a CHOICE."); try { IType e = is.decodeAny("choice"); Iterator it = this.iterator(); while (it.hasNext()) { t = (Type) it.next(); found = t.tag().equals(e.tag()); if (found) { cat.info("Found a "+t.getClass().getName()); t.value(e.value()); break; } } } catch (IOException x) { cat.warn("Exception ("+String.valueOf(x)+") encountered while decoding a "+cn); if (x instanceof ASNException || x instanceof EOFException) { cat.warn("Resetting stream..."); is.reset(); } throw x; } if (!found && !isOptional()) throw new ASNException("No valid alternative for "+cn+" (CHOICE) was found..."); cat.debug("<== "+cn+".decode()"); } /** * Encodes a CHOICE to an output stream. * * @param os the ASN.1 stream to write to. * @exception RuntimeException always. */ public void encode(ASNWriter os) throws IOException { String cn = this.getClass().getName(); cat.debug("==> "+cn+".encode()"); boolean found = false; for (Iterator it = this.iterator(); it.hasNext(); ) { IType t = (Type) it.next(); found = !t.isBlank(); if (found) { cat.info("Encoding "+t.getClass().getName()+"..."); t.encode(os); break; } } if (!found && !isOptional()) throw new BlankElementException(cn); cat.debug("<== "+cn+".encode()"); } /** * Sets the current value of this instance to the designated one. For a * CHOICE, this operation consists of iterating through the elements of * the designated value, and assigning the first non-blank element (with * the same tag) in this instance's corresponding component, 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)+")"); cat.debug("value is a "+String.valueOf(value.getClass().getName())); if (value instanceof IType) cat.debug("Tag="+String.valueOf( ((IType) value).tag() )); this.reset(); if (value instanceof Any) { Any src = (Any) value; for (Iterator dst = this.iterator(); dst.hasNext(); ) { IType td = (IType) dst.next(); if (td.tag().equals(src.tag())) { td.value(src.value()); cat.info("Assigned value to "+td.getClass().getName()); break; } } } else { 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()); td.value(ts.value()); } } cat.debug("<== "+cn+".value()"); } // 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(" (CHOICE)").append(ls); int i = 1; boolean found = false; for (Iterator it = this.iterator(); it.hasNext(); i++) { IType t = (Type) it.next(); found = !t.isBlank(); if (found) { sb.append("-- alternative #").append(i) .append(" (").append(t.getClass().getName()).append("): ") .append(String.valueOf(t)).append(ls); break; } } if (!found) sb.append("-- N/A").append(ls); sb.append("-- End ").append(cn).append(" (CHOICE)"); return sb.toString(); } }