001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.cocoon.forms.flow.javascript;
019:
020: import org.apache.cocoon.forms.formmodel.AggregateField;
021: import org.apache.cocoon.forms.formmodel.BooleanField;
022: import org.apache.cocoon.forms.formmodel.Field;
023: import org.apache.cocoon.forms.formmodel.MultiValueField;
024: import org.apache.cocoon.forms.formmodel.Output;
025: import org.apache.cocoon.forms.formmodel.Repeater;
026: import org.apache.cocoon.forms.formmodel.Widget;
027: import org.apache.cocoon.forms.formmodel.WidgetState;
028: import org.mozilla.javascript.Context;
029: import org.mozilla.javascript.NativeArray;
030: import org.mozilla.javascript.Scriptable;
031: import org.mozilla.javascript.ScriptableObject;
032: import org.mozilla.javascript.Undefined;
033: import org.mozilla.javascript.Wrapper;
034:
035: import java.util.Collection;
036:
037: /**
038: * @version $Id: ScriptableWidget.java 449149 2006-09-23 03:58:05Z crossley $
039: *
040: */
041: public class ScriptableWidget extends ScriptableObject {
042:
043: Widget delegate;
044:
045: public String getClassName() {
046: return "Widget";
047: }
048:
049: public ScriptableWidget() {
050: }
051:
052: public ScriptableWidget(Object widget) {
053: this .delegate = (Widget) unwrap(widget);
054: }
055:
056: private Object unwrap(Object obj) {
057: if (obj == Undefined.instance) {
058: return null;
059: }
060: if (obj instanceof Wrapper) {
061: return ((Wrapper) obj).unwrap();
062: }
063: return obj;
064: }
065:
066: private ScriptableWidget wrap(Widget w) {
067: ScriptableWidget result = new ScriptableWidget(w);
068: result.setPrototype(getClassPrototype(this , "Widget"));
069: result.setParentScope(getParentScope());
070: return result;
071: }
072:
073: public boolean has(String id, Scriptable start) {
074: if (delegate instanceof Repeater) {
075: if (id.equals("length")) {
076: return true;
077: }
078: } else if (delegate instanceof MultiValueField) {
079: if (id.equals("length")) {
080: return true;
081: }
082: } else if (delegate != null) {
083: Widget sub = delegate.lookupWidget(id);
084: if (sub != null) {
085: return true;
086: }
087: }
088: return super .has(id, start);
089: }
090:
091: public boolean has(int index, Scriptable start) {
092: if (delegate instanceof Repeater) {
093: Repeater repeater = (Repeater) delegate;
094: return index >= 0 && index < repeater.getSize();
095: }
096: if (delegate instanceof MultiValueField) {
097: Object[] values = (Object[]) delegate.getValue();
098: return index >= 0 && index < values.length;
099: }
100: return super .has(index, start);
101: }
102:
103: public Object get(String id, Scriptable start) {
104: if (delegate instanceof Repeater) {
105: if (id.equals("length")) {
106: Repeater repeater = (Repeater) delegate;
107: return new Integer(repeater.getSize());
108: }
109: } else if (delegate instanceof MultiValueField) {
110: if (id.equals("length")) {
111: Object[] values = (Object[]) delegate.getValue();
112: return new Integer(values.length);
113: }
114: } else if (delegate != null) {
115: Widget sub = delegate.lookupWidget(id);
116: if (sub != null) {
117: if (sub instanceof Field || sub instanceof BooleanField
118: || sub instanceof AggregateField
119: || sub instanceof Output) {
120: return sub.getValue();
121: }
122: return wrap(sub);
123: }
124: }
125: return super .get(id, start);
126: }
127:
128: public Object get(int index, Scriptable start) {
129: if (delegate instanceof Repeater) {
130: Repeater repeater = (Repeater) delegate;
131: if (index >= 0) {
132: while (index >= repeater.getSize()) {
133: repeater.addRow();
134: }
135: return wrap(repeater.getRow(index));
136: }
137: }
138: if (delegate instanceof MultiValueField) {
139: Object[] values = (Object[]) delegate.getValue();
140: if (index >= 0 && index < values.length) {
141: return values[index];
142: } else {
143: return NOT_FOUND;
144: }
145: }
146: return super .get(index, start);
147: }
148:
149: public void delete(int index) {
150: if (delegate instanceof Repeater) {
151: Repeater repeater = (Repeater) delegate;
152: if (index >= 0 && index < repeater.getSize()) {
153: repeater.removeRow(index);
154: return;
155: }
156: } else if (delegate instanceof MultiValueField) {
157: MultiValueField field = (MultiValueField) delegate;
158: Object[] values = (Object[]) field.getValue();
159: if (values != null && values.length > index) {
160: Object[] newValues = new Object[values.length - 1];
161: int i;
162: for (i = 0; i < index; i++) {
163: newValues[i] = values[i];
164: }
165: i++;
166: for (; i < values.length; i++) {
167: newValues[i - 1] = values[i];
168: }
169: field.setValues(newValues);
170: }
171: return;
172: }
173: super .delete(index);
174: }
175:
176: public void put(String id, Scriptable start, Object value) {
177: if (delegate instanceof Repeater) {
178: if (id.equals("length")) {
179: int len = (int) Context.toNumber(value);
180: Repeater repeater = (Repeater) delegate;
181: int size = repeater.getSize();
182: if (size > len) {
183: while (repeater.getSize() > len) {
184: repeater.removeRow(repeater.getSize() - 1);
185: }
186: } else {
187: for (int i = size; i < len; ++i) {
188: repeater.addRow();
189: }
190: }
191: }
192: } else if (delegate != null) {
193: Widget sub = delegate.lookupWidget(id);
194: if (sub instanceof Field) {
195: Field field = (Field) sub;
196: value = unwrap(value);
197: if (value instanceof Double) {
198: // make cforms accept a JS Number
199: Class typeClass = field.getFieldDefinition()
200: .getDatatype().getTypeClass();
201: if (typeClass == long.class
202: || typeClass == Long.class) {
203: value = new Long(((Number) value).longValue());
204: } else if (typeClass == int.class
205: || typeClass == Integer.class) {
206: value = new Integer(((Number) value).intValue());
207: } else if (typeClass == float.class
208: || typeClass == Float.class) {
209: value = new Float(((Number) value).floatValue());
210: } else if (typeClass == short.class
211: || typeClass == Short.class) {
212: value = new Short(((Number) value).shortValue());
213: }
214: }
215: field.setValue(value);
216: return;
217: } else if (sub instanceof BooleanField) {
218: BooleanField field = (BooleanField) sub;
219: value = unwrap(value);
220: field.setValue(value);
221: } else if (sub instanceof Output) {
222: Output field = (Output) sub;
223: value = unwrap(value);
224: field.setValue(value);
225: } else if (sub instanceof Repeater) {
226: Repeater repeater = (Repeater) sub;
227: if (value instanceof NativeArray) {
228: NativeArray arr = (NativeArray) value;
229: Object length = getProperty(arr, "length");
230: int len = ((Number) length).intValue();
231: for (int i = repeater.getSize(); i >= len; --i) {
232: repeater.removeRow(i);
233: }
234: for (int i = 0; i < len; i++) {
235: Object elemValue = getProperty(arr, i);
236: if (elemValue instanceof Scriptable) {
237: Scriptable s = (Scriptable) elemValue;
238: Object[] ids = s.getIds();
239: ScriptableWidget wid = wrap(repeater
240: .getRow(i));
241: for (int j = 0; j < ids.length; j++) {
242: String idStr = ids[j].toString();
243: wid.put(idStr, wid, getProperty(s,
244: idStr));
245: }
246: }
247: }
248: return;
249: }
250: } else if (sub instanceof MultiValueField) {
251: MultiValueField field = (MultiValueField) sub;
252: Object[] values = null;
253: if (value instanceof NativeArray) {
254: NativeArray arr = (NativeArray) value;
255: Object length = getProperty(arr, "length");
256: int len = ((Number) length).intValue();
257: values = new Object[len];
258: for (int i = 0; i < len; i++) {
259: Object elemValue = getProperty(arr, i);
260: values[i] = unwrap(elemValue);
261: }
262: } else if (value instanceof Object[]) {
263: values = (Object[]) value;
264: } else if (value instanceof Collection) {
265: values = ((Collection) value).toArray();
266: }
267: field.setValues(values);
268: } else {
269: if (value instanceof Scriptable) {
270: Scriptable s = (Scriptable) value;
271: Object[] ids = s.getIds();
272: ScriptableWidget wid = wrap(sub);
273: for (int j = 0; j < ids.length; j++) {
274: String idStr = ids[j].toString();
275: wid.put(idStr, wid, getProperty(s, idStr));
276: }
277: return;
278: }
279: }
280: }
281: super .put(id, start, value);
282: }
283:
284: public String jsGet_id() {
285: return delegate.getId();
286: }
287:
288: public WidgetState jsGet_state() {
289: return delegate.getState();
290: }
291:
292: public void jsSet_state(Object stateObj) {
293: Object obj = unwrap(stateObj);
294: WidgetState state = null;
295:
296: if (obj instanceof String) {
297: state = WidgetState.stateForName((String) obj);
298: } else if (obj instanceof WidgetState) {
299: state = (WidgetState) obj;
300: }
301:
302: if (state == null) {
303: throw new IllegalArgumentException(
304: "Invalid value for widgetState " + stateObj);
305: }
306:
307: delegate.setState(state);
308: }
309:
310: public Object jsGet_parent() {
311: if (delegate != null) {
312: return wrap(delegate.getParent());
313: }
314: return Undefined.instance;
315: }
316:
317: public boolean jsFunction_equals(Object other) {
318: if (other instanceof ScriptableWidget) {
319: ScriptableWidget otherWidget = (ScriptableWidget) other;
320: return delegate.equals(otherWidget.delegate);
321: }
322: return false;
323: }
324:
325: public void jsFunction_remove(int index) {
326: delete(index);
327: }
328:
329: }
|