// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;

/**
 * Realm
 */
public class Realm implements Cloneable {

	/**
	 * realm
	 */
	private String realm;

	/**
	 * Class constructor
	 */
	private Realm() {
	}

	/**
	 * Class constructor
	 *
	 * @param name is of type String
	 * @exception RealmException an exception
	 * @see krb5.lib.RealmException
	 */
	public Realm(String name) throws RealmException {
		realm = parseRealm(name);
	}

	/**
	 * Clones a copy of the object
	 *
	 * @return Object is a result
	 */
	public Object clone() {
		Realm new_realm = new Realm();
		if (realm != null)
			new_realm.realm = realm;
		return new_realm;
	}

	/**
	 * Compares 2 realms
	 *
	 * @return boolean is a result
	 * @param other is of type Realm
	 * @see krb5.lib.Realm
	 */
	public boolean equals(Realm other) {
		if ((realm != null && other.realm == null) ||
			(realm == null && other.realm != null))
			return false;
		if (realm != null && other.realm != null)
			return realm.equals(other.realm);
		return true;
	}

	/**
	 * Class constructor
	 *
	 * @param ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @exception RealmException an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.RealmException
	 */
	public Realm(EncodeRef ref) throws Asn1Exception,
		RealmException {
		realm = decode.GeneralString(ref);
		if (realm == null || realm.length() == 0)
			throw new RealmException(Krb5.REALM_NULL);
		if (!isValidRealmString(realm))
			throw new RealmException(Krb5.REALM_ILLCHAR);
	}

	/**
	 * Converts to a printable string
	 *
	 * @return String is a result
	 */
	public String toString() {
		return realm;
	}

	/**
	 * Parses the value at the separator
	 *
	 * @return String is a result
	 * @param name is of type String
	 * @exception RealmException an exception
	 * @see krb5.lib.RealmException
	 */
	protected static String parseRealmAtSeparator(String name) throws RealmException {
		String result = null;
		if (name == null)
			return null;
		int i = 0;
		while (i < name.length()) {
			if (name.charAt(i) == Krb5.NAME_REALM_SEPARATOR) {
				if (i == 0 || name.charAt(i - 1) != '\\') {
					if (i + 1 < name.length())
						result = name.substring(i + 1, name.length());
					break;
				}
			}
			i++;
		}
		if (result != null) {
			if (result.length() == 0)
				throw new RealmException(Krb5.REALM_NULL);
			if (!isValidRealmString(result))
				throw new RealmException(Krb5.REALM_ILLCHAR);
		}
		return result;
	}

	/**
	 * Parses realm
	 *
	 * @return String is a result
	 * @param name is of type String
	 * @exception RealmException an exception
	 * @see krb5.lib.RealmException
	 */
	protected static String parseRealm(String name) throws RealmException {
		String result = parseRealmAtSeparator(name);
		if (result == null)
			result = name;
		if (result == null || result.length() == 0)
			throw new RealmException(Krb5.REALM_NULL);
		if (!isValidRealmString(result))
			throw new RealmException(Krb5.REALM_ILLCHAR);
		return result;
	}

	/**
	 * Is the realm valid
	 *
	 * @return boolean is a result
	 * @param name is of type String
	 */
	protected static boolean isValidRealmString(String name) {
		if (name == null)
			return false;
		if (name.length() == 0)
			return false;
		for (int i = 0; i < name.length(); i++) {
			if (name.charAt(i) == '/' ||
				name.charAt(i) == ':' ||
				name.charAt(i) == '\0') {
				return false;
			}
		}
		return true;
	}

	/**
	 * Encodes the object in asn1
	 *
	 * @return byte[] is a result
	 * @exception Asn1Exception an exception
	 * @see krb5.lib.Asn1Exception
	 */
	public byte[] asn1Encode() throws Asn1Exception {
		return encode.GeneralString(toString());
	}

}