/** * */ package org.freeplane.plugin.script.proxy; import groovy.lang.Closure; import groovy.lang.MissingMethodException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Vector; import org.freeplane.features.attribute.Attribute; import org.freeplane.features.attribute.AttributeController; import org.freeplane.features.attribute.NodeAttributeTableModel; import org.freeplane.features.attribute.mindmapmode.MAttributeController; import org.freeplane.features.format.IFormattedObject; import org.freeplane.features.map.NodeModel; import org.freeplane.plugin.script.ScriptContext; class AttributesProxy extends AbstractProxy<NodeModel> implements Proxy.Attributes { AttributesProxy(final NodeModel delegate, final ScriptContext scriptContext) { super(delegate, scriptContext); } @Deprecated public Object get(final String name) { return getFirst(name); } public Object getFirst(final String name) { final int index = findAttribute(name); if (index == -1) { return null; } final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); return attributeTableModel.getAttribute(index).getValue(); } public List<Object> getAll(final String name) { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return Collections.emptyList(); } final ArrayList<Object> result = new ArrayList<Object>(); for (final Attribute attribute : attributeTableModel.getAttributes()) { if (attribute.getName().equals(name)) { result.add(attribute.getValue()); } } return result; } public List<String> getNames() { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return Collections.emptyList(); } final ArrayList<String> result = new ArrayList<String>(attributeTableModel.getRowCount()); for (final Attribute a : attributeTableModel.getAttributes()) { result.add(a.getName()); } return result; } @Deprecated public List<String> getAttributeNames() { return getNames(); } public List<? extends Convertible> getValues() { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return Collections.emptyList(); } final ArrayList<Convertible> result = new ArrayList<Convertible>(attributeTableModel.getRowCount()); for (final Attribute a : attributeTableModel.getAttributes()) { result.add(ProxyUtils.attributeValueToConvertible(getDelegate(), getScriptContext(), a.getValue())); } return result; } public Map<String, Object> getMap() { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return Collections.emptyMap(); } final LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(attributeTableModel.getRowCount()); for (final Attribute a : attributeTableModel.getAttributes()) { result.put(a.getName(), a.getValue()); } return result; } public List<? extends Convertible> findValues(Closure<Boolean> closure) { try { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return Collections.emptyList(); } final ArrayList<Convertible> result = new ArrayList<Convertible>( attributeTableModel.getRowCount()); for (final Attribute a : attributeTableModel.getAttributes()) { final Object bool = closure.call(new Object[] { a.getName(), a.getValue() }); if (result == null) { throw new RuntimeException("findValues(): closure returned null instead of boolean/Boolean"); } if ((Boolean) bool) result.add(ProxyUtils.attributeValueToConvertible(getDelegate(), getScriptContext(), a.getValue())); } return result; } catch (final MissingMethodException e) { throw new RuntimeException("findValues(): closure needs to accept two args and must return boolean/Boolean" + " e.g. findValues{k,v -> k != 'TOTAL'}", e); } catch (final ClassCastException e) { throw new RuntimeException("findValues(): closure returned " + e.getMessage() + " instead of boolean/Boolean"); } } public Object get(final int index) { return getAndCheckNodeAttributeTableModelForIndex(index, "get:").getValue(index); } private NodeAttributeTableModel getAndCheckNodeAttributeTableModelForIndex(final int index, String errorPrefix) { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { throw new IndexOutOfBoundsException(errorPrefix + index); } return attributeTableModel; } public String getKey(int index) { return getAndCheckNodeAttributeTableModelForIndex(index, "getKey:").getAttribute(index).getName(); } public void set(final int index, final Object value) { final NodeAttributeTableModel attributeTableModel = getAndCheckNodeAttributeTableModelForIndex(index, "set1:"); String oldPattern = getOldValueFormatPattern(attributeTableModel, index); getAttributeController().performSetValueAt(attributeTableModel, ProxyUtils.transformObject(value, oldPattern), index, 1); } public void set(final int index, final String name, final Object value) { final NodeAttributeTableModel attributeTableModel = getAndCheckNodeAttributeTableModelForIndex(index, "set2:"); String oldPattern = getOldValueFormatPattern(attributeTableModel, index); getAttributeController().setAttribute(getDelegate(), index, new Attribute(name, ProxyUtils.transformObject(value, oldPattern))); } public int findFirst(final String name) { final List<String> attributeNames = getAttributeNames(); for (int i = 0; i < attributeNames.size(); i++) { if (attributeNames.get(i).equals(name)) { return i; } } return -1; } @Deprecated public int findAttribute(final String name) { return findFirst(name); } @Deprecated public boolean remove(final String name) { final int index = findFirst(name); if (index == -1) { return false; } getAttributeController().removeAttribute(getDelegate(), index); return true; } public boolean removeAll(final String name) { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return false; } final ArrayList<Integer> toRemove = new ArrayList<Integer>(); final Vector<Attribute> attributes = attributeTableModel.getAttributes(); for (int i = 0; i < attributes.size(); ++i) { if (attributes.get(i).getName().equals(name)) { toRemove.add(i); } } // do it backwards in order not to invalidate the first indexes for (int i = toRemove.size() - 1; i >= 0; --i) { getAttributeController().removeAttribute(getDelegate(), toRemove.get(i)); } return !toRemove.isEmpty(); } public void remove(final int index) { getAndCheckNodeAttributeTableModelForIndex(index, "remove:"); getAttributeController().removeAttribute(getDelegate(), index); } public void clear() { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); final int size = attributeTableModel.getRowCount(); for (int i = size - 1; i >= 0; i--) { getAttributeController().removeAttribute(getDelegate(), i); } } public void set(final String name, final Object value) { final int index = findFirst(name); if (index == -1) { final Attribute attribute = new Attribute(name, ProxyUtils.transformObject(value, null)); getAttributeController().addAttribute(getDelegate(), attribute); } else { final String oldPattern = getOldValueFormatPattern(getNodeAttributeTableModel(), index); final Attribute attribute = new Attribute(name, ProxyUtils.transformObject(value, oldPattern)); getAttributeController().setAttribute(getDelegate(), index, attribute); } } private String getOldValueFormatPattern(NodeAttributeTableModel attributeTableModel, int index) { final Object value = attributeTableModel.getAttribute(index).getValue(); return (value instanceof IFormattedObject) ? ((IFormattedObject) value).getPattern() : null; } public void add(final String name, final Object value) { final Attribute attribute = new Attribute(name, ProxyUtils.transformObject(value, null)); getAttributeController().addAttribute(getDelegate(), attribute); } public int size() { final NodeAttributeTableModel attributeTableModel = getNodeAttributeTableModel(); if (attributeTableModel == null) { return 0; } return attributeTableModel.getRowCount(); } public boolean isEmpty() { return size() == 0; } private MAttributeController getAttributeController() { return (MAttributeController) AttributeController.getController(); } private NodeAttributeTableModel getNodeAttributeTableModel() { return NodeAttributeTableModel.getModel(getDelegate()); } /** make <code>if (node.attributes) println "has attributes"</code> work. */ public boolean asBoolean() { return !isEmpty(); } }