/*******************************************************************************
* 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.tcmodification.extension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.IRealBuildObjectAssociation;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.IObjectSet;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.Messages;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.ObjectSet;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.ObjectSetList;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.PerTypeMapStorage;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.TcModificationUtil;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.extension.MatchObjectElement.PatternElement;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
public class RulesManager {
private static RulesManager fInstance;
private static final String EXTENSION_POINT_ID = ManagedBuilderCorePlugin.getUniqueIdentifier() + ".tcModificationInfo"; //$NON-NLS-1$
private ConflictDefinition[] fConflictDefinitions;
private Map<MatchObjectElement, IObjectSet> fMatchObjectMap = new HashMap<MatchObjectElement, IObjectSet>();
private PerTypeMapStorage<IRealBuildObjectAssociation, Set<IRealBuildObjectAssociation>> fObjToChildSuperClassMap;
private StarterJob fStarter;
private boolean fIsStartInited;
private class StarterJob extends Job {
private StarterJob() {
super(Messages.getString("RulesManager.1")); //$NON-NLS-1$
setSystem(true);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
loadExtensions();
} finally {
fStarter = null;
}
return Status.OK_STATUS;
}
}
private RulesManager(){
}
public static RulesManager getInstance(){
if(fInstance == null)
fInstance = getInstanceSynch();
return fInstance;
}
public synchronized static RulesManager getInstanceSynch(){
if(fInstance == null)
fInstance = new RulesManager();
return fInstance;
}
public void start(){
if(fIsStartInited)
return;
synchronized (this) {
if(fIsStartInited)
return;
fIsStartInited = true;
}
fStarter = new StarterJob();
fStarter.schedule();
}
private void loadExtensions(){
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID);
if(extensionPoint == null){
fConflictDefinitions = new ConflictDefinition[0];
} else {
IExtension[] extensions = extensionPoint.getExtensions();
List<ConflictDefinition> conflictDefs = new ArrayList<ConflictDefinition>();
for (int i = 0; i < extensions.length; ++i) {
IExtension extension = extensions[i];
IConfigurationElement[] elements = extension.getConfigurationElements();
for(int k = 0; k < elements.length; k++){
IConfigurationElement el = elements[k];
String elName = el.getName();
if(ConflictDefinitionElement.ELEMENT_NAME.equals(elName)){
try {
ConflictDefinitionElement cde = new ConflictDefinitionElement(el);
ConflictDefinition cd = resolve(cde);
if(cd != null)
conflictDefs.add(cd);
} catch (IllegalArgumentException e){
ManagedBuilderCorePlugin.log(e);
}
}
}
}
fConflictDefinitions = conflictDefs.toArray(new ConflictDefinition[conflictDefs.size()]);
}
}
private ConflictDefinition resolve(ConflictDefinitionElement el) throws IllegalArgumentException {
MatchObjectElement mos[] = el.getMatchObjects();
if(mos.length != 2)
throw new IllegalArgumentException();
IObjectSet oss[] = new IObjectSet[mos.length];
for(int i = 0; i < mos.length; i++){
oss[i] = resolve(mos[i]);
if(oss[i].getNumObjects() == 0){
//no conflicts
return null;
}
}
return new ConflictDefinition(new ObjectSetList(oss));
}
private IObjectSet resolve(MatchObjectElement el){
IObjectSet oSet = fMatchObjectMap.get(el);
if(oSet == null){
int type = el.getObjectType();
PatternElement[] patterns = el.getPatterns();
HashSet<IRealBuildObjectAssociation> objectsSet = new HashSet<IRealBuildObjectAssociation>();
for(int i = 0; i < patterns.length; i++){
PatternElement pattern = patterns[i];
processPattern(type, pattern, objectsSet);
}
oSet = new ObjectSet(type, objectsSet);
fMatchObjectMap.put(el, oSet);
}
return oSet;
}
private IRealBuildObjectAssociation[] getObjectsForId(int objType, String id, int idType){
if(idType == PatternElement.TYPE_ID_EXACT_MATCH){
IRealBuildObjectAssociation obj = TcModificationUtil.getObjectById(objType, id);
if(obj != null)
return new IRealBuildObjectAssociation[]{obj};
return new IRealBuildObjectAssociation[0];
}
IRealBuildObjectAssociation[] allObjs = TcModificationUtil.getExtensionObjects(objType);
Pattern pattern = Pattern.compile(id);
List<IRealBuildObjectAssociation> list = new ArrayList<IRealBuildObjectAssociation>();
for(int i = 0; i < allObjs.length; i++){
if(pattern.matcher(allObjs[i].getId()).matches())
list.add(allObjs[i]);
}
return list.toArray(new IRealBuildObjectAssociation[list.size()]);
}
private Set<IRealBuildObjectAssociation> processPattern(int objType, PatternElement el, Set<IRealBuildObjectAssociation> set){
if(set == null)
set = new HashSet<IRealBuildObjectAssociation>();
String ids[] = el.getIds();
if(el.getSearchType() == PatternElement.TYPE_SEARCH_EXTENSION_OBJECT){
for(int i = 0; i < ids.length; i++){
IRealBuildObjectAssociation objs[] = getObjectsForId(objType, ids[i], el.getIdType());
for(int k = 0; k < objs.length; k++){
set.add(objs[k].getRealBuildObject());
}
}
} else if (el.getSearchType() == PatternElement.TYPE_SEARCH_ALL_EXTENSION_SUPERCLASSES){
IRealBuildObjectAssociation[] allReal = TcModificationUtil.getRealObjects(objType);
for(int i = 0; i < ids.length; i++){
IRealBuildObjectAssociation []objs = getObjectsForId(objType, ids[i], el.getIdType());
for(int k = 0; k < objs.length; k++){
IRealBuildObjectAssociation obj = objs[k];
set.add(obj.getRealBuildObject());
Set<IRealBuildObjectAssociation> childRealSet = getChildSuperClassRealSet(obj, allReal);
set.addAll(childRealSet);
// for(int k = 0; k < allReal.length; k++){
// IRealBuildObjectAssociation otherReal = allReal[k];
// if(otherReal == obj || set.contains(otherReal))
// continue;
//
// if("tcm.derive.tc1".equals(otherReal.getId())){
// int f = 0; f++;
// }
// IRealBuildObjectAssociation[] identics = otherReal.getIdenticBuildObjects();
// for(int j = 0; j < identics.length; j++){
// IRealBuildObjectAssociation identic = identics[j];
// for(identic = identic.getSuperClassObject(); identic != null; identic = identic.getSuperClassObject()){
// if(identic == obj){
// set.add(identic.getRealBuildObject());
// }
// }
// }
// }
}
}
}
return set;
}
private Set<IRealBuildObjectAssociation> getChildSuperClassRealSet(IRealBuildObjectAssociation obj, IRealBuildObjectAssociation[] all){
if(fObjToChildSuperClassMap == null)
fObjToChildSuperClassMap = new PerTypeMapStorage<IRealBuildObjectAssociation, Set<IRealBuildObjectAssociation>>();
if(all == null)
all = TcModificationUtil.getExtensionObjects(obj.getType());
Map<IRealBuildObjectAssociation, Set<IRealBuildObjectAssociation>> map = fObjToChildSuperClassMap.getMap(obj.getType(), true);
Set<IRealBuildObjectAssociation> set = map.get(obj);
if(set == null){
set = createChildSuperClassRealSet(obj, all, null);
map.put(obj, set);
}
return set;
}
private static Set<IRealBuildObjectAssociation> createChildSuperClassRealSet(IRealBuildObjectAssociation obj, IRealBuildObjectAssociation[] all, Set<IRealBuildObjectAssociation> set){
if(set == null)
set = new HashSet<IRealBuildObjectAssociation>();
if(all == null)
all = TcModificationUtil.getExtensionObjects(obj.getType());
for(int i = 0; i < all.length; i++){
IRealBuildObjectAssociation cur = all[i];
for(IRealBuildObjectAssociation el = cur.getSuperClassObject(); el != null; el = el.getSuperClassObject()){
if(el == obj){
IRealBuildObjectAssociation realQuickTest = null;
for(IRealBuildObjectAssociation found = cur; found != obj; found = found.getSuperClassObject()){
IRealBuildObjectAssociation real = found.getRealBuildObject();
if(real != realQuickTest){
set.add(real);
realQuickTest = real;
}
}
}
}
}
return set;
}
public ObjectSetListBasedDefinition[] getRules(int ruleType){
checkInitialization();
return fConflictDefinitions.clone();
}
private void checkInitialization(){
if(!fIsStartInited)
throw new IllegalStateException();
StarterJob starter = fStarter;
if(starter != null){
try {
starter.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}