/*******************************************************************************
* Copyright (c) 2011, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The class representing persistent storage for language settings entries {@link ICLanguageSettingEntry}.
*/
public class LanguageSettingsSerializableStorage extends LanguageSettingsStorage {
private static final String ELEM_LANGUAGE = "language"; //$NON-NLS-1$
private static final String ATTR_LANGUAGE_ID = "id"; //$NON-NLS-1$
private static final String ELEM_RESOURCE = "resource"; //$NON-NLS-1$
private static final String ATTR_PROJECT_PATH = "project-relative-path"; //$NON-NLS-1$
private static final String ELEM_ENTRY = LanguageSettingsExtensionManager.ELEM_ENTRY;
private static final String ATTR_ENTRY_KIND = LanguageSettingsExtensionManager.ATTR_ENTRY_KIND;
private static final String ATTR_ENTRY_NAME = LanguageSettingsExtensionManager.ATTR_ENTRY_NAME;
private static final String ATTR_ENTRY_VALUE = LanguageSettingsExtensionManager.ATTR_ENTRY_VALUE;
private static final String ELEM_ENTRY_FLAG = LanguageSettingsExtensionManager.ELEM_ENTRY_FLAG;
/**
* Serialize the provider entries under parent XML element.
*
* @param elementProvider - element where to serialize the entries.
*/
public void serializeEntries(Element elementProvider) {
synchronized (fStorage) {
for (Entry<String, Map<String, List<ICLanguageSettingEntry>>> entryLang : fStorage.entrySet()) {
serializeLanguage(elementProvider, entryLang.getKey(), entryLang.getValue());
}
}
}
/**
* Serialize the provider entries for a given language list.
*/
private void serializeLanguage(Element parentElement, String langId, Map<String, List<ICLanguageSettingEntry>> langMap) {
if (langId!=null) {
Element elementLanguage = XmlUtil.appendElement(parentElement, ELEM_LANGUAGE, new String[] {ATTR_LANGUAGE_ID, langId});
parentElement = elementLanguage;
}
for (Entry<String, List<ICLanguageSettingEntry>> entryRc : langMap.entrySet()) {
serializeResource(parentElement, entryRc.getKey(), entryRc.getValue());
}
}
/**
* Serialize the provider entries for a given resource list.
*/
private void serializeResource(Element parentElement, String rcProjectPath, List<ICLanguageSettingEntry> rcList) {
if (rcProjectPath!=null) {
Element elementRc = XmlUtil.appendElement(parentElement, ELEM_RESOURCE, new String[] {ATTR_PROJECT_PATH, rcProjectPath});
parentElement = elementRc;
}
serializeSettingEntries(parentElement, rcList);
}
/**
* Serialize given settings entries.
*/
private void serializeSettingEntries(Element parentElement, List<ICLanguageSettingEntry> settingEntries) {
for (ICLanguageSettingEntry entry : settingEntries) {
Element elementSettingEntry = XmlUtil.appendElement(parentElement, ELEM_ENTRY, new String[] {
ATTR_ENTRY_KIND, LanguageSettingEntriesSerializer.kindToString(entry.getKind()),
ATTR_ENTRY_NAME, entry.getName(),
});
switch (entry.getKind()) {
case ICSettingEntry.MACRO:
elementSettingEntry.setAttribute(ATTR_ENTRY_VALUE, entry.getValue());
break;
// case ICLanguageSettingEntry.LIBRARY_FILE:
// // YAGNI: sourceAttachment fields may need to be covered
// break;
}
int flags = entry.getFlags();
if (flags != 0) {
// Element elementFlag =
XmlUtil.appendElement(elementSettingEntry, ELEM_ENTRY_FLAG, new String[] {
ATTR_ENTRY_VALUE, LanguageSettingEntriesSerializer.composeFlagsString(entry.getFlags())
});
}
}
}
/**
* Load provider entries from XML provider element.
*
* @param providerNode - parent XML element "provider" where entries are defined.
*/
public void loadEntries(Element providerNode) {
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = providerNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_LANGUAGE.equals(elementNode.getNodeName())) {
loadLanguageElement(elementNode, null);
} else if (ELEM_RESOURCE.equals(elementNode.getNodeName())) {
loadResourceElement(elementNode, null, null);
} else if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(null, null, settings);
}
}
/**
* Load a setting entry from XML element.
*/
private ICLanguageSettingEntry loadSettingEntry(Node parentElement) {
String settingKind = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_KIND);
String settingName = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_NAME);
NodeList flagNodes = parentElement.getChildNodes();
int flags = 0;
for (int i=0;i<flagNodes.getLength();i++) {
Node flagNode = flagNodes.item(i);
if (flagNode.getNodeType() != Node.ELEMENT_NODE || !ELEM_ENTRY_FLAG.equals(flagNode.getNodeName()))
continue;
String settingFlags = XmlUtil.determineAttributeValue(flagNode, ATTR_ENTRY_VALUE);
int bitFlag = LanguageSettingEntriesSerializer.composeFlags(settingFlags);
flags |= bitFlag;
}
String settingValue = null;
int kind = LanguageSettingEntriesSerializer.stringToKind(settingKind);
if (kind == ICSettingEntry.MACRO)
settingValue = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_VALUE);
ICLanguageSettingEntry entry = (ICLanguageSettingEntry) CDataUtil.createEntry(kind, settingName, settingValue, null, flags);
return entry;
}
/**
* Load entries defined in language element.
*/
private void loadLanguageElement(Node parentNode, String cfgId) {
String langId = XmlUtil.determineAttributeValue(parentNode, ATTR_LANGUAGE_ID);
if (langId.length() == 0) {
langId=null;
}
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = parentNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_RESOURCE.equals(elementNode.getNodeName())) {
loadResourceElement(elementNode, cfgId, langId);
} else if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(null, langId, settings);
}
}
/**
* Load entries defined in resource element.
*/
private void loadResourceElement(Node parentNode, String cfgId, String langId) {
String rcProjectPath = XmlUtil.determineAttributeValue(parentNode, ATTR_PROJECT_PATH);
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = parentNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(rcProjectPath, langId, settings);
}
}
@Override
public LanguageSettingsSerializableStorage clone() throws CloneNotSupportedException {
return (LanguageSettingsSerializableStorage) super.clone();
}
}