1
/*******************************************************************************
2
* Copyright (c) 2007, 2008 Intel Corporation and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Intel Corporation - Initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.core.settings.model.util;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.LinkedHashMap;
17
import java.util.List;
21
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
22
import org.eclipse.cdt.core.settings.model.ICMacroEntry;
23
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
25
public class SettingsSet {
26
public static final int READ_ONLY = 1;
27
public static final int WRITABLE = 1 << 1;
29
private SettingLevel[] fLevels;
30
public class SettingLevel {
31
private int fFlagsToSet;
32
private int fFlagsToClear;
33
private boolean fIsReadOnly;
34
private boolean fIsOverrideSupported;
35
private LinkedHashMap<EntryNameKey, EntryInfo> fEntries;
36
HashSet<String> fOverrideSet;
37
private Object fContext;
39
private SettingLevel(){
40
fEntries = new LinkedHashMap<EntryNameKey, EntryInfo>();
43
public boolean isReadOnly(){
47
public void setReadOnly(boolean readOnly){
48
fIsReadOnly = readOnly;
51
public boolean isOverrideSupported(){
52
return fIsOverrideSupported;
55
public void setOverrideSupported(boolean supported){
56
fIsOverrideSupported = supported;
59
public void setFlagsToSet(int flags){
63
public boolean containsOverrideInfo(){
64
return fOverrideSet != null;
67
public void setFlagsToClear(int flags){
68
fFlagsToClear = flags;
71
public int getFlagsToSet(){
75
public int getFlagsToClear(){
79
public int getFlags(int baseFlags){
80
return (baseFlags | fFlagsToSet) & (~fFlagsToClear);
83
@SuppressWarnings("unchecked")
84
public Set<String> getOverrideSet(){
85
if(fOverrideSet != null)
86
return (HashSet<String>)fOverrideSet.clone();
87
return new HashSet<String>();
90
public void addEntries(ICLanguageSettingEntry entries[]){
92
for(int i = 0; i < entries.length; i++){
98
public void addEntries(List<ICLanguageSettingEntry> list){
99
for(ICLanguageSettingEntry se : list)
103
public void addEntry(ICLanguageSettingEntry entry){
104
addEntry(entry, null);
107
public void addEntry(ICLanguageSettingEntry entry, Object customInfo){
108
entry = CDataUtil.createEntry(entry, fFlagsToSet, fFlagsToClear);
109
EntryInfo info = new EntryInfo(entry, customInfo);
110
fEntries.put(info.getContentsKey(), info);
113
public void addOverrideName(String name){
114
if(fOverrideSet == null)
115
fOverrideSet = new HashSet<String>();
117
fOverrideSet.add(name);
120
public void addOverrideNameSet(Set<String> set){
123
if(fOverrideSet != null){
124
fOverrideSet.addAll(set);
125
} else if(set.size() != 0){
126
fOverrideSet = new HashSet<String>(set);
130
public void removeOverrideName(String name){
131
if(fOverrideSet == null)
134
fOverrideSet.remove(name);
136
if(fOverrideSet.size() == 0)
145
public Map<EntryNameKey, EntryInfo> clearAndGetMap(){
146
Map<EntryNameKey, EntryInfo> map = fEntries;
147
fEntries = new LinkedHashMap<EntryNameKey, EntryInfo>();
152
public EntryInfo[] getInfos(){
153
return fEntries.values().toArray(new EntryInfo[fEntries.size()]);
156
public ICLanguageSettingEntry[] getEntries(){
157
List<ICLanguageSettingEntry> list = getEntriesList(false);
158
return list.toArray(new ICLanguageSettingEntry[list.size()]);
161
public ICLanguageSettingEntry[] getEntries(boolean includeOverridden){
162
List<ICLanguageSettingEntry> list = getEntriesList(includeOverridden);
163
return list.toArray(new ICLanguageSettingEntry[list.size()]);
166
public List<ICLanguageSettingEntry> getEntriesList(boolean includeOverridden){
167
List<ICLanguageSettingEntry> list = new ArrayList<ICLanguageSettingEntry>();
168
EntryInfo infos[] = getInfos();
169
for(EntryInfo info : infos){
170
if(includeOverridden || !info.isOverridden())
171
list.add(info.getEntry());
177
public Object getContext(){
181
public void setContext(Object context){
186
public static class EntryInfo {
187
private ICLanguageSettingEntry fEntry;
188
private EntryNameKey fNameKey;
189
private boolean fIsOverRidden;
190
private Object fCustomInfo;
192
private EntryInfo(ICLanguageSettingEntry entry, Object customInfo){
194
fCustomInfo = customInfo;
197
public EntryNameKey getContentsKey(){
198
if(fNameKey == null){
199
fNameKey = new EntryNameKey(fEntry);
204
private void makeOverridden(boolean overrridden){
205
fIsOverRidden = overrridden;
208
public ICLanguageSettingEntry getEntry(){
212
public boolean isOverridden(){
213
return fIsOverRidden;
216
public Object getCustomInfo(){
221
public SettingsSet(int num){
222
fLevels = new SettingLevel[num];
223
for(int i = 0; i < num; i++){
224
fLevels[i] = new SettingLevel();
228
public SettingLevel[] getLevels(){
229
return (SettingLevel[])fLevels.clone();
232
public void adjustOverrideState(){
233
Set<String> set = new HashSet<String>();
235
for(int i = 0; i < fLevels.length; i++){
237
if(level.isOverrideSupported() && level.fOverrideSet != null)
238
set.addAll(level.fOverrideSet);
239
adjustOverrideState(fLevels[i], set);
243
private void adjustOverrideState(SettingLevel level, Set<String> overridenSet){
244
for(EntryInfo info : level.getInfos()){
245
if(overridenSet.add(info.getEntry().getName())){
246
info.makeOverridden(false);
248
info.makeOverridden(true);
253
public ICLanguageSettingEntry[] getEntries(){
254
return getEntries(READ_ONLY | WRITABLE);
257
public ICLanguageSettingEntry[] getEntries(int types){
258
adjustOverrideState();
259
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
260
for(SettingLevel sl : fLevels){
261
if(isCompatible(sl, types))
262
getEntries(sl, entries);
264
return entries.toArray(new ICLanguageSettingEntry[entries.size()]);
267
private void getEntries(SettingLevel level, List<ICLanguageSettingEntry> list){
268
for(EntryInfo info : level.getInfos())
269
if(!info.isOverridden())
270
list.add(info.getEntry());
273
private boolean isCompatible(SettingLevel level, int types){
274
if((types & READ_ONLY) == 0 && level.isReadOnly())
276
if((types & WRITABLE) == 0 && !level.isReadOnly())
282
private int getWritableLevelNum(){
283
for(int i = 0; i <fLevels.length; i++){
284
if(!fLevels[i].isReadOnly())
291
private int getOverrideLevelNum(){
292
for(int i = 0; i <fLevels.length; i++){
293
if(fLevels[i].isOverrideSupported())
300
@SuppressWarnings("unchecked")
301
public void applyEntries(ICLanguageSettingEntry[] entries){
302
HashMap<EntryNameKey, Object[]> map = getEntryLevelMap(WRITABLE | READ_ONLY);
303
Map<EntryNameKey, Object[]> mapCopy = (HashMap<EntryNameKey, Object[]>)map.clone();
304
Map<EntryNameKey, EntryInfo>[] clearedInfos = new Map [fLevels.length];
306
for(int i = 0; i < fLevels.length; i++){
307
if(!fLevels[i].isReadOnly())
308
clearedInfos[i] = fLevels[i].clearAndGetMap();
311
Integer levelInteger;
313
ICLanguageSettingEntry entry;
314
int writableLevel = getWritableLevelNum();
317
for(int i = 0; i < entries.length; i++){
319
EntryNameKey key = new EntryNameKey(entry);
320
Object[] o = (Object[])map.get(key);
323
if(o != null && valueMatches(entry, o[1])){
325
levelInteger = (Integer)o[0];
326
if (! entry.isBuiltIn()) // allow overwrite existing entry,
327
levelInteger = null; // even with the same value
332
levelNum = levelInteger != null ? levelInteger.intValue() : writableLevel;
334
level = fLevels[levelNum];
335
if(!level.isReadOnly()){
336
Map<EntryNameKey, EntryInfo> clearedInfo = clearedInfos[levelNum];
337
Object customInfo = null;
338
if(clearedInfo != null){
339
EntryInfo info = (EntryInfo)clearedInfo.get(key);
340
if(info != null && entry.equalsByContents(info.getEntry()))
341
customInfo = info.getCustomInfo();
343
level.addEntry(entry, customInfo);
348
int overrideLevel = getOverrideLevelNum();
349
if(overrideLevel >= 0){
350
level = fLevels[overrideLevel];
351
if(level.isOverrideSupported() && !mapCopy.isEmpty()){
352
for(EntryNameKey enk : mapCopy.keySet()){
353
ICSettingEntry e = enk.getEntry();
354
if ((e.getFlags() & ICSettingEntry.BUILTIN) == 0)
356
String str = e.getName();
358
level.addOverrideName(str);
362
adjustOverrideState();
365
public HashMap<EntryNameKey, Object[]> getEntryLevelMap(int types){
366
HashMap<EntryNameKey, Object[]> map = new HashMap<EntryNameKey, Object[]>();
367
for(int i = 0; i < fLevels.length; i++){
368
if(isCompatible(fLevels[i], types))
369
addLevelInfoToMap(fLevels[i], i, map);
374
private void addLevelInfoToMap(SettingLevel level, int l, Map<EntryNameKey, Object[]> map){
375
for(EntryInfo info : level.getInfos()){
376
EntryNameKey key = info.getContentsKey();
377
if(!map.containsKey(key))
378
map.put(key, new Object[]{new Integer(l), info.getEntry()});
382
private static boolean valueMatches(ICLanguageSettingEntry e, Object o) {
383
if (!(e instanceof ICMacroEntry))
384
return true; // ignore values for other entries
385
if (!(o instanceof ICMacroEntry))
386
return false; // cannot compare different entries
387
String s1 = e.getValue();
388
String s2 = ((ICMacroEntry)o).getValue();
389
if (s1 == null && s2 == null)
392
return s1.equals(s2);
394
return s2.equals(s1);