0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2006 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal;
0011:
0012: import java.util.ArrayList;
0013: import java.util.Collection;
0014: import java.util.HashSet;
0015: import java.util.Iterator;
0016: import java.util.List;
0017:
0018: import org.eclipse.core.runtime.IConfigurationElement;
0019: import org.eclipse.core.runtime.Platform;
0020: import org.eclipse.jface.viewers.IStructuredSelection;
0021: import org.eclipse.ui.IActionFilter;
0022: import org.eclipse.ui.internal.util.BundleUtility;
0023: import org.eclipse.ui.internal.util.Util;
0024: import org.osgi.framework.Bundle;
0025:
0026: /**
0027: * An ActionExpression is used to evaluate the enablement / visibility criteria
0028: * for an action.
0029: */
0030: public class ActionExpression {
0031:
0032: private static abstract class AbstractExpression {
0033:
0034: /**
0035: * The hash code for this object. This value is computed lazily, and
0036: * marked as invalid when one of the values on which it is based
0037: * changes.
0038: */
0039: protected transient int expressionHashCode = HASH_CODE_NOT_COMPUTED;
0040:
0041: /**
0042: * Extract the object class tests from the expression. This allows
0043: * clients (e.g. the decorator manager) to handle object class testing
0044: * in a more optimized way. This method extracts the objectClass test
0045: * from the expression and returns the object classes. The expression is
0046: * not changed and a <code>null</code> is returned if no object class
0047: * is found.
0048: *
0049: * @return String[] the object class names or <code>null</code> if
0050: * none was found.
0051: */
0052: public String[] extractObjectClasses() {
0053: return null;
0054: }
0055:
0056: /**
0057: * Returns whether the expression is valid for the given object.
0058: *
0059: * @param object
0060: * the object to validate against (can be <code>null</code>)
0061: * @return boolean whether the expression is valid for the object.
0062: */
0063: public abstract boolean isEnabledFor(Object object);
0064:
0065: /**
0066: * Returns whether or not the receiver is potentially valid for the
0067: * object via just the extension type. Currently the only supported
0068: * expression type is <code>EXP_TYPE_OBJECT_CLASS</code>.
0069: *
0070: * @param object
0071: * the object to validate against (can be <code>null</code>)
0072: * @param expressionType
0073: * the expression type to consider
0074: * @return boolean whether the expression is potentially valid for the
0075: * object.
0076: */
0077: public boolean isEnabledForExpression(Object object,
0078: String expressionType) {
0079: return false;
0080: }
0081:
0082: /**
0083: * Return the value of the expression type that the receiver is enabled
0084: * for. If the receiver is not enabled for the expressionType then
0085: * return <code>null</code>.
0086: *
0087: * @param expressionType
0088: * the expression type to consider
0089: * @return Collection of String if there are values for this expression
0090: * or <code>null</code> if this is not possible in the
0091: * receiver or any of it's children
0092: */
0093: public Collection valuesForExpression(String expressionType) {
0094: return null;
0095: }
0096: }
0097:
0098: private static class AndExpression extends CompositeExpression {
0099:
0100: /**
0101: * Creates and populates the expression from the attributes and sub-
0102: * elements of the configuration element.
0103: *
0104: * @param element
0105: * The element that will be used to determine the expressions
0106: * for And.
0107: * @throws IllegalStateException
0108: * if the expression tag is not defined in the schema.
0109: */
0110: public AndExpression(IConfigurationElement element)
0111: throws IllegalStateException {
0112: super (element);
0113: }
0114:
0115: public final boolean equals(final Object object) {
0116: if (object instanceof AndExpression) {
0117: final AndExpression that = (AndExpression) object;
0118: return Util.equals(this .list, that.list);
0119: }
0120:
0121: return false;
0122: }
0123:
0124: /*
0125: * (non-Javadoc) Method declared on AbstractExpression.
0126: */
0127: public boolean isEnabledFor(Object object) {
0128: Iterator iter = list.iterator();
0129: while (iter.hasNext()) {
0130: AbstractExpression expr = (AbstractExpression) iter
0131: .next();
0132: if (!expr.isEnabledFor(object)) {
0133: return false;
0134: }
0135: }
0136: return true;
0137: }
0138: }
0139:
0140: private static abstract class CompositeExpression extends
0141: AbstractExpression {
0142: /**
0143: *
0144: */
0145: protected ArrayList list;
0146:
0147: /**
0148: * Creates and populates the expression from the attributes and sub-
0149: * elements of the configuration element.
0150: *
0151: * @param element
0152: * The composite element we will create the expression from.
0153: * @throws IllegalStateException
0154: * if the expression tag is not defined in the schema.
0155: */
0156: public CompositeExpression(IConfigurationElement element)
0157: throws IllegalStateException {
0158: super ();
0159:
0160: IConfigurationElement[] children = element.getChildren();
0161: if (children.length == 0) {
0162: throw new IllegalStateException(
0163: "Composite expression cannot be empty"); //$NON-NLS-1$
0164: }
0165:
0166: list = new ArrayList(children.length);
0167: for (int i = 0; i < children.length; i++) {
0168: String tag = children[i].getName();
0169: AbstractExpression expr = createExpression(children[i]);
0170: if (EXP_TYPE_OBJECT_CLASS.equals(tag)) {
0171: list.add(0, expr);
0172: } else {
0173: list.add(expr);
0174: }
0175: }
0176: }
0177:
0178: /*
0179: * (non-Javadoc)
0180: *
0181: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#extractObjectClasses()
0182: */
0183: public String[] extractObjectClasses() {
0184: Iterator iterator = list.iterator();
0185: List classNames = null;
0186: while (iterator.hasNext()) {
0187: AbstractExpression next = (AbstractExpression) iterator
0188: .next();
0189: String[] objectClasses = next.extractObjectClasses();
0190: if (objectClasses != null) {
0191: if (classNames == null) {
0192: classNames = new ArrayList();
0193: }
0194: for (int i = 0; i < objectClasses.length; i++) {
0195: classNames.add(objectClasses[i]);
0196: }
0197: }
0198: }
0199: if (classNames == null) {
0200: return null;
0201: }
0202:
0203: String[] returnValue = new String[classNames.size()];
0204: classNames.toArray(returnValue);
0205: return returnValue;
0206: }
0207:
0208: /**
0209: * Computes the hash code for this object based on the id.
0210: *
0211: * @return The hash code for this object.
0212: */
0213: public final int hashCode() {
0214: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0215: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0216: + Util.hashCode(list);
0217: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0218: expressionHashCode++;
0219: }
0220: }
0221: return expressionHashCode;
0222: }
0223:
0224: /*
0225: * (non-Javadoc) Method declared on AbstractExpression.
0226: */
0227: public boolean isEnabledForExpression(Object object,
0228: String expressionType) {
0229: Iterator iterator = list.iterator();
0230: while (iterator.hasNext()) {
0231: AbstractExpression next = (AbstractExpression) iterator
0232: .next();
0233: if (next.isEnabledForExpression(object, expressionType)) {
0234: return true;
0235: }
0236: }
0237: return false;
0238: }
0239:
0240: /*
0241: * (non-Javadoc)
0242: *
0243: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#valuesForExpression(java.lang.String)
0244: */
0245: public Collection valuesForExpression(String expressionType) {
0246: Iterator iterator = list.iterator();
0247: Collection allValues = null;
0248: while (iterator.hasNext()) {
0249: AbstractExpression next = (AbstractExpression) iterator
0250: .next();
0251: Collection values = next
0252: .valuesForExpression(expressionType);
0253: if (values != null) {
0254: if (allValues == null) {
0255: allValues = values;
0256: } else {
0257: allValues.addAll(values);
0258: }
0259: }
0260:
0261: }
0262: return allValues;
0263: }
0264: }
0265:
0266: private static class NotExpression extends SingleExpression {
0267:
0268: /**
0269: * Creates and populates the expression from the attributes and sub-
0270: * elements of the configuration element.
0271: *
0272: * @param element
0273: * The element that will be used to create the definition for
0274: * the receiver.
0275: * @throws IllegalStateException
0276: * if the expression tag is not defined in the schema.
0277: */
0278: public NotExpression(IConfigurationElement element)
0279: throws IllegalStateException {
0280: super (element);
0281: }
0282:
0283: /*
0284: * (non-Javadoc) Method declared on AbstractExpression.
0285: */
0286: public boolean isEnabledFor(Object object) {
0287: return !super .isEnabledFor(object);
0288: }
0289: }
0290:
0291: private static class ObjectClassExpression extends
0292: AbstractExpression {
0293: private String className;
0294:
0295: private boolean extracted;
0296:
0297: /**
0298: * Creates and populates the expression from the attributes and sub-
0299: * elements of the configuration element.
0300: *
0301: * @param element
0302: * The element that will be used to determine the expressions
0303: * for objectClass.
0304: * @throws IllegalStateException
0305: * if the expression tag is not defined in the schema.
0306: */
0307: public ObjectClassExpression(IConfigurationElement element)
0308: throws IllegalStateException {
0309: super ();
0310:
0311: className = element.getAttribute(ATT_NAME);
0312: if (className == null) {
0313: throw new IllegalStateException(
0314: "Object class expression missing name attribute"); //$NON-NLS-1$
0315: }
0316: }
0317:
0318: /**
0319: * Create an ObjectClass expression based on the className. Added for
0320: * backwards compatibility.
0321: *
0322: * @param className
0323: */
0324: public ObjectClassExpression(String className) {
0325: super ();
0326:
0327: if (className != null) {
0328: this .className = className;
0329: } else {
0330: throw new IllegalStateException(
0331: "Object class expression must have class name"); //$NON-NLS-1$
0332: }
0333: }
0334:
0335: /**
0336: * Check the interfaces the whole way up. If one of them matches
0337: * className return <code>true</code>.
0338: *
0339: * @param interfaceToCheck
0340: * The interface whose name we are testing against.
0341: * @return <code>true</code> if one of the interfaces in the hierarchy
0342: * matches className, <code>false</code> otherwise.
0343: */
0344: private boolean checkInterfaceHierarchy(Class interfaceToCheck) {
0345: if (interfaceToCheck.getName().equals(className)) {
0346: return true;
0347: }
0348: Class[] super Interfaces = interfaceToCheck.getInterfaces();
0349: for (int i = 0; i < super Interfaces.length; i++) {
0350: if (checkInterfaceHierarchy(super Interfaces[i])) {
0351: return true;
0352: }
0353: }
0354: return false;
0355: }
0356:
0357: public final boolean equals(final Object object) {
0358: if (object instanceof ObjectClassExpression) {
0359: final ObjectClassExpression that = (ObjectClassExpression) object;
0360: return Util.equals(this .className, that.className)
0361: && Util.equals(this .extracted, that.extracted);
0362: }
0363:
0364: return false;
0365: }
0366:
0367: /*
0368: * (non-Javadoc)
0369: *
0370: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#extractObjectClasses()
0371: */
0372: public String[] extractObjectClasses() {
0373: extracted = true;
0374: return new String[] { className };
0375: }
0376:
0377: /**
0378: * Computes the hash code for this object based on the id.
0379: *
0380: * @return The hash code for this object.
0381: */
0382: public final int hashCode() {
0383: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0384: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0385: + Util.hashCode(className);
0386: expressionHashCode = expressionHashCode * HASH_FACTOR
0387: + Util.hashCode(extracted);
0388: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0389: expressionHashCode++;
0390: }
0391: }
0392: return expressionHashCode;
0393: }
0394:
0395: /*
0396: * (non-Javadoc) Method declared on AbstractExpression.
0397: */
0398: public boolean isEnabledFor(Object object) {
0399: if (object == null) {
0400: return false;
0401: }
0402: if (extracted) {
0403: return true;
0404: }
0405:
0406: Class clazz = object.getClass();
0407: while (clazz != null) {
0408: // test the class itself
0409: if (clazz.getName().equals(className)) {
0410: return true;
0411: }
0412:
0413: // test all the interfaces the class implements
0414: Class[] interfaces = clazz.getInterfaces();
0415: for (int i = 0; i < interfaces.length; i++) {
0416: if (checkInterfaceHierarchy(interfaces[i])) {
0417: return true;
0418: }
0419: }
0420:
0421: // get the superclass
0422: clazz = clazz.getSuperclass();
0423: }
0424:
0425: return false;
0426: }
0427:
0428: /*
0429: * (non-Javadoc) Method declared on AbstractExpression.
0430: */
0431: public boolean isEnabledForExpression(Object object,
0432: String expressionType) {
0433: if (expressionType.equals(EXP_TYPE_OBJECT_CLASS)) {
0434: return isEnabledFor(object);
0435: }
0436: return false;
0437: }
0438: }
0439:
0440: private static class ObjectStateExpression extends
0441: AbstractExpression {
0442: private String name;
0443:
0444: private String value;
0445:
0446: /**
0447: * Creates and populates the expression from the attributes and sub-
0448: * elements of the configuration element.
0449: *
0450: * @param element
0451: * The element that will be used to determine the expressions
0452: * for objectState.
0453: * @throws IllegalStateException
0454: * if the expression tag is not defined in the schema.
0455: */
0456: public ObjectStateExpression(IConfigurationElement element)
0457: throws IllegalStateException {
0458: super ();
0459:
0460: name = element.getAttribute(ATT_NAME);
0461: value = element.getAttribute(ATT_VALUE);
0462: if (name == null || value == null) {
0463: throw new IllegalStateException(
0464: "Object state expression missing attribute"); //$NON-NLS-1$
0465: }
0466: }
0467:
0468: public final boolean equals(final Object object) {
0469: if (object instanceof ObjectStateExpression) {
0470: final ObjectStateExpression that = (ObjectStateExpression) object;
0471: return Util.equals(this .name, that.name)
0472: && Util.equals(this .value, that.value);
0473: }
0474:
0475: return false;
0476: }
0477:
0478: private IActionFilter getActionFilter(Object object) {
0479: return (IActionFilter) Util.getAdapter(object,
0480: IActionFilter.class);
0481: }
0482:
0483: /**
0484: * Computes the hash code for this object based on the id.
0485: *
0486: * @return The hash code for this object.
0487: */
0488: public final int hashCode() {
0489: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0490: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0491: + Util.hashCode(name);
0492: expressionHashCode = expressionHashCode * HASH_FACTOR
0493: + Util.hashCode(value);
0494: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0495: expressionHashCode++;
0496: }
0497: }
0498: return expressionHashCode;
0499: }
0500:
0501: /*
0502: * (non-Javadoc) Method declared on AbstractExpression.
0503: */
0504: public boolean isEnabledFor(Object object) {
0505: if (object == null) {
0506: return false;
0507: }
0508:
0509: // Try out the object first.
0510: if (preciselyMatches(object)) {
0511: return true;
0512: }
0513:
0514: // Try out the underlying resource.
0515: Class resourceClass = LegacyResourceSupport
0516: .getResourceClass();
0517: if (resourceClass == null) {
0518: return false;
0519: }
0520:
0521: if (resourceClass.isInstance(object)) {
0522: return false;
0523: }
0524:
0525: Object res = Util.getAdapter(object, resourceClass);
0526: if (res == null) {
0527: return false;
0528: }
0529:
0530: return preciselyMatches(res);
0531:
0532: }
0533:
0534: private boolean preciselyMatches(Object object) {
0535: // Get the action filter.
0536: IActionFilter filter = getActionFilter(object);
0537: if (filter == null) {
0538: return false;
0539: }
0540:
0541: // Run the action filter.
0542: return filter.testAttribute(object, name, value);
0543: }
0544:
0545: /*
0546: * (non-Javadoc)
0547: *
0548: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#valuesForExpression(java.lang.String)
0549: */
0550: public Collection valuesForExpression(String expressionType) {
0551: if (expressionType.equals(name)) {
0552: Collection returnValue = new HashSet();
0553: returnValue.add(value);
0554: return returnValue;
0555: }
0556: return null;
0557: }
0558:
0559: }
0560:
0561: private static class OrExpression extends CompositeExpression {
0562:
0563: /**
0564: * Creates and populates the expression from the attributes and sub-
0565: * elements of the configuration element.
0566: *
0567: * @param element
0568: * The element that will be used to determine the expressions
0569: * for Or.
0570: * @throws IllegalStateException
0571: * if the expression tag is not defined in the schema.
0572: */
0573: public OrExpression(IConfigurationElement element)
0574: throws IllegalStateException {
0575: super (element);
0576: }
0577:
0578: public final boolean equals(final Object object) {
0579: if (object instanceof OrExpression) {
0580: final OrExpression that = (OrExpression) object;
0581: return Util.equals(this .list, that.list);
0582: }
0583:
0584: return false;
0585: }
0586:
0587: /*
0588: * (non-Javadoc) Method declared on AbstractExpression.
0589: */
0590: public boolean isEnabledFor(Object object) {
0591: Iterator iter = list.iterator();
0592: while (iter.hasNext()) {
0593: AbstractExpression expr = (AbstractExpression) iter
0594: .next();
0595: if (expr.isEnabledFor(object)) {
0596: return true;
0597: }
0598: }
0599: return false;
0600: }
0601: }
0602:
0603: private static class PluginStateExpression extends
0604: AbstractExpression {
0605: private String id;
0606:
0607: private String value;
0608:
0609: /**
0610: * Creates and populates the expression from the attributes and sub-
0611: * elements of the configuration element.
0612: *
0613: * @param element
0614: * The element that will be used to determine the expressions
0615: * for pluginState.
0616: * @throws IllegalStateException
0617: * if the expression tag is not defined in the schema.
0618: */
0619: public PluginStateExpression(IConfigurationElement element)
0620: throws IllegalStateException {
0621: super ();
0622:
0623: id = element.getAttribute(ATT_ID);
0624: value = element.getAttribute(ATT_VALUE);
0625: if (id == null || value == null) {
0626: throw new IllegalStateException(
0627: "Plugin state expression missing attribute"); //$NON-NLS-1$
0628: }
0629: }
0630:
0631: public final boolean equals(final Object object) {
0632: if (object instanceof PluginStateExpression) {
0633: final PluginStateExpression that = (PluginStateExpression) object;
0634: return Util.equals(this .id, that.id)
0635: && Util.equals(this .value, that.value);
0636: }
0637:
0638: return false;
0639: }
0640:
0641: /**
0642: * Computes the hash code for this object based on the id.
0643: *
0644: * @return The hash code for this object.
0645: */
0646: public final int hashCode() {
0647: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0648: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0649: + Util.hashCode(id);
0650: expressionHashCode = expressionHashCode * HASH_FACTOR
0651: + Util.hashCode(value);
0652: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0653: expressionHashCode++;
0654: }
0655: }
0656: return expressionHashCode;
0657: }
0658:
0659: /*
0660: * (non-Javadoc) Method declared on AbstractExpression.
0661: */
0662: public boolean isEnabledFor(Object object) {
0663: Bundle bundle = Platform.getBundle(id);
0664: if (!BundleUtility.isReady(bundle)) {
0665: return false;
0666: }
0667: if (value.equals(PLUGIN_INSTALLED)) {
0668: return true;
0669: }
0670: if (value.equals(PLUGIN_ACTIVATED)) {
0671: return BundleUtility.isActivated(bundle);
0672: }
0673: return false;
0674: }
0675: }
0676:
0677: private static class SingleExpression extends AbstractExpression {
0678: private AbstractExpression child;
0679:
0680: /**
0681: * Create a single expression from the abstract definition.
0682: *
0683: * @param expression
0684: * The expression that will be the child of the new single
0685: * expression.
0686: * @throws IllegalStateException
0687: * if the expression tag is not defined in the schema.
0688: */
0689: public SingleExpression(AbstractExpression expression)
0690: throws IllegalStateException {
0691: super ();
0692:
0693: if (expression != null) {
0694: child = expression;
0695: } else {
0696: throw new IllegalStateException(
0697: "Single expression must contain 1 expression"); //$NON-NLS-1$
0698: }
0699: }
0700:
0701: /**
0702: * Creates and populates the expression from the attributes and sub-
0703: * elements of the configuration element.
0704: *
0705: * @param element
0706: * The element to create the expression from.
0707: * @throws IllegalStateException
0708: * if the expression tag is not defined in the schema.
0709: */
0710: public SingleExpression(IConfigurationElement element)
0711: throws IllegalStateException {
0712: super ();
0713:
0714: IConfigurationElement[] children = element.getChildren();
0715: if (children.length != 1) {
0716: throw new IllegalStateException(
0717: "Single expression does not contain only 1 expression"); //$NON-NLS-1$
0718: }
0719: child = createExpression(children[0]);
0720: }
0721:
0722: public final boolean equals(final Object object) {
0723: if (object instanceof SingleExpression) {
0724: final SingleExpression that = (SingleExpression) object;
0725: return Util.equals(this .child, that.child);
0726: }
0727:
0728: return false;
0729: }
0730:
0731: /*
0732: * (non-Javadoc)
0733: *
0734: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#extractObjectClasses()
0735: */
0736: public String[] extractObjectClasses() {
0737: return child.extractObjectClasses();
0738: }
0739:
0740: /**
0741: * Computes the hash code for this object based on the id.
0742: *
0743: * @return The hash code for this object.
0744: */
0745: public final int hashCode() {
0746: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0747: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0748: + Util.hashCode(child);
0749: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0750: expressionHashCode++;
0751: }
0752: }
0753: return expressionHashCode;
0754: }
0755:
0756: /*
0757: * (non-Javadoc) Method declared on AbstractExpression.
0758: */
0759: public boolean isEnabledFor(Object object) {
0760: return child.isEnabledFor(object);
0761: }
0762:
0763: /*
0764: * (non-Javadoc) Method declared on AbstractExpression.
0765: */
0766: public boolean isEnabledForExpression(Object object,
0767: String expressionType) {
0768: return child.isEnabledForExpression(object, expressionType);
0769: }
0770:
0771: /*
0772: * (non-Javadoc)
0773: *
0774: * @see org.eclipse.ui.internal.ActionExpression.AbstractExpression#valuesForExpression(java.lang.String)
0775: */
0776: public Collection valuesForExpression(String expressionType) {
0777: return child.valuesForExpression(expressionType);
0778: }
0779:
0780: }
0781:
0782: private static class SystemPropertyExpression extends
0783: AbstractExpression {
0784: private String name;
0785:
0786: private String value;
0787:
0788: /**
0789: * Creates and populates the expression from the attributes and sub-
0790: * elements of the configuration element.
0791: *
0792: * @param element
0793: * The element that will be used to determine the expressions
0794: * for systemProperty.
0795: * @throws IllegalStateException
0796: * if the expression tag is not defined in the schema.
0797: */
0798: public SystemPropertyExpression(IConfigurationElement element)
0799: throws IllegalStateException {
0800: super ();
0801:
0802: name = element.getAttribute(ATT_NAME);
0803: value = element.getAttribute(ATT_VALUE);
0804: if (name == null || value == null) {
0805: throw new IllegalStateException(
0806: "System property expression missing attribute"); //$NON-NLS-1$
0807: }
0808: }
0809:
0810: /*
0811: * (non-Javadoc) Method declared on AbstractExpression.
0812: */
0813: public boolean isEnabledFor(Object object) {
0814: String str = System.getProperty(name);
0815: if (str == null) {
0816: return false;
0817: }
0818: return value.equals(str);
0819: }
0820:
0821: public final boolean equals(final Object object) {
0822: if (object instanceof SystemPropertyExpression) {
0823: final SystemPropertyExpression that = (SystemPropertyExpression) object;
0824: return Util.equals(this .name, that.name)
0825: && Util.equals(this .value, that.value);
0826: }
0827:
0828: return false;
0829: }
0830:
0831: /**
0832: * Computes the hash code for this object based on the id.
0833: *
0834: * @return The hash code for this object.
0835: */
0836: public final int hashCode() {
0837: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0838: expressionHashCode = HASH_INITIAL * HASH_FACTOR
0839: + Util.hashCode(name);
0840: expressionHashCode = expressionHashCode * HASH_FACTOR
0841: + Util.hashCode(value);
0842: if (expressionHashCode == HASH_CODE_NOT_COMPUTED) {
0843: expressionHashCode++;
0844: }
0845: }
0846: return expressionHashCode;
0847: }
0848: }
0849:
0850: private static final String ATT_ID = "id"; //$NON-NLS-1$
0851:
0852: private static final String ATT_NAME = "name"; //$NON-NLS-1$
0853:
0854: private static final String ATT_VALUE = "value"; //$NON-NLS-1$
0855:
0856: /**
0857: * Constant definition for AND.
0858: *
0859: */
0860: public static final String EXP_TYPE_AND = "and"; //$NON-NLS-1$
0861:
0862: /**
0863: * Constant definition for NOT.
0864: *
0865: */
0866: public static final String EXP_TYPE_NOT = "not"; //$NON-NLS-1$
0867:
0868: /**
0869: * Constant definition for objectClass.
0870: *
0871: */
0872: public static final String EXP_TYPE_OBJECT_CLASS = "objectClass"; //$NON-NLS-1$
0873:
0874: /**
0875: * Constant definition for objectState.
0876: *
0877: */
0878: public static final String EXP_TYPE_OBJECT_STATE = "objectState"; //$NON-NLS-1$
0879:
0880: /**
0881: * Constant definition for OR.
0882: *
0883: */
0884: public static final String EXP_TYPE_OR = "or"; //$NON-NLS-1$
0885:
0886: /**
0887: * Constant definition for pluginState.
0888: *
0889: */
0890: public static final String EXP_TYPE_PLUG_IN_STATE = "pluginState"; //$NON-NLS-1$
0891:
0892: /**
0893: * Constant definition for systemProperty.
0894: *
0895: */
0896: public static final String EXP_TYPE_SYSTEM_PROPERTY = "systemProperty"; //$NON-NLS-1$
0897:
0898: /**
0899: * The constant integer hash code value meaning the hash code has not yet
0900: * been computed.
0901: */
0902: private static final int HASH_CODE_NOT_COMPUTED = -1;
0903:
0904: /**
0905: * A factor for computing the hash code for all schemes.
0906: */
0907: private static final int HASH_FACTOR = 89;
0908:
0909: /**
0910: * The seed for the hash code for all schemes.
0911: */
0912: private static final int HASH_INITIAL = ActionExpression.class
0913: .getName().hashCode();
0914:
0915: private static final String PLUGIN_ACTIVATED = "activated"; //$NON-NLS-1$
0916:
0917: private static final String PLUGIN_INSTALLED = "installed"; //$NON-NLS-1$
0918:
0919: /**
0920: * Create an expression from the attributes and sub-elements of the
0921: * configuration element.
0922: *
0923: * @param element
0924: * The IConfigurationElement with a tag defined in the public
0925: * constants.
0926: * @return AbstractExpression based on the definition
0927: * @throws IllegalStateException
0928: * if the expression tag is not defined in the schema.
0929: */
0930: private static AbstractExpression createExpression(
0931: IConfigurationElement element) throws IllegalStateException {
0932: String tag = element.getName();
0933: if (tag.equals(EXP_TYPE_OR)) {
0934: return new OrExpression(element);
0935: }
0936: if (tag.equals(EXP_TYPE_AND)) {
0937: return new AndExpression(element);
0938: }
0939: if (tag.equals(EXP_TYPE_NOT)) {
0940: return new NotExpression(element);
0941: }
0942: if (tag.equals(EXP_TYPE_OBJECT_STATE)) {
0943: return new ObjectStateExpression(element);
0944: }
0945: if (tag.equals(EXP_TYPE_OBJECT_CLASS)) {
0946: return new ObjectClassExpression(element);
0947: }
0948: if (tag.equals(EXP_TYPE_PLUG_IN_STATE)) {
0949: return new PluginStateExpression(element);
0950: }
0951: if (tag.equals(EXP_TYPE_SYSTEM_PROPERTY)) {
0952: return new SystemPropertyExpression(element);
0953: }
0954:
0955: throw new IllegalStateException(
0956: "Action expression unrecognized element: " + tag); //$NON-NLS-1$
0957: }
0958:
0959: /**
0960: * The hash code for this object. This value is computed lazily, and marked
0961: * as invalid when one of the values on which it is based changes.
0962: */
0963: private transient int hashCode = HASH_CODE_NOT_COMPUTED;
0964:
0965: private SingleExpression root;
0966:
0967: /**
0968: * Creates an action expression for the given configuration element.
0969: *
0970: * @param element
0971: * The element to build the expression from.
0972: */
0973: public ActionExpression(IConfigurationElement element) {
0974: try {
0975: root = new SingleExpression(element);
0976: } catch (IllegalStateException e) {
0977: e.printStackTrace();
0978: root = null;
0979: }
0980: }
0981:
0982: /**
0983: * Create an instance of the receiver with the given expression type and
0984: * value. Currently the only supported expression type is
0985: * <code>EXP_TYPE_OBJECT_CLASS</code>.
0986: *
0987: * @param expressionType
0988: * The expression constant we are creating an instance of.
0989: * @param expressionValue
0990: * The name of the class we are creating an expression for.
0991: */
0992: public ActionExpression(String expressionType,
0993: String expressionValue) {
0994: if (expressionType.equals(EXP_TYPE_OBJECT_CLASS)) {
0995: root = new SingleExpression(new ObjectClassExpression(
0996: expressionValue));
0997: }
0998: }
0999:
1000: public final boolean equals(final Object object) {
1001: if (object instanceof ActionExpression) {
1002: final ActionExpression that = (ActionExpression) object;
1003: return Util.equals(this .root, that.root);
1004: }
1005:
1006: return false;
1007: }
1008:
1009: /**
1010: * Extract the object class test from the expression. This allows clients
1011: * (e.g. the decorator manager) to handle object class testing in a more
1012: * optimized way. This method removes the objectClass test from the
1013: * expression and returns the object class. The expression is not changed
1014: * and a <code>null</code> is returned if no object class is found.
1015: *
1016: * @return the object class or <code>null</code> if none was found.
1017: */
1018: public String[] extractObjectClasses() {
1019: return root.extractObjectClasses();
1020: }
1021:
1022: /**
1023: * Computes the hash code for this object based on the id.
1024: *
1025: * @return The hash code for this object.
1026: */
1027: public final int hashCode() {
1028: if (hashCode == HASH_CODE_NOT_COMPUTED) {
1029: hashCode = HASH_INITIAL * HASH_FACTOR + Util.hashCode(root);
1030: if (hashCode == HASH_CODE_NOT_COMPUTED) {
1031: hashCode++;
1032: }
1033: }
1034: return hashCode;
1035: }
1036:
1037: /**
1038: * Returns whether the expression is valid for all elements of the given
1039: * selection.
1040: *
1041: * @param selection
1042: * the structured selection to use
1043: * @return boolean whether the expression is valid for the selection.
1044: */
1045: public boolean isEnabledFor(IStructuredSelection selection) {
1046: if (root == null) {
1047: return false;
1048: }
1049:
1050: if (selection == null || selection.isEmpty()) {
1051: return root.isEnabledFor(null);
1052: }
1053:
1054: Iterator elements = selection.iterator();
1055: while (elements.hasNext()) {
1056: if (!isEnabledFor(elements.next())) {
1057: return false;
1058: }
1059: }
1060: return true;
1061: }
1062:
1063: /**
1064: * Returns whether the expression is valid for the given object.
1065: *
1066: * @param object
1067: * the object to validate against (can be <code>null</code>)
1068: * @return boolean whether the expression is valid for the object.
1069: */
1070: public boolean isEnabledFor(Object object) {
1071: if (root == null) {
1072: return false;
1073: }
1074: return root.isEnabledFor(object);
1075: }
1076:
1077: /**
1078: * Returns whether or not the receiver is potentially valid for the object
1079: * via just the extension type. Currently the only supported expression type
1080: * is <code>EXP_TYPE_OBJECT_CLASS</code>.
1081: *
1082: * @param object
1083: * the object to validate against (can be <code>null</code>)
1084: * @param expressionType
1085: * the expression type to consider
1086: * @return boolean whether the expression is potentially valid for the
1087: * object.
1088: */
1089: public boolean isEnabledForExpression(Object object,
1090: String expressionType) {
1091: if (root == null) {
1092: return false;
1093: }
1094: return root.isEnabledForExpression(object, expressionType);
1095: }
1096:
1097: /**
1098: * Return the values of the expression type that the receiver is enabled
1099: * for. If the receiver is not enabled for the expressionType then return
1100: * <code>null</code>.
1101: *
1102: * @param expressionType
1103: * the expression type to consider
1104: * @return Collection if there are values for this expression or
1105: * <code>null</code> if this is not possible in the receiver or
1106: * any of it's children
1107: */
1108: public Collection valuesForExpression(String expressionType) {
1109: return root.valuesForExpression(expressionType);
1110: }
1111: }
|