/******************************************************************************* * Copyright (c) 2007 Intel 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: * Intel Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.cdt.managedbuilder.core.IResourceInfo; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.tcmodification.ToolListMap; import org.eclipse.cdt.managedbuilder.internal.tcmodification.ToolListMap.CollectionEntry; import org.eclipse.core.runtime.IConfigurationElement; public class ToolChainModificationHelper { private static ToolListMap createRealToToolMap(ITool[] tools, boolean ext){ ToolListMap lMap = new ToolListMap(); for(int i = 0; i < tools.length; i++){ ITool tool = tools[i]; ITool rt = ManagedBuildManager.getRealTool(tool); if(rt == null) rt = tool; ITool t = ext ? ManagedBuildManager.getExtensionTool(tool) : tool; if(t == null) t = tool; lMap.add(rt, t); } return lMap; } // private static ListMap calculateDifference(ListMap m1, ListMap m2){ // m1 = (ListMap)m1.clone(); // Set ceSet2 = m2.collectionEntrySet(); // // for(Iterator iter = ceSet2.iterator(); iter.hasNext(); ){ // CollectionEntry entry = (CollectionEntry)iter.next(); // Collection c1 = m2.get((ITool) entry.getKey(), false); // if(c1 != null){ // Collection c2 = entry.getValue(); // int i = c2.size(); // for(Iterator c1Iter = c1.iterator(); i >= 0 && c1Iter.hasNext(); i--){ // c1Iter.next(); // c1Iter.remove(); // } // } // } // // return m1; // } static public ToolListModificationInfo getModificationInfo(IResourceInfo rcInfo, ITool[] fromTools, ITool[] addedTools, ITool[] removedTools){ ToolListMap addedMap = createRealToToolMap(addedTools, false); for(int i = 0; i < removedTools.length; i++){ ITool removedTool = removedTools[i]; ITool realTool = ManagedBuildManager.getRealTool(removedTool); if(realTool == null) realTool = removedTool; addedMap.remove(realTool, 0); } ToolListMap removedMap = createRealToToolMap(removedTools, false); for(int i = 0; i < addedTools.length; i++){ ITool addedTool = addedTools[i]; ITool realTool = ManagedBuildManager.getRealTool(addedTool); if(realTool == null) realTool = addedTool; removedMap.remove(realTool, 0); } addedMap.clearEmptyLists(); removedMap.clearEmptyLists(); ToolListMap curMap = createRealToToolMap(fromTools, false); for (CollectionEntry entry : removedMap.collectionEntrySet()) { List<ITool> cur = curMap.get(entry.getKey(), false); List<ITool> removed = entry.getValue(); if(cur != null){ int numToRemove = removed.size(); int curSize = cur.size(); if(curSize <= numToRemove){ curMap.removeAll(entry.getKey()); } else { for(int i = 0; i < numToRemove; i++){ cur.remove(0); } } } } curMap.clearEmptyLists(); for (CollectionEntry entry : addedMap.collectionEntrySet()) { List<ITool> cur = curMap.get(entry.getKey(), true); List<ITool> added = entry.getValue(); int numToAdd = added.size(); numToAdd -= cur.size(); for(int i = 0; i < numToAdd; i++){ cur.add(added.get(i)); } if(cur.size() == 0) curMap.removeAll(entry.getKey()); } curMap.clearEmptyLists(); List<ITool> resultingList = new ArrayList<ITool>(); curMap.putValuesToCollection(resultingList); return getModificationInfo(rcInfo, fromTools, resultingList.toArray(new ITool[resultingList.size()])); } static public ToolListModificationInfo getModificationInfo(IResourceInfo rcInfo, ITool[] fromTools, ITool[] toTools){ ToolListMap curMap = createRealToToolMap(fromTools, false); List<ToolInfo> resultingList = new ArrayList<ToolInfo>(); List<ToolInfo> addedList = new ArrayList<ToolInfo>(7); List<ToolInfo> remainedList = new ArrayList<ToolInfo>(7); List<ToolInfo> removedList = new ArrayList<ToolInfo>(7); List<ITool> removedToolsList = new ArrayList<ITool>(7); for(int i = 0; i < toTools.length; i++){ ITool tool = toTools[i]; ITool realTool = ManagedBuildManager.getRealTool(tool); if(realTool == null) realTool = tool; ITool remaining = curMap.remove(realTool, 0); ToolInfo tInfo; if(remaining != null){ tInfo = new ToolInfo(rcInfo, remaining, ToolInfo.REMAINED); remainedList.add(tInfo); } else { tInfo = new ToolInfo(rcInfo, tool, ToolInfo.ADDED); addedList.add(tInfo); } resultingList.add(tInfo); } curMap.valuesToCollection(removedToolsList); for (ITool t : removedToolsList) { removedList.add(new ToolInfo(rcInfo, t, ToolInfo.REMOVED)); } ToolInfo[] added = listToArray(addedList); ToolInfo[] removed = listToArray(removedList); adjustAddedList(added, removed); calculateConverterTools(rcInfo, removed, added, null, null); return new ToolListModificationInfo(rcInfo, listToArray(resultingList), added, removed, listToArray(remainedList)); } private static ITool getCommonSuperClass(ITool tool1, ITool tool2){ for(int i = 0; tool2 != null; tool2 = tool2.getSuperClass(), i++){ if(getSuperClassLevel(tool1, tool2) != -1) return tool2; } return null; } private static int getSuperClassLevel(ITool tool, ITool superClass){ for(int i = 0; tool != null; tool = tool.getSuperClass(), i++){ if(superClass == tool) return i; } return -1; } private static int getLevel(ITool tool){ int i= 0; for(; tool != null; tool = tool.getSuperClass(), i++) { // empty } return i; } private static ITool getBestMatchTool(ITool realTool, ToolInfo[] tools){ int num = -1; ITool bestMatch = null; ITool[] identicTools = ManagedBuildManager.findIdenticalTools(realTool); for(int i = 0; i < tools.length; i++){ ITool extTool = ManagedBuildManager.getExtensionTool(tools[i].getInitialTool()); for(int k = 0; k < identicTools.length; k++){ ITool identic = identicTools[k]; ITool commonSuper = getCommonSuperClass(extTool, identic); if(commonSuper != null){ int level = getLevel(commonSuper); if(level > num){ bestMatch = identic; num = level; } } } } return bestMatch; } private static void adjustAddedList(ToolInfo[] adds, ToolInfo[] removes){ for(int i = 0; i < adds.length; i++){ ToolInfo add = adds[i]; ITool bestMatch = getBestMatchTool(add.getRealTool(), removes); if(bestMatch != null){ add.updateInitialTool(bestMatch); } } } private static ToolInfo[] listToArray(List<ToolInfo> list){ return list.toArray(new ToolInfo[list.size()]); } private static Map<ITool, ConverterInfo> calculateConverterTools(IResourceInfo rcInfo, ToolInfo[] removed, ToolInfo[] added, List<ToolInfo> remainingRemoved, List<ToolInfo> remainingAdded){ if(remainingAdded == null) remainingAdded = new ArrayList<ToolInfo>(added.length); if(remainingRemoved == null) remainingRemoved = new ArrayList<ToolInfo>(removed.length); remainingAdded.clear(); remainingRemoved.clear(); remainingAdded.addAll(Arrays.asList(added)); remainingRemoved.addAll(Arrays.asList(removed)); Map<ITool, ConverterInfo> resultMap = new HashMap<ITool, ConverterInfo>(); for(Iterator<ToolInfo> rIter = remainingRemoved.iterator(); rIter.hasNext();){ ToolInfo rti = rIter.next(); ITool r = rti.getInitialTool(); if(r == null || r.getParentResourceInfo() != rcInfo) continue; Map<String, IConfigurationElement> map = ManagedBuildManager.getConversionElements(r); if(map.size() == 0) continue; for(Iterator<ToolInfo> aIter = remainingAdded.iterator(); aIter.hasNext();){ ToolInfo ati = aIter.next(); ITool a = ati.getBaseTool(); if(a == null || a.getParentResourceInfo() == rcInfo) continue; a = ati.getBaseExtensionTool(); if(a == null) continue; IConfigurationElement el = getToolConverterElement(r, a); if(el != null){ ConverterInfo ci = new ConverterInfo(rcInfo, r, a, el); resultMap.put(r, ci); rIter.remove(); aIter.remove(); ati.setConversionInfo(rti, ci); rti.setConversionInfo(ati, ci); break; } } } return resultMap; } private static IConfigurationElement getToolConverterElement(ITool fromTool, ITool toTool){ return ((Tool)fromTool).getConverterModificationElement(toTool); } }