/*******************************************************************************
* Copyright (c) 2007, 2008 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.tcmodification;
import java.util.ArrayList;
import java.util.Arrays;
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.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IFileInfo;
import org.eclipse.cdt.managedbuilder.core.IFolderInfo;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
import org.eclipse.cdt.managedbuilder.internal.core.FolderInfo;
import org.eclipse.cdt.managedbuilder.internal.core.IRealBuildObjectAssociation;
import org.eclipse.cdt.managedbuilder.internal.core.ResourceConfiguration;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.extension.ObjectSetListBasedDefinition;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.extension.RulesManager;
import org.eclipse.cdt.managedbuilder.tcmodification.IFileInfoModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IFolderInfoModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IToolChainModificationManager;
import org.eclipse.core.runtime.IPath;
public class ToolChainModificationManager implements
IToolChainModificationManager {
private static ToolChainModificationManager fInstance;
private ToolChainModificationManager(){
}
public static ToolChainModificationManager getInstance(){
if(fInstance == null)
fInstance = getInstanceSynch();
return fInstance;
}
private static synchronized ToolChainModificationManager getInstanceSynch() {
if(fInstance == null)
fInstance = new ToolChainModificationManager();
return fInstance;
}
public void start(){
RulesManager.getInstance().start();
}
@Override
public IFileInfoModification createModification(IFileInfo rcInfo) {
return new FileInfoModification((ResourceConfiguration)rcInfo);
}
@Override
public IFolderInfoModification createModification(IFolderInfo rcInfo) {
FolderInfo foInfo = (FolderInfo)rcInfo;
if(foInfo.isRoot())
return new ConfigurationModification(foInfo);
return new FolderInfoModification(foInfo);
}
@Override
public IFolderInfoModification createModification(IConfiguration cfg,
IFolderInfoModification base) throws IllegalArgumentException {
IResourceInfo baseRcInfo = base.getResourceInfo();
IPath path = baseRcInfo.getPath();
IResourceInfo rcInfo = cfg.getResourceInfo(path, true);
FolderInfo folderInfo;
if(rcInfo != null){
if(rcInfo instanceof FolderInfo){
folderInfo = (FolderInfo)rcInfo;
} else {
throw new IllegalArgumentException();
}
} else {
folderInfo = (FolderInfo)cfg.createFolderInfo(path);
}
return folderInfo.isRoot() ?
new ConfigurationModification(folderInfo, (ConfigurationModification)base)
: new FolderInfoModification(folderInfo, (FolderInfoModification)base);
}
@Override
public IFileInfoModification createModification(IConfiguration cfg,
IFileInfoModification base) throws IllegalArgumentException {
IResourceInfo baseRcInfo = base.getResourceInfo();
IPath path = baseRcInfo.getPath();
IResourceInfo rcInfo = cfg.getResourceInfo(path, true);
ResourceConfiguration fileInfo;
if(rcInfo != null){
if(rcInfo instanceof ResourceConfiguration){
fileInfo = (ResourceConfiguration)rcInfo;
} else {
throw new IllegalArgumentException();
}
} else {
fileInfo = (ResourceConfiguration)cfg.createFileInfo(path);
}
return new FileInfoModification(fileInfo, (FileInfoModification)base);
}
public static boolean checkFlags(int flags, int value){
return (flags & value) == value;
}
public static int addFlags(int flags, int value){
return flags |= value;
}
public static int clearFlags(int flags, int value){
return flags &= (~value);
}
private boolean getMatchingObjects(int type, IObjectSet[] oSets, Set<IRealBuildObjectAssociation> skipSet, IRealBuildObjectAssociation additionalSkip, Set<IRealBuildObjectAssociation> result){
Set<IRealBuildObjectAssociation> tmp = null;
boolean added = false;
for (IObjectSet os : oSets) {
int setType = os.getObjectType();
if(setType != type)
continue;
if(tmp == null)
tmp = new HashSet<IRealBuildObjectAssociation>();
else
tmp.clear();
os.getRealBuildObjects(tmp);
if(skipSet != null)
tmp.removeAll(skipSet);
if(additionalSkip != null)
tmp.remove(additionalSkip);
if(result.addAll(tmp)){
added = true;
}
}
return added;
}
public ConflictMatchSet getConflictInfo(int objType, PerTypeMapStorage<IRealBuildObjectAssociation, Set<IPath>> parent){
//parent should be passed - it is constant no need to recalculate every time
//PerTypeMapStorage parent = TcModificationUtil.createParentObjectsRealToolToPathSet(foInfo);
ConflictMatchSet conflicts = getConflictMatches(objType, parent, null);
return conflicts;
}
public static class ConflictMatch {
final int fMatchType;
final Map<IRealBuildObjectAssociation, Set<IPath>> fRObjToPathMap;
final int fConflictType;
final Set<IRealBuildObjectAssociation> fConflicts;
ConflictMatch(int matchType, Map<IRealBuildObjectAssociation, Set<IPath>> rtToPathMap, int conflictType, Set<IRealBuildObjectAssociation> conflicts){
fMatchType = matchType;
fRObjToPathMap = Collections.unmodifiableMap(rtToPathMap);
fConflictType = conflictType;
fConflicts = Collections.unmodifiableSet(conflicts);
}
}
public static class ConflictMatchSet {
ConflictMatch[] fConflicts;
Map<? extends IRealBuildObjectAssociation, List<ConflictMatch>> fObjToConflictListMap;
ConflictMatchSet(ConflictMatch[] coflicts, Map<? extends IRealBuildObjectAssociation, List<ConflictMatch>> objToConflictMap){
fConflicts = coflicts;
fObjToConflictListMap = objToConflictMap;
}
}
private ConflictMatchSet getConflictMatches(int type, PerTypeMapStorage<IRealBuildObjectAssociation, Set<IPath>> rtToPath, PerTypeSetStorage<IRealBuildObjectAssociation> skip){
//conversion:
//1.first filter applicable to not-this
//2. get variants for applicable ones
//1.first filter applicable to not-this
List<ConflictMatch> conflictList = new ArrayList<ConflictMatch>();
Map<IRealBuildObjectAssociation, List<ConflictMatch>> objToConflictMatchMap = new HashMap<IRealBuildObjectAssociation, List<ConflictMatch>>();
ObjectSetListBasedDefinition[] defs = RulesManager.getInstance().getRules(ObjectSetListBasedDefinition.CONFLICT);
for(int i = 0; i < defs.length; i++){
ObjectSetListBasedDefinition def= defs[i];
ObjectSetList sl = def.getObjectSetList();
IObjectSet oss[] = sl.getObjectSets();
for(int k = 0; k < oss.length; k++){
IObjectSet os = oss[k];
int objType = os.getObjectType();
Map<IRealBuildObjectAssociation, Set<IPath>> rtToPathMap = rtToPath.getMap(objType, false);
if(rtToPathMap == null)
continue;
@SuppressWarnings("unchecked")
Map<IRealBuildObjectAssociation, Set<IPath>> clone = (Map<IRealBuildObjectAssociation, Set<IPath>>)((HashMap<IRealBuildObjectAssociation, Set<IPath>>)rtToPathMap).clone();
rtToPathMap = clone;
Set<IRealBuildObjectAssociation> skipSet = skip != null ? (Set<IRealBuildObjectAssociation>)skip.getSet(objType, false) : null;
Set<IRealBuildObjectAssociation> objSet = rtToPathMap.keySet();
if(skipSet != null)
objSet.removeAll(skipSet);
os.retainMatches(objSet);
if(objSet.size() != 0){
List<IObjectSet> remainingList = new ArrayList<IObjectSet>(Arrays.asList(oss));
remainingList.remove(os);
IObjectSet[] remaining = remainingList.toArray(new IObjectSet[remainingList.size()]);
//get objects matching remaining
Set<IRealBuildObjectAssociation> skipSet2 = skip != null ? (Set<IRealBuildObjectAssociation>)skip.getSet(type, false) : null;
Set<IRealBuildObjectAssociation> matchingObjects = new HashSet<IRealBuildObjectAssociation>();
getMatchingObjects(type, remaining, skipSet2, null, matchingObjects);
if(matchingObjects.size() != 0){
ConflictMatch conflict = new ConflictMatch(objType, rtToPathMap, type, matchingObjects);
for (IRealBuildObjectAssociation bo : matchingObjects) {
List<ConflictMatch> list = TcModificationUtil.getArrayList(objToConflictMatchMap, bo);
list.add(conflict);
}
conflictList.add(conflict);
}
// break;
}
}
}
return new ConflictMatchSet(conflictList.toArray(new ConflictMatch[conflictList.size()]), objToConflictMatchMap);
}
}