/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" */ package com.sun.solaris.domain.pools; import java.util.regex.*; /** * This class provides the base implementation of an Expression. All * types of Expression must inherit from this class. * * An objective is always specified in terms of an expression. The * only recognized expressions are those known by this class. An * expression is create using the valueOf() factory method, which is * why Expressions must be known to this class. */ abstract class Expression { /** * Expression importance */ private long imp = -1; /** * Expression name */ private String name; /** * Sole constructor. (For invocation by subclass constructors) */ protected Expression(long imp, String name) { this.imp = imp; this.name = name; } /** * Return the name of the expression. */ String getName() { return (this.name); } /** * Return the importance of the expression. */ long getImportance() { return (imp); } /** * Returns the supplied string as an expression. * * This utility function attempts to identify the supplied * string as an expression. It tries in turn each of the known * sub-classes until finally, if none can be recognized, an * exception is thrown. This function is not immune to * mistakenly mis-classifying an expression. It is the * responsibility of the concrete Exrpession classes to ensure * that syntactic integrity is maintained with respect to * potential cases of mistaken identity. * * @param raw The candidate expression * @throws IllegalArgumentException If no valid expression can * be found */ static Expression valueOf(String raw) throws IllegalArgumentException { Expression exp = null; /* * TODO It would be better if subclasses registered, * but this hard coded list will do until such a time */ if ((exp = KVOpExpression.valueOf(raw)) == null) if ((exp = KVExpression.valueOf(raw)) == null) exp = KExpression.valueOf(raw); if (exp == null) throw new IllegalArgumentException( "unrecognized expression: " + raw); return (exp); } /** * Ensure that the supplied importance is a valid value. * * @param imps String representation of the importance. * * @throws IllegalArgumentException if the importance is not * valid. */ protected static long validateImportance(String imps) throws IllegalArgumentException { long imp; try { imp = Long.parseLong(imps); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("importance value " + imps + " is not legal"); } if (imp < 0) throw new IllegalArgumentException("importance value " + imps + " is not legal (must be positive)"); return (imp); } /** * Ensure that the supplied keyword is a member of the * supplied keys. * * @param keys Array of valid key strings. * @param key Key sought. * * @throws IllegalArgumentException if the sought key is not * a member of the keys array. */ protected static void validateKeyword(String keys[], String key) throws IllegalArgumentException { for (int i = 0; i < keys.length; i++) { if (keys[i].compareTo(key) == 0) return; } throw new IllegalArgumentException("keyword " + key + " is not recognized"); } /** * Return true if the supplied expression "contradicts" this * expression. The definition of contradiction is left down to * each implementing sub-class. * * @param o Expression to examine for contradiction. */ public abstract boolean contradicts(Expression o); } /** * This class implements the functionality for a key-value-operator * expression. * * The general form of this expression is defined in the pattern * member. A simplified rendition of which is: * * [[imp]:] * * key is a string which identifies the expression * op is the operator for the expression ( < | > | ~) * value is the value of the expression * * For example: * * 10: utilization < 80 */ final class KVOpExpression extends Expression { /** * The operator for this expression. */ private char op; /** * The value of this expression. */ private int val; /** * The pattern used to recognize this type of expression. */ private static final Pattern pattern = Pattern.compile( "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s*([~<>])\\s*(\\d+)\\s*"); /** * The array of valid keys for this type of expression. */ private static final String keys[] = { "utilization" }; /** * A greater than operator. */ static final char GT = '>'; /** * A less than operator. */ static final char LT = '<'; /** * A near to operator. */ static final char NT = '~'; /** * Private constructor used in the valueOf() factory method. * * @param imp The importance of this expression. * @param name The name of this expression. * @param op The operator of this expression. * @param val The value of this expression. */ private KVOpExpression(long imp, String name, String op, int val) { super(imp, name); this.op = op.charAt(0); this.val = val; } /** * Create and return an expression from the input string. * * Determine if the input string matches the syntax defined by * this expression. If the expression cannot be matched, an * exception will be thrown. * * @param raw Candidate expression string. * * @throws IllegalArgumentExpression if the string is not a * valid expression of this type. */ static Expression valueOf(String raw) throws IllegalArgumentException { KVOpExpression exp = null; Matcher m = pattern.matcher(raw); if (m.matches()) { long imp = 1; int val = Integer.parseInt(m.group(5)); if (m.group(2) != null) imp = validateImportance(m.group(2)); validateKeyword(keys, m.group(3)); if (val > 100 || val < 0) throw new IllegalArgumentException( "expression value " + val + " is outside the legal range (0-100)"); exp = new KVOpExpression(imp, m.group(3), m.group(4), val); } return (exp); } /** * Return the operator for this expression. */ char getOp() { return (op); } /** * Return the value of this expression. */ int getValue() { return (val); } /** * Return a string representation of this expresssion. */ public String toString() { return ("(" + getImportance() + ", " + getName() + ", '" + op + "', " + val + ")"); } /** * Indicates whether some other KVOpExpression is "equal to * this one. * @param o the reference object with which to compare. * @return true if this object is the same as the * o argument; false otherwise. * @see #hashCode() */ public boolean equals(Object o) { if (o == this) return (true); if (!(o instanceof KVOpExpression)) return (false); KVOpExpression other = (KVOpExpression) o; if (getName().compareTo(other.getName()) != 0 || op != other.getOp() || val != other.getValue()) return (false); return (true); } /** * Returns a hash code value for the object. This method is * supported for the benefit of hashtables such as those provided by * java.util.Hashtable. * * @return a hash code value for this object. * @see #equals(java.lang.Object) * @see java.util.Hashtable */ public int hashCode() { return (getName().hashCode() + (int) op + val); } /** * Return true if the supplied expression "contradicts" this * expression. If the supplied expression is not of the same * type, then it cannot contradict it. If the names are * different then there can be no contradiction. * * Contradiction occurs if the operator is the same or if they * aren't the same and the operator is < or > and the values * aren't simultanteously achievable. * * @param o Expression to examine for contradiction. */ public boolean contradicts(Expression o) { if (!(o instanceof KVOpExpression)) return (false); KVOpExpression other = (KVOpExpression) o; if (getName().compareTo(other.getName()) != 0) return (false); if (getOp() != other.getOp()) { if (getOp() != NT && other.getOp() != NT) { if (getOp() == GT) { if (getValue() < other.getValue()) return (false); } else { if (getValue() > other.getValue()) return (false); } } else return (false); } return (true); } } /** * This class implements the functionality for a key-value expression. * * The general form of this expression is defined in the pattern * member. A simplified rendition of which is: * * [[imp]:] * * key is a string which identifies the expression * value is the value of the expression * * For example: * * 10: locality tight */ final class KVExpression extends Expression { /** * The value of this expression. */ private String val; /** * The pattern used to recognize this type of expression. */ private static final Pattern pattern = Pattern.compile( "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s+(tight|loose|none)\\s*"); /** * The array of valid keys for this type of expression. */ private static final String keys[] = { "locality" }; /** * Private constructor used in the valueOf() factory method. * * @param imp The importance of this expression. * @param name The name of this expression. * @param val The value of this expression. */ private KVExpression(long imp, String name, String val) { super(imp, name); this.val = val; } /** * Create and return an expression from the input string. * * Determine if the input string matches the syntax defined by * this expression. If the expression cannot be matched, an * exception will be thrown. * * @param raw Candidate expression string. * * @throws IllegalArgumentExpression if the string is not a * valid expression of this type. */ static Expression valueOf(String raw) throws IllegalArgumentException { KVExpression exp = null; Matcher m = pattern.matcher(raw); if (m.matches()) { long imp = 1; if (m.group(2) != null) imp = validateImportance(m.group(2)); validateKeyword(keys, m.group(3)); exp = new KVExpression(imp, m.group(3), m.group(4)); } return (exp); } /** * Return the value of this expression. */ String getValue() { return (val); } /** * Return a string representation of this expresssion. */ public String toString() { StringBuffer buf = new StringBuffer(); buf.append("("); buf.append(getImportance()); buf.append(", "); buf.append(getName()); buf.append(", "); buf.append(val); buf.append(")"); return (buf.toString()); } /** * Indicates whether some other KVExpression is "equal to * this one. * @param o the reference object with which to compare. * @return true if this object is the same as the * o argument; false otherwise. * @see #hashCode() */ public boolean equals(Object o) { if (o == this) return (true); if (!(o instanceof KVExpression)) return (false); KVExpression other = (KVExpression) o; if (getName().compareTo(other.getName()) != 0 || val.compareTo(other.getValue()) != 0) return (false); return (true); } /** * Returns a hash code value for the object. This method is * supported for the benefit of hashtables such as those provided by * java.util.Hashtable. * * @return a hash code value for this object. * @see #equals(java.lang.Object) * @see java.util.Hashtable */ public int hashCode() { return (getName().hashCode() + val.hashCode()); } /** * Return true if the supplied expression "contradicts" this * expression. If the supplied expression is not of the same * type, then it cannot contradict it. If the names are * different then there can be no contradiction. * * Contradiction occurs if the value is different. * * @param o Expression to examine for contradiction. */ public boolean contradicts(Expression o) { if (!(o instanceof KVExpression)) return (false); KVExpression other = (KVExpression) o; if (getName().compareTo(other.getName()) != 0) return (false); if (val.compareTo(other.getValue()) == 0) return (false); return (true); } } /** * This class implements the functionality for a key expression. * * The general form of this expression is defined in the pattern * member. A simplified rendition of which is: * * [[imp]:] * * key is a string which identifies the expression * * For example: * * 10: wt-load */ final class KExpression extends Expression { /** * The pattern used to recognize this type of expression. */ private static final Pattern pattern = Pattern.compile( "\\s*((\\d+)\\s*:)?\\s*([\\w-]+)\\s*"); /** * The array of valid keys for this type of expression. */ private static final String keys[] = { "wt-load" }; /** * Private constructor used in the valueOf() factory method. * * @param imp The importance of this expression. * @param name The name of this expression. */ private KExpression(long imp, String name) { super(imp, name); } /** * Create and return an expression from the input string. * * Determine if the input string matches the syntax defined by * this expression. If the expression cannot be matched, an * exception will be thrown. * * @param raw Candidate expression string. * * @throws IllegalArgumentExpression if the string is not a * valid expression of this type. */ static Expression valueOf(String raw) throws IllegalArgumentException { KExpression exp = null; Matcher m = pattern.matcher(raw); if (m.matches()) { long imp = 1; if (m.group(2) != null) imp = validateImportance(m.group(2)); validateKeyword(keys, m.group(3)); exp = new KExpression(imp, m.group(3)); } return (exp); } /** * Return a string representation of this expresssion. */ public String toString() { return ("(" + getImportance() + ", " + getName() + ")"); } /** * Indicates whether some other KExpression is "equal to * this one. * @param o the reference object with which to compare. * @return true if this object is the same as the * o argument; false otherwise. * @see #hashCode() */ public boolean equals(Object o) { if (o == this) return (true); if (!(o instanceof KExpression)) return (false); KExpression other = (KExpression) o; if (getName().compareTo(other.getName()) != 0) return (false); return (true); } /** * Returns a hash code value for the object. This method is * supported for the benefit of hashtables such as those provided by * java.util.Hashtable. * * @return a hash code value for this object. * @see #equals(java.lang.Object) * @see java.util.Hashtable */ public int hashCode() { return (getName().hashCode()); } /** * Return true if the supplied expression "contradicts" this * expression. If the supplied expression is not of the same * type, then it cannot contradict it. If the names are * different then there can be no contradiction. * * @param o Expression to examine for contradiction. */ public boolean contradicts(Expression o) { if (!(o instanceof KExpression)) return (false); KExpression other = (KExpression) o; if (getName().compareTo(other.getName()) != 0) return (false); return (true); } }