package net.sourceforge.pmd.eclipse.ui.preferences.editors; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertySource; import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; import net.sourceforge.pmd.eclipse.util.Util; import net.sourceforge.pmd.lang.rule.properties.MethodMultiProperty; import net.sourceforge.pmd.util.ClassUtil; import net.sourceforge.pmd.util.CollectionUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Text; /** * * @author Brian Remedios */ public class MultiMethodEditorFactory extends AbstractMultiValueEditorFactory { public static final MultiMethodEditorFactory instance = new MultiMethodEditorFactory(); private MultiMethodEditorFactory() { } public PropertyDescriptor<?> createDescriptor(String name, String optionalDescription, Control[] otherData) { return new MethodMultiProperty(name, "Method value " + name, new Method[] {MethodEditorFactory.stringLength}, new String[] { "java.lang" }, 0.0f); } public static String[] signaturesFor(Method[] methods) { String[] typeNames = new String[methods.length]; for (int i=0; i<typeNames.length; i++) { typeNames[i] = Util.signatureFor(methods[i], MethodEditorFactory.UnwantedPrefixes); } return typeNames; } private static String asString(Map<String, List<Method>> methodGroups) { if (methodGroups.isEmpty()) return ""; StringBuilder sb = new StringBuilder(); Iterator<Entry<String, List<Method>>> iter = methodGroups.entrySet().iterator(); Entry<String, List<Method>> entry = iter.next(); sb.append(entry.getKey()).append('['); allSignaturesOn(sb, entry.getValue(), ","); sb.append(']'); while (iter.hasNext()) { entry = iter.next(); sb.append(" ").append(entry.getKey()).append('['); allSignaturesOn(sb, entry.getValue(), ", "); sb.append(']'); } return sb.toString(); } private static void allSignaturesOn(StringBuilder sb, List<Method> methods, String delimiter) { sb.append( Util.signatureFor(methods.get(0), MethodEditorFactory.UnwantedPrefixes) ); for (int i=1; i<methods.size(); i++) { sb.append(delimiter).append( Util.signatureFor(methods.get(i), MethodEditorFactory.UnwantedPrefixes) ); } } protected void fillWidget(Text textWidget, PropertyDescriptor<?> desc, PropertySource source) { Method[] values = (Method[])valueFor(source, desc); if (values == null) { textWidget.setText(""); return; } Map<String, List<Method>> methodMap = ClassUtil.asMethodGroupsByTypeName(values); textWidget.setText(values == null ? "" : asString(methodMap)); adjustRendering(source, desc, textWidget); } protected Control addWidget(Composite parent, Object value, PropertyDescriptor<?> desc, PropertySource source) { MethodPicker widget = new MethodPicker(parent, SWT.SINGLE | SWT.BORDER, MethodEditorFactory.UnwantedPrefixes); setValue(widget, value); return widget; } protected void setValue(Control widget, Object value) { Method method = value == null ? null : (Method)value; ((MethodPicker)widget).setMethod(method); } protected void configure(final Text textWidget, final PropertyDescriptor<?> desc, final PropertySource source, final ValueChangeListener listener) { textWidget.setEditable(false); } protected void update(PropertySource source, PropertyDescriptor<?> desc, List<Object> newValues) { source.setProperty((MethodMultiProperty)desc, newValues.toArray(new Method[newValues.size()])); } @Override protected Object addValueIn(Control widget, PropertyDescriptor<?> desc, PropertySource source) { Method newValue = ((MethodPicker)widget).getMethod(); if (newValue == null) return null; Method[] currentValues = (Method[])valueFor(source, desc); Method[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, newValue); if (currentValues.length == newValues.length) return null; // nothing changed source.setProperty((MethodMultiProperty)desc, newValues); return newValue; } protected Object valueFrom(Control valueControl) { // not necessary for this type return null; } }