/******************************************************************************* * Copyright (c) 2017 PDT Extension Group 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: * PDT Extension Group - initial API and implementation * Kaloyan Raev - [501269] externalize strings *******************************************************************************/ package org.eclipse.php.composer.api.objects; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.php.composer.api.collection.JsonArray; import org.eclipse.php.composer.api.entities.JsonEntity; import org.eclipse.php.composer.api.entities.JsonValue; /** * Represents a script entry in the scripts entity of a composer package. */ public class Script extends JsonObject { /** * Used as a wrapper for string values, since Script objects (i.e. events) * can hold duplicate string values (i.e. handler values). The HandlerValue * wrapper class holds a handler value but also its index (i.e. position) * when stored in the "handlers" array of a Script object. The index * information could be seen as redundant, but it's used (and necessary) for * the TreeViewer in the ScriptsSection class to compare handler values * retrieved by ScriptsController instances because TreeViewers don't * support duplicate (string) values. To make it simple, the HandlerValue * class is used to handle only unique values (per Script object) in * TreeViewers. * * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=510095 */ public static class HandlerValue extends JsonValue { private transient int index = 0; public HandlerValue(String value) { super(value); } public void setIndex(int index) { this.index = index; } public void setValue(String value) { this.value = value; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof HandlerValue)) { return false; } HandlerValue other = (HandlerValue) obj; if (index != other.index) { return false; } String s1 = getAsString(); String s2 = other.getAsString(); if (s1 != null) { return s1.equals(s2); } return s1 == s2; } public HandlerValue clone() { HandlerValue clone = new HandlerValue(getAsString()); clone.setIndex(index); return clone; } } private transient JsonArray handlers = new JsonArray(); public Script() { super(); listen(); handlers.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { firePropertyChange(getScript() + "." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); //$NON-NLS-1$ } }); } public Script(String scriptname, HandlerValue handler) { this(); setScript(scriptname); add(handler); } @Override protected Object buildJson() { try { Method mtd = JsonEntity.class.getDeclaredMethod("buildJson"); //$NON-NLS-1$ return mtd.invoke(handlers); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected List<String> getOwnProperties() { String[] props = new String[] { "handlers" }; //$NON-NLS-1$ List<String> list = new ArrayList<String>(Arrays.asList(props)); list.addAll(super.getOwnProperties()); return list; } /** * Returns the name. * * @return the name */ public String getScript() { return getAsString("script"); //$NON-NLS-1$ } /** * Sets the name. * * @param name * the name to set */ public void setScript(String script) { set("script", script); //$NON-NLS-1$ } public HandlerValue get(int index) throws IndexOutOfBoundsException { return (HandlerValue) handlers.get(index); } public void add(HandlerValue handler) { handlers.add(handler); handler.setIndex(handlers.size() - 1); } public void add(int index, HandlerValue handler) throws IndexOutOfBoundsException { handlers.add(index, handler); handler.setIndex(index); } public void remove(int index) throws IndexOutOfBoundsException { handlers.remove(index); updateIndexes(); } @Override public boolean has(String handler) { throw new UnsupportedOperationException(); } /** * Clears the handlers from this script */ public void clear() { handlers.clear(); } public void addHandlers(JsonArray handlers) { if (handlers == this.handlers) { return; } for (Object handler : handlers) { add((HandlerValue) handler); } } public void addHandlers(Script script) { if (script == this) { return; } addHandlers(script.getHandlers()); } private void updateIndexes() { int index = 0; for (Object handler : handlers) { ((HandlerValue) handler).setIndex(index++); } } public Object getHandlersJsonValue() { return getJsonValue(handlers); } /** * Returns the handler and if there are more than one, returns the first * one. * * @return the version */ public HandlerValue getFirst() { return (HandlerValue) handlers.get(0); } private JsonArray getHandlers() { return handlers; } /** * Removes a handler from the script */ public void remove(HandlerValue handler) { handlers.remove(handler); updateIndexes(); } public void removeAll() { handlers.clear(); } public HandlerValue[] toArray() { return handlers.toArray(new HandlerValue[0]); } /* * (non-Javadoc) * * @see org.eclipse.php.composer.api.entities.AbstractJsonObject#size() */ public int size() { return handlers.size(); } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ public Script clone() { Script clone = new Script(); cloneProperties(clone); clone.clear(); for (Object value : handlers) { // Handlers must also be cloned to not be shared among Script // objects. See ScriptsSection#handleEdit() and condition // "if (cpscript.equals(dialog.getScript())) {...}". clone.add(((HandlerValue) value).clone()); } return clone; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof Script) { Script script = (Script) obj; return script == this || (getScript() == null ? script.getScript() == null : getScript().equals(script.getScript())) && getHandlers().equals(script.getHandlers()); } return false; } }