summaryrefslogtreecommitdiffstats
path: root/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param')
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java202
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java134
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries10
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java267
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java27
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java51
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java42
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java171
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java54
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java323
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java261
14 files changed, 1545 insertions, 0 deletions
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java
new file mode 100644
index 0000000..91969fc
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Alena Laskavaia
+ * 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:
+ * Alena Laskavaia - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StreamTokenizer;
+
+/**
+ * Default implementation of problem preference. It keeps preference metadata
+ * together with preference value. Some implementations may separate them.
+ *
+ */
+public abstract class AbstractProblemPreference implements IProblemPreference {
+ /**
+ * default key for a preference
+ */
+ public static final String PARAM = "params"; //$NON-NLS-1$
+ private String key = PARAM;
+ private String label = ""; //$NON-NLS-1$
+ private String toolTip = null;
+ private String uiInfo;
+ private IProblemPreference parent;
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getToolTip() {
+ return toolTip;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getUiInfo() {
+ return uiInfo;
+ }
+
+ /**
+ * Set preference key for itself
+ *
+ * @param key
+ */
+ public void setKey(String key) {
+ if (key == null)
+ throw new NullPointerException("key"); //$NON-NLS-1$
+ if (isValidIdentifier(key))
+ this.key = key;
+ else
+ throw new IllegalArgumentException(
+ "Key must have java identifier syntax or number, i.e no dots and other funky stuff: " + key); //$NON-NLS-1$
+ }
+
+ protected boolean isValidIdentifier(String id) {
+ if (id == null)
+ return false;
+ int n = id.length();
+ if (n == 0)
+ return false;
+ if (id.equals("#")) //$NON-NLS-1$
+ return true;
+ for (int i = 0; i < n; i++)
+ if (!Character.isJavaIdentifierPart(id.charAt(i)))
+ return false;
+ return true;
+ }
+
+ /**
+ * Sets a label for UI control
+ *
+ * @param label
+ */
+ public void setLabel(String label) {
+ if (label == null)
+ throw new NullPointerException("Label cannot be null"); //$NON-NLS-1$
+ this.label = label;
+ }
+
+ /**
+ * Sets tooltip for ui control. Not supported now.
+ *
+ * @param tooltip
+ */
+ public void setToolTip(String tooltip) {
+ this.toolTip = tooltip;
+ }
+
+ /**
+ * Sets uiinfo for ui control. Not supported now.
+ *
+ * @param uiinfo
+ */
+ public void setUiInfo(String uiinfo) {
+ this.uiInfo = uiinfo;
+ }
+
+ public Object getValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setValue(Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @param str
+ * @return
+ */
+ protected StreamTokenizer getImportTokenizer(String str) {
+ ByteArrayInputStream st = new ByteArrayInputStream(str.getBytes());
+ StreamTokenizer tokenizer = new StreamTokenizer(new InputStreamReader(
+ st));
+ tokenizer.resetSyntax();
+ tokenizer.quoteChar('"');
+ tokenizer.wordChars('_', '_');
+ tokenizer.wordChars('-', '-');
+ tokenizer.wordChars('.', '.');
+ tokenizer.wordChars('0', '9');
+ tokenizer.wordChars('a', 'z');
+ tokenizer.wordChars('A', 'Z');
+ tokenizer.wordChars(128 + 32, 255);
+ tokenizer.whitespaceChars(0, ' ');
+ tokenizer.commentChar('/');
+ return tokenizer;
+ }
+
+ public IProblemPreference getParent() {
+ return parent;
+ }
+
+ /**
+ * @param parent
+ * the parent to set
+ */
+ public void setParent(IProblemPreference parent) {
+ this.parent = parent;
+ }
+
+ public String getQualifiedKey() {
+ if (parent == null)
+ return getKey();
+ return parent.getQualifiedKey() + "." + getKey(); //$NON-NLS-1$
+ }
+
+ /**
+ * @param tokenizer
+ * @throws IOException
+ */
+ public abstract void importValue(StreamTokenizer tokenizer)
+ throws IOException;
+
+ public void importValue(String str) {
+ StreamTokenizer tokenizer = getImportTokenizer(str);
+ try {
+ importValue(tokenizer);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(str, e);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ protected String escape(String x) {
+ x = x.replaceAll("[\"\\\\]", "\\\\$0"); //$NON-NLS-1$//$NON-NLS-2$
+ return "\"" + x + "\""; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ /**
+ * @param str
+ * @return
+ */
+ protected String unescape(String str) {
+ StreamTokenizer tokenizer = getImportTokenizer(str);
+ try {
+ tokenizer.nextToken();
+ } catch (IOException e) {
+ return null;
+ }
+ String sval = tokenizer.sval;
+ return sval;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java
new file mode 100644
index 0000000..fd146b0
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Alena Laskavaia
+ * 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:
+ * Alena Laskavaia - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.util.regex.Pattern;
+
+/**
+ * Preference representing a problem preference of a basic type.
+ *
+ * @see IProblemPreferenceDescriptor.PreferenceType for types.
+ *
+ */
+public class BasicProblemPreference extends AbstractProblemPreference {
+ protected Object value;
+ private PreferenceType type = PreferenceType.TYPE_STRING;
+
+ public PreferenceType getType() {
+ return type;
+ }
+
+ /**
+ * Set preferene type
+ *
+ * @param type
+ */
+ public void setType(PreferenceType type) {
+ if (type == null)
+ throw new NullPointerException("Type cannot be null"); //$NON-NLS-1$
+ this.type = type;
+ }
+
+ /**
+ * Generate an info with given key and label
+ *
+ * @param key
+ * - property id (use in actual property hash of a checker)
+ * @param label
+ * - label to be shown to user
+ * @param type
+ * - parameter type
+ */
+ public BasicProblemPreference(String key, String label, PreferenceType type) {
+ this(key, label);
+ setType(type);
+ }
+
+ /**
+ * Generate an info with given key and label
+ *
+ * @param key
+ * - property id (use in actual property hash of a checker)
+ * @param label
+ * - label to be shown to user
+ */
+ public BasicProblemPreference(String key, String label) {
+ setKey(key);
+ setLabel(label);
+ }
+
+ @Override
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ @Override
+ public Object getValue() {
+ return value;
+ }
+
+ public String exportValue() {
+ Pattern pat = Pattern.compile("^[A-Za-z0-9._-]+$"); //$NON-NLS-1$
+ String x = String.valueOf(getValue());
+ if (pat.matcher(x).find() == false)
+ return escape(x);
+ return x;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.cdt.codan.core.param.IProblemPreferenceValue#importValue(
+ * java.lang.String)
+ */
+ @Override
+ public void importValue(String str) {
+ if (str.startsWith("\"")) //$NON-NLS-1$
+ str = unescape(str);
+ switch (getType()) {
+ case TYPE_STRING:
+ setValue(str);
+ break;
+ case TYPE_INTEGER:
+ setValue(Integer.parseInt(str));
+ break;
+ case TYPE_BOOLEAN:
+ setValue(Boolean.valueOf(str));
+ break;
+ case TYPE_FILE:
+ setValue(new File(str));
+ break;
+ default:
+ throw new IllegalArgumentException(getType()
+ + " is not supported for basic type"); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "(" + type + ")" + getKey() + ((value == null) ? "" : "=" + value); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+ }
+
+ @Override
+ public void importValue(StreamTokenizer tokenizer) {
+ try {
+ tokenizer.nextToken();
+ String val = tokenizer.sval;
+ importValue(val);
+ } catch (IOException e) {
+ new IllegalArgumentException(e);
+ }
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries
new file mode 100644
index 0000000..4f3cdf4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries
@@ -0,0 +1,10 @@
+/AbstractProblemPreference.java/1.8/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
+/BasicProblemPreference.java/1.7/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
+/FileScopeProblemPreference.java/1.4/Wed Jun 2 00:39:31 2010//TCDT_7_0_0
+/IProblemPreference.java/1.3/Tue May 25 01:33:22 2010//TCDT_7_0_0
+/IProblemPreferenceCompositeDescriptor.java/1.4/Mon May 31 02:53:25 2010//TCDT_7_0_0
+/IProblemPreferenceCompositeValue.java/1.4/Tue Jun 1 02:24:14 2010//TCDT_7_0_0
+/IProblemPreferenceDescriptor.java/1.6/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
+/IProblemPreferenceValue.java/1.4/Tue Jun 1 02:24:14 2010//TCDT_7_0_0
+/ListProblemPreference.java/1.6/Tue Jun 1 02:24:14 2010//TCDT_7_0_0
+/MapProblemPreference.java/1.6/Tue Jun 1 02:24:14 2010//TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository
new file mode 100644
index 0000000..d959de5
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository
@@ -0,0 +1 @@
+org.eclipse.cdt/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root
new file mode 100644
index 0000000..04efa23
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@dev.eclipse.org:/cvsroot/tools
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java
new file mode 100644
index 0000000..bdb36f0
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.cdt.codan.core.Messages;
+import org.eclipse.cdt.codan.internal.core.CharOperation;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * Custom preference for resource scope
+ *
+ * @noextend This class is not intended to be extended by clients.
+ * @since 1.0
+ */
+public class FileScopeProblemPreference extends AbstractProblemPreference {
+ /**
+ * Key for the scope preference
+ */
+ public static final String KEY = "fileScope"; //$NON-NLS-1$
+ /**
+ * Exclusion attribute
+ */
+ public static final String EXCLUSION = "exclusion"; //$NON-NLS-1$
+ /**
+ * Inclusion attribute
+ */
+ public static final String INCLUSION = "inclusion"; //$NON-NLS-1$
+ private IResource resource;
+ private IPath[] inclusion = new IPath[0];
+ private IPath[] exclusion = new IPath[0];
+
+ /**
+ * Default constructor
+ */
+ public FileScopeProblemPreference() {
+ setKey(KEY);
+ setLabel(Messages.FileScopeProblemPreference_Label);
+ }
+
+ public PreferenceType getType() {
+ return PreferenceType.TYPE_CUSTOM;
+ }
+
+ /**
+ * Get attribute. Possible keys are EXCUSION and INCLUSION
+ *
+ * @param key
+ * @return class attribute for given key
+ */
+ public IPath[] getAttribute(String key) {
+ if (key == EXCLUSION)
+ return exclusion;
+ if (key == INCLUSION)
+ return inclusion;
+ return null;
+ }
+
+ /**
+ * Set attribute to a value. Possible keys are EXCUSION and INCLUSION
+ *
+ * @param key
+ * @param value
+ */
+ public void setAttribute(String key, IPath[] value) {
+ if (key == EXCLUSION)
+ exclusion = value.clone();
+ if (key == INCLUSION)
+ inclusion = value.clone();
+ }
+
+ /**
+ * @return null for workspace, or project of the resource it is applicable
+ * for
+ */
+ public IProject getProject() {
+ if (resource != null)
+ return resource.getProject();
+ return null;
+ }
+
+ /**
+ * @return path of the resource it is applicable to
+ */
+ public IPath getPath() {
+ if (resource != null)
+ return resource.getFullPath();
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+ return root.getFullPath();
+ }
+
+ /**
+ * @param resource
+ * the resource to set
+ */
+ public void setResource(IResource resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * @return the resource for which scope is define. Null if workspace.
+ */
+ public IResource getResource() {
+ return resource;
+ }
+
+ public String exportValue() {
+ return exportPathList(INCLUSION, inclusion) + "," //$NON-NLS-1$
+ + exportPathList(EXCLUSION, exclusion);
+ }
+
+ protected String exportPathList(String key, IPath[] arr) {
+ String res = key + "=>("; //$NON-NLS-1$
+ for (int i = 0; i < arr.length; i++) {
+ if (i != 0)
+ res += ","; //$NON-NLS-1$
+ res += escape(arr[i].toPortableString());
+ }
+ return res + ")"; //$NON-NLS-1$
+ }
+
+ @Override
+ public void importValue(StreamTokenizer tokenizer) throws IOException {
+ List<IPath> inc = importPathList(tokenizer, INCLUSION);
+ inclusion = inc.toArray(new IPath[inc.size()]);
+ checkChar(tokenizer, ',');
+ List<IPath> exc = importPathList(tokenizer, EXCLUSION);
+ exclusion = exc.toArray(new IPath[exc.size()]);
+ }
+
+ private void checkChar(StreamTokenizer tokenizer, char c)
+ throws IOException {
+ tokenizer.nextToken();
+ if (tokenizer.ttype != c)
+ throw new IllegalArgumentException("Expected " + c); //$NON-NLS-1$
+ }
+
+ private void checkKeyword(StreamTokenizer tokenizer, String keyword)
+ throws IOException {
+ tokenizer.nextToken();
+ if (tokenizer.sval == null || !tokenizer.sval.equals(keyword))
+ throw new IllegalArgumentException("Expected " + keyword); //$NON-NLS-1$
+ }
+
+ protected List<IPath> importPathList(StreamTokenizer tokenizer,
+ String keyword) throws IOException {
+ checkKeyword(tokenizer, keyword);
+ checkChar(tokenizer, '=');
+ checkChar(tokenizer, '>');
+ ArrayList<IPath> list = new ArrayList<IPath>();
+ int token;
+ int index = 0;
+ try {
+ checkChar(tokenizer, '(');
+ token = tokenizer.nextToken();
+ if (token != ')')
+ tokenizer.pushBack();
+ else
+ return Collections.emptyList();
+ while (true) {
+ token = tokenizer.nextToken();
+ if (tokenizer.sval == null)
+ throw new IllegalArgumentException();
+ list.add(new Path(tokenizer.sval));
+ token = tokenizer.nextToken();
+ if (token == ')')
+ break;
+ tokenizer.pushBack();
+ checkChar(tokenizer, ',');
+ index++;
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ return list;
+ }
+
+ @Override
+ public Object getValue() {
+ return this;
+ }
+
+ @Override
+ public void setValue(Object value) {
+ if (this == value)
+ return;
+ FileScopeProblemPreference scope = (FileScopeProblemPreference) value;
+ setAttribute(INCLUSION, scope.getAttribute(INCLUSION));
+ setAttribute(EXCLUSION, scope.getAttribute(EXCLUSION));
+ this.resource = scope.getResource();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.param.AbstractProblemPreference#clone()
+ */
+ @Override
+ public Object clone() {
+ FileScopeProblemPreference scope = (FileScopeProblemPreference) super
+ .clone();
+ scope.setValue(this);
+ return scope;
+ }
+
+ /**
+ * Checks that resource denotated by the given path is in scope (defined by
+ * exclusion/inclusion settings of this class). In inclusion list is defined
+ * check first if it belongs to it, returns false if not.
+ * Then checks if it belongs to exclusion list and return false if it is.
+ *
+ * @param path
+ * - resource path
+ * @return true is given path is in scope
+ */
+ public boolean isInScope(IPath path) {
+ //System.err.println("test " + file + " " + exportValue());
+ if (inclusion.length > 0) {
+ if (!matchesFilter(path, inclusion))
+ return false;
+ }
+ if (exclusion.length > 0) {
+ if (matchesFilter(path, exclusion))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks that given path matches on the paths provided as second argument
+ *
+ * @param resourcePath - resource path
+ * @param paths - array of path patterns, for pattern see
+ * {@link CharOperation#pathMatch}
+ * @return true if matches with at least one pattern in the array
+ */
+ public boolean matchesFilter(IPath resourcePath, IPath[] paths) {
+ char[] path = resourcePath.toString().toCharArray();
+ for (int i = 0, length = paths.length; i < length; i++) {
+ char[] pattern = paths[i].toString().toCharArray();
+ if (CharOperation.pathMatch(pattern, path, true, '/')) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java
new file mode 100644
index 0000000..6b0c316
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+/**
+ * Problem preference. If problem has more than one it can be composite, i.e.
+ * map. Instead of implementing this interface clients must extend
+ * {@link AbstractProblemPreference} class.
+ *
+ * Problem Preference constist of preference metadata
+ * (IProblemPreferenceDescriptor)
+ * and value of preference (IProblemPreferenceValue).
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProblemPreference extends Cloneable, IProblemPreferenceValue,
+ IProblemPreferenceDescriptor {
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java
new file mode 100644
index 0000000..392e0a2
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+/**
+ * Composite descriptor. For descriptors like map and list.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProblemPreferenceCompositeDescriptor {
+ /**
+ * Available if type is composite. Returns value of subdescriptor with the
+ * name of key. For the "list" type key is the number (index).
+ *
+ * @param key
+ * - name of the subdescriptor.
+ * @return child preference of the given key
+ */
+ IProblemPreference getChildDescriptor(String key);
+
+ /**
+ * Available for composite types. Returns array of children.
+ *
+ * @return array of children. 0 size of none.
+ */
+ IProblemPreference[] getChildDescriptors();
+
+ /**
+ * Add preference
+ *
+ * @param preference
+ * @return added preference
+ */
+ IProblemPreference addChildDescriptor(IProblemPreference preference);
+
+ /**
+ * Remove preference
+ *
+ * @param preference
+ */
+ void removeChildDescriptor(IProblemPreference preference);
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java
new file mode 100644
index 0000000..f44a659
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 Alena Laskavaia
+ * 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:
+ * Alena Laskavaia - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+/**
+ * Interface for container type preferences, such as map or list
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProblemPreferenceCompositeValue {
+ /**
+ * Returns value of the child element of a given key
+ *
+ * @param key
+ * @return value of the child preference
+ */
+ Object getChildValue(String key);
+
+ /**
+ * Sets the value of the child element of a given key
+ *
+ * @param key
+ * @param value
+ */
+ void setChildValue(String key, Object value);
+
+ /**
+ * Removes child element matching the given key
+ *
+ * @param key
+ */
+ void removeChildValue(String key);
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java
new file mode 100644
index 0000000..f6f97e0
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Alena Laskavaia
+ * 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:
+ * Alena Laskavaia - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Problem parameter usually key=value settings that allows to alter checker
+ * behaviour for given problem. For example if checker finds violation of naming
+ * conventions for function, parameter would be the pattern of allowed names.
+ *
+ * IProblemPreferenceDescriptor represent preference's meta-info for the ui. If
+ * more than one parameter is required it can be map or list of sub-preferences.
+ * This is only needed for auto-generated ui for parameter
+ * editing. For more complex cases custom ui control should be used. Extend
+ * {@link AbstractProblemPreference} class
+ * to implement this interface.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProblemPreferenceDescriptor extends Cloneable {
+ /**
+ * Type of the user preference
+ */
+ public enum PreferenceType {
+ /**
+ * String type, represented by string input field by default
+ */
+ TYPE_STRING("string"), //$NON-NLS-1$
+ /**
+ * Integer type, represented by integer input field by default
+ */
+ TYPE_INTEGER("integer"), //$NON-NLS-1$
+ /**
+ * Boolean type, represented by checkbox (boolean input field)
+ */
+ TYPE_BOOLEAN("boolean"), //$NON-NLS-1$
+ /**
+ * File type, represented by file picker input field
+ */
+ TYPE_FILE("file"), //$NON-NLS-1$
+ /**
+ * List type, represented by list (table) control
+ */
+ TYPE_LIST("list"), //$NON-NLS-1$
+ /**
+ * Map type, represented by composite of children fields
+ */
+ TYPE_MAP("map"), //$NON-NLS-1$
+ /**
+ * Custom type, represented by string input field by default
+ */
+ TYPE_CUSTOM("custom"); //$NON-NLS-1$
+ private String literal;
+
+ private PreferenceType(String literal) {
+ this.literal = literal;
+ }
+
+ /**
+ * @param name - name of the type literal (i.e. comes from name() or
+ * toString())
+ * @return type represented by this name
+ */
+ public static PreferenceType valueOfLiteral(String name) {
+ PreferenceType[] values = values();
+ for (int i = 0; i < values.length; i++) {
+ PreferenceType e = values[i];
+ if (e.literal.equals(name))
+ return e;
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return literal;
+ }
+
+ /**
+ * @param value
+ * @return parameter type corresponding to the value java type
+ */
+ public static PreferenceType typeOf(Object value) {
+ if (value instanceof Boolean)
+ return TYPE_BOOLEAN;
+ if (value instanceof String)
+ return TYPE_STRING;
+ if (value instanceof Integer)
+ return TYPE_INTEGER;
+ if (value instanceof File)
+ return TYPE_FILE;
+ if (value instanceof List)
+ return TYPE_LIST;
+ if (value instanceof Map)
+ return TYPE_MAP;
+ return TYPE_CUSTOM;
+ }
+ }
+
+ /**
+ * Key of the preference. Key must be java-like identified or number. Cannot
+ * contain dots. Cannot be null.
+ *
+ * @return key
+ */
+ String getKey();
+
+ /**
+ * type of the parameter, supports boolean, integer, string, file, list and
+ * map. For list type child preference can be
+ * accessed by number (index), if map is the type child preference can be
+ * accessed by a key (string)
+ *
+ * @return type of the preference
+ */
+ PreferenceType getType();
+
+ /**
+ * Additional info on how it is represented in the ui, for example boolean
+ * can be represented as checkbox, drop-down and so on, Values TBD.
+ * Not supported at the moment.
+ *
+ * @return ui info or null if not set
+ */
+ String getUiInfo();
+
+ /**
+ * User visible label for the parameter control in UI
+ *
+ * @return the label
+ */
+ String getLabel();
+
+ /**
+ * Detailed explanation of parameter. Not supported at the moment.
+ *
+ * @return the toolTip text
+ */
+ String getToolTip();
+
+ /**
+ * default clone implementation
+ *
+ * @return clone of the object
+ */
+ Object clone();
+
+ /**
+ * @return parent preference
+ */
+ IProblemPreference getParent();
+
+ /**
+ * Combined key of values from parents plus itself separated by dot
+ *
+ * @return qualified key
+ */
+ String getQualifiedKey();
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java
new file mode 100644
index 0000000..cbe9f4f
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+/**
+ * Value of the problem preference. If more than one it can be composite, i.e.
+ * map.Extend {@link AbstractProblemPreference} class
+ * to implement this interface.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProblemPreferenceValue extends Cloneable {
+ /**
+ * Get value of preference.
+ *
+ * @return object that represents the value. Limited number of object types
+ * are allowed.
+ * @see IProblemPreferenceDescriptor.PreferenceType
+ */
+ Object getValue();
+
+ /**
+ * Set value of preference represented by this object.
+ *
+ * @param value
+ */
+ void setValue(Object value);
+
+ /**
+ * Export value in string representation required for storing in eclipse
+ * preferences.
+ *
+ * @return string representation of the value
+ */
+ String exportValue();
+
+ /**
+ * Import value from string into internal object state.
+ *
+ * @param str
+ * - string from preferences, previously exported by exportValue
+ * method.
+ */
+ void importValue(String str);
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java
new file mode 100644
index 0000000..333cb31
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * List implementation of IProblemPreference.
+ *
+ * @noextend This class is not intended to be extended by clients.
+ */
+public class ListProblemPreference extends AbstractProblemPreference implements
+ IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor {
+ /**
+ * Constant that represent a key for "shared" child preference (descriptor)
+ * of all elements
+ */
+ public static final String COMMON_DESCRIPTOR_KEY = "#"; //$NON-NLS-1$
+ protected ArrayList<Object> list = new ArrayList<Object>();
+ protected IProblemPreference childDescriptor;
+
+ /**
+ * @param key
+ * - key to access this preference
+ * @param label
+ * - label to be shown in UI
+ */
+ public ListProblemPreference(String key, String label) {
+ setKey(key);
+ setLabel(label);
+ }
+
+ public PreferenceType getType() {
+ return PreferenceType.TYPE_LIST;
+ }
+
+ /**
+ * Set child descriptor (all elements have the same). Value and key
+ * of it would be ignored and reset.
+ *
+ * @param desc
+ * @return set child descriptor
+ */
+ public IProblemPreference setChildDescriptor(IProblemPreference desc) {
+ childDescriptor = desc;
+ if (desc != null) {
+ childDescriptor.setValue(null);
+ ((AbstractProblemPreference) childDescriptor)
+ .setKey(COMMON_DESCRIPTOR_KEY);
+ }
+ return desc;
+ }
+
+ /**
+ * Sets common descriptor for all elements, if value if not null sets the
+ * value for its key also. Do not make assumptions of values of desc after
+ * you pass it to this function.
+ *
+ * @return read only preference matching the key
+ */
+ public IProblemPreference addChildDescriptor(IProblemPreference desc) {
+ Object value = desc.getValue();
+ String key = desc.getKey();
+ setChildDescriptor(desc);
+ setChildValue(key, value);
+ return getChildDescriptor(key);
+ }
+
+ /**
+ *
+ * @return descriptor of the child elements
+ */
+ public IProblemPreference getChildDescriptor() {
+ return childDescriptor;
+ }
+
+ /**
+ * Returns cloned descriptor of the i'th child. Modifying return value would
+ * not affect internal state of the list element.
+ *
+ * @param i - index of the element
+ * @return child preference
+ */
+ public IProblemPreference getChildDescriptor(int i) {
+ Object value = list.get(i);
+ AbstractProblemPreference desc = (AbstractProblemPreference) childDescriptor
+ .clone();
+ desc.setKey(String.valueOf(i));
+ desc.setValue(value);
+ return desc;
+ }
+
+ /**
+ * Get read only problem preference for element equal to key's int value.
+ * If key is null or # return generic descriptor with null value.
+ *
+ * @throws NumberFormatException
+ * if key is not number
+ */
+ public IProblemPreference getChildDescriptor(String key)
+ throws NumberFormatException {
+ if (key == null || key.equals(COMMON_DESCRIPTOR_KEY)) {
+ // return common descriptor
+ return getChildDescriptor();
+ }
+ Integer iv = Integer.valueOf(key);
+ if (iv.intValue() >= list.size()) {
+ // create one
+ AbstractProblemPreference clone = (AbstractProblemPreference) childDescriptor
+ .clone();
+ clone.setKey(key);
+ return clone;
+ }
+ return getChildDescriptor(iv.intValue());
+ }
+
+ /**
+ * Return array of clones values of child preferences.
+ */
+ public IProblemPreference[] getChildDescriptors() {
+ IProblemPreference[] res = new IProblemPreference[list.size()];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = getChildDescriptor(i);
+ }
+ return res;
+ }
+
+ public Object getChildValue(String key) {
+ int index = Integer.parseInt(key);
+ return getChildValue(index);
+ }
+
+ /**
+ * @param index - index of the element
+ * @return child value by index
+ */
+ public Object getChildValue(int index) {
+ return list.get(index);
+ }
+
+ public void setChildValue(String key, Object value) {
+ int i = Integer.valueOf(key).intValue();
+ setChildValue(i, value);
+ }
+
+ /**
+ * @param i - index of the element
+ * @param value - value of the child element
+ */
+ public void setChildValue(int i, Object value) {
+ if (value != null) {
+ while (i >= list.size()) {
+ list.add(null);
+ }
+ list.set(i, value);
+ } else {
+ while (i == list.size() - 1) {
+ list.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Adds value to the list
+ *
+ * @param value
+ */
+ public void addChildValue(Object value) {
+ list.add(value);
+ }
+
+ /**
+ * Removes child value by key
+ */
+ public void removeChildValue(String key) {
+ int index = Integer.parseInt(key);
+ list.remove(index);
+ }
+
+ @Override
+ public Object clone() {
+ ListProblemPreference list1 = (ListProblemPreference) super.clone();
+ list1.list = new ArrayList<Object>();
+ list1.setChildDescriptor((IProblemPreference) getChildDescriptor()
+ .clone());
+ for (Iterator<Object> iterator = list.iterator(); iterator.hasNext();) {
+ Object value = iterator.next();
+ list1.addChildValue(value);
+ }
+ return list1;
+ }
+
+ public String exportValue() {
+ StringBuffer buf = new StringBuffer("("); //$NON-NLS-1$
+ for (Iterator<Object> iterator = list.iterator(); iterator.hasNext();) {
+ IProblemPreference d = (IProblemPreference) childDescriptor.clone();
+ d.setValue(iterator.next());
+ buf.append(d.exportValue());
+ if (iterator.hasNext())
+ buf.append(","); //$NON-NLS-1$
+ }
+ return buf.toString() + ")"; //$NON-NLS-1$
+ }
+
+ @Override
+ public void importValue(String str) {
+ StreamTokenizer tokenizer = getImportTokenizer(str);
+ try {
+ importValue(tokenizer);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(str, e);
+ }
+ }
+
+ @Override
+ public void importValue(StreamTokenizer tokenizer) {
+ clear();
+ int token;
+ int index = 0;
+ try {
+ token = tokenizer.nextToken();
+ String chara = String.valueOf((char) token);
+ if (token != '(')
+ throw new IllegalArgumentException(chara);
+ token = tokenizer.nextToken();
+ if (token != ')')
+ tokenizer.pushBack();
+ else
+ return;
+ while (true) {
+ String ik = String.valueOf(index);
+ IProblemPreference desc = getChildDescriptor(ik);
+ if (desc != null && desc instanceof AbstractProblemPreference) {
+ ((AbstractProblemPreference) desc).importValue(tokenizer);
+ setChildValue(ik, desc.getValue());
+ }
+ token = tokenizer.nextToken();
+ if (token == ')')
+ break;
+ if (token != ',')
+ throw new IllegalArgumentException(chara);
+ index++;
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * If info key is '#' resets common descriptor to null, otherwise removes
+ * value
+ */
+ public void removeChildDescriptor(IProblemPreference info) {
+ if (info.getKey().equals(COMMON_DESCRIPTOR_KEY))
+ setChildDescriptor(null);
+ else
+ removeChildValue(info.getKey());
+ }
+
+ /**
+ * @return children size
+ */
+ public int size() {
+ return list.size();
+ }
+
+ /**
+ * Removes all values from the list
+ */
+ public void clear() {
+ list.clear();
+ }
+
+ /**
+ * @return array of values of children elements.
+ */
+ @Override
+ public Object getValue() {
+ return getValues();
+ }
+
+ /**
+ * Sets list value to values of array given as argument.
+ *
+ * @param value - must be Object[]
+ */
+ @Override
+ public void setValue(Object value) {
+ Object[] values = (Object[]) value;
+ if (Arrays.deepEquals(getValues(), values)) {
+ return;
+ }
+ list.clear();
+ for (int i = 0; i < values.length; i++) {
+ Object object = values[i];
+ list.add(object);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return childDescriptor + ":" + list.toString(); //$NON-NLS-1$
+ }
+
+ /**
+ * @return array of values of children elements.
+ */
+ public Object[] getValues() {
+ return list.toArray(new Object[list.size()]);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java
new file mode 100644
index 0000000..6e865f0
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 QNX Software Systems
+ * 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:
+ * QNX Software Systems (Alena Laskavaia) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.param;
+
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences;
+
+/**
+ * MapProblemPreference - for checker that needs more than one preferences and
+ * they all differently "named".
+ * For example checker for parameter names shadowing would have two boolean
+ * options:
+ * "check contructors" and
+ * "check setters". In this case you use this type.
+ * {@link AbstractCheckerWithProblemPreferences} class has map as default top
+ * level parameter preference.
+ *
+ * @noextend This class is not intended to be extended by clients.
+ */
+public class MapProblemPreference extends AbstractProblemPreference implements
+ IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor {
+ protected LinkedHashMap<String, IProblemPreference> hash = new LinkedHashMap<String, IProblemPreference>();
+
+ /**
+ * Default constuctor
+ */
+ public MapProblemPreference() {
+ super();
+ }
+
+ /**
+ * @param key
+ * - key for itself
+ * @param label
+ * - label for this group of parameters
+ */
+ public MapProblemPreference(String key, String label) {
+ setKey(key);
+ setLabel(label);
+ }
+
+ public PreferenceType getType() {
+ return PreferenceType.TYPE_MAP;
+ }
+
+ /**
+ * Get parameter preference for element by key
+ *
+ */
+ public IProblemPreference getChildDescriptor(String key) {
+ return hash.get(key);
+ }
+
+ /**
+ * Adds or replaces child descriptor and value for the element with the key
+ * equals to desc.getKey(). The desc object would be put in the map, some of
+ * its field may be modified.
+ *
+ * @param desc
+ */
+ public IProblemPreference addChildDescriptor(IProblemPreference desc) {
+ ((AbstractProblemPreference) desc).setParent(this);
+ hash.put(desc.getKey(), desc);
+ return desc;
+ }
+
+ /**
+ * Return list of child descriptors. Client should threat returned value as
+ * read only,
+ * and not assume that modifying its elements would modify actual child
+ * values.
+ */
+ public IProblemPreference[] getChildDescriptors() {
+ return hash.values().toArray(
+ new IProblemPreference[hash.values().size()]);
+ }
+
+ /**
+ * Returns value of the child element by its key
+ */
+ public Object getChildValue(String key) {
+ IProblemPreference childInfo = getChildDescriptor(key);
+ return childInfo.getValue();
+ }
+
+ /**
+ * Set child value by its key
+ */
+ public void setChildValue(String key, Object value) {
+ IProblemPreference pref = getChildDescriptor(key);
+ if (pref == null)
+ throw new IllegalArgumentException("Preference for " + key //$NON-NLS-1$
+ + " must exists before setting its value"); //$NON-NLS-1$
+ pref.setValue(value);
+ hash.put(key, pref); // cannot assume getChildDescriptor returns shared value
+ }
+
+ /**
+ * Removes child value and descriptor by key
+ */
+ public void removeChildValue(String key) {
+ hash.remove(key);
+ }
+
+ @Override
+ public Object clone() {
+ MapProblemPreference map = (MapProblemPreference) super.clone();
+ map.hash = new LinkedHashMap<String, IProblemPreference>();
+ for (Iterator<String> iterator = hash.keySet().iterator(); iterator
+ .hasNext();) {
+ String key = iterator.next();
+ map.hash.put(key, (IProblemPreference) hash.get(key).clone());
+ }
+ return map;
+ }
+
+ public String exportValue() {
+ StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$
+ for (Iterator<String> iterator = hash.keySet().iterator(); iterator
+ .hasNext();) {
+ String key = iterator.next();
+ IProblemPreference d = hash.get(key);
+ buf.append(key + "=>" + d.exportValue()); //$NON-NLS-1$
+ if (iterator.hasNext())
+ buf.append(","); //$NON-NLS-1$
+ }
+ return buf.toString() + "}"; //$NON-NLS-1$
+ }
+
+ @Override
+ public void importValue(String str) {
+ StreamTokenizer tokenizer = getImportTokenizer(str);
+ try {
+ importValue(tokenizer);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(str + ":" + e.toString(), e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @param tokenizer
+ */
+ @Override
+ public void importValue(StreamTokenizer tokenizer) {
+ int token;
+ try {
+ token = tokenizer.nextToken();
+ String chara = String.valueOf((char) token);
+ if (token != '{') {
+ throw new IllegalArgumentException(chara);
+ }
+ while (true) {
+ token = tokenizer.nextToken();
+ String key = tokenizer.sval;
+ token = tokenizer.nextToken();
+ if (token != '=')
+ throw new IllegalArgumentException(chara);
+ token = tokenizer.nextToken();
+ if (token != '>')
+ throw new IllegalArgumentException(chara);
+ IProblemPreference desc = getChildDescriptor(key);
+ if (desc != null && desc instanceof AbstractProblemPreference) {
+ ((AbstractProblemPreference) desc).importValue(tokenizer);
+ setChildValue(key, desc.getValue());
+ }
+ token = tokenizer.nextToken();
+ if (token == '}')
+ break;
+ if (token != ',')
+ throw new IllegalArgumentException(chara);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Removes child descriptor by its key
+ */
+ public void removeChildDescriptor(IProblemPreference info) {
+ hash.remove(info.getKey());
+ }
+
+ /**
+ * @return size of the map
+ */
+ public int size() {
+ return hash.size();
+ }
+
+ /**
+ * Clears the map
+ */
+ public void clear() {
+ hash.clear();
+ }
+
+ @Override
+ public String toString() {
+ return hash.values().toString();
+ }
+
+ /**
+ * Value of this preference is a map key=>value of child preferences.
+ * Modifying this returned map would not change internal state of this
+ * object.
+ */
+ @Override
+ public Object getValue() {
+ LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
+ for (Iterator<IProblemPreference> iterator = hash.values().iterator(); iterator
+ .hasNext();) {
+ IProblemPreference pref = iterator.next();
+ map.put(pref.getKey(), pref.getValue());
+ }
+ return map;
+ }
+
+ /**
+ * Set values for this object child elements. Elements are not present in
+ * this map would be removed.
+ * Preference descriptors for the keys must be set before calling this
+ * method, unless value if instanceof {@link IProblemPreference}.
+ *
+ * @param value - must be Map<String,Object>
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void setValue(Object value) {
+ Map<String, Object> map = (Map<String, Object>) value;
+ LinkedHashMap<String, IProblemPreference> hash2 = (LinkedHashMap<String, IProblemPreference>) hash
+ .clone();
+ hash.clear();
+ for (Iterator<String> iterator = map.keySet().iterator(); iterator
+ .hasNext();) {
+ String key = iterator.next();
+ Object value2 = map.get(key);
+ if (value2 instanceof IProblemPreference) {
+ hash.put(key, (IProblemPreference) value2);
+ } else {
+ setChildValue(key, value2);
+ IProblemPreference pref = hash2.get(key);
+ pref.setValue(value2);
+ hash.put(key, pref);
+ }
+ }
+ }
+}