/*******************************************************************************
* Copyright (c) 2007, 2009 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.dataprovider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.extension.CLanguageData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.IKindBasedInfo;
import org.eclipse.cdt.core.settings.model.util.KindBasedStore;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.FolderInfo;
import org.eclipse.cdt.managedbuilder.internal.core.InputType;
import org.eclipse.cdt.managedbuilder.internal.core.ResourceConfiguration;
/**
* This class holds the language data for managed build tool
*
* It current holds both the main kind => BuildEntryStorage
* mapping as well as mappings on the currently undef'd kinds
* (e.g. a language setting entry defined by scanner discovery
* but later re-defined by a build system setting )
*/
public class BuildLanguageData extends CLanguageData {
private static final IOption[] EMPTY_OPTION_ARRAY = new IOption[0];
private final String fId;
private ITool fTool;
private IInputType fInputType;
/** The main kind => BuildEntryStorage store
* The BuildEntryStorage calls back to this BuildLanguageData
* to work out which entries are actually (un)defined. */
private KindBasedStore<BuildEntryStorage> fKindToEntryStore = new KindBasedStore<BuildEntryStorage>();
/** Indicates that the option array stores have been inited */
private volatile boolean fOptionStoreInited;
private KindBasedStore<IOption[]> fKindToOptionArrayStore = new KindBasedStore<IOption[]>();
private KindBasedStore<IOption[]> fKindToUndefOptionArrayStore = new KindBasedStore<IOption[]>();
// private Map fKindToEntryArrayMap = new HashMap();
// private ProfileInfoProvider fDiscoveredInfo;
public BuildLanguageData(ITool tool, IInputType inType){
fTool = tool;
if(inType != null){
// inType = tool.getEdtableInputType(inType);
fInputType = inType;
if(inType.getParent() != tool)
throw new IllegalArgumentException();
// IInputType extType = inType;
// for(;extType != null && !extType.isExtensionElement(); extType = extType.getSuperClass());
// String typeId;
// if(extType != null)
// typeId = extType.getId();
// else
// typeId = inType.getId();
fId = inType.getId();//new StringBuffer(fTool.getId()).append(".").append(typeId).toString();
} else {
fInputType = null;
fId = new StringBuffer(fTool.getId()).append(".").append("languagedata").toString(); //$NON-NLS-1$ //$NON-NLS-2$
}
// fDiscoveredInfo = new ProfileInfoProvider(this);
}
private void obtainEditableInputType(){
if(fInputType != null){
// IInputType old = fInputType;
fInputType = fTool.getEditableInputType(fInputType);
// if(old != fInputType){
// fDiscoveredInfo.checkUpdateInputType(fInputType);
// }
}
}
@Override
public void setEntries(int kind, ICLanguageSettingEntry entries[]) {
BuildEntryStorage storage = getEntryStorage(kind);
if(storage != null)
storage.setEntries(entries);
}
private BuildEntryStorage getEntryStorage(int kind){
if(getOptionsForKind(kind).length == 0 && isToolChainDiscoveryProfile())
return null;
BuildEntryStorage storage = fKindToEntryStore.get(kind);
if(storage == null){
storage = new BuildEntryStorage(kind, this);
fKindToEntryStore.put(kind, storage);
}
return storage;
}
private void notifyOptionsChangeForKind(int kind){
fOptionStoreInited = false;
BuildEntryStorage storage = getEntryStorage(kind);
if(storage != null)
storage.optionsChanged();
}
public void optionsChanged(int type){
int kind = ManagedBuildManager.optionTypeToEntryKind(type);
if(kind == 0)
kind = ManagedBuildManager.optionUndefTypeToEntryKind(type);
if(kind != 0)
notifyOptionsChangeForKind(kind);
}
// private ProfileInfoProvider getDiscoveredInfoProvider(){
// return fDiscoveredInfo;
// }
/*
private String getOptionValueFromEntry(ICLanguageSettingEntry entry){
String optValue = entry.getName();
if(entry.getKind() == ICLanguageSettingEntry.MACRO){
String macroValue = entry.getValue();
StringBuffer buf = new StringBuffer(optValue).append('=').append(macroValue);
optValue = buf.toString();
}
return optValue;
}
*/
@Override
public String getLanguageId() {
return fInputType != null ? fInputType.getLanguageId(fTool) : null;
}
@Override
public ICLanguageSettingEntry[] getEntries(int kinds) {
List<ICLanguageSettingEntry> list = new ArrayList<ICLanguageSettingEntry>();
if((kinds & ICLanguageSettingEntry.INCLUDE_PATH) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.INCLUDE_PATH);
if(storage != null)
storage.getEntries(list);
} else if((kinds & ICLanguageSettingEntry.INCLUDE_FILE) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.INCLUDE_FILE);
if(storage != null)
storage.getEntries(list);
} else if((kinds & ICLanguageSettingEntry.MACRO) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.MACRO);
if(storage != null)
storage.getEntries(list);
} else if((kinds & ICLanguageSettingEntry.MACRO_FILE) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.MACRO_FILE);
if(storage != null)
storage.getEntries(list);
} else if((kinds & ICLanguageSettingEntry.LIBRARY_PATH) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.LIBRARY_PATH);
if(storage != null)
storage.getEntries(list);
} else if((kinds & ICLanguageSettingEntry.LIBRARY_FILE) != 0) {
BuildEntryStorage storage = getEntryStorage(ICLanguageSettingEntry.LIBRARY_FILE);
if(storage != null)
storage.getEntries(list);
}
return list.toArray(new ICLanguageSettingEntry[list.size()]);
}
public void updateInputType(IInputType type){
fInputType = type;
}
@Override
public String[] getSourceContentTypeIds() {
if(fInputType != null){
return fInputType.getSourceContentTypeIds();
}
return null;
}
@Override
public String[] getSourceExtensions() {
return fInputType != null ? fInputType.getSourceExtensions(fTool) : fTool.getPrimaryInputExtensions();
}
@Override
public int getSupportedEntryKinds() {
KindBasedStore<IOption[]> store = getKindToOptionArrayStore();
IKindBasedInfo<IOption[]>[] infos = store.getContents();
int kinds = 0;
for(int i = 0; i < infos.length; i++){
if(infos[i].getInfo().length > 0)
kinds |= infos[i].getKind();
}
return kinds;
}
private KindBasedStore<IOption[]> getKindToOptionArrayStore(){
initOptionStores();
return fKindToOptionArrayStore;
}
private void initOptionStores() {
if(!fOptionStoreInited) {
synchronized (this) {
if(!fOptionStoreInited) {
calculateKindToOptionArrayStore();
calculateKindToUndefOptionArrayStore();
fOptionStoreInited = true;
}
}
}
}
private KindBasedStore<IOption[]> getKindToUndefOptionArrayStore(){
initOptionStores();
return fKindToUndefOptionArrayStore;
}
private void calculateKindToOptionArrayStore(){
fKindToOptionArrayStore.clear();
Map<Integer, List<IOption>> kindToOptionList = new HashMap<Integer, List<IOption>>();
IOption options[] = fTool.getOptions();
for (final IOption option : options) {
try {
Integer entryKind = ManagedBuildManager.optionTypeToEntryKind(option.getValueType());
if(entryKind != 0){
if (!kindToOptionList.containsKey(entryKind))
kindToOptionList.put(entryKind, new ArrayList<IOption>(3){{add(option);}});
else
kindToOptionList.get(entryKind).add(option);
}
} catch (BuildException e) {
}
}
IKindBasedInfo<IOption[]>[] infos = fKindToOptionArrayStore.getContents();
for (IKindBasedInfo<IOption[]> info : infos) {
List<IOption> list = kindToOptionList.get(info.getKind());
if(list != null){
IOption[] opts = list.toArray(new IOption[list.size()]);
info.setInfo(opts);
} else {
info.setInfo(EMPTY_OPTION_ARRAY);
}
}
}
private void calculateKindToUndefOptionArrayStore(){
fKindToUndefOptionArrayStore.clear();
Map<Integer, List<IOption>> kindToOptionList = new HashMap<Integer, List<IOption>>();
IOption options[] = fTool.getOptions();
for (final IOption option : options) {
try {
Integer entryKind = ManagedBuildManager.optionUndefTypeToEntryKind(option.getValueType());
if(entryKind != 0){
if (!kindToOptionList.containsKey(entryKind))
kindToOptionList.put(entryKind, new ArrayList<IOption>(3){{add(option);}});
else
kindToOptionList.get(entryKind).add(option);
}
} catch (BuildException e) {
}
}
IKindBasedInfo<IOption[]>[] infos = fKindToUndefOptionArrayStore.getContents();
for (IKindBasedInfo<IOption[]> info : infos) {
List<IOption> list = kindToOptionList.get(info.getKind());
if(list != null){
IOption[] opts = list.toArray(new IOption[list.size()]);
info.setInfo(opts);
} else {
info.setInfo(EMPTY_OPTION_ARRAY);
}
}
}
IOption[] getUndefOptionsForKind(int entryKind){
KindBasedStore<IOption[]> store = getKindToUndefOptionArrayStore();
return store.get(entryKind);
}
IOption[] getOptionsForKind(int entryKind){
KindBasedStore<IOption[]> store = getKindToOptionArrayStore();
return store.get(entryKind);
}
/* private IOption[] getOptionsForType(int type){
Map map = getTypeToOptionArrayMap();
return (IOption[])map.get(new Integer(type));
}
*/
@Override
public void setLanguageId(String id) {
if(CDataUtil.objectsEqual(id, fInputType.getLanguageId(fTool))){
// fInputType = fTool.getEdtableInputType(fInputType);
obtainEditableInputType();
fInputType.setLanguageIdAttribute(id);
}
}
@Override
public String getId() {
return fId;
}
@Override
public String getName() {
String name;
if(fInputType == null){
name = fTool.getName();
if(name == null){
String[] exts = getSourceExtensions();
if(exts.length != 0){
name = CDataUtil.arrayToString(exts, ","); //$NON-NLS-1$
} else {
name = fTool.getId();
}
}
} else {
name = fInputType.getLanguageName(fTool);
}
return name;
}
@Override
public boolean isValid() {
// TODO Auto-generated method stub
return true;
}
public void setName(String name) {
// TODO Auto-generated method stub
}
public ITool getTool(){
return fTool;
}
public IInputType getInputType() {
return fInputType;
}
boolean isToolChainDiscoveryProfile(){
return fInputType != null ?
((InputType)fInputType).getDiscoveryProfileIdAttribute() == null :
true;
}
String getDiscoveryProfileId(){
if(fInputType != null)
return fInputType.getDiscoveryProfileId(fTool);
IBuildObject bo = fTool.getParent();
if(bo instanceof IToolChain)
return ((IToolChain)bo).getScannerConfigDiscoveryProfileId();
else if(bo instanceof IResourceInfo){
IToolChain tCh = ((ResourceConfiguration)bo).getBaseToolChain();
if(tCh != null)
return tCh.getScannerConfigDiscoveryProfileId();
}
return null;
}
public IConfiguration getConfiguration(){
return fTool.getParentResourceInfo().getParent();
}
@Override
public void setSourceContentTypeIds(String[] ids) {
String[] headerIds = fInputType.getHeaderContentTypeIds();
List<String> newSrc = new ArrayList<String>(ids.length);
List<String> newHeaders = new ArrayList<String>(ids.length);
for(int i = 0; i < ids.length; i++){
String id = ids[i];
int j = 0;
for(; j < headerIds.length; j++){
if(id.equals(headerIds[j])){
newHeaders.add(id);
break;
}
}
if(j == headerIds.length){
newSrc.add(id);
}
}
String newSrcIds[] = newSrc.toArray(new String[newSrc.size()]);
String newHeaderIds[] = newHeaders.toArray(new String[newHeaders.size()]);
if(!Arrays.equals(newSrcIds, fInputType.getSourceContentTypeIds())){
// fInputType = fTool.getEdtableInputType(fInputType);
obtainEditableInputType();
fInputType.setSourceContentTypeIds(newSrcIds);
}
if(!Arrays.equals(newHeaderIds, fInputType.getHeaderContentTypeIds())){
// fInputType = fTool.getEdtableInputType(fInputType);
obtainEditableInputType();
fInputType.setHeaderContentTypeIds(newHeaderIds);
}
}
@Override
public void setSourceExtensions(String[] exts) {
// TODO Auto-generated method stub
}
void clearCachedData(){
fKindToEntryStore.clear();
}
@Override
public boolean containsDiscoveredScannerInfo() {
IResourceInfo rcInfo = fTool.getParentResourceInfo();
if(rcInfo instanceof FolderInfo){
return ((FolderInfo)rcInfo).containsDiscoveredScannerInfo();
}
return true;
}
}