//////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1993, 1994, 1995.
// Unpublished work.  All Rights Reserved.
// 
// The software contained on this media is the property of the
// DSTC Pty Ltd.  Use of this software is strictly in accordance
// with the license agreement in the accompanying LICENSE.DOC 
// file. If your distribution of this software does not contain 
// a LICENSE.DOC file then you have no rights to use this 
// software in any manner and should contact DSTC at the address 
// below to determine an appropriate licensing arrangement.
// 
//      DSTC Pty Ltd
//      Level 7, GP South
//      University of Queensland
//      St Lucia, 4072
//      Australia
//      Tel: +61 7 3365 4310
//      Fax: +61 7 3365 4311
//      Email: jcsi@dstc.qut.edu.au
// 
// This software is being provided "AS IS" without warranty of
// any kind.  In no event shall DSTC Pty Ltd be liable for
// damage of any kind arising out of or in connection with
// the use or performance of this software.
// 
//////////////////////////////////////////////////////////////////////////// 

package com.dstc.security.x509;

import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Hashtable;
import java.lang.Comparable;
import java.util.Vector;
import com.dstc.security.asn1.Asn1;
import com.dstc.security.asn1.Asn1Exception;
import com.dstc.security.asn1.Sequence;
import com.dstc.security.asn1.SetOf;
import com.dstc.security.asn1.PrintableString;
import com.dstc.security.asn1.T61String;
import com.dstc.security.asn1.IA5String;
import com.dstc.security.asn1.Oid;
import com.dstc.security.provider.OID;

/**
 * <p>A class representing the x.500 ASN.1 structure RelativeDistinguishedName.
 *
 * <pre>
 *    RelativeDistinguishedName  ::=
 *                       SET SIZE (1 .. MAX) OF AttributeTypeAndValue
 *
 *    AttributeTypeAndValue           ::=     SEQUENCE {
 *          type    AttributeType,
 *          value   AttributeValue }
 *  
 *    AttributeType           ::=   OBJECT IDENTIFIER
 *
 *    AttributeValue            ::=   CHOICE {
 *          DirectoryString,
 *          IA5String
 *          }
 * </pre>
 *
 * @see com.dstc.security.x509.X500Name
 *
 * @version 0.98, 98/07/01
 * @author Ming Yung
 */
public class RDN extends SetOf implements Comparable
{
  private static Hashtable orderedTypes;
  static
  {
    orderedTypes = new Hashtable();
    orderedTypes.put("C", "A");
    orderedTypes.put("ST", "B");
    orderedTypes.put("L", "C");
    orderedTypes.put("O", "D");
    orderedTypes.put("OU", "E");
    orderedTypes.put("CN", "F");
    orderedTypes.put("EmailAddress", "H");
    /*orderedTypes.put("C", "F");
    orderedTypes.put("ST", "E");
    orderedTypes.put("L", "D");
    orderedTypes.put("O", "C");
    orderedTypes.put("OU", "B");
    orderedTypes.put("CN", "A");
    orderedTypes.put("EmailAddress", "H");*/
  }

  private Vector rdnComponents = new Vector();

  /**
   * Constructs an RDN from a single type-value pair of the form
   * "type=value"
   */
  public RDN(String rdn) throws IOException
  {
    try
    {
      StringTokenizer tknz = new StringTokenizer(rdn, "=", false);
      String type = tknz.nextToken().trim();
      String value = tknz.nextToken().trim();
      AttributeTypeAndValue attVal = new AttributeTypeAndValue(type, value);
      rdnComponents.addElement(attVal);
      addComponent(attVal);
    }
    catch (Exception e)
    {
      throw new IOException(e.getMessage());
    }
  }

  /**
   * Constructs an RDN from a DER encoding
   */
  public RDN(byte encoded[]) throws Asn1Exception 
  {
    doDecode(encoded);

    for (int i=0; i<components.size(); i++)
    {
      rdnComponents.addElement(
        new AttributeTypeAndValue(((Asn1)components.elementAt(i)).encode()));
    }  
  }

  public String getName()
  {
    StringBuffer st = new StringBuffer();
    for (int i=0; i<rdnComponents.size(); i++)
    {
      st.append(((AttributeTypeAndValue)rdnComponents.elementAt(i)).getName());
    }
    return st.toString();
  }

  //Assumes only one component in RDN
  private String getTypeOrder()
  {
    return (String)orderedTypes.get(((AttributeTypeAndValue)
      rdnComponents.iterator().next()).getType());
  }
    
  public int compareTo(Object o)
  {
    return getTypeOrder().compareTo(((RDN)o).getTypeOrder());
  }
}
