| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.cocoon.forms.flow.javascript; |
| import org.apache.cocoon.forms.formmodel.AggregateField; |
| import org.apache.cocoon.forms.formmodel.BooleanField; |
| import org.apache.cocoon.forms.formmodel.Field; |
| import org.apache.cocoon.forms.formmodel.MultiValueField; |
| import org.apache.cocoon.forms.formmodel.Output; |
| import org.apache.cocoon.forms.formmodel.Repeater; |
| import org.apache.cocoon.forms.formmodel.Widget; |
| import org.apache.cocoon.forms.formmodel.WidgetState; |
| import org.mozilla.javascript.Context; |
| import org.mozilla.javascript.NativeArray; |
| import org.mozilla.javascript.Scriptable; |
| import org.mozilla.javascript.ScriptableObject; |
| import org.mozilla.javascript.Undefined; |
| import org.mozilla.javascript.Wrapper; |
| |
| import java.util.Collection; |
| |
| /** |
| * @version $Id$ |
| * |
| */ |
| public class ScriptableWidget extends ScriptableObject { |
| |
| Widget delegate; |
| |
| public String getClassName() { |
| return "Widget"; |
| } |
| |
| public ScriptableWidget() { |
| } |
| |
| public ScriptableWidget(Object widget) { |
| this.delegate = (Widget)unwrap(widget); |
| } |
| |
| private Object unwrap(Object obj) { |
| if (obj == Undefined.instance) { |
| return null; |
| } |
| if (obj instanceof Wrapper) { |
| return ((Wrapper)obj).unwrap(); |
| } |
| return obj; |
| } |
| |
| private ScriptableWidget wrap(Widget w) { |
| ScriptableWidget result = new ScriptableWidget(w); |
| result.setPrototype(getClassPrototype(this, "Widget")); |
| result.setParentScope(getParentScope()); |
| return result; |
| } |
| |
| public boolean has(String id, Scriptable start) { |
| if (delegate instanceof Repeater) { |
| if (id.equals("length")) { |
| return true; |
| } |
| } else if (delegate instanceof MultiValueField) { |
| if (id.equals("length")) { |
| return true; |
| } |
| } else if (delegate != null) { |
| Widget sub = delegate.lookupWidget(id); |
| if (sub != null) { |
| return true; |
| } |
| } |
| return super.has(id, start); |
| } |
| |
| public boolean has(int index, Scriptable start) { |
| if (delegate instanceof Repeater) { |
| Repeater repeater = (Repeater)delegate; |
| return index >= 0 && index < repeater.getSize(); |
| } |
| if (delegate instanceof MultiValueField) { |
| Object[] values = (Object[])delegate.getValue(); |
| return index >= 0 && index < values.length; |
| } |
| return super.has(index, start); |
| } |
| |
| public Object get(String id, Scriptable start) { |
| if (delegate instanceof Repeater) { |
| if (id.equals("length")) { |
| Repeater repeater = (Repeater)delegate; |
| return new Integer(repeater.getSize()); |
| } |
| } else if (delegate instanceof MultiValueField) { |
| if (id.equals("length")) { |
| Object[] values = (Object[])delegate.getValue(); |
| return new Integer(values.length); |
| } |
| } else if (delegate != null) { |
| Widget sub = delegate.lookupWidget(id); |
| if (sub != null) { |
| if (sub instanceof Field || |
| sub instanceof BooleanField || |
| sub instanceof AggregateField || |
| sub instanceof Output) { |
| return sub.getValue(); |
| } |
| return wrap(sub); |
| } |
| } |
| return super.get(id, start); |
| } |
| |
| public Object get(int index, Scriptable start) { |
| if (delegate instanceof Repeater) { |
| Repeater repeater = (Repeater)delegate; |
| if (index >= 0) { |
| while (index >= repeater.getSize()) { |
| repeater.addRow(); |
| } |
| return wrap(repeater.getRow(index)); |
| } |
| } |
| if (delegate instanceof MultiValueField) { |
| Object[] values = (Object[])delegate.getValue(); |
| if (index >= 0 && index < values.length) { |
| return values[index]; |
| } else { |
| return NOT_FOUND; |
| } |
| } |
| return super.get(index, start); |
| } |
| |
| public void delete(int index) { |
| if (delegate instanceof Repeater) { |
| Repeater repeater = (Repeater)delegate; |
| if (index >= 0 && index < repeater.getSize()) { |
| repeater.removeRow(index); |
| return; |
| } |
| } else if (delegate instanceof MultiValueField) { |
| MultiValueField field = (MultiValueField)delegate; |
| Object[] values = (Object[])field.getValue(); |
| if (values != null && values.length > index) { |
| Object[] newValues = new Object[values.length-1]; |
| int i; |
| for (i = 0; i < index; i++) { |
| newValues[i] = values[i]; |
| } |
| i++; |
| for (;i < values.length;i++) { |
| newValues[i-1] = values[i]; |
| } |
| field.setValues(newValues); |
| } |
| return; |
| } |
| super.delete(index); |
| } |
| |
| public void put(String id, Scriptable start, Object value) { |
| if (delegate instanceof Repeater) { |
| if (id.equals("length")) { |
| int len = (int)Context.toNumber(value); |
| Repeater repeater = (Repeater)delegate; |
| int size = repeater.getSize(); |
| if (size > len) { |
| while (repeater.getSize() > len) { |
| repeater.removeRow(repeater.getSize() -1); |
| } |
| } else { |
| for (int i = size; i < len; ++i) { |
| repeater.addRow(); |
| } |
| } |
| } |
| } else if (delegate != null) { |
| Widget sub = delegate.lookupWidget(id); |
| if (sub instanceof Field) { |
| Field field = (Field)sub; |
| value = unwrap(value); |
| if (value instanceof Double) { |
| // make cforms accept a JS Number |
| Class typeClass = |
| field.getFieldDefinition().getDatatype().getTypeClass(); |
| if (typeClass == long.class || typeClass == Long.class) { |
| value = new Long(((Number)value).longValue()); |
| } else if (typeClass == int.class || typeClass == Integer.class) { |
| value = new Integer(((Number)value).intValue()); |
| } else if (typeClass == float.class || typeClass == Float.class) { |
| value = new Float(((Number)value).floatValue()); |
| } else if (typeClass == short.class || typeClass == Short.class) { |
| value = new Short(((Number)value).shortValue()); |
| } |
| } |
| field.setValue(value); |
| return; |
| } else if (sub instanceof BooleanField) { |
| BooleanField field = (BooleanField)sub; |
| value = unwrap(value); |
| field.setValue(value); |
| } else if (sub instanceof Output) { |
| Output field = (Output)sub; |
| value = unwrap(value); |
| field.setValue(value); |
| } else if (sub instanceof Repeater) { |
| Repeater repeater = (Repeater)sub; |
| if (value instanceof NativeArray) { |
| NativeArray arr = (NativeArray)value; |
| Object length = getProperty(arr, "length"); |
| int len = ((Number)length).intValue(); |
| for (int i = repeater.getSize(); i >= len; --i) { |
| repeater.removeRow(i); |
| } |
| for (int i = 0; i < len; i++) { |
| Object elemValue = getProperty(arr, i); |
| if (elemValue instanceof Scriptable) { |
| Scriptable s = (Scriptable)elemValue; |
| Object[] ids = s.getIds(); |
| ScriptableWidget wid = wrap(repeater.getRow(i)); |
| for (int j = 0; j < ids.length; j++) { |
| String idStr = ids[j].toString(); |
| wid.put(idStr, wid, getProperty(s, idStr)); |
| } |
| } |
| } |
| return; |
| } |
| } else if (sub instanceof MultiValueField) { |
| MultiValueField field = (MultiValueField)sub; |
| Object[] values = null; |
| if (value instanceof NativeArray) { |
| NativeArray arr = (NativeArray)value; |
| Object length = getProperty(arr, "length"); |
| int len = ((Number)length).intValue(); |
| values = new Object[len]; |
| for (int i = 0; i < len; i++) { |
| Object elemValue = getProperty(arr, i); |
| values[i] = unwrap(elemValue); |
| } |
| } else if (value instanceof Object[]) { |
| values = (Object[])value; |
| } else if (value instanceof Collection ) { |
| values = ((Collection)value).toArray(); |
| } |
| field.setValues(values); |
| } else { |
| if (value instanceof Scriptable) { |
| Scriptable s = (Scriptable)value; |
| Object[] ids = s.getIds(); |
| ScriptableWidget wid = wrap(sub); |
| for (int j = 0; j < ids.length; j++) { |
| String idStr = ids[j].toString(); |
| wid.put(idStr, wid, getProperty(s, idStr)); |
| } |
| return; |
| } |
| } |
| } |
| super.put(id, start, value); |
| } |
| |
| public String jsGet_id() { |
| return delegate.getId(); |
| } |
| |
| public WidgetState jsGet_state() { |
| return delegate.getState(); |
| } |
| |
| public void jsSet_state(Object stateObj) { |
| Object obj = unwrap(stateObj); |
| WidgetState state = null; |
| |
| if (obj instanceof String) { |
| state = WidgetState.stateForName((String)obj); |
| } else if (obj instanceof WidgetState) { |
| state = (WidgetState)obj; |
| } |
| |
| if (state == null) { |
| throw new IllegalArgumentException("Invalid value for widgetState " + stateObj); |
| } |
| |
| delegate.setState(state); |
| } |
| |
| public Object jsGet_parent() { |
| if (delegate != null) { |
| return wrap(delegate.getParent()); |
| } |
| return Undefined.instance; |
| } |
| |
| public boolean jsFunction_equals(Object other) { |
| if (other instanceof ScriptableWidget) { |
| ScriptableWidget otherWidget = (ScriptableWidget)other; |
| return delegate.equals(otherWidget.delegate); |
| } |
| return false; |
| } |
| |
| public void jsFunction_remove(int index) { |
| delete(index); |
| } |
| |
| } |