blob: 8768d9573917b074bd49dadc96b4d5050c9ee8c1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.bindings;
import org.eclipse.jface.util.Util;
/**
* <p>
* A sequence of one or more triggers. None of these triggers may be
* <code>null</code>.
* </p>
*
* @since 3.1
*/
public abstract class TriggerSequence {
/**
* The value to see that hash code to if the hash code is not yet computed.
*/
private static final int HASH_CODE_NOT_COMPUTED = -1;
/**
* A factor for computing the hash code for all trigger sequences.
*/
private static final int HASH_FACTOR = 89;
/**
* An internal constant used only in this object's hash code algorithm.
*/
private static final int HASH_INITIAL = TriggerSequence.class.getName()
.hashCode();
/**
* The hash code for this object. This value is computed lazily, and marked
* as invalid when one of the values on which it is based changes. This
* values is <code>HASH_CODE_NOT_COMPUTED</code> iff the hash code has not
* yet been computed.
*/
protected transient int hashCode = HASH_CODE_NOT_COMPUTED;
/**
* The list of trigger in this sequence. This value is never
* <code>null</code>, and never contains <code>null</code> elements.
*/
protected final Trigger[] triggers;
/**
* Constructs a new instance of <code>TriggerSequence</code>.
*
* @param triggers
* The triggers contained within this sequence; must not be
* <code>null</code> or contain <code>null</code> elements.
* May be empty.
*/
public TriggerSequence(final Trigger[] triggers) {
if (triggers == null) {
throw new NullPointerException("The triggers cannot be null"); //$NON-NLS-1$
}
for (int i = 0; i < triggers.length; i++) {
if (triggers[i] == null) {
throw new IllegalArgumentException(
"All triggers in a trigger sequence must be an instance of Trigger"); //$NON-NLS-1$
}
}
final int triggerLength = triggers.length;
this.triggers = new Trigger[triggerLength];
System.arraycopy(triggers, 0, this.triggers, 0, triggerLength);
}
/**
* Returns whether or not this key sequence ends with the given key
* sequence.
*
* @param triggerSequence
* a trigger sequence. Must not be <code>null</code>.
* @param equals
* whether or not an identical trigger sequence should be
* considered as a possible match.
* @return <code>true</code>, iff the given trigger sequence ends with
* this trigger sequence.
*/
public final boolean endsWith(final TriggerSequence triggerSequence,
final boolean equals) {
if (triggerSequence == null) {
throw new NullPointerException(
"Cannot end with a null trigger sequence"); //$NON-NLS-1$
}
return Util.endsWith(triggers, triggerSequence.triggers, equals);
}
public final boolean equals(final Object object) {
// Check if they're the same.
if (object == this) {
return true;
}
// Check if they're the same type.
if (!(object instanceof TriggerSequence))
return false;
final TriggerSequence triggerSequence = (TriggerSequence) object;
return Util.equals(triggers, triggerSequence.triggers);
}
/**
* Formats this trigger sequence into the current default look.
*
* @return A string representation for this trigger sequence using the
* default look; never <code>null</code>.
*/
public abstract String format();
/**
* <p>
* Returns a list of prefixes for the current sequence. A prefix is any
* leading subsequence in a <code>TriggerSequence</code>. A prefix is
* also an instance of <code>TriggerSequence</code>.
* </p>
* <p>
* For example, consider a trigger sequence that consists of four triggers:
* A, B, C and D. The prefixes would be "", "A", "A B", and "A B C". The
* list of prefixes must always be the same as the size of the trigger list.
* </p>
*
* @return The array of possible prefixes for this sequence. This array must
* not be <code>null</code>, but may be empty. It must only
* contains instances of <code>TriggerSequence</code>.
*/
public abstract TriggerSequence[] getPrefixes();
/**
* Returns the list of triggers.
*
* @return The triggers; never <code>null</code> and guaranteed to only
* contain instances of <code>Trigger</code>.
*/
public final Trigger[] getTriggers() {
final int triggerLength = triggers.length;
final Trigger[] triggerCopy = new Trigger[triggerLength];
System.arraycopy(triggers, 0, triggerCopy, 0, triggerLength);
return triggerCopy;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public final int hashCode() {
if (hashCode == HASH_CODE_NOT_COMPUTED) {
hashCode = HASH_INITIAL;
hashCode = hashCode * HASH_FACTOR + Util.hashCode(triggers);
if (hashCode == HASH_CODE_NOT_COMPUTED) {
hashCode++;
}
}
return hashCode;
}
/**
* Returns whether or not this trigger sequence is empty.
*
* @return <code>true</code>, iff the trigger sequence is empty.
*/
public final boolean isEmpty() {
return (triggers.length == 0);
}
/**
* Returns whether or not this trigger sequence starts with the given
* trigger sequence.
*
* @param triggerSequence
* a trigger sequence. Must not be <code>null</code>.
* @param equals
* whether or not an identical trigger sequence should be
* considered as a possible match.
* @return <code>true</code>, iff the given trigger sequence starts with
* this key sequence.
*/
public final boolean startsWith(final TriggerSequence triggerSequence,
final boolean equals) {
if (triggerSequence == null)
throw new NullPointerException(
"A trigger sequence cannot start with null"); //$NON-NLS-1$
return Util.startsWith(triggers, triggerSequence.triggers, equals);
}
}