/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org2.eclipse.php.internal.core.preferences;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Preferences;
import org2.eclipse.php.internal.core.IPHPEplCoreConstants;
import org2.eclipse.php.util.StringUtils;
import com.aptana.editor.php.core.preferences.TaskTag;
import com.aptana.editor.php.epl.PHPEplPlugin;
/**
* A task tags provider listens to any task-tags preferences changes and notify any listener about the changes.
*
* @author shalom
*/
@SuppressWarnings( { "unchecked", "deprecation", "rawtypes" })
public class TaskTagsProvider
{
private static TaskTagsProvider instance;
private HashMap projectToTaskTagListener;
private HashMap projectToPropagatorListeners;
private boolean isInstalled;
private PreferencesSupport preferencesSupport;
private PreferencesPropagator preferencesPropagator;
private static final String NODES_QUALIFIER = PHPEplPlugin.PLUGIN_ID;
private static final Preferences store = PHPEplPlugin.getDefault().getPluginPreferences();
/**
* Constructs a new TaskTagsProvider.
*/
private TaskTagsProvider()
{
install();
}
/**
* Returns a single instance of the TaskTagsProvider.
*
* @return A TaskTagsProvider instance
*/
public static TaskTagsProvider getInstance()
{
if (instance == null)
{
instance = new TaskTagsProvider();
}
return instance;
}
/**
* Returns the Workspace task tags.
*
* @return The task tags defined for the workspace preferences.
*/
public TaskTag[] getWorkspaceTaskTags()
{
String priorities = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_PRIORITIES);
String tags = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_TAGS);
TaskTag[] workspaceTags = getTagsAndPropertiesFrom(tags, priorities);
return workspaceTags;
}
/**
* Returns true if the defined workspace task tags are case sensitive.
*
* @return true if the defined workspace task tags are case sensitive; false otherwise.
*/
public boolean isWorkspaceTagsCaseSensitive()
{
String caseSensitive = preferencesSupport
.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_CASE_SENSITIVE);
return IPHPEplCoreConstants.ENABLED.equals(caseSensitive);
}
/**
* Returns the IProject's task tags. In case the given project does not have a specific task tags, null is returned
* (since the project uses the workspace definitions).
*
* @param project
* An IProject reference.
* @return The specific task tags for the given project, or null if the project uses the workspace defined tags.
*/
public TaskTag[] getProjectTaskTags(IProject project)
{
String priorities = preferencesSupport.getProjectSpecificPreferencesValue(IPHPEplCoreConstants.TASK_PRIORITIES,
null, project);
String projectTags = preferencesSupport.getProjectSpecificPreferencesValue(IPHPEplCoreConstants.TASK_TAGS,
null, project);
if (projectTags == null || priorities == null)
{
return null;
}
TaskTag[] tags = getTagsAndPropertiesFrom(projectTags, priorities);
return tags;
}
/**
* Returns true if the defined project's task tags are case sensitive. In case that the project does not have a
* specific settings, the return value is by isWorkspaceTagsCaseSensitive.
*
* @param project
* An IProject reference.
* @return true if the defined project's task tags are case sensitive; false otherwise.
*/
public boolean getProjectTagsCaseSensitive(IProject project)
{
String caseSensitive = preferencesSupport.getProjectSpecificPreferencesValue(
IPHPEplCoreConstants.TASK_CASE_SENSITIVE, null, project);
if (caseSensitive == null)
{
return isWorkspaceTagsCaseSensitive();
}
return IPHPEplCoreConstants.ENABLED.equals(caseSensitive);
}
/**
* Adds a TaskTagsListener.
*
* @param listener
* A TaskTagsListener.
* @param project
* A related project.
*/
public void addTaskTagsListener(ITaskTagsListener listener, IProject project)
{
projectToTaskTagListener.put(project, listener);
installPropagatorListeners(project);
}
/**
* Removes a TaskTagsListener.
*
* @param listener
* A TaskTagsListener.
* @param project
* A related project.
*/
public void removeTaskTagsListener(ITaskTagsListener listener, IProject project)
{
projectToTaskTagListener.remove(project);
uninstallPropagatorListeners(project);
}
// Install propagator listeners for the given project.
private void installPropagatorListeners(IProject project)
{
if (project != null && projectToPropagatorListeners.get(project) != null)
{
return;
}
IPreferencesPropagatorListener[] listeners = new IPreferencesPropagatorListener[] {
new InnerTaskTagsListener(project), new InnerTaskPrioritiesListener(project),
new InnerTaskCaseListener(project) };
if (project != null)
{
preferencesPropagator.addPropagatorListener(listeners[0], IPHPEplCoreConstants.TASK_TAGS);
preferencesPropagator.addPropagatorListener(listeners[1], IPHPEplCoreConstants.TASK_PRIORITIES);
preferencesPropagator.addPropagatorListener(listeners[2], IPHPEplCoreConstants.TASK_CASE_SENSITIVE);
}
projectToPropagatorListeners.put(project, listeners);
}
// Uninstall propagator listeners for the given project.
private void uninstallPropagatorListeners(IProject project)
{
IPreferencesPropagatorListener[] listeners = (IPreferencesPropagatorListener[]) projectToPropagatorListeners
.get(project);
if (listeners != null && project != null)
{
preferencesPropagator.removePropagatorListener(listeners[0], IPHPEplCoreConstants.TASK_TAGS);
preferencesPropagator.removePropagatorListener(listeners[1], IPHPEplCoreConstants.TASK_PRIORITIES);
preferencesPropagator.removePropagatorListener(listeners[2], IPHPEplCoreConstants.TASK_CASE_SENSITIVE);
}
projectToPropagatorListeners.remove(project);
}
/**
* Install this task-tags provider.
*/
protected synchronized void install()
{
if (isInstalled)
{
return;
}
preferencesSupport = new PreferencesSupport(PHPEplPlugin.PLUGIN_ID, PHPEplPlugin.getDefault()
.getPluginPreferences());
projectToTaskTagListener = new HashMap();
projectToPropagatorListeners = new HashMap();
preferencesPropagator = PreferencePropagatorFactory.getPreferencePropagator(NODES_QUALIFIER, store);
isInstalled = true;
}
/**
* Uninstall this task-tags provider.
*/
protected synchronized void uninstall()
{
if (!isInstalled)
{
return;
}
// Uninstall the propagator listeners
Set keys = projectToPropagatorListeners.keySet();
IProject[] projects = new IProject[keys.size()];
keys.toArray(projects);
for (IProject element : projects)
{
uninstallPropagatorListeners(element);
}
preferencesSupport = null;
preferencesPropagator = null;
projectToTaskTagListener = null;
projectToPropagatorListeners = null;
isInstalled = false;
}
// Notify a taskTagsChanged to all the listeners.
private void notifyTaskTagChange(TaskTagsEvent event)
{
ITaskTagsListener[] allListeners = new ITaskTagsListener[projectToTaskTagListener.size()];
projectToTaskTagListener.values().toArray(allListeners);
for (ITaskTagsListener element : allListeners)
{
element.taskTagsChanged(event);
}
}
// Notify a taskTagsChanged to all the listeners.
private void notifyTaskPriorityChange(TaskTagsEvent event)
{
ITaskTagsListener[] allListeners = new ITaskTagsListener[projectToTaskTagListener.size()];
projectToTaskTagListener.values().toArray(allListeners);
for (ITaskTagsListener element : allListeners)
{
element.taskPrioritiesChanged(event);
}
}
// Notify a taskTagsChanged to all the listeners.
private void notifyTaskCaseChange(TaskTagsEvent event)
{
ITaskTagsListener[] allListeners = new ITaskTagsListener[projectToTaskTagListener.size()];
projectToTaskTagListener.values().toArray(allListeners);
for (ITaskTagsListener element : allListeners)
{
element.taskCaseChanged(event);
}
}
/*
* Returns the tags into the workspace tags list.
* @param tags
* @param priorities
*/
private TaskTag[] getTagsAndPropertiesFrom(String tagString, String priorityString)
{
String[] tags = StringUtils.unpack(tagString);
String[] priorities = StringUtils.unpack(priorityString);
List list = new ArrayList();
for (String element : priorities)
{
Integer number = null;
if (IPHPEplCoreConstants.TASK_PRIORITY_HIGH.equals(element))
{
number = new Integer(IMarker.PRIORITY_HIGH);
}
else if (IPHPEplCoreConstants.TASK_PRIORITY_LOW.equals(element))
{
number = new Integer(IMarker.PRIORITY_LOW);
}
else
{
number = new Integer(IMarker.PRIORITY_NORMAL);
}
list.add(number);
}
Integer[] allPriorities = new Integer[list.size()];
list.toArray(allPriorities);
TaskTag[] taskTags = new TaskTag[Math.min(tags.length, priorities.length)];
for (int i = 0; i < taskTags.length; i++)
{
taskTags[i] = new TaskTag(tags[i], allPriorities[i].intValue());
}
return taskTags;
}
// ////////////////////////////////////////////////////////////////////////////////////////////
// ///////////////////// IPreferencesPropagatorListeners
// ////////////////////////
// ////////////////////////////////////////////////////////////////////////////////////////////
private abstract class AbstractTasksListener implements IPreferencesPropagatorListener
{
private IProject project;
public AbstractTasksListener(IProject project)
{
this.project = project;
}
public IProject getProject()
{
return project;
}
}
// Listen to task-tags strings changes
private class InnerTaskTagsListener extends AbstractTasksListener
{
public InnerTaskTagsListener(IProject project)
{
super(project);
}
public void preferencesEventOccured(PreferencesPropagatorEvent event)
{
String newValue = (String) event.getNewValue();
if (newValue == null)
{
newValue = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_TAGS);
}
// Check that the other value are synchronized at this stage and
// send an event only if they are.
String priorities = preferencesSupport.getProjectSpecificPreferencesValue(
IPHPEplCoreConstants.TASK_PRIORITIES, null, getProject());
if (priorities == null)
{
priorities = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_PRIORITIES);
}
if (StringUtils.occurrencesOf(priorities, ',') == StringUtils.occurrencesOf(newValue, ','))
{
TaskTag[] taskTags = getTagsAndPropertiesFrom(newValue, priorities);
IProject eventProject = (event.getSource() != null && event.getSource() instanceof IProject) ? (IProject) event
.getSource()
: null;
TaskTagsEvent taskEvent = new TaskTagsEvent(TaskTagsProvider.this, eventProject, taskTags,
getProjectTagsCaseSensitive(getProject()));
notifyTaskTagChange(taskEvent);
}
}
}
// Listen to task-tags priorities changes
private class InnerTaskPrioritiesListener extends AbstractTasksListener
{
public InnerTaskPrioritiesListener(IProject project)
{
super(project);
}
public void preferencesEventOccured(PreferencesPropagatorEvent event)
{
String newValue = (String) event.getNewValue();
if (newValue == null)
{
newValue = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_PRIORITIES);
}
// Check that the other value are synchronized at this stage and
// send an event only if they are.
String tags = preferencesSupport.getProjectSpecificPreferencesValue(IPHPEplCoreConstants.TASK_TAGS, null,
getProject());
if (tags == null)
{
tags = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_TAGS);
}
if (StringUtils.occurrencesOf(tags, ',') == StringUtils.occurrencesOf(newValue, ','))
{
TaskTag[] taskTags = getTagsAndPropertiesFrom(tags, newValue);
TaskTagsEvent taskEvent = new TaskTagsEvent(TaskTagsProvider.this, getProject(), taskTags,
getProjectTagsCaseSensitive(getProject()));
notifyTaskPriorityChange(taskEvent);
}
}
}
// Listen to task-tags case sensitivity changes
private class InnerTaskCaseListener extends AbstractTasksListener
{
public InnerTaskCaseListener(IProject project)
{
super(project);
}
public void preferencesEventOccured(PreferencesPropagatorEvent event)
{
String tags = preferencesSupport.getProjectSpecificPreferencesValue(IPHPEplCoreConstants.TASK_TAGS, null,
getProject());
String priorities = null;
if (tags == null)
{
tags = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_TAGS);
priorities = preferencesSupport.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_PRIORITIES);
}
else
{
priorities = preferencesSupport.getProjectSpecificPreferencesValue(
IPHPEplCoreConstants.TASK_PRIORITIES, "", getProject());//$NON-NLS-1$
}
if (StringUtils.occurrencesOf(priorities, ',') == StringUtils.occurrencesOf(tags, ','))
{
TaskTag[] taskTags = getTagsAndPropertiesFrom(tags, priorities);
TaskTagsEvent taskEvent = null;
String newValue = (String) event.getNewValue();
if (newValue == null)
{
newValue = preferencesSupport
.getWorkspacePreferencesValue(IPHPEplCoreConstants.TASK_CASE_SENSITIVE);
}
if (IPHPEplCoreConstants.ENABLED.equals(newValue))
{
taskEvent = new TaskTagsEvent(TaskTagsProvider.this, getProject(), taskTags, true);
}
else
{
taskEvent = new TaskTagsEvent(TaskTagsProvider.this, getProject(), taskTags, false);
}
notifyTaskCaseChange(taskEvent);
}
}
}
}