17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate package com.sun.solaris.domain.pools;
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate import java.util.regex.*;
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /**
347c478bd9Sstevel@tonic-gate  * This class provides the base implementation of an Expression. All
357c478bd9Sstevel@tonic-gate  * types of Expression must inherit from this class.
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * An objective is always specified in terms of an expression. The
387c478bd9Sstevel@tonic-gate  * only recognized expressions are those known by this class. An
397c478bd9Sstevel@tonic-gate  * expression is create using the valueOf() factory method, which is
407c478bd9Sstevel@tonic-gate  * why Expressions must be known to this class.
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate abstract class Expression
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate 	/**
457c478bd9Sstevel@tonic-gate 	 * Expression importance
467c478bd9Sstevel@tonic-gate 	 */
477c478bd9Sstevel@tonic-gate 	private long imp = -1;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	/**
507c478bd9Sstevel@tonic-gate 	 * Expression name
517c478bd9Sstevel@tonic-gate 	 */
527c478bd9Sstevel@tonic-gate 	private String name;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	/**
557c478bd9Sstevel@tonic-gate 	 * Sole constructor.  (For invocation by subclass constructors)
567c478bd9Sstevel@tonic-gate 	 */
Expression(long imp, String name)577c478bd9Sstevel@tonic-gate 	protected Expression(long imp, String name)
587c478bd9Sstevel@tonic-gate 	{
597c478bd9Sstevel@tonic-gate 		this.imp = imp;
607c478bd9Sstevel@tonic-gate 		this.name = name;
617c478bd9Sstevel@tonic-gate 	}
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	/**
647c478bd9Sstevel@tonic-gate 	 * Return the name of the expression.
657c478bd9Sstevel@tonic-gate 	 */
getName()667c478bd9Sstevel@tonic-gate 	String getName()
677c478bd9Sstevel@tonic-gate 	{
687c478bd9Sstevel@tonic-gate 		return (this.name);
697c478bd9Sstevel@tonic-gate 	}
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	/**
727c478bd9Sstevel@tonic-gate 	 * Return the importance of the expression.
737c478bd9Sstevel@tonic-gate 	 */
getImportance()747c478bd9Sstevel@tonic-gate 	long getImportance()
757c478bd9Sstevel@tonic-gate 	{
767c478bd9Sstevel@tonic-gate 		return (imp);
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	/**
807c478bd9Sstevel@tonic-gate 	 * Returns the supplied string as an expression.
817c478bd9Sstevel@tonic-gate 	 *
827c478bd9Sstevel@tonic-gate 	 * This utility function attempts to identify the supplied
837c478bd9Sstevel@tonic-gate 	 * string as an expression. It tries in turn each of the known
847c478bd9Sstevel@tonic-gate 	 * sub-classes until finally, if none can be recognized, an
857c478bd9Sstevel@tonic-gate 	 * exception is thrown. This function is not immune to
867c478bd9Sstevel@tonic-gate 	 * mistakenly mis-classifying an expression. It is the
877c478bd9Sstevel@tonic-gate 	 * responsibility of the concrete Exrpession classes to ensure
887c478bd9Sstevel@tonic-gate 	 * that syntactic integrity is maintained with respect to
897c478bd9Sstevel@tonic-gate 	 * potential cases of mistaken identity.
907c478bd9Sstevel@tonic-gate 	 *
917c478bd9Sstevel@tonic-gate 	 * @param raw The candidate expression
927c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentException If no valid expression can
937c478bd9Sstevel@tonic-gate 	 * be found
947c478bd9Sstevel@tonic-gate 	 */
valueOf(String raw)957c478bd9Sstevel@tonic-gate 	static Expression valueOf(String raw) throws IllegalArgumentException
967c478bd9Sstevel@tonic-gate 	{
977c478bd9Sstevel@tonic-gate 		Expression exp = null;
987c478bd9Sstevel@tonic-gate 		/*
997c478bd9Sstevel@tonic-gate 		 * TODO It would be better if subclasses registered,
1007c478bd9Sstevel@tonic-gate 		 * but this hard coded list will do until such a time
1017c478bd9Sstevel@tonic-gate 		 */
1027c478bd9Sstevel@tonic-gate 		if ((exp = KVOpExpression.valueOf(raw)) == null)
1037c478bd9Sstevel@tonic-gate 			if ((exp = KVExpression.valueOf(raw)) == null)
1047c478bd9Sstevel@tonic-gate 				exp = KExpression.valueOf(raw);
1057c478bd9Sstevel@tonic-gate 		if (exp == null)
1067c478bd9Sstevel@tonic-gate 			throw new IllegalArgumentException(
1077c478bd9Sstevel@tonic-gate 			    "unrecognized expression: " + raw);
1087c478bd9Sstevel@tonic-gate 		return (exp);
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	/**
1127c478bd9Sstevel@tonic-gate 	 * Ensure that the supplied importance is a valid value.
1137c478bd9Sstevel@tonic-gate 	 *
1147c478bd9Sstevel@tonic-gate 	 * @param imps String representation of the importance.
1157c478bd9Sstevel@tonic-gate 	 *
1167c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentException if the importance is not
1177c478bd9Sstevel@tonic-gate 	 * valid.
1187c478bd9Sstevel@tonic-gate 	 */
validateImportance(String imps)1197c478bd9Sstevel@tonic-gate 	protected static long validateImportance(String imps)
1207c478bd9Sstevel@tonic-gate 	    throws IllegalArgumentException
1217c478bd9Sstevel@tonic-gate 	{
1227c478bd9Sstevel@tonic-gate 		long imp;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 		try {
1257c478bd9Sstevel@tonic-gate 			imp = Long.parseLong(imps);
1267c478bd9Sstevel@tonic-gate 		} catch (NumberFormatException nfe) {
1277c478bd9Sstevel@tonic-gate 			throw new IllegalArgumentException("importance value " +
1287c478bd9Sstevel@tonic-gate 			    imps + " is not legal");
1297c478bd9Sstevel@tonic-gate 		}
130*55fea89dSDan Cross 
1317c478bd9Sstevel@tonic-gate 		if (imp < 0)
1327c478bd9Sstevel@tonic-gate 			throw new IllegalArgumentException("importance value " +
1337c478bd9Sstevel@tonic-gate 			    imps + " is not legal (must be positive)");
1347c478bd9Sstevel@tonic-gate 		return (imp);
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/**
1387c478bd9Sstevel@tonic-gate 	 * Ensure that the supplied keyword is a member of the
1397c478bd9Sstevel@tonic-gate 	 * supplied keys.
1407c478bd9Sstevel@tonic-gate 	 *
1417c478bd9Sstevel@tonic-gate 	 * @param keys Array of valid key strings.
1427c478bd9Sstevel@tonic-gate 	 * @param key Key sought.
1437c478bd9Sstevel@tonic-gate 	 *
1447c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentException if the sought key is not
1457c478bd9Sstevel@tonic-gate 	 * a member of the keys array.
1467c478bd9Sstevel@tonic-gate 	 */
validateKeyword(String keys[], String key)1477c478bd9Sstevel@tonic-gate 	protected static void validateKeyword(String keys[], String key)
1487c478bd9Sstevel@tonic-gate 	    throws IllegalArgumentException
1497c478bd9Sstevel@tonic-gate 	{
1507c478bd9Sstevel@tonic-gate 		for (int i = 0; i < keys.length; i++) {
1517c478bd9Sstevel@tonic-gate 			if (keys[i].compareTo(key) == 0)
1527c478bd9Sstevel@tonic-gate 				return;
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 		throw new IllegalArgumentException("keyword " + key +
1557c478bd9Sstevel@tonic-gate 		    " is not recognized");
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	/**
1597c478bd9Sstevel@tonic-gate 	 * Return true if the supplied expression "contradicts" this
1607c478bd9Sstevel@tonic-gate 	 * expression. The definition of contradiction is left down to
1617c478bd9Sstevel@tonic-gate 	 * each implementing sub-class.
1627c478bd9Sstevel@tonic-gate 	 *
1637c478bd9Sstevel@tonic-gate 	 * @param o Expression to examine for contradiction.
1647c478bd9Sstevel@tonic-gate 	 */
contradicts(Expression o)1657c478bd9Sstevel@tonic-gate 	public abstract boolean contradicts(Expression o);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /**
1697c478bd9Sstevel@tonic-gate  * This class implements the functionality for a key-value-operator
1707c478bd9Sstevel@tonic-gate  * expression.
1717c478bd9Sstevel@tonic-gate  *
1727c478bd9Sstevel@tonic-gate  * The general form of this expression is defined in the pattern
1737c478bd9Sstevel@tonic-gate  * member. A simplified rendition of which is:
1747c478bd9Sstevel@tonic-gate  *
1757c478bd9Sstevel@tonic-gate  * [[imp]:] <key> <op> <value>
1767c478bd9Sstevel@tonic-gate  *
1777c478bd9Sstevel@tonic-gate  * key is a string which identifies the expression
1787c478bd9Sstevel@tonic-gate  * op is the operator for the expression ( < | > | ~)
1797c478bd9Sstevel@tonic-gate  * value is the value of the expression
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  * For example:
1827c478bd9Sstevel@tonic-gate  *
1837c478bd9Sstevel@tonic-gate  * 10: utilization < 80
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate final class KVOpExpression extends Expression
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	/**
1887c478bd9Sstevel@tonic-gate 	 * The operator for this expression.
1897c478bd9Sstevel@tonic-gate 	 */
1907c478bd9Sstevel@tonic-gate 	private char op;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/**
1937c478bd9Sstevel@tonic-gate 	 * The value of this expression.
1947c478bd9Sstevel@tonic-gate 	 */
1957c478bd9Sstevel@tonic-gate 	private int val;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	/**
1987c478bd9Sstevel@tonic-gate 	 * The pattern used to recognize this type of expression.
1997c478bd9Sstevel@tonic-gate 	 */
2007c478bd9Sstevel@tonic-gate 	private static final Pattern pattern = Pattern.compile(
2017c478bd9Sstevel@tonic-gate 	    "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s*([~<>])\\s*(\\d+)\\s*");
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/**
2047c478bd9Sstevel@tonic-gate 	 * The array of valid keys for this type of expression.
2057c478bd9Sstevel@tonic-gate 	 */
2067c478bd9Sstevel@tonic-gate 	private static final String keys[] = { "utilization" };
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/**
2097c478bd9Sstevel@tonic-gate 	 * A greater than operator.
2107c478bd9Sstevel@tonic-gate 	 */
2117c478bd9Sstevel@tonic-gate 	static final char GT = '>';
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	/**
2147c478bd9Sstevel@tonic-gate 	 * A less than operator.
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	static final char LT = '<';
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/**
2197c478bd9Sstevel@tonic-gate 	 * A near to operator.
2207c478bd9Sstevel@tonic-gate 	 */
2217c478bd9Sstevel@tonic-gate 	static final char NT = '~';
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/**
2247c478bd9Sstevel@tonic-gate 	 * Private constructor used in the valueOf() factory method.
2257c478bd9Sstevel@tonic-gate 	 *
2267c478bd9Sstevel@tonic-gate 	 * @param imp The importance of this expression.
2277c478bd9Sstevel@tonic-gate 	 * @param name The name of this expression.
2287c478bd9Sstevel@tonic-gate 	 * @param op The operator of this expression.
2297c478bd9Sstevel@tonic-gate 	 * @param val The value of this expression.
2307c478bd9Sstevel@tonic-gate 	 */
KVOpExpression(long imp, String name, String op, int val)2317c478bd9Sstevel@tonic-gate 	private KVOpExpression(long imp, String name, String op, int val)
2327c478bd9Sstevel@tonic-gate 	{
2337c478bd9Sstevel@tonic-gate 		super(imp, name);
2347c478bd9Sstevel@tonic-gate 		this.op = op.charAt(0);
2357c478bd9Sstevel@tonic-gate 		this.val = val;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	/**
2397c478bd9Sstevel@tonic-gate 	 * Create and return an expression from the input string.
2407c478bd9Sstevel@tonic-gate 	 *
2417c478bd9Sstevel@tonic-gate 	 * Determine if the input string matches the syntax defined by
2427c478bd9Sstevel@tonic-gate 	 * this expression. If the expression cannot be matched, an
2437c478bd9Sstevel@tonic-gate 	 * exception will be thrown.
2447c478bd9Sstevel@tonic-gate 	 *
2457c478bd9Sstevel@tonic-gate 	 * @param raw Candidate expression string.
2467c478bd9Sstevel@tonic-gate 	 *
2477c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentExpression if the string is not a
2487c478bd9Sstevel@tonic-gate 	 * valid expression of this type.
2497c478bd9Sstevel@tonic-gate 	 */
valueOf(String raw)2507c478bd9Sstevel@tonic-gate 	static Expression valueOf(String raw) throws IllegalArgumentException
2517c478bd9Sstevel@tonic-gate 	{
2527c478bd9Sstevel@tonic-gate 		KVOpExpression exp = null;
2537c478bd9Sstevel@tonic-gate 		Matcher m = pattern.matcher(raw);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 		if (m.matches()) {
2567c478bd9Sstevel@tonic-gate 			long imp = 1;
2577c478bd9Sstevel@tonic-gate 			int val = Integer.parseInt(m.group(5));
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 			if (m.group(2) != null)
2607c478bd9Sstevel@tonic-gate 				imp = validateImportance(m.group(2));
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 			validateKeyword(keys, m.group(3));
2637c478bd9Sstevel@tonic-gate 			if (val > 100 || val < 0)
2647c478bd9Sstevel@tonic-gate 				throw new IllegalArgumentException(
2657c478bd9Sstevel@tonic-gate 				    "expression value " + val +
2667c478bd9Sstevel@tonic-gate 				    " is outside the legal range (0-100)");
2677c478bd9Sstevel@tonic-gate 			exp = new KVOpExpression(imp, m.group(3),
2687c478bd9Sstevel@tonic-gate 			    m.group(4), val);
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 		return (exp);
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	/**
2747c478bd9Sstevel@tonic-gate 	 * Return the operator for this expression.
2757c478bd9Sstevel@tonic-gate 	 */
getOp()2767c478bd9Sstevel@tonic-gate 	char getOp()
2777c478bd9Sstevel@tonic-gate 	{
2787c478bd9Sstevel@tonic-gate 		return (op);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	/**
2827c478bd9Sstevel@tonic-gate 	 * Return the value of this expression.
2837c478bd9Sstevel@tonic-gate 	 */
getValue()2847c478bd9Sstevel@tonic-gate 	int getValue()
2857c478bd9Sstevel@tonic-gate 	{
2867c478bd9Sstevel@tonic-gate 		return (val);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/**
2907c478bd9Sstevel@tonic-gate 	 * Return a string representation of this expresssion.
2917c478bd9Sstevel@tonic-gate 	 */
toString()2927c478bd9Sstevel@tonic-gate 	public String toString()
2937c478bd9Sstevel@tonic-gate 	{
2947c478bd9Sstevel@tonic-gate 		return ("(" + getImportance() + ", " + getName() + ", '" + op +
2957c478bd9Sstevel@tonic-gate 		    "', " + val + ")");
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	/**
2997c478bd9Sstevel@tonic-gate 	 * Indicates whether some other KVOpExpression is "equal to
3007c478bd9Sstevel@tonic-gate 	 * this one.
3017c478bd9Sstevel@tonic-gate 	 * @param o the reference object with which to compare.
3027c478bd9Sstevel@tonic-gate 	 * @return <code>true</code> if this object is the same as the
3037c478bd9Sstevel@tonic-gate 	 * o argument; <code>false</code> otherwise.
3047c478bd9Sstevel@tonic-gate 	 * @see	#hashCode()
3057c478bd9Sstevel@tonic-gate 	 */
equals(Object o)3067c478bd9Sstevel@tonic-gate 	public boolean equals(Object o)
3077c478bd9Sstevel@tonic-gate 	{
3087c478bd9Sstevel@tonic-gate 		if (o == this)
3097c478bd9Sstevel@tonic-gate 			return (true);
3107c478bd9Sstevel@tonic-gate 		if (!(o instanceof KVOpExpression))
3117c478bd9Sstevel@tonic-gate 			return (false);
3127c478bd9Sstevel@tonic-gate 		KVOpExpression other = (KVOpExpression) o;
3137c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0 ||
3147c478bd9Sstevel@tonic-gate 		    op != other.getOp() || val != other.getValue())
315*55fea89dSDan Cross 			return (false);
3167c478bd9Sstevel@tonic-gate 		return (true);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	/**
3207c478bd9Sstevel@tonic-gate 	 * Returns a hash code value for the object. This method is
3217c478bd9Sstevel@tonic-gate 	 * supported for the benefit of hashtables such as those provided by
3227c478bd9Sstevel@tonic-gate 	 * <code>java.util.Hashtable</code>.
3237c478bd9Sstevel@tonic-gate 	 *
3247c478bd9Sstevel@tonic-gate 	 * @return a hash code value for this object.
3257c478bd9Sstevel@tonic-gate 	 * @see	#equals(java.lang.Object)
3267c478bd9Sstevel@tonic-gate 	 * @see	java.util.Hashtable
3277c478bd9Sstevel@tonic-gate 	 */
hashCode()3287c478bd9Sstevel@tonic-gate 	public int hashCode()
3297c478bd9Sstevel@tonic-gate 	{
3307c478bd9Sstevel@tonic-gate 		return (getName().hashCode() + (int) op + val);
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	/**
3347c478bd9Sstevel@tonic-gate 	 * Return true if the supplied expression "contradicts" this
3357c478bd9Sstevel@tonic-gate 	 * expression. If the supplied expression is not of the same
3367c478bd9Sstevel@tonic-gate 	 * type, then it cannot contradict it. If the names are
3377c478bd9Sstevel@tonic-gate 	 * different then there can be no contradiction.
3387c478bd9Sstevel@tonic-gate 	 *
3397c478bd9Sstevel@tonic-gate 	 * Contradiction occurs if the operator is the same or if they
3407c478bd9Sstevel@tonic-gate 	 * aren't the same and the operator is < or > and the values
3417c478bd9Sstevel@tonic-gate 	 * aren't simultanteously achievable.
3427c478bd9Sstevel@tonic-gate 	 *
3437c478bd9Sstevel@tonic-gate 	 * @param o Expression to examine for contradiction.
3447c478bd9Sstevel@tonic-gate 	 */
contradicts(Expression o)3457c478bd9Sstevel@tonic-gate 	public boolean contradicts(Expression o)
3467c478bd9Sstevel@tonic-gate 	{
3477c478bd9Sstevel@tonic-gate 		if (!(o instanceof KVOpExpression))
3487c478bd9Sstevel@tonic-gate 			return (false);
3497c478bd9Sstevel@tonic-gate 		KVOpExpression other = (KVOpExpression) o;
3507c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0)
3517c478bd9Sstevel@tonic-gate 			return (false);
3527c478bd9Sstevel@tonic-gate 		if (getOp() != other.getOp()) {
3537c478bd9Sstevel@tonic-gate 			if (getOp() != NT && other.getOp() != NT) {
3547c478bd9Sstevel@tonic-gate 				if (getOp() == GT) {
3557c478bd9Sstevel@tonic-gate 					if (getValue() < other.getValue())
3567c478bd9Sstevel@tonic-gate 						return (false);
3577c478bd9Sstevel@tonic-gate 				} else {
3587c478bd9Sstevel@tonic-gate 					if (getValue() > other.getValue())
3597c478bd9Sstevel@tonic-gate 						return (false);
3607c478bd9Sstevel@tonic-gate 				}
3617c478bd9Sstevel@tonic-gate 			} else
3627c478bd9Sstevel@tonic-gate 				return (false);
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 		return (true);
365*55fea89dSDan Cross 	}
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /**
3697c478bd9Sstevel@tonic-gate  * This class implements the functionality for a key-value expression.
3707c478bd9Sstevel@tonic-gate  *
3717c478bd9Sstevel@tonic-gate  * The general form of this expression is defined in the pattern
3727c478bd9Sstevel@tonic-gate  * member. A simplified rendition of which is:
3737c478bd9Sstevel@tonic-gate  *
3747c478bd9Sstevel@tonic-gate  * [[imp]:] <key> <value>
3757c478bd9Sstevel@tonic-gate  *
3767c478bd9Sstevel@tonic-gate  * key is a string which identifies the expression
3777c478bd9Sstevel@tonic-gate  * value is the value of the expression
3787c478bd9Sstevel@tonic-gate  *
3797c478bd9Sstevel@tonic-gate  * For example:
3807c478bd9Sstevel@tonic-gate  *
3817c478bd9Sstevel@tonic-gate  * 10: locality tight
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate final class KVExpression extends Expression
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate 	/**
3867c478bd9Sstevel@tonic-gate 	 * The value of this expression.
3877c478bd9Sstevel@tonic-gate 	 */
3887c478bd9Sstevel@tonic-gate 	private String val;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/**
3917c478bd9Sstevel@tonic-gate 	 * The pattern used to recognize this type of expression.
3927c478bd9Sstevel@tonic-gate 	 */
3937c478bd9Sstevel@tonic-gate 	private static final Pattern pattern = Pattern.compile(
3947c478bd9Sstevel@tonic-gate 	    "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s+(tight|loose|none)\\s*");
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/**
3977c478bd9Sstevel@tonic-gate 	 * The array of valid keys for this type of expression.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	private static final String keys[] = { "locality" };
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/**
4027c478bd9Sstevel@tonic-gate 	 * Private constructor used in the valueOf() factory method.
4037c478bd9Sstevel@tonic-gate 	 *
4047c478bd9Sstevel@tonic-gate 	 * @param imp The importance of this expression.
4057c478bd9Sstevel@tonic-gate 	 * @param name The name of this expression.
4067c478bd9Sstevel@tonic-gate 	 * @param val The value of this expression.
4077c478bd9Sstevel@tonic-gate 	 */
KVExpression(long imp, String name, String val)4087c478bd9Sstevel@tonic-gate 	private KVExpression(long imp, String name, String val)
4097c478bd9Sstevel@tonic-gate 	{
4107c478bd9Sstevel@tonic-gate 		super(imp, name);
4117c478bd9Sstevel@tonic-gate 		this.val = val;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	/**
4157c478bd9Sstevel@tonic-gate 	 * Create and return an expression from the input string.
4167c478bd9Sstevel@tonic-gate 	 *
4177c478bd9Sstevel@tonic-gate 	 * Determine if the input string matches the syntax defined by
4187c478bd9Sstevel@tonic-gate 	 * this expression. If the expression cannot be matched, an
4197c478bd9Sstevel@tonic-gate 	 * exception will be thrown.
4207c478bd9Sstevel@tonic-gate 	 *
4217c478bd9Sstevel@tonic-gate 	 * @param raw Candidate expression string.
4227c478bd9Sstevel@tonic-gate 	 *
4237c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentExpression if the string is not a
4247c478bd9Sstevel@tonic-gate 	 * valid expression of this type.
4257c478bd9Sstevel@tonic-gate 	 */
valueOf(String raw)4267c478bd9Sstevel@tonic-gate 	static Expression valueOf(String raw) throws IllegalArgumentException
4277c478bd9Sstevel@tonic-gate 	{
4287c478bd9Sstevel@tonic-gate 		KVExpression exp = null;
4297c478bd9Sstevel@tonic-gate 		Matcher m = pattern.matcher(raw);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 		if (m.matches()) {
4327c478bd9Sstevel@tonic-gate 			long imp = 1;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			if (m.group(2) != null)
4357c478bd9Sstevel@tonic-gate 				imp = validateImportance(m.group(2));
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 			validateKeyword(keys, m.group(3));
4387c478bd9Sstevel@tonic-gate 			exp = new KVExpression(imp, m.group(3), m.group(4));
4397c478bd9Sstevel@tonic-gate 		}
4407c478bd9Sstevel@tonic-gate 		return (exp);
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	/**
4447c478bd9Sstevel@tonic-gate 	 * Return the value of this expression.
4457c478bd9Sstevel@tonic-gate 	 */
getValue()4467c478bd9Sstevel@tonic-gate 	String getValue()
4477c478bd9Sstevel@tonic-gate 	{
4487c478bd9Sstevel@tonic-gate 		return (val);
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	/**
4527c478bd9Sstevel@tonic-gate 	 * Return a string representation of this expresssion.
4537c478bd9Sstevel@tonic-gate 	 */
toString()4547c478bd9Sstevel@tonic-gate 	public String toString()
4557c478bd9Sstevel@tonic-gate 	{
4567c478bd9Sstevel@tonic-gate 		StringBuffer buf = new StringBuffer();
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		buf.append("(");
4597c478bd9Sstevel@tonic-gate 		buf.append(getImportance());
4607c478bd9Sstevel@tonic-gate 		buf.append(", ");
4617c478bd9Sstevel@tonic-gate 		buf.append(getName());
4627c478bd9Sstevel@tonic-gate 		buf.append(", ");
4637c478bd9Sstevel@tonic-gate 		buf.append(val);
4647c478bd9Sstevel@tonic-gate 		buf.append(")");
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		return (buf.toString());
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	/**
4707c478bd9Sstevel@tonic-gate 	 * Indicates whether some other KVExpression is "equal to
4717c478bd9Sstevel@tonic-gate 	 * this one.
4727c478bd9Sstevel@tonic-gate 	 * @param o the reference object with which to compare.
4737c478bd9Sstevel@tonic-gate 	 * @return <code>true</code> if this object is the same as the
4747c478bd9Sstevel@tonic-gate 	 * o argument; <code>false</code> otherwise.
4757c478bd9Sstevel@tonic-gate 	 * @see	#hashCode()
4767c478bd9Sstevel@tonic-gate 	 */
equals(Object o)4777c478bd9Sstevel@tonic-gate 	public boolean equals(Object o)
4787c478bd9Sstevel@tonic-gate 	{
4797c478bd9Sstevel@tonic-gate 		if (o == this)
4807c478bd9Sstevel@tonic-gate 			return (true);
4817c478bd9Sstevel@tonic-gate 		if (!(o instanceof KVExpression))
4827c478bd9Sstevel@tonic-gate 			return (false);
4837c478bd9Sstevel@tonic-gate 		KVExpression other = (KVExpression) o;
4847c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0 ||
4857c478bd9Sstevel@tonic-gate 		    val.compareTo(other.getValue()) != 0)
486*55fea89dSDan Cross 			return (false);
4877c478bd9Sstevel@tonic-gate 		return (true);
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	/**
4917c478bd9Sstevel@tonic-gate 	 * Returns a hash code value for the object. This method is
4927c478bd9Sstevel@tonic-gate 	 * supported for the benefit of hashtables such as those provided by
4937c478bd9Sstevel@tonic-gate 	 * <code>java.util.Hashtable</code>.
4947c478bd9Sstevel@tonic-gate 	 *
4957c478bd9Sstevel@tonic-gate 	 * @return a hash code value for this object.
4967c478bd9Sstevel@tonic-gate 	 * @see	#equals(java.lang.Object)
4977c478bd9Sstevel@tonic-gate 	 * @see	java.util.Hashtable
4987c478bd9Sstevel@tonic-gate 	 */
hashCode()4997c478bd9Sstevel@tonic-gate 	public int hashCode()
5007c478bd9Sstevel@tonic-gate 	{
5017c478bd9Sstevel@tonic-gate 		return (getName().hashCode() + val.hashCode());
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/**
5057c478bd9Sstevel@tonic-gate 	 * Return true if the supplied expression "contradicts" this
5067c478bd9Sstevel@tonic-gate 	 * expression. If the supplied expression is not of the same
5077c478bd9Sstevel@tonic-gate 	 * type, then it cannot contradict it. If the names are
5087c478bd9Sstevel@tonic-gate 	 * different then there can be no contradiction.
5097c478bd9Sstevel@tonic-gate 	 *
5107c478bd9Sstevel@tonic-gate 	 * Contradiction occurs if the value is different.
5117c478bd9Sstevel@tonic-gate 	 *
5127c478bd9Sstevel@tonic-gate 	 * @param o Expression to examine for contradiction.
5137c478bd9Sstevel@tonic-gate 	 */
contradicts(Expression o)5147c478bd9Sstevel@tonic-gate 	public boolean contradicts(Expression o)
5157c478bd9Sstevel@tonic-gate 	{
5167c478bd9Sstevel@tonic-gate 		if (!(o instanceof KVExpression))
5177c478bd9Sstevel@tonic-gate 			return (false);
5187c478bd9Sstevel@tonic-gate 		KVExpression other = (KVExpression) o;
5197c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0)
5207c478bd9Sstevel@tonic-gate 			return (false);
5217c478bd9Sstevel@tonic-gate 		if (val.compareTo(other.getValue()) == 0)
5227c478bd9Sstevel@tonic-gate 			return (false);
5237c478bd9Sstevel@tonic-gate 		return (true);
524*55fea89dSDan Cross 	}
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate /**
5287c478bd9Sstevel@tonic-gate  * This class implements the functionality for a key expression.
5297c478bd9Sstevel@tonic-gate  *
5307c478bd9Sstevel@tonic-gate  * The general form of this expression is defined in the pattern
5317c478bd9Sstevel@tonic-gate  * member. A simplified rendition of which is:
5327c478bd9Sstevel@tonic-gate  *
5337c478bd9Sstevel@tonic-gate  * [[imp]:] <key>
5347c478bd9Sstevel@tonic-gate  *
5357c478bd9Sstevel@tonic-gate  * key is a string which identifies the expression
5367c478bd9Sstevel@tonic-gate  *
5377c478bd9Sstevel@tonic-gate  * For example:
5387c478bd9Sstevel@tonic-gate  *
5397c478bd9Sstevel@tonic-gate  * 10: wt-load
5407c478bd9Sstevel@tonic-gate  */
5417c478bd9Sstevel@tonic-gate final class KExpression extends Expression
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate 	/**
5447c478bd9Sstevel@tonic-gate 	 * The pattern used to recognize this type of expression.
5457c478bd9Sstevel@tonic-gate 	 */
5467c478bd9Sstevel@tonic-gate 	private static final Pattern pattern = Pattern.compile(
5477c478bd9Sstevel@tonic-gate 	    "\\s*((\\d+)\\s*:)?\\s*([\\w-]+)\\s*");
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	/**
5507c478bd9Sstevel@tonic-gate 	 * The array of valid keys for this type of expression.
5517c478bd9Sstevel@tonic-gate 	 */
5527c478bd9Sstevel@tonic-gate 	private static final String keys[] = { "wt-load" };
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/**
5557c478bd9Sstevel@tonic-gate 	 * Private constructor used in the valueOf() factory method.
5567c478bd9Sstevel@tonic-gate 	 *
5577c478bd9Sstevel@tonic-gate 	 * @param imp The importance of this expression.
5587c478bd9Sstevel@tonic-gate 	 * @param name The name of this expression.
5597c478bd9Sstevel@tonic-gate 	 */
KExpression(long imp, String name)5607c478bd9Sstevel@tonic-gate 	private KExpression(long imp, String name)
5617c478bd9Sstevel@tonic-gate 	{
5627c478bd9Sstevel@tonic-gate 		super(imp, name);
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	/**
5667c478bd9Sstevel@tonic-gate 	 * Create and return an expression from the input string.
5677c478bd9Sstevel@tonic-gate 	 *
5687c478bd9Sstevel@tonic-gate 	 * Determine if the input string matches the syntax defined by
5697c478bd9Sstevel@tonic-gate 	 * this expression. If the expression cannot be matched, an
5707c478bd9Sstevel@tonic-gate 	 * exception will be thrown.
5717c478bd9Sstevel@tonic-gate 	 *
5727c478bd9Sstevel@tonic-gate 	 * @param raw Candidate expression string.
5737c478bd9Sstevel@tonic-gate 	 *
5747c478bd9Sstevel@tonic-gate 	 * @throws IllegalArgumentExpression if the string is not a
5757c478bd9Sstevel@tonic-gate 	 * valid expression of this type.
5767c478bd9Sstevel@tonic-gate 	 */
valueOf(String raw)5777c478bd9Sstevel@tonic-gate 	static Expression valueOf(String raw) throws IllegalArgumentException
5787c478bd9Sstevel@tonic-gate 	{
5797c478bd9Sstevel@tonic-gate 		KExpression exp = null;
5807c478bd9Sstevel@tonic-gate 		Matcher m = pattern.matcher(raw);
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 		if (m.matches()) {
5837c478bd9Sstevel@tonic-gate 			long imp = 1;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 			if (m.group(2) != null)
5867c478bd9Sstevel@tonic-gate 				imp = validateImportance(m.group(2));
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 			validateKeyword(keys, m.group(3));
5897c478bd9Sstevel@tonic-gate 			exp = new KExpression(imp, m.group(3));
5907c478bd9Sstevel@tonic-gate 		}
5917c478bd9Sstevel@tonic-gate 		return (exp);
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/**
5957c478bd9Sstevel@tonic-gate 	 * Return a string representation of this expresssion.
5967c478bd9Sstevel@tonic-gate 	 */
toString()5977c478bd9Sstevel@tonic-gate 	public String toString()
5987c478bd9Sstevel@tonic-gate 	{
5997c478bd9Sstevel@tonic-gate 		return ("(" + getImportance() + ", " + getName() + ")");
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	/**
6037c478bd9Sstevel@tonic-gate 	 * Indicates whether some other KExpression is "equal to
6047c478bd9Sstevel@tonic-gate 	 * this one.
6057c478bd9Sstevel@tonic-gate 	 * @param o the reference object with which to compare.
6067c478bd9Sstevel@tonic-gate 	 * @return <code>true</code> if this object is the same as the
6077c478bd9Sstevel@tonic-gate 	 * o argument; <code>false</code> otherwise.
6087c478bd9Sstevel@tonic-gate 	 * @see	#hashCode()
6097c478bd9Sstevel@tonic-gate 	 */
equals(Object o)6107c478bd9Sstevel@tonic-gate 	public boolean equals(Object o)
6117c478bd9Sstevel@tonic-gate 	{
6127c478bd9Sstevel@tonic-gate 		if (o == this)
6137c478bd9Sstevel@tonic-gate 			return (true);
6147c478bd9Sstevel@tonic-gate 		if (!(o instanceof KExpression))
6157c478bd9Sstevel@tonic-gate 			return (false);
6167c478bd9Sstevel@tonic-gate 		KExpression other = (KExpression) o;
6177c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0)
618*55fea89dSDan Cross 			return (false);
6197c478bd9Sstevel@tonic-gate 		return (true);
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	/**
6237c478bd9Sstevel@tonic-gate 	 * Returns a hash code value for the object. This method is
6247c478bd9Sstevel@tonic-gate 	 * supported for the benefit of hashtables such as those provided by
6257c478bd9Sstevel@tonic-gate 	 * <code>java.util.Hashtable</code>.
6267c478bd9Sstevel@tonic-gate 	 *
6277c478bd9Sstevel@tonic-gate 	 * @return a hash code value for this object.
6287c478bd9Sstevel@tonic-gate 	 * @see	#equals(java.lang.Object)
6297c478bd9Sstevel@tonic-gate 	 * @see	java.util.Hashtable
6307c478bd9Sstevel@tonic-gate 	 */
hashCode()6317c478bd9Sstevel@tonic-gate 	public int hashCode()
6327c478bd9Sstevel@tonic-gate 	{
6337c478bd9Sstevel@tonic-gate 		return (getName().hashCode());
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	/**
6377c478bd9Sstevel@tonic-gate 	 * Return true if the supplied expression "contradicts" this
6387c478bd9Sstevel@tonic-gate 	 * expression. If the supplied expression is not of the same
6397c478bd9Sstevel@tonic-gate 	 * type, then it cannot contradict it. If the names are
6407c478bd9Sstevel@tonic-gate 	 * different then there can be no contradiction.
6417c478bd9Sstevel@tonic-gate 	 *
6427c478bd9Sstevel@tonic-gate 	 * @param o Expression to examine for contradiction.
6437c478bd9Sstevel@tonic-gate 	 */
contradicts(Expression o)6447c478bd9Sstevel@tonic-gate 	public boolean contradicts(Expression o)
6457c478bd9Sstevel@tonic-gate 	{
6467c478bd9Sstevel@tonic-gate 		if (!(o instanceof KExpression))
6477c478bd9Sstevel@tonic-gate 			return (false);
6487c478bd9Sstevel@tonic-gate 		KExpression other = (KExpression) o;
6497c478bd9Sstevel@tonic-gate 		if (getName().compareTo(other.getName()) != 0)
6507c478bd9Sstevel@tonic-gate 			return (false);
6517c478bd9Sstevel@tonic-gate 		return (true);
652*55fea89dSDan Cross 	}
6537c478bd9Sstevel@tonic-gate }
654