/******************************************************************************* * 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) { if (str.length()==0) return; 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()]); } }