| package org.eclipse.epf.library.validation; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.epf.library.LibraryPlugin; |
| import org.eclipse.epf.library.LibraryResources; |
| import org.eclipse.epf.library.edit.LibraryEditPlugin; |
| import org.eclipse.epf.library.edit.LibraryEditResources; |
| import org.eclipse.epf.library.edit.util.LibraryEditUtil; |
| import org.eclipse.epf.library.edit.util.Misc; |
| import org.eclipse.epf.library.edit.util.TngUtil; |
| import org.eclipse.epf.library.edit.validation.ValidationStatus; |
| import org.eclipse.epf.library.util.LibraryUtil; |
| import org.eclipse.epf.persistence.FileManager; |
| import org.eclipse.epf.uma.MethodElement; |
| import org.eclipse.epf.uma.MethodPlugin; |
| import org.eclipse.epf.uma.UmaPackage; |
| import org.eclipse.epf.uma.util.UmaUtil; |
| import org.eclipse.epf.validation.LibraryEValidator; |
| |
| public class UndeclaredDependencyCheck extends ValidationAction { |
| |
| private Map<MethodPlugin, Set<MethodPlugin>> baseMap; |
| private Map<MethodPlugin, Set<MethodPlugin>> problemPluginMap; |
| private Map<String, Set<MethodElement>> problemElementMap; |
| private boolean skipContent = true; |
| |
| public UndeclaredDependencyCheck(ValidationManager mgr) { |
| super(mgr); |
| } |
| |
| @Override |
| public void run() { |
| Set<MethodPlugin> pluginSet = getMgr().getPluginSet(); |
| if (pluginSet == null || pluginSet.isEmpty()) { |
| return; |
| } |
| |
| //Initialization |
| problemPluginMap = new HashMap<MethodPlugin, Set<MethodPlugin>>(); |
| problemElementMap = new HashMap<String, Set<MethodElement>>(); |
| baseMap = new HashMap<MethodPlugin, Set<MethodPlugin>>(); |
| |
| Misc.clearCachedMap(); |
| for (MethodPlugin plugin : pluginSet) { |
| Set baseSet = new HashSet(); |
| baseSet.addAll(Misc.getAllBase1(plugin)); |
| baseMap.put(plugin, baseSet); |
| } |
| Misc.clearCachedMap(); |
| |
| //Validation check |
| Set<MethodElement> processed = new HashSet<MethodElement>(); |
| for (MethodPlugin plugin : pluginSet) { |
| checkReferences(plugin, processed); |
| } |
| |
| |
| MultiStatus multiStatus = new MultiStatus(LibraryPlugin.PLUGIN_ID, 0, "", null); //$NON-NLS-1$ |
| //Build markers |
| for (Map.Entry<MethodPlugin, Set<MethodPlugin>> entry : problemPluginMap |
| .entrySet()) { |
| MethodPlugin plugin = entry.getKey(); |
| Set<MethodPlugin> set = entry.getValue(); |
| |
| String msg0 = LibraryResources.bind(LibraryResources.UndeclaredDep_MarkerTxt1, (new String[] {plugin.getName()})); |
| for (MethodPlugin p : set) { |
| IMarker marker = getMgr().createMarker(plugin); |
| String msg = msg0 + " '" + p.getName() + "'"; //$NON-NLS-1$ //$NON-NLS-2$ |
| String key = plugin.getGuid() + p.getGuid(); |
| Set<MethodElement> elements = problemElementMap.get(key); |
| if (elements != null && !elements.isEmpty()) { |
| String line2msg0 = ". \n" + LibraryResources.UndeclaredDep_MarkerTxt2 + " "; //$NON-NLS-1$ //$NON-NLS-2$ |
| String line2msg = line2msg0; |
| for (MethodElement e : elements) { |
| if (line2msg.length() > 155) { |
| line2msg += " ... "; //$NON-NLS-1$ |
| break; |
| } |
| if (line2msg != line2msg0) { |
| line2msg += "; "; //$NON-NLS-1$ |
| } |
| line2msg += TngUtil.getLabelWithPath(e); |
| } |
| msg += line2msg; |
| } |
| try { |
| marker.setAttribute(IMarker.MESSAGE, msg); |
| |
| marker.setAttribute(IMarker.SEVERITY, |
| IMarker.SEVERITY_WARNING); |
| |
| marker.setAttribute(IMarker.LOCATION, TngUtil.getLabelWithPath(plugin)); |
| marker.setAttribute(ValidationManager.validationType, ValidationManager.validationType_undeclaredDependancyCheck); |
| |
| MarkerInfo markerInfo = new MarkerInfo(plugin, p, elements); |
| getMgr().addToMarkInfoMap(marker, markerInfo); |
| |
| multiStatus.add(new ValidationStatus(IStatus.WARNING, 0, LibraryResources.UndeclaredDep_MarkerTxt0, plugin, null)); |
| |
| } catch (Exception e) { |
| LibraryPlugin.getDefault().getLogger().logError(e); |
| } |
| } |
| } |
| |
| LibraryEValidator.appendDiagnostics(multiStatus, getMgr().getDiagnostics()); |
| //Clear |
| problemPluginMap = null; |
| problemElementMap = null; |
| baseMap =null; |
| } |
| |
| private void addToProblemPluginMap(MethodPlugin plugin, MethodPlugin referencedPlugin) { |
| Set<MethodPlugin> set = problemPluginMap.get(plugin); |
| if (set == null) { |
| set = new HashSet<MethodPlugin>(); |
| problemPluginMap.put(plugin, set); |
| } |
| set.add(referencedPlugin); |
| } |
| |
| |
| private void checkReferences(MethodElement me, Set<MethodElement> processed) { |
| if (processed.contains(me)) { |
| return; |
| } |
| processed.add(me); |
| MethodPlugin ownerPlugin = UmaUtil.getMethodPlugin(me); |
| if ( ! getMgr().getPluginSet().contains(ownerPlugin)) { |
| return; |
| } |
| |
| Set<MethodPlugin> baseSet = baseMap.get(ownerPlugin); |
| |
| EList<EReference> refList = me.eClass().getEAllReferences(); |
| if (refList == null || refList.isEmpty()) { |
| return; |
| } |
| for (EReference ref : refList) { |
| if (skipContent && LibraryUtil.isContentRef(ref)) { |
| continue; |
| } |
| if (ref == UmaPackage.eINSTANCE.getRole_Modifies()) { |
| continue; |
| } |
| Object obj = me.eGet(ref); |
| if (obj instanceof MethodElement) { |
| MethodElement referenced = (MethodElement) obj; |
| recordOneHit(me, ownerPlugin, baseSet, referenced); |
| checkReferences(referenced, processed); |
| |
| } else if (obj instanceof List) { |
| List list = (List) obj; |
| for (Object itemObj : list) { |
| if (itemObj instanceof MethodElement) { |
| MethodElement referenced = (MethodElement) itemObj; |
| recordOneHit(me, ownerPlugin, baseSet, referenced); |
| checkReferences(referenced, processed); |
| } |
| } |
| } |
| } |
| } |
| |
| private void recordOneHit(MethodElement me, MethodPlugin ownerPlugin, |
| Set<MethodPlugin> baseSet, MethodElement referenced) { |
| MethodPlugin referencedPlugin = UmaUtil.getMethodPlugin(referenced); |
| if (referencedPlugin != null && referencedPlugin != ownerPlugin && !baseSet.contains(referencedPlugin)) { |
| addToProblemPluginMap(ownerPlugin, referencedPlugin); |
| String key = ownerPlugin.getGuid() + referencedPlugin.getGuid(); |
| Set<MethodElement> set = problemElementMap.get(key); |
| if (set == null) { |
| set = new HashSet<MethodElement>(); |
| problemElementMap.put(key, set); |
| } |
| set.add(me); |
| } |
| } |
| |
| public void clearResults() { |
| } |
| |
| public String addPluginFix(IMarker marker) { |
| String emptyStr = ""; //$NON-NLS-1$ |
| |
| Object obj = getMgr().getMarkInfo(marker); |
| MarkerInfo info = obj instanceof MarkerInfo ? (MarkerInfo) obj : null; |
| if (info == null) { |
| return emptyStr; |
| } |
| if (info.referencing == null || info.referenced == null || info.referencing == info.referenced) { |
| return emptyStr; |
| } |
| |
| if (Misc.isBaseOf(info.referencing, info.referenced, new HashMap())) { |
| return LibraryEditResources.circular_dependency_error_msg; |
| } |
| |
| info.referencing.getBases().add(info.referenced); |
| Resource resource = info.referencing.eResource(); |
| if (resource == null || !LibraryEditUtil.getInstance().save(Collections.singleton(resource))) { |
| info.referencing.getBases().remove(info.referenced); |
| LibraryPlugin.getDefault().getLogger().logError("addPluginFix falied at save");//$NON-NLS-1$ |
| return emptyStr; |
| } |
| |
| getMgr().removeFromMarkInfoMap(marker); |
| return emptyStr; |
| } |
| |
| public String removeReferenceFix(IMarker marker) { |
| String emptyStr = ""; //$NON-NLS-1$ |
| |
| Object infoObj = getMgr().getMarkInfo(marker); |
| MarkerInfo info = infoObj instanceof MarkerInfo ? (MarkerInfo) infoObj : null; |
| if (info == null || info.referenced == null) { |
| return emptyStr; |
| } |
| Set<MethodElement> offenderElements = info.offenderElements; |
| if (offenderElements == null || offenderElements.isEmpty()) { |
| return emptyStr; |
| } |
| Set<Resource> resources = new HashSet<Resource>(); |
| for (MethodElement e : offenderElements) { |
| Resource res = e.eResource(); |
| if (res != null) { |
| resources.add(res); |
| } |
| } |
| List<String> pathList = new ArrayList<String>(); |
| for (Resource res : resources) { |
| pathList.add(res.getURI().toFileString()); |
| } |
| |
| IStatus status = FileManager.getInstance().checkModify(pathList.toArray(new String[pathList.size()]), LibraryPlugin.getDefault().getContext()); |
| if (!status.isOK()) { |
| info.referencing.getBases().remove(info.referenced); |
| LibraryPlugin.getDefault().getLogger().logError("addPluginFix falied at file check");//$NON-NLS-1$ |
| return emptyStr; |
| } |
| |
| for (MethodElement me : offenderElements) { |
| EList<EReference> refList = me.eClass().getEAllReferences(); |
| if (refList == null) { |
| continue; |
| } |
| for (EReference ref : refList) { |
| if (skipContent && LibraryUtil.isContentRef(ref)) { |
| continue; |
| } |
| if (ref == UmaPackage.eINSTANCE.getRole_Modifies()) { |
| continue; |
| } |
| Object obj = me.eGet(ref); |
| if (obj instanceof MethodElement) { |
| MethodElement referenced = (MethodElement) obj; |
| if (info.referenced == UmaUtil.getMethodPlugin(referenced)) { |
| me.eSet(ref, null); |
| } |
| |
| } else if (obj instanceof List) { |
| List list = (List) obj; |
| for (int i = list.size() - 1; i >= 0 ; i--) { |
| Object itemObj = list.get(i); |
| if (itemObj instanceof MethodElement) { |
| MethodElement referenced = (MethodElement) itemObj; |
| if (info.referenced == UmaUtil.getMethodPlugin(referenced)) { |
| list.remove(i); |
| } |
| } |
| } |
| } |
| } |
| |
| } |
| |
| if (!LibraryEditUtil.getInstance().save(resources)) { |
| info.referencing.getBases().remove(info.referenced); |
| LibraryPlugin.getDefault().getLogger().logError("addPluginFix falied at save");//$NON-NLS-1$ |
| return emptyStr; |
| } |
| |
| getMgr().removeFromMarkInfoMap(marker); |
| return emptyStr; |
| } |
| |
| static class MarkerInfo { |
| MethodPlugin referencing; |
| MethodPlugin referenced; |
| Set<MethodElement> offenderElements; |
| public MarkerInfo(MethodPlugin referencing, MethodPlugin referenced, Set<MethodElement> offenderElements) { |
| this.referencing = referencing; |
| this.referenced = referenced; |
| this.offenderElements = offenderElements; |
| } |
| } |
| |
| } |