/******************************************************************************* * Copyright (c) 2007, 2010 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.internal.core.settings.model; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.settings.model.CExternalSetting; import org.eclipse.cdt.core.settings.model.ICBuildSetting; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICFileDescription; import org.eclipse.cdt.core.settings.model.ICFolderDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSetting; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; import org.eclipse.cdt.core.settings.model.ICOutputEntry; import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.core.settings.model.ICSettingBase; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.ICSourceEntry; import org.eclipse.cdt.core.settings.model.WriteAccessException; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.EntryContentsKey; import org.eclipse.cdt.core.settings.model.util.KindBasedStore; import org.eclipse.cdt.internal.core.settings.model.CExternalSettinsDeltaCalculator.ExtSettingsDelta; import org.eclipse.core.runtime.CoreException; /** * Responsible for applying external settings delta to a given ICConfigurationDescrptions */ public class CExternalSettingsDeltaProcessor { /** * Main entrance point for applying a full array of external settings delta * @param des ICConfigurationDescription * @param deltas ExtSettingsDelta array * @return boolean indicating whether there was change */ static boolean applyDelta(ICConfigurationDescription des, ExtSettingsDelta deltas[]){ return applyDelta(des, deltas, KindBasedStore.ORED_ALL_ENTRY_KINDS); } /** * Applies the deltas to all resource description (overriden resource configs) * in the configuration description * @param des The configuration description to be updated * @param deltas deltas to be applied * @param kindMask * @return */ static boolean applyDelta(ICConfigurationDescription des, ExtSettingsDelta deltas[], int kindMask){ ICResourceDescription rcDess[] = des.getResourceDescriptions(); boolean changed = false; for (ICResourceDescription rcDes : rcDess) { if(applyDelta(rcDes, deltas, kindMask)) changed = true; } if((kindMask & ICSettingEntry.SOURCE_PATH) != 0){ if(applySourceEntriesChange(des, deltas)) changed = true; } if((kindMask & ICSettingEntry.OUTPUT_PATH) != 0){ if(applyOutputEntriesChange(des, deltas)) changed = true; } return changed; } static boolean applySourceEntriesChange(ICConfigurationDescription cfgDes, ExtSettingsDelta[] deltas){ ICSettingEntry[][] diff = CExternalSettinsDeltaCalculator.getAllEntries(deltas, ICSettingEntry.SOURCE_PATH); if(diff == null) return false; ICSourceEntry[] current = cfgDes.getSourceEntries(); if(current.length == 1){ ICSourceEntry cur = current[0]; if(cur.getFullPath().segmentCount() == 1 && cur.getExclusionPatterns().length == 0){ current = new ICSourceEntry[0]; } } List<ICSourceEntry> newEntries = calculateUpdatedEntries(current, diff[0], diff[1]); if(newEntries != null){ try { cfgDes.setSourceEntries(newEntries.toArray(new ICSourceEntry[newEntries.size()])); } catch (WriteAccessException e) { CCorePlugin.log(e); } catch (CoreException e) { CCorePlugin.log(e); } return true; } return false; } static boolean applyOutputEntriesChange(ICConfigurationDescription cfgDes, ExtSettingsDelta[] deltas){ ICSettingEntry[][] diff = CExternalSettinsDeltaCalculator.getAllEntries(deltas, ICSettingEntry.OUTPUT_PATH); if(diff == null) return false; ICBuildSetting bs = cfgDes.getBuildSetting(); if(bs == null) return false; ICOutputEntry[] current = bs.getOutputDirectories(); if(current.length == 1){ ICOutputEntry cur = current[0]; if(cur.getFullPath().segmentCount() == 1 && cur.getExclusionPatterns().length == 0){ current = new ICOutputEntry[0]; } } List<ICOutputEntry> newEntries = calculateUpdatedEntries(current, diff[0], diff[1]); if(newEntries != null){ try { bs.setOutputDirectories(newEntries.toArray(new ICOutputEntry[newEntries.size()])); } catch (WriteAccessException e) { CCorePlugin.log(e); } return true; } return false; } static boolean applyDelta(ICResourceDescription rcDes, ExtSettingsDelta deltas[], int kindMask){ if(rcDes.getType() == ICSettingBase.SETTING_FOLDER){ return applyDelta((ICFolderDescription)rcDes, deltas, kindMask); } return applyDelta((ICFileDescription)rcDes, deltas, kindMask); } static boolean applyDelta(ICFileDescription des, ExtSettingsDelta deltas[], int kindMask){ ICLanguageSetting setting = des.getLanguageSetting(); if(setting == null) return false; boolean changed = false; for (ExtSettingsDelta delta : deltas) { if(isSettingCompatible(setting, delta.fSetting)){ if(applyDelta(setting, delta, kindMask)) changed = true; } } return changed; } static boolean applyDelta(ICFolderDescription des, ExtSettingsDelta deltas[], int kindMask){ ICLanguageSetting settings[] = des.getLanguageSettings(); if(settings == null || settings.length == 0) return false; boolean changed = false; for (ICLanguageSetting setting : settings) { if(applyDelta(setting, deltas, kindMask)) changed = true; } return changed; } static boolean applyDelta(ICLanguageSetting setting, ExtSettingsDelta[] deltas, int kindMask){ boolean changed = false; for (ExtSettingsDelta delta : deltas) { if(isSettingCompatible(setting, delta.fSetting)){ if(applyDelta(setting, delta, kindMask)) changed = true; } } return changed; } static boolean applyDelta(ICLanguageSetting setting, ExtSettingsDelta delta, int kindMask){ int kinds[] = KindBasedStore.getLanguageEntryKinds(); ICLanguageSettingEntry entries[]; ICSettingEntry diff[][]; boolean changed = false; for (int kind : kinds) { if((kind & kindMask) == 0) continue; diff = delta.getEntriesDelta(kind); if(diff == null) continue; entries = setting.getSettingEntries(kind); List<ICLanguageSettingEntry> list = calculateUpdatedEntries(entries, diff[0], diff[1]); if(list != null){ setting.setSettingEntries(kind, list); changed = true; } } return changed; } private static <T extends ICSettingEntry> List<T> calculateUpdatedEntries(T current[], ICSettingEntry added[], ICSettingEntry removed[]){ LinkedHashMap<EntryContentsKey, ICSettingEntry> map = new LinkedHashMap<EntryContentsKey, ICSettingEntry>(); boolean changed = false; if(added != null){ CDataUtil.fillEntriesMapByContentsKey(map, added); } if(current != null){ CDataUtil.fillEntriesMapByContentsKey(map, current); if(current.length != map.size()){ changed = true; } } else { if(map.size() != 0){ changed = true; } } if(removed != null){ for (ICSettingEntry entry : removed) { EntryContentsKey cKey = new EntryContentsKey(entry); ICSettingEntry cur = map.get(cKey); if(cur != null && !cur.isBuiltIn()){ map.remove(cKey); changed = true; } } } @SuppressWarnings("unchecked") Collection<T> values = (Collection<T>) map.values(); return changed ? new ArrayList<T>(values) : null; } private static boolean isSettingCompatible(ICLanguageSetting setting, CExternalSetting provider){ String ids[] = provider.getCompatibleLanguageIds(); if(ids != null && ids.length > 0){ String id = setting.getLanguageId(); if(id != null){ if(contains(ids, id)) return true; return false; } return false; } ids = provider.getCompatibleContentTypeIds(); if(ids != null && ids.length > 0){ String[] cTypeIds = setting.getSourceContentTypeIds(); if(cTypeIds.length != 0){ for (String id : cTypeIds) { if(contains(ids, id)) return true; } return false; } return false; } ids = provider.getCompatibleExtensions(); if(ids != null && ids.length > 0){ String [] srcIds = setting.getSourceExtensions(); if(srcIds.length != 0){ for (String id : srcIds) { if(contains(ids, id)) return true; } return false; } return false; } return true; } private static boolean contains(Object array[], Object value){ for (Object element : array) { if(element.equals(value)) return true; } return false; } }