/*******************************************************************************
* Copyright (c) 2000, 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.core.internal.events;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.internal.resources.ModelObject;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
/**
* The concrete implementation of <tt>ICommand</tt>. This object stores information about a
* particular builder, including a reference to the builder instance itself if it has been
* instantiated.
*/
public class BuildCommand extends ModelObject implements ICommand {
/**
* Internal flag masks for different build triggers.
*/
private static final int MASK_AUTO= 0x01;
private static final int MASK_INCREMENTAL= 0x02;
private static final int MASK_FULL= 0x04;
private static final int MASK_CLEAN= 0x08;
/**
* Flag bit indicating if this build command is configurable
*/
private static final int MASK_CONFIGURABLE= 0x10;
/**
* Flag bit indicating if the configurable bit has been loaded from the builder extension
* declaration in XML yet.
*/
private static final int MASK_CONFIG_COMPUTED= 0x20;
private static final int ALL_TRIGGERS= MASK_AUTO | MASK_CLEAN | MASK_FULL | MASK_INCREMENTAL;
protected HashMap arguments;
/**
* The builder instance for this command. Null if the builder has not yet been instantiated.
*/
protected IncrementalProjectBuilder builder;
/**
* The triggers that this builder will respond to. Since build triggers are not bit-maskable, we
* use internal bit masks to represent each trigger (MASK_* constants). By default, a command
* responds to all build triggers.
*/
private int triggers= ALL_TRIGGERS;
/**
* Returns the trigger bit mask for the given trigger constant.
*/
private static int maskForTrigger(int trigger) {
switch (trigger) {
case IncrementalProjectBuilder.AUTO_BUILD:
return MASK_AUTO;
case IncrementalProjectBuilder.INCREMENTAL_BUILD:
return MASK_INCREMENTAL;
case IncrementalProjectBuilder.FULL_BUILD:
return MASK_FULL;
case IncrementalProjectBuilder.CLEAN_BUILD:
return MASK_CLEAN;
}
return 0;
}
public BuildCommand() {
super(""); //$NON-NLS-1$
this.arguments= new HashMap(0);
}
public Object clone() {
BuildCommand result= null;
result= (BuildCommand)super.clone();
if (result == null)
return null;
result.setArguments(getArguments());
//don't let references to builder instances leak out because they reference trees
result.setBuilder(null);
return result;
}
/**
* Computes whether this build command allows configuration of its triggers, based on
* information in the builder extension declaration.
*/
private void computeIsConfigurable() {
triggers|= MASK_CONFIG_COMPUTED;
IExtension extension= Platform.getExtensionRegistry().getExtension(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_BUILDERS, name);
if (extension != null) {
IConfigurationElement[] configs= extension.getConfigurationElements();
if (configs.length != 0) {
String value= configs[0].getAttribute("isConfigurable"); //$NON-NLS-1$
setConfigurable(value != null && value.equalsIgnoreCase(Boolean.TRUE.toString()));
}
}
}
/* (non-Javadoc)
* Method declared on Object
*/
public boolean equals(Object object) {
if (this == object)
return true;
if (!(object instanceof BuildCommand))
return false;
BuildCommand command= (BuildCommand)object;
// equal if same builder name and equal argument tables
return getBuilderName().equals(command.getBuilderName()) && getArguments(false).equals(command.getArguments(false)) && triggers == command.triggers;
}
/**
* @see ICommand#getArguments()
*/
public Map getArguments() {
return getArguments(true);
}
public Map getArguments(boolean makeCopy) {
return arguments == null ? null : (makeCopy ? (Map)arguments.clone() : arguments);
}
public IncrementalProjectBuilder getBuilder() {
return builder;
}
/**
* @see ICommand#getBuilderName()
*/
public String getBuilderName() {
return getName();
}
/* (non-Javadoc)
* Method declared on Object
*/
public int hashCode() {
// hash on name alone
return 37 * getName().hashCode() + triggers;
}
/**
* @see ICommand#isBuilding(int)
*/
public boolean isBuilding(int trigger) {
return (triggers & maskForTrigger(trigger)) != 0;
}
public boolean isConfigurable() {
if ((triggers & MASK_CONFIG_COMPUTED) == 0)
computeIsConfigurable();
return (triggers & MASK_CONFIGURABLE) != 0;
}
/**
* @see ICommand#setArguments(Map)
*/
public void setArguments(Map value) {
// copy parameter for safety's sake
arguments= value == null ? null : new HashMap(value);
}
public void setBuilder(IncrementalProjectBuilder builder) {
this.builder= builder;
}
/**
* @see ICommand#setBuilderName(String)
*/
public void setBuilderName(String value) {
//don't allow builder name to be null
setName(value == null ? "" : value); //$NON-NLS-1$
}
/**
* @see ICommand#setBuilding(int, boolean)
*/
public void setBuilding(int trigger, boolean value) {
if (!isConfigurable())
return;
if (value)
triggers|= maskForTrigger(trigger);
else
triggers&= ~maskForTrigger(trigger);
}
/**
* Sets whether this build command allows its build triggers to be configured. This value should
* only be set when the builder extension declaration is read from the registry, or when a build
* command is read from the project description file on disk. The value is not otherwise
* mutable.
*/
public void setConfigurable(boolean value) {
triggers|= MASK_CONFIG_COMPUTED;
if (value)
triggers|= MASK_CONFIGURABLE;
else
triggers= ALL_TRIGGERS;
}
/**
* For debugging purposes only
*/
public String toString() {
return "BuildCommand(" + getName() + ")";//$NON-NLS-1$ //$NON-NLS-2$
}
}