diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PathSettingsContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PathSettingsContainer.java index 8fccc36d27e..5b034ee6a9f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PathSettingsContainer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PathSettingsContainer.java @@ -12,19 +12,19 @@ package org.eclipse.cdt.core.settings.model.util; 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 org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; public class PathSettingsContainer { private static final Object INEXISTENT_VALUE = new Object(); - private static final int INIT_CHILDREN_MAP_CAPACITY = 2; +// private static final int INIT_CHILDREN_MAP_CAPACITY = 2; - private Map fChildrenMap; +// private Map fChildrenMap; +// private Map fPatternMap; + private PatternNameMap fPatternChildrenMap; private Object fValue; private IPath fPath; private String fName; @@ -32,24 +32,31 @@ public class PathSettingsContainer { private PathSettingsContainer fDirectParentContainer; private List fListeners; + private boolean fIsPatternMode; + private static final int ADDED = 1; private static final int REMOVED = 2; private static final int VALUE_CHANGED = 3; private static final int PATH_CHANGED = 4; - + public static PathSettingsContainer createRootContainer(){ - return new PathSettingsContainer(); + return createRootContainer(false); + } + + public static PathSettingsContainer createRootContainer(boolean patternMode){ + return new PathSettingsContainer(patternMode); + } + + private PathSettingsContainer(boolean pattternMode){ + this(null, null, "", pattternMode); //$NON-NLS-1$ } - private PathSettingsContainer(){ - this(null, null, new String()); - } - - private PathSettingsContainer(PathSettingsContainer root, PathSettingsContainer parent, String name){ + private PathSettingsContainer(PathSettingsContainer root, PathSettingsContainer parent, String name, boolean patternMode){ fRootContainer = root; fDirectParentContainer = parent; fName = name; + fIsPatternMode = patternMode; if(fRootContainer == null){ fRootContainer = this; // fPath = new Path(name); @@ -58,18 +65,18 @@ public class PathSettingsContainer { } } - private Map getChildrenMap(boolean create){ - if(fChildrenMap == null && create) - fChildrenMap = new HashMap(INIT_CHILDREN_MAP_CAPACITY); - return fChildrenMap; + private PatternNameMap getPatternChildrenMap(boolean create){ + if(fPatternChildrenMap == null && create) + fPatternChildrenMap = new PatternNameMap(); + return fPatternChildrenMap; } - private PathSettingsContainer getChild(String name, boolean create){ - Map map = getChildrenMap(create); - if(map != null){ - PathSettingsContainer child = (PathSettingsContainer)map.get(name); + private PathSettingsContainer getExacChild(String name, boolean create){ + PatternNameMap pMap = getPatternChildrenMap(create); + if(pMap != null){ + PathSettingsContainer child = (PathSettingsContainer)pMap.get(name); if(child == null && create){ - child = new PathSettingsContainer(fRootContainer, this, name); + child = new PathSettingsContainer(fRootContainer, this, name, fIsPatternMode); connectChild(child); } return child; @@ -77,6 +84,15 @@ public class PathSettingsContainer { return null; } + private List getChildren(String name){ + PatternNameMap pMap = getPatternChildrenMap(false); + if(pMap != null){ + return pMap.getValues(name); + } + return null; + } + + private void notifyChange(PathSettingsContainer container, int type, Object oldValue, boolean childrenAffected){ List list = getListenersList(false); if(list != null && list.size() > 0){ @@ -110,8 +126,8 @@ public class PathSettingsContainer { } public boolean hasChildren(){ - Map map = getChildrenMap(false); - return map != null && map.size() != 0; + PatternNameMap pMap = getPatternChildrenMap(false); + return pMap != null && pMap.size() != 0; } public PathSettingsContainer getChildContainer(IPath path, boolean create, boolean exactPath){ @@ -168,11 +184,11 @@ public class PathSettingsContainer { } private List doGetDirectChildren(List list){ - Map map = getChildrenMap(false); - if(map != null){ + PatternNameMap pMap = getPatternChildrenMap(false); + if(pMap != null){ if(list == null) list = new ArrayList(); - for(Iterator iter = map.values().iterator(); iter.hasNext(); ){ + for(Iterator iter = pMap.values().iterator(); iter.hasNext(); ){ PathSettingsContainer cr = (PathSettingsContainer)iter.next(); if(cr.fValue == INEXISTENT_VALUE){ cr.doGetDirectChildren(list); @@ -242,11 +258,11 @@ public class PathSettingsContainer { } private void disconnectChild(PathSettingsContainer child){ - getChildrenMap(true).remove(child.getName()); + getPatternChildrenMap(true).remove(child.getName()); } private void connectChild(PathSettingsContainer child){ - getChildrenMap(true).put(child.getName(), child); + getPatternChildrenMap(true).put(child.getName(), child); } public boolean isValid(){ @@ -254,12 +270,12 @@ public class PathSettingsContainer { } public void removeChildren(){ - Map map = getChildrenMap(false); - if(map == null || map.size() == 0) + PatternNameMap pMap = getPatternChildrenMap(false); + if(pMap == null || pMap.size() == 0) return; - Collection c = map.values(); + Collection c = pMap.values(); PathSettingsContainer childContainers[] = (PathSettingsContainer[])c.toArray(new PathSettingsContainer[c.size()]); for(int i = 0; i < childContainers.length; i++){ @@ -269,7 +285,7 @@ public class PathSettingsContainer { } private void deleteChild(PathSettingsContainer child){ - getChildrenMap(false).remove(child.getName()); + getPatternChildrenMap(false).remove(child.getName()); } private String getName(){ @@ -280,12 +296,31 @@ public class PathSettingsContainer { PathSettingsContainer container = null; if(path.segmentCount() == 0) container = this; - else { - PathSettingsContainer child = getChild(path.segment(0), create); + else if (create || exactPath || !fIsPatternMode) { + PathSettingsContainer child = getExacChild(path.segment(0), create); if(child != null) container = child.findContainer(path.removeFirstSegments(1), create, exactPath); else if(!exactPath) container = this; + } else { + //looking for container using patterns in read mode (i.e. not creating new container) + List list = getChildren(path.segment(0)); + if(list != null){ + int size = list.size(); + PathSettingsContainer child, childFound; + + for(int i = 0; i < size; i++){ + child = (PathSettingsContainer)list.get(i); + childFound = child.findContainer(path.removeFirstSegments(1), false, false); + if(container == null) + container = childFound; + else if(container.getPath().segmentCount() < childFound.getPath().segmentCount()){ + container = childFound; + } + } + } + if(container == null) + container = this; } return container; } @@ -298,9 +333,9 @@ public class PathSettingsContainer { if(fValue != INEXISTENT_VALUE && !visitor.visit(this)) return false; - Map map = getChildrenMap(false); - if(map != null){ - for(Iterator iter = map.values().iterator(); iter.hasNext();){ + PatternNameMap pMap = getPatternChildrenMap(false); + if(pMap != null){ + for(Iterator iter = pMap.values().iterator(); iter.hasNext();){ PathSettingsContainer child = (PathSettingsContainer)iter.next(); if(!child.doAccept(visitor)) return false; @@ -330,8 +365,8 @@ public class PathSettingsContainer { if(!moveChildren){ if(hasChildren()){ - PathSettingsContainer cr = new PathSettingsContainer(fRootContainer, fDirectParentContainer, fName); - for(Iterator iter = fChildrenMap.values().iterator(); iter.hasNext();){ + PathSettingsContainer cr = new PathSettingsContainer(fRootContainer, fDirectParentContainer, fName, fIsPatternMode); + for(Iterator iter = fPatternChildrenMap.values().iterator(); iter.hasNext();){ PathSettingsContainer child = (PathSettingsContainer)iter.next(); iter.remove(); child.setParent(cr); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PatternNameMap.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PatternNameMap.java new file mode 100644 index 00000000000..098d44a4e6f --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/PatternNameMap.java @@ -0,0 +1,241 @@ +/******************************************************************************* + * 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.core.settings.model.util; + +import java.util.AbstractCollection; +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.NoSuchElementException; + +import org.eclipse.cdt.core.model.CoreModelUtil; + +public class PatternNameMap { + private static final char[] SPEC_CHARS = new char[]{'*', '?'}; + + private Map fChildrenMap; + private Map fPatternMap; + private Collection fValues; + + private static class StringCharArray { + private String fString; + private char[] fCharArray; + + StringCharArray(String string){ + fString = string; + } + + char[] getCharArray(){ + if(fCharArray == null){ + fCharArray = fString.toCharArray(); + } + return fCharArray; + } + + public boolean equals(Object obj) { + if(obj == this) + return true; + + if(!(obj instanceof StringCharArray)) + return false; + + return fString.equals(((StringCharArray)obj).fString); + } + + public int hashCode() { + return fString.hashCode(); + } + + public String toString() { + return fString; + } + } + + private class EmptyIterator implements Iterator{ + + public boolean hasNext() { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public void remove() { + throw new IllegalStateException(); + } + + } + + private class ValuesCollection extends AbstractCollection { + + private class Iter implements Iterator { + private Iterator fEntrySetIter; + private Map.Entry fCur; + + Iter (Iterator entryIter){ + this.fEntrySetIter = entryIter; + } + public boolean hasNext() { + return fEntrySetIter.hasNext(); + } + + public Object next() { + fCur = (Map.Entry)fEntrySetIter.next(); + return fCur.getValue(); + } + + public void remove() { + fEntrySetIter.remove(); + removePattern((String)fCur.getKey()); + } + + } + + public Iterator iterator() { + return fChildrenMap != null ? (Iterator)new Iter(fChildrenMap.entrySet().iterator()) : (Iterator)new EmptyIterator(); + } + + public int size() { + return PatternNameMap.this.size(); + } + + public void clear(){ + PatternNameMap.this.clear(); + } + + public boolean contains(Object o){ + return fChildrenMap != null ? fChildrenMap.containsValue(o) : false; + } + } + + public Object get(String name){ + return fChildrenMap != null ? fChildrenMap.get(name) : null; + } + + public int size(){ + return fChildrenMap != null ? fChildrenMap.size() : 0; + } + + public boolean hasPatterns(){ + return fPatternMap != null && fPatternMap.size() != 0; + } + + public List getValues(String name){ + if(fChildrenMap == null) + return null; + + Object val = fChildrenMap.get(name); + if(hasPatterns()){ + List list; + if(val != null){ + list = new ArrayList(3); + list.add(val); + } else { + list = null;; + } + + Map.Entry entry; + StringCharArray strCA; + char[] nameCharArray = name.toCharArray(); + for(Iterator iter = fPatternMap.entrySet().iterator(); iter.hasNext();){ + entry = (Map.Entry)iter.next(); + strCA = (StringCharArray)entry.getKey(); + if(CoreModelUtil.match(strCA.getCharArray(), nameCharArray, true)){ + if(list == null) + list = new ArrayList(2); + list.add(entry.getValue()); + } + } + return list; + } else if (val != null){ + List list = new ArrayList(1); + list.add(val); + return list; + } + return null; + } + + public Object put(String name, Object value){ + if(value == null) + return remove(name); + + Object oldValue; + if(fChildrenMap == null){ + fChildrenMap = new HashMap(); + oldValue = null; + } else { + oldValue = fChildrenMap.get(name); + } + + fChildrenMap.put(name, value); + + if(isPatternName(name)){ + StringCharArray strCA = new StringCharArray(name); + if(fPatternMap == null) + fPatternMap = new HashMap(); + + fPatternMap.put(strCA, value); + } + + return oldValue; + } + + public Object remove(String name){ + if(fChildrenMap != null){ + Object oldVal = fChildrenMap.remove(name); + if(fChildrenMap.size() == 0){ + fChildrenMap = null; + fPatternMap = null; + } else { + removePattern(name); + } + return oldVal; + } + return null; + } + + private void removePattern(String name){ + if (fPatternMap != null){ + fPatternMap.remove(new StringCharArray(name)); + if(fPatternMap.size() == 0) + fPatternMap = null; + } + } + + private static boolean hasSpecChars(String str){ + for(int i = 0; i < SPEC_CHARS.length; i++){ + if(str.indexOf(SPEC_CHARS[i]) != -1) + return true; + } + return false; + } + + public static boolean isPatternName(String str){ + //TODO: check escape chars + return hasSpecChars(str); + } + + public void clear(){ + fChildrenMap = null; + fPatternMap = null; + } + + public Collection values(){ + if(fValues == null) + fValues = new ValuesCollection(); + return fValues; + } +} + diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationDescriptionCache.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationDescriptionCache.java index a726a196ab7..f1e65e0d508 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationDescriptionCache.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationDescriptionCache.java @@ -90,7 +90,7 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData ((CBuildSettingCache)fBuildData).initEnvironmentCache(); ICdtVariable vars[] = CdtVariableManager.getDefault().getVariables(this); fMacros = new StorableCdtVariables(vars, true); - fInitializing = false; +// fInitializing = false; } CConfigurationDescriptionCache(ICConfigurationDescription baseDescription, CConfigurationData base, CConfigurationSpecSettings settingsBase, CProjectDescription parent, ICStorageElement rootEl) throws CoreException { @@ -138,7 +138,7 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData fSpecSettings.serialize(); fBaseDescription = null; - fInitializing = false; +// fInitializing = false; } public StorableCdtVariables getCachedVariables(){ @@ -420,4 +420,8 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData public boolean isPreferenceConfiguration() { return getProjectDescription() == null; } + + void doneInitialization(){ + fInitializing = false; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java index 33e5e5bc920..3f7cabec8f8 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java @@ -82,6 +82,7 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon } } + doneInitializing(); fIsLoadding = false; } @@ -99,8 +100,17 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon } } + doneInitializing(); + fIsApplying = false; } + + private void doneInitializing(){ + for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){ + CConfigurationDescriptionCache cache = (CConfigurationDescriptionCache)iter.next(); + cache.doneInitialization(); + } + } public boolean isLoadding(){ return fIsLoadding; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java index 3c21ecf5eea..224092ec677 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java @@ -2657,6 +2657,7 @@ public class CProjectDescriptionManager { rootEl = rootParent.importChild(baseRootEl); CConfigurationDescriptionCache cache = new CConfigurationDescriptionCache(des, baseData, cfgDes.getSpecSettings(), null, rootEl); cache.applyData(); + cache.doneInitialization(); return cache; } @@ -2734,6 +2735,7 @@ public class CProjectDescriptionManager { } CConfigurationDescriptionCache cache = new CConfigurationDescriptionCache(cfgEl, null); cache.loadData(); + cache.doneInitialization(); return cache; }