| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 2006 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 implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.library.configuration.closure; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; |
| import org.eclipse.epf.library.IConfigurationClosure; |
| import org.eclipse.epf.library.IConfigurationManager; |
| import org.eclipse.epf.library.LibraryPlugin; |
| import org.eclipse.epf.library.LibraryResources; |
| import org.eclipse.epf.library.LibraryService; |
| import org.eclipse.epf.library.configuration.ConfigDataBase; |
| import org.eclipse.epf.library.configuration.ConfigurationData; |
| import org.eclipse.epf.library.configuration.ConfigurationHelper; |
| import org.eclipse.epf.library.configuration.ConfigurationProperties; |
| import org.eclipse.epf.library.configuration.SupportingElementData; |
| import org.eclipse.epf.library.edit.command.IActionManager; |
| import org.eclipse.epf.library.edit.util.MethodElementPropertyMgr; |
| import org.eclipse.epf.library.edit.util.MethodElementPropertyMgr.ChangeEvent; |
| import org.eclipse.epf.library.util.LibraryProblemMonitor; |
| import org.eclipse.epf.library.util.LibraryUtil; |
| import org.eclipse.epf.uma.MethodConfiguration; |
| import org.eclipse.epf.uma.MethodElement; |
| import org.eclipse.epf.uma.MethodLibrary; |
| import org.eclipse.epf.uma.MethodPackage; |
| import org.eclipse.epf.uma.MethodPlugin; |
| import org.eclipse.epf.uma.VariabilityElement; |
| import org.eclipse.ui.views.properties.IPropertyDescriptor; |
| import org.eclipse.ui.views.properties.IPropertySource; |
| |
| /** |
| * A method configuration closure. |
| * |
| * @author Jinhua Xi |
| * @author Kelvin Low |
| * @since 1.0 |
| */ |
| public class ConfigurationClosure implements IConfigurationClosure { |
| |
| // If true, generate debug traces. |
| protected static boolean debug = LibraryPlugin.getDefault().isDebugging(); |
| |
| protected MethodConfiguration config = null; |
| |
| protected MethodLibrary library = null; |
| |
| protected IConfigurationManager configManager = null; |
| |
| protected DependencyManager dependencyManager = null; |
| |
| protected IActionManager actionMgr; |
| |
| // Node change information. The object are the model objects |
| // check the linked objects in needed |
| protected List selectedNotes = new ArrayList(); |
| |
| private List<ElementError> errors = new ArrayList<ElementError>(); |
| |
| private boolean abortCheckError = false; |
| |
| // marker ID |
| public static final String multipleReplacersMARKER_ID = "org.eclipse.epf.library.multipleReplacers"; //$NON-NLS-1$ |
| |
| public static final String replacerGuids = "replacerGuids"; //$NON-NLS-1$ |
| |
| // A map of invalid nodes to ElementDependencyError objects. |
| protected Map<Object, ElementDependencyError> invalidNodesMap = |
| new HashMap<Object, ElementDependencyError>(); |
| |
| //protected List changedNodes = new ArrayList(); |
| |
| private List<ClosureListener> listeners; |
| |
| private MethodElementPropertyMgr.ChangeEventListener configPropListener; |
| |
| private Map<MethodElement, IMarker> replacerElementMarkerMap; |
| /** |
| * Creates a new instance. |
| * |
| * @param actionMgr |
| * The IActionManager to use to change the MethodConfiguration. If null, config will be changed directly. |
| * @param config |
| * A method configuration. |
| */ |
| public ConfigurationClosure(IActionManager actionMgr, MethodConfiguration config) { |
| this.config = config; |
| this.actionMgr = actionMgr; |
| |
| configManager = LibraryService.getInstance().getConfigurationManager( |
| config); |
| if (configManager != null) { |
| library = configManager.getMethodLibrary(); |
| dependencyManager = configManager.getDependencyManager(); |
| |
| ConfigurationProperties props = configManager.getConfigurationProperties(); |
| configPropListener = new MethodElementPropertyMgr.ChangeEventListener() { |
| public void notifyChange(ChangeEvent event) { |
| refreshErrormarks(); |
| } |
| }; |
| props.addListener(configPropListener); |
| } |
| |
| // configuration changed, re-build the analyze the configuration for errors |
| checkError(); |
| } |
| |
| /** |
| * Returns the method configuration manager. |
| * |
| * @return A <code>ConfigurationManager</code>. |
| */ |
| public IConfigurationManager getConfigurationManager() { |
| return configManager; |
| } |
| |
| /** |
| * Returns the method configuration. |
| * |
| * @return A <code>MethodConfiguration</code>. |
| */ |
| public MethodConfiguration getConfiguration() { |
| return config; |
| } |
| |
| /** |
| * Returns the containining method library. |
| * |
| * @return A <code>MethodConfiguration</code>. |
| */ |
| public MethodLibrary getLibrary() { |
| return library; |
| } |
| |
| // /** |
| // * Sets the method plug-ins and packages selection. |
| // * |
| // * @param elements |
| // * an array of method plug-ins and packages |
| // */ |
| // public void setSelections(Object[] elements) { |
| // |
| // if ( elements == null ) { |
| // return; |
| // } |
| // |
| // // clear the old selections |
| // selectedNotes.clear(); |
| // for (int i = 0; i < elements.length; i++ ) { |
| // selectedNotes.add(elements[i]); |
| // } |
| // } |
| |
| |
| /** |
| * Builds the selection list based on the method configuration. |
| * |
| */ |
| public void checkError() { |
| if (isRunningCheckError()) { |
| if (ConfigDataBase.localDebug) { |
| System.out.println("LD> checkError skipped");//$NON-NLS-1$ |
| } |
| return; |
| } |
| try { |
| if (ConfigDataBase.localDebug) { |
| System.out.println("LD> checkError_ ->");//$NON-NLS-1$ |
| } |
| checkError_(); |
| } catch (Exception e) { |
| LibraryPlugin.getDefault().getLogger().logError(e); |
| } finally { |
| if (ConfigDataBase.localDebug) { |
| System.out.println("LD> checkError_ <-");//$NON-NLS-1$ |
| } |
| setRunningCheckError(false); |
| } |
| } |
| |
| private boolean runningCheckError = false; |
| |
| //Be aware of side effect of the call |
| private synchronized boolean isRunningCheckError() { |
| boolean ret = runningCheckError; |
| if (! ret) { //make sure no 2 threads can be runningCheckError at the same time |
| runningCheckError = true; |
| } |
| return ret; |
| } |
| private synchronized void setRunningCheckError(boolean b) { |
| runningCheckError = b; |
| } |
| |
| private void checkError_() { |
| |
| // Bug 206724 - SCM: Always prompt check out elements for a opened configuration when refresh source control status |
| // don't need to validate the configuration, rely on the caller to validate it before call this method. |
| // Validate the method configuration with the action manager. |
| //LibraryUtil.validateMethodConfiguration(actionMgr, config); |
| |
| // initial fill the selections |
| selectedNotes.clear(); |
| selectedNotes.addAll(config.getMethodPluginSelection()); |
| selectedNotes.addAll(config.getMethodPackageSelection()); |
| |
| // Re-build the selections to auto add the process packages. |
| clearErrorMarks(); |
| |
| // Cleanup the old status and rebuild the list. |
| invalidNodesMap.clear(); |
| |
| processChangedNodes(getSelection()); |
| |
| processReplacers(); |
| |
| } |
| |
| private void processReplacers() { |
| Set<VariabilityElement> replacerSet = dependencyManager.getReplacerSet(); |
| if (replacerSet == null || replacerSet.isEmpty()) { |
| return; |
| } |
| |
| clearReplacerElementMarkerMap(); |
| replacerElementMarkerMap = new HashMap<MethodElement, IMarker>(); |
| Map<VariabilityElement, List> baseReplacersMap = new HashMap<VariabilityElement, List>(); |
| for (VariabilityElement ve: replacerSet) { |
| VariabilityElement base = ve.getVariabilityBasedOnElement(); |
| List<MethodElement> replacers = baseReplacersMap.get(base); |
| if (replacers == null) { |
| replacers = new ArrayList<MethodElement>(); |
| baseReplacersMap.put(base, replacers); |
| } |
| replacers.add(ve); |
| processReplacerError(replacerElementMarkerMap, base, replacers); |
| } |
| |
| } |
| |
| private static void processReplacerError(Map<MethodElement, IMarker> elementMarkerMap, |
| MethodElement base, Collection<MethodElement> replacers) { |
| if (replacers == null || replacers.isEmpty() || replacers.size() < 2) { |
| return; |
| } |
| IMarker marker = elementMarkerMap.get(base); |
| if (marker == null) { |
| Resource res = base.eResource(); |
| if (res == null) { |
| return; |
| } |
| |
| URI containerURI = res.getURI(); |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IPath path = new Path(containerURI.toFileString()); |
| IFile file = workspace.getRoot().getFileForLocation(path); |
| if (file == null) { |
| return; |
| } |
| String location = containerURI != null ? containerURI |
| .toFileString() : ""; //$NON-NLS-1$ |
| |
| try { |
| marker = file.createMarker(multipleReplacersMARKER_ID); |
| marker.setAttribute(IMarker.LOCATION, location); |
| marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); |
| marker.setAttribute(LibraryProblemMonitor.Guid, base.getGuid()); |
| |
| } catch (Exception e) { |
| LibraryPlugin.getDefault().getLogger().logError(e); |
| } |
| } |
| |
| |
| String replacerGuidsValue = ""; //$NON-NLS-1$ |
| for (MethodElement replacer: replacers) { |
| if (replacerGuidsValue.length() != 0) { |
| replacerGuidsValue += ", "; //$NON-NLS-1$ |
| } |
| replacerGuidsValue += replacer.getGuid(); |
| } |
| String errMsg = LibraryResources.bind(LibraryResources.ElementError_having_multiple_replacers, |
| (new String[] {LibraryUtil.getTypePath(base), |
| replacerGuidsValue })); |
| |
| try { |
| marker.setAttribute(replacerGuids, replacerGuidsValue); |
| marker.setAttribute(IMarker.MESSAGE, errMsg); |
| } catch (Exception e) { |
| LibraryPlugin.getDefault().getLogger().logError(e); |
| } |
| |
| } |
| |
| private void clearErrorMarks() { |
| // Re-build the selections to auto add the process packages. |
| |
| for (Iterator<ElementError> it = errors.iterator(); it.hasNext(); ) { |
| ElementError error = it.next(); |
| notifyError(error, ClosureListener.ERROR_REMOVED); |
| } |
| } |
| |
| public void refreshErrormarks() { |
| clearErrorMarks(); |
| for (Iterator<ElementError> it = errors.iterator(); it.hasNext(); ) { |
| ElementError error = it.next(); |
| notifyError(error, ClosureListener.ERROR_ADDED); |
| } |
| } |
| |
| // private void selectProcessPackages(Activity a) { |
| // if (a == null) { |
| // return; |
| // } |
| // |
| // for (Iterator it = a.getBreakdownElements().iterator(); it.hasNext();) { |
| // BreakdownElement e = (BreakdownElement) it.next(); |
| // Object pkg = e.eContainer(); |
| // if (!selectedNotes.contains(pkg)) { |
| // selectedNotes.add(pkg); |
| // changedNodes.add(pkg); |
| // } |
| // |
| // if (e instanceof Activity) { |
| // selectProcessPackages((Activity) e); |
| // } |
| // } |
| // } |
| |
| // /** |
| // * Adds a method plug-in or package to the closure. |
| // * |
| // * @param element |
| // * A method element. |
| // * @param addChildren |
| // * if <code>true</code>, add all child method elements. |
| // */ |
| // private void add(EObject element, boolean addChildren) { |
| // if (!LibraryUtil.selectable(element)) { |
| // return; |
| // } |
| // |
| // if (!selectedNotes.contains(element)) { |
| // selectedNotes.add(element); |
| // |
| // // Save the changed nodes so that we can update the status later. |
| // addChanged(element); |
| // |
| // if (element instanceof MethodPlugin) { |
| // selectSystemPackages((MethodPlugin) element); |
| // } |
| // } |
| // |
| // // Add the parent method element as well. |
| // EObject parent = element.eContainer(); |
| // if ((parent != null) && !selectedNotes.contains(parent)) { |
| // add(parent, false); |
| // } |
| // |
| // // Add children as needed. |
| // if (addChildren) { |
| // EList elements = element.eContents(); |
| // if (elements != null) { |
| // for (Iterator it = elements.iterator(); it.hasNext();) { |
| // EObject child = (EObject) it.next(); |
| // add(child, true); |
| // } |
| // } |
| // } |
| // } |
| // |
| // private void addChanged(Object element) { |
| // if (!changedNodes.contains(element)) { |
| // changedNodes.add(element); |
| // } |
| // } |
| |
| // private void selectSystemPackages(MethodPlugin plugin) { |
| // List pkgs = TngUtil.getAllSystemPackages(plugin); |
| // for (Iterator it = pkgs.iterator(); it.hasNext();) { |
| // EObject pkg = (EObject) it.next(); |
| // add(pkg, false); |
| // } |
| // } |
| |
| /** |
| * Checks whether a method plug-in or package is selected. |
| * |
| * @return <code>true</code> if the given element is selected. |
| */ |
| public boolean isSelected(Object input) { |
| if ((input instanceof MethodLibrary) || input == config |
| || selectedNotes.contains(input)) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Gets the element dependency error for a method element. |
| * |
| * @element A method element. |
| * |
| * @return An <code>ElementDependencyError</code>. |
| */ |
| public ElementDependencyError getError(Object element) { |
| return getError(element, false); |
| } |
| |
| private ElementDependencyError getError(Object element, boolean create) { |
| ElementDependencyError error = (ElementDependencyError) invalidNodesMap |
| .get(element); |
| if (error == null && create) { |
| error = new ElementDependencyError(element); |
| invalidNodesMap.put(element, error); |
| } |
| return error; |
| } |
| |
| /** |
| * check if there is error in this configuration closure |
| * |
| * @return boolean |
| */ |
| public boolean hasError() { |
| for (Iterator it = invalidNodesMap.values().iterator(); it.hasNext();) { |
| ElementDependencyError error = (ElementDependencyError) it.next(); |
| if (error.isError()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * check if there is any problem (error/warning) with this configuration closure. |
| * @return boolean |
| */ |
| public boolean hasProblem() { |
| return invalidNodesMap.size() > 0; |
| } |
| |
| /** |
| * Returns all the errors. |
| * |
| */ |
| public List<ElementError> getAllErrors() { |
| /* Old code |
| List<PackageError> errors = new ArrayList<PackageError>(); |
| for (Iterator it = invalidNodesMap.values().iterator(); it.hasNext();) { |
| ElementDependencyError error = (ElementDependencyError) it.next(); |
| errors.addAll(error.getAll()); |
| } |
| */ |
| return errors; |
| } |
| |
| /** |
| * Returns all the dependency errors. |
| * |
| * @return An array of <code>ElementDependencyError</code> |
| */ |
| public Object[] getDependencyErrors() { |
| return invalidNodesMap.values().toArray(); |
| } |
| |
| /** |
| * Returns all the invalid elements. |
| * |
| * @return A list of invalid elements. |
| */ |
| public List<Object> getInvalidElements() { |
| return new ArrayList<Object>(invalidNodesMap.keySet()); |
| } |
| |
| private void removeError(Object element) { |
| if (invalidNodesMap.containsKey(element)) { |
| invalidNodesMap.remove(element); |
| |
| // // Error status changed, add it to the changed list. |
| // if (!changedNodes.contains(element)) { |
| // changedNodes.add(element); |
| // } |
| } |
| } |
| |
| // /** |
| // * Returns all the changed elements. These are elements whose check states |
| // * have changed or whose image have changed due to error. |
| // * |
| // * @return A list of changed method elements. |
| // */ |
| // public List getChangedElements() { |
| // List items = new ArrayList(changedNodes); |
| // for (Iterator it = invalidNodesMap.keySet().iterator(); it.hasNext();) { |
| // Object item = it.next(); |
| // if (!items.contains(item)) { |
| // items.add(item); |
| // } |
| // } |
| // return items; |
| // } |
| |
| /** |
| * Returns the method plug-ins and packages selection. |
| * |
| * @return An array of method plug-ins and packages. |
| */ |
| public Object[] getSelection() { |
| return selectedNotes.toArray(); |
| } |
| |
| private void processChangedNodes(Object[] changedNodes) { |
| getConfigurationManager().getSupportingElementData().beginUpdateSupportingElements(); |
| processChangedNodes_(changedNodes); |
| /* if (isAbortCheckError()) { |
| return; |
| }*/ |
| Map<String, ElementReference> refMap = new HashMap<String, ElementReference>(); |
| getConfigurationManager().getSupportingElementData().endUpdateSupportingElements(refMap); |
| if (isAbortCheckError()) { |
| return; |
| } |
| for (ElementReference ref : refMap.values()) { |
| ElementError error = ConfigurationErrorMatrix.getError(config, ref); |
| if (error != null) { |
| errors.add(error); |
| notifyError(error, ClosureListener.ERROR_ADDED); |
| processPackageError(LibraryUtil.getSelectable(ref.element), |
| LibraryUtil.getSelectable(ref.refElement), error |
| .getErrorLevel()); |
| } |
| } |
| } |
| |
| private void processChangedNodes_(Object[] changedNodes) { |
| SupportingElementData seData = getConfigurationManager().getSupportingElementData(); |
| |
| // for all the changed notes, |
| // all all contained elements and check if the elements are in config or not |
| // if the elements are in config, the referenced elements should also be in config |
| |
| for (int i = 0; i <changedNodes.length; i++) { |
| if (isAbortCheckError()) { |
| return; |
| } |
| |
| // the elements are either plugin or package |
| Object changedElement = changedNodes[i]; |
| if (seData.isSupportingSelectable((MethodElement) changedElement)) { |
| continue; |
| } |
| |
| PackageDependency dependency = dependencyManager |
| .getDependency((MethodElement) changedElement); |
| if (dependency == null) { |
| continue; |
| } |
| |
| List refs = dependency.getAllElementReferences(); |
| if ( refs == null || refs.size() == 0 ) { |
| continue; |
| } |
| |
| for (Iterator itr = refs.iterator(); itr.hasNext(); ) { |
| ElementReference ref = (ElementReference)itr.next(); |
| checkReference(ref); |
| } |
| } |
| |
| // for all the elements in the added category, check their references as well |
| List<MethodElement> list = new ArrayList<MethodElement>(); |
| list.addAll(configManager.getConfigurationData().getAddedElements()); |
| for ( Iterator<MethodElement> it = list.iterator(); it.hasNext(); ) { |
| MethodElement e = it.next(); |
| |
| PackageDependency dependency = |
| dependencyManager.getDependency((MethodElement)e.eContainer()); |
| if (dependency == null) { |
| continue; |
| } |
| |
| List refs = dependency.getAllElementReferences(); |
| if ( refs == null || refs.size() == 0 ) { |
| continue; |
| } |
| |
| for (Iterator itr = refs.iterator(); itr.hasNext(); ) { |
| ElementReference ref = (ElementReference)itr.next(); |
| if ( ref.getElement() == e ) { |
| checkReference(ref); |
| } |
| } |
| |
| } |
| |
| } |
| |
| private void checkReference(ElementReference ref) { |
| MethodElement e = ref.getElement(); |
| MethodElement e_ref = ref.getRefElement(); |
| SupportingElementData seData = getConfigurationManager().getSupportingElementData(); |
| ConfigurationData configData = getConfigurationManager().getConfigurationData(); |
| |
| |
| //System.out.println("LD> e: " + e); |
| //System.out.println("LD> e_ref: " + e_ref); |
| |
| if ( e instanceof MethodPackage || e instanceof MethodConfiguration ) { |
| return; |
| } |
| |
| // Bug 207609 - Replaced elements are not considered for configuration error "missing mandatory input" |
| // if the element is replaced, ignore the reference |
| if ( e instanceof VariabilityElement ) { |
| VariabilityElement replacer = ConfigurationHelper.getReplacer((VariabilityElement)e, config); |
| if ( replacer != null ) { |
| return; |
| } |
| } |
| |
| // the element might be subtracted, so ignore it |
| /* if ( !ConfigurationHelper.inConfig(e, config, true, false)) { |
| return; |
| }*/ |
| if ( configData.isSubstracted(e)) { |
| return; |
| } |
| |
| // if the referenced element is not in config, log error |
| if ( !ConfigurationHelper.inConfig(e_ref, config) |
| && !seData.isSupportingElementCallDuringUpdating(ref)) { |
| |
| /* |
| String message = LibraryResources.bind(LibraryResources.ElementError_missing_element, |
| (new String[] {LibraryUtil.getTypeName(e), |
| LibraryUtil.getTypeName(e_ref) })); |
| |
| ElementError error = new ElementError( |
| this, ErrorInfo.WARNING, |
| message, e, e_ref, ErrorInfo.REFERENCE_TO); //$NON-NLS-1$ |
| */ |
| ElementError error = ConfigurationErrorMatrix.getError(config, ref); |
| if ( error == null ) { |
| return; |
| } |
| |
| errors.add(error); |
| notifyError(error, ClosureListener.ERROR_ADDED); |
| |
| // process package error |
| processPackageError(LibraryUtil.getSelectable(e), LibraryUtil.getSelectable(e_ref), error.getErrorLevel() ); |
| } |
| } |
| |
| private void processPackageError(Object pkg, Object pkg_ref, int errorLevel ) { |
| if ( errorLevel > 0 ) { |
| ElementDependencyError error = getError(pkg, true); |
| |
| PackageError pkgerror = error.getError(pkg_ref); |
| if ( pkgerror == null ) { |
| String message = LibraryResources.configClosureWarning_msg1; |
| |
| pkgerror = new PackageError(errorLevel, message, |
| pkg, pkg_ref, ErrorInfo.REFERENCE_TO); |
| error.addError(pkgerror); |
| |
| } else { |
| pkgerror.setErrorLevel(errorLevel); |
| |
| // need to recalc the error bits |
| error.calculateErrorBits(); |
| } |
| } else { |
| // remove the error |
| removeError(pkg); |
| } |
| |
| updateParentsForErrors((EObject)pkg); |
| |
| } |
| |
| private void notifyError(ElementError error, int type ) { |
| |
| if ( error == null || listeners == null || listeners.size() == 0 ) { |
| return; |
| } |
| |
| try { |
| |
| for (Iterator<ClosureListener> iter = listeners.iterator();iter.hasNext();) { |
| ClosureListener listener = iter.next(); |
| |
| listener.fireEvent(type, config, error); |
| } |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| |
| // /** |
| // * Validates the element dependency when the element is selected. When the |
| // * element is selected, we need to do the following: 1. Check error for |
| // * references 2. Remove error for dependents associated with element 3. |
| // * Update parents: if the selection is valid, remove all errors from parents |
| // * associated with this element if the selection is invalid, set error to |
| // * all parents. |
| // * |
| // * @param dependency |
| // * ElementDependency |
| // */ |
| // private void validateSelected(PackageDependency dependency) { |
| // Object changedElement = dependency.getElement(); |
| // |
| // // Since this element is selected, remove all previous errors. |
| // removeError(changedElement); |
| // |
| // if (changedElement instanceof MethodLibrary) { |
| // return; |
| // } |
| // |
| // // Since this element is selected, check all dependency errors in the |
| // // dependent elements. |
| // List dependents = dependency.getDependents(); |
| // if (dependents != null && dependents.size() > 0) { |
| // Object element; |
| // for (Iterator itr = dependents.iterator(); itr.hasNext();) { |
| // element = itr.next(); |
| // |
| // ElementDependencyError error = getError(element, false); |
| // if (error != null) { |
| // PackageError pkgerror = error.removeError(changedElement); |
| // if (error.size() == 0) { |
| // removeError(element); |
| // |
| // // Clear the parent error introduced by this element. |
| // updateParentsForErrors((EObject) element); |
| // } |
| // |
| // // notify the error listener about the error removed |
| // notifyErrorRemoved(pkgerror); |
| // |
| // } |
| // } |
| // } |
| // |
| // // If an element is checked, check the element it depends on, |
| // // which should be checked as well. |
| // List refs = dependency.getReferences(); |
| // if (refs != null && refs.size() > 0) { |
| // PackageReference ref; |
| // Object element; |
| // for (Iterator itr = refs.iterator(); itr.hasNext();) { |
| // ref = (PackageReference) itr.next(); |
| // element = ref.getRefElement(); |
| // |
| // if (element instanceof MethodLibrary) { |
| // continue; |
| // } |
| // |
| // // Don't warn on optional inputs not being |
| // // present, so added the canIgnore() method |
| // if (!isSelected(element) && !canIgnore(ref)) { |
| // String message; |
| // int errorType = 0; |
| // if (ref.hasBaseReference()) { |
| // errorType = ErrorInfo.ERROR; |
| // message = LibraryResources.configClosureWarning_msg2; |
| // } else { |
| // errorType = ErrorInfo.WARNING; |
| // message = LibraryResources.configClosureWarning_msg3; |
| // } |
| // |
| // ElementDependencyError error = getError(changedElement, |
| // true); |
| // |
| // PackageError pkgerror = new PackageError(this, errorType, message, |
| // changedElement, element, ErrorInfo.REFERENCE_TO); |
| // error.addError(pkgerror); |
| // |
| // // notify the error listener about the error added |
| // notifyErrorAdded(pkgerror); |
| // |
| // } else { |
| // ElementDependencyError error = getError(changedElement, |
| // false); |
| // if (error != null) { |
| // PackageError pkgerror = error.removeError(element); |
| // |
| // // notify the error listener about the error removed |
| // notifyErrorRemoved(pkgerror); |
| // |
| // } |
| // } |
| // } |
| // } |
| // |
| // // Finally, update the parents. |
| // updateParentsForErrors((EObject) changedElement); |
| // } |
| // |
| // /** |
| // * Validates the ElementDependency when the element is unselected. When the |
| // * element is unselected, we need to do the following: 1. check error for |
| // * dependencts 2. remove error for references associated with element, in |
| // * case of any added when the element was check 3. update parents: if the |
| // * selection is valid, remove all errors from parents associated with this |
| // * element if the selection is invalid, set error to all parents. |
| // * |
| // * @param dependency |
| // * A <code>ElementDependency</code> object. |
| // */ |
| // private void validateUnSelected(PackageDependency dependency) { |
| // Object changedElement = dependency.getElement(); |
| // |
| // // Since this element is un-selected, remove all previous errors. |
| // removeError(changedElement); |
| // |
| // if (changedElement instanceof MethodLibrary) { |
| // return; |
| // } |
| // |
| // // Since this element is un-selected, remove all errors in the |
| // // referenced elements. |
| // List refs = dependency.getReferences(); |
| // if (refs != null && refs.size() > 0) { |
| // ElementReference ref; |
| // Object element; |
| // for (Iterator itr = refs.iterator(); itr.hasNext();) { |
| // ref = (ElementReference) itr.next(); |
| // element = ref.getRefElement(); |
| // |
| // ElementDependencyError error = getError(element, false); |
| // if (error != null) { |
| // PackageError pkgerror = error.removeError(changedElement); |
| // if (error.size() == 0) { |
| // removeError(element); |
| // |
| // // Clear the parent error introduced by this element. |
| // updateParentsForErrors((EObject) element); |
| // |
| // } |
| // |
| // // notify the error listener about the error removed |
| // notifyErrorRemoved(pkgerror); |
| // |
| // } |
| // } |
| // } |
| // |
| // // If an element is unchecked, check the dependent elements. |
| // // If there are check elements depending on it, the element can't be |
| // // unchecked. |
| // List dependents = dependency.getDependents(); |
| // if (dependents != null && dependents.size() > 0) { |
| // Object element; |
| // for (Iterator itr = dependents.iterator(); itr.hasNext();) { |
| // element = itr.next(); |
| // |
| // if (element instanceof MethodLibrary) { |
| // continue; |
| // } |
| // |
| // if (isSelected(element)) { |
| // // Determine the type of dependency. |
| // PackageDependency childDep = dependencyManager |
| // .getDependency((MethodElement) element); |
| // |
| // validateSelected(childDep); |
| // } else { |
| // removeError(changedElement); |
| // } |
| // } |
| // } |
| // |
| // // finally, update the parents |
| // updateParentsForErrors((EObject) changedElement); |
| // } |
| // |
| private void updateParentError(EObject parent, EObject element, |
| int errorType) { |
| if (parent == null || (parent instanceof MethodLibrary)) { |
| return; |
| } |
| |
| // if ((parent instanceof MethodPackage) |
| // && ConfigurationHelper.isGlobalPackage((MethodPackage) parent)) { |
| // updateParentError(parent.eContainer(), element, errorType); |
| // return; |
| // } |
| |
| // Remove the error associated with this element from all parents. |
| ElementDependencyError error = getError(parent, false); |
| if (error != null && error.size() > 0) { |
| error.removeError(element); |
| } |
| |
| if (errorType != ErrorInfo.NONE) { |
| // Propegate the error to all parents. |
| error = getError(parent, true); |
| String message = LibraryResources.configClosureWarning_msg1; |
| PackageError pkgerr = new PackageError(errorType, message, parent, element, |
| ErrorInfo.NONE); |
| error.addError(pkgerr); |
| } else if ((error != null) && (error.size() == 0)) { |
| removeError(parent); |
| } |
| |
| updateParentError(parent.eContainer(), element, errorType); |
| } |
| |
| private void updateParentsForErrors(EObject element) { |
| int errorType = ErrorInfo.NONE; |
| |
| ElementDependencyError error = getError(element); |
| if (error != null && error.size() > 0) { |
| if (error.isError() || error.isChildError()) { |
| errorType = PackageError.CHILD_ERROR; |
| } else if (error.isWarning() || error.isChildWarning()) { |
| errorType = PackageError.CHILD_WARNING; |
| } |
| } |
| |
| updateParentError(element.eContainer(), element, errorType); |
| } |
| |
| /** |
| * accept the cutrrent selection, fix the errors and ignore any warning message. |
| * |
| */ |
| public void fixErrors() { |
| boolean changed = true; |
| boolean forceCheck = true; |
| while (changed) { |
| changed = fixProblems(true, forceCheck); |
| forceCheck = false; |
| } |
| } |
| |
| /** |
| * fix all error(s) and warnign(s) |
| * |
| */ |
| public void fixProblems() { |
| boolean changed = true; |
| boolean forceCheck = true; |
| while (changed) { |
| changed = fixProblems(false, forceCheck); |
| forceCheck = false; |
| } |
| } |
| |
| private boolean fixProblems(boolean errorOnly, boolean forceCheck) { |
| // Note: make closure will select elements as needed. |
| // so we need to make a copy of the current selcted ones |
| // in order to trace the status |
| //List currentSelected = new ArrayList(selectedNotes); |
| |
| // if force check is set, run check anyway |
| boolean changed = forceCheck; |
| |
| // list of errorInfo objects |
| List errors = getAllErrors(); |
| if (errors.size() > 0) { |
| invalidNodesMap.clear(); |
| PackageError error; |
| EObject causeElement; |
| //boolean ownerSelected, causeSelected; |
| for (Iterator it = errors.iterator(); it.hasNext();) { |
| error = (PackageError) it.next(); |
| |
| //ownerElement = (EObject) error.getOwnerElement(); |
| causeElement = (EObject) error.getCauseElement(); |
| //addChanged(ownerElement); |
| //addChanged(causeElement); |
| // if (error.isChildError() || error.isChildWarning()) { |
| // continue; |
| // } |
| |
| boolean isError = error.isError(); |
| boolean isWarning = error.isWarning(); |
| if (!isError && !isWarning || !isError && errorOnly) { |
| continue; |
| } |
| |
| if ( !isSelected(causeElement) && selectErrorElement(causeElement) ) { |
| changed = true; |
| } |
| } |
| } |
| |
| if ( changed ) { |
| checkError(); |
| } |
| |
| return changed; |
| } |
| |
| private boolean selectErrorElement(EObject element) { |
| |
| boolean selected = true; |
| if (element instanceof MethodPlugin |
| && !config.getMethodPluginSelection().contains(element)) { |
| config.getMethodPluginSelection().add((MethodPlugin) element); |
| } else if ( element instanceof MethodPackage |
| && !config.getMethodPackageSelection().contains(element)){ |
| config.getMethodPackageSelection().add((MethodPackage) element); |
| } else { |
| selected = false; |
| } |
| |
| return selected; |
| } |
| |
| // /** |
| // * update the method configuration in the library with the current selections |
| // */ |
| // public void saveMethodConfiguration() { |
| // List plugins = config.getMethodPluginSelection(); |
| // List packages = config.getMethodPackageSelection(); |
| // |
| // plugins.clear(); |
| // packages.clear(); |
| // |
| // EObject element; |
| // for (Iterator it = selectedNotes.iterator(); it.hasNext();) { |
| // element = (EObject) it.next(); |
| // if (element instanceof MethodPlugin) { |
| // if (!plugins.contains(element)) { |
| // plugins.add(element); |
| // } |
| // } else if ((element instanceof MethodPackage) |
| // && !ConfigurationHelper |
| // .isGlobalPackage((MethodPackage) element)) { |
| // if (!packages.contains(element)) { |
| // packages.add(element); |
| // } |
| // } |
| // } |
| // } |
| |
| /** |
| * Packages the library based on the selection. |
| * <p> |
| * Note: This will change the current library. Before calling this method, a |
| * copy of the current library should be created with the following steps: |
| * 1. Create a new <code>ConfigurationManager</code> with a copy of the |
| * original library, 2. Rebuild the dependency, 3. Create a |
| * <code>ConfigurationClosure</code> with the current configuration. |
| * |
| * @return A <code>MethodLibrary</code>. |
| */ |
| public MethodLibrary packageLibrary(boolean removeBrokenReferences) { |
| processSelection(library, removeBrokenReferences); |
| |
| // Remove the configurations except for the current one. |
| List configs = library.getPredefinedConfigurations(); |
| configs.clear(); |
| configs.add(config); |
| |
| return library; |
| } |
| |
| /** |
| * process the selected package by removeing all unselected elements and any |
| * missing references |
| * |
| * @param element |
| */ |
| private void processSelection(EObject element, |
| boolean removeBrokenReferences) { |
| if (removeBrokenReferences) { |
| // Iterator the references and remove broken references. |
| EList references = element.eCrossReferences(); |
| if (references != null) { |
| for (Iterator it = new ArrayList(references).iterator(); it |
| .hasNext();) { |
| EObject ref = (EObject) it.next(); |
| EObject pkgRef = LibraryUtil.getSelectable(ref); |
| if (pkgRef != null && !isSelected(pkgRef)) { |
| removeReference(element, ref); |
| } |
| } |
| } |
| } |
| |
| EList elements = element.eContents(); |
| if (elements != null) { |
| for (Iterator it = new ArrayList(elements).iterator(); it.hasNext();) { |
| EObject child = (EObject) it.next(); |
| |
| // If the child element is selectable but it is not in the |
| // configuration, remove it. |
| if (LibraryUtil.selectable(child) && !isSelected(child)) { |
| EcoreUtil.remove(child); |
| } else { |
| processSelection(child, removeBrokenReferences); |
| } |
| } |
| } |
| } |
| |
| private void removeReference(EObject ownerElement, EObject refElement) { |
| AdapterFactoryContentProvider provider = configManager |
| .getContentProvider(); |
| IPropertySource ps = provider.getPropertySource(ownerElement); |
| IPropertyDescriptor[] pds = ps.getPropertyDescriptors(); |
| if (pds != null && pds.length > 0) { |
| for (int i = 0; i < pds.length; i++) { |
| IPropertyDescriptor descriptor = (IPropertyDescriptor) pds[i]; |
| Object id = descriptor.getId(); |
| Object value = ps.getPropertyValue(id); |
| |
| // Check whether the value needs to be converted to an editable |
| // value. |
| IPropertySource source = provider.getPropertySource(value); |
| if (source != null) { |
| value = source.getEditableValue(); |
| } |
| if (value instanceof EList) { |
| EList refList = (EList) value; |
| if (refList.contains(refElement)) { |
| if (debug) { |
| System.out |
| .println("Reference [" + LibraryUtil.getName(refElement) //$NON-NLS-1$ |
| + "] removed from [" //$NON-NLS-1$ |
| + LibraryUtil.getName(ownerElement) |
| + "]'s reference list"); //$NON-NLS-1$ |
| } |
| refList.remove(refElement); |
| ps.setPropertyValue(id, refList); |
| } |
| } else if (value instanceof MethodElement) { |
| if (debug) { |
| System.out |
| .println("Reference [" + LibraryUtil.getName(refElement) //$NON-NLS-1$ |
| + "] removed from [" //$NON-NLS-1$ |
| + LibraryUtil.getName(ownerElement) |
| + "]"); //$NON-NLS-1$ |
| } |
| ps.setPropertyValue(id, null); |
| } |
| |
| } |
| } |
| } |
| |
| /** |
| * Disposes resources allocated by this closure. |
| */ |
| public void dispose() { |
| |
| clearErrorMarks(); |
| |
| if (configManager != null) { |
| ConfigurationProperties props = configManager.getConfigurationProperties(); |
| props.removeListener(configPropListener); |
| } |
| |
| configManager = null; |
| config = null; |
| library = null; |
| dependencyManager = null; |
| actionMgr = null; |
| //selectedNotes.clear(); |
| //changedNodes.clear(); |
| if (invalidNodesMap != null) { |
| invalidNodesMap.clear(); |
| } |
| if (listeners != null) { |
| listeners.clear(); |
| } |
| clearReplacerElementMarkerMap(); |
| } |
| |
| private void clearReplacerElementMarkerMap() { |
| if (replacerElementMarkerMap != null) { |
| for (IMarker marker: replacerElementMarkerMap.values()) { |
| try { |
| marker.delete(); |
| } catch (Exception e) { |
| LibraryPlugin.getDefault().getLogger().logError(e); |
| } |
| } |
| } |
| replacerElementMarkerMap = null; |
| } |
| |
| // private boolean canIgnore(PackageReference pkgRef) { |
| // return pkgRef.canIgnore(); |
| // } |
| |
| public void addListener(ClosureListener listener) { |
| if (listeners == null) { |
| listeners = new ArrayList<ClosureListener>(); |
| } |
| if (!listeners.contains(listener)) { |
| listeners.add(listener); |
| } |
| |
| notifyListener(listener, this.errors); |
| } |
| |
| public void removeListener(ClosureListener listener) { |
| if (listeners != null) { |
| if (listeners.contains(listener)) { |
| listeners.remove(listener); |
| } |
| } |
| } |
| |
| // private void notifyErrorAdded(PackageError pkgerror) { |
| // //notifyListeners(ClosureListener.ERROR_ADDED, pkgerror); |
| // } |
| // |
| // private void notifyErrorRemoved(PackageError pkgerror) { |
| // //notifyListeners(ClosureListener.ERROR_REMOVED, pkgerror); |
| // } |
| |
| private void notifyListener(ClosureListener listener, List errors) { |
| |
| for ( Iterator it = errors.iterator(); it.hasNext(); ) { |
| ElementError error = (ElementError)it.next(); |
| listener.fireEvent(ClosureListener.ERROR_ADDED, config, error); |
| } |
| } |
| |
| public synchronized boolean isAbortCheckError() { |
| return abortCheckError; |
| } |
| |
| public synchronized void setAbortCheckError(boolean abortCheckError) { |
| this.abortCheckError = abortCheckError; |
| if (ConfigDataBase.localDebug) { |
| System.out.println("LD> setAbortCheckError: " + abortCheckError);//$NON-NLS-1$ |
| } |
| } |
| |
| // /** |
| // * add this element into the configuration |
| // * this is for quick fix action |
| // * our default implementation is to select the owning package |
| // * @param element |
| // * @return IStatus |
| // */ |
| // public IStatus selectElement(MethodElement element) { |
| // |
| // //if the element is subtracted, we can't select the element |
| // // return an error |
| // if ( configManager.getConfigurationData().isElementInSubtractedCategory(element)) { |
| // String message = LibraryResources.bind(LibraryResources.QuickfixError_reason1, |
| // (new String[] {LibraryUtil.getTypeName(element)})); |
| // return new Status(IStatus.ERROR, |
| // LibraryPlugin.getDefault().getId(), IStatus.OK, message, null); |
| // } |
| // |
| // // for quick fix, we just select the package of the element |
| // // and the child packages |
| // Object owner = LibraryUtil.getSelectable(element); |
| // if ( owner != null && owner instanceof MethodPackage) { |
| // config.getMethodPackageSelection().add(owner); |
| // } |
| // |
| // return Status.OK_STATUS; |
| // } |
| } |