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.woody.flow.javascript;
019:
020: import org.apache.cocoon.woody.formmodel.AggregateField;
021: import org.apache.cocoon.woody.formmodel.BooleanField;
022: import org.apache.cocoon.woody.formmodel.Field;
023: import org.apache.cocoon.woody.formmodel.MultiValueField;
024: import org.apache.cocoon.woody.formmodel.Output;
025: import org.apache.cocoon.woody.formmodel.Repeater;
026: import org.apache.cocoon.woody.formmodel.Widget;
027: import org.mozilla.javascript.Context;
028: import org.mozilla.javascript.NativeArray;
029: import org.mozilla.javascript.Scriptable;
030: import org.mozilla.javascript.ScriptableObject;
031: import org.mozilla.javascript.Undefined;
032: import org.mozilla.javascript.Wrapper;
033:
034: /**
035: * @version $Id: ScriptableWidget.java 487681 2006-12-15 21:55:33Z joerg $
036: *
037: */
038: public class ScriptableWidget extends ScriptableObject {
039:
040: Widget delegate;
041:
042: public String getClassName() {
043: return "Widget";
044: }
045:
046: public ScriptableWidget() {
047: }
048:
049: public ScriptableWidget(Object widget) {
050: this .delegate = (Widget) unwrap(widget);
051: }
052:
053: private Object unwrap(Object obj) {
054: if (obj == Undefined.instance) {
055: return null;
056: }
057: if (obj instanceof Wrapper) {
058: return ((Wrapper) obj).unwrap();
059: }
060: return obj;
061: }
062:
063: private ScriptableWidget wrap(Widget w) {
064: ScriptableWidget result = new ScriptableWidget(w);
065: result.setPrototype(getClassPrototype(this , "Widget"));
066: result.setParentScope(getParentScope());
067: return result;
068: }
069:
070: public boolean has(String id, Scriptable start) {
071: if (delegate instanceof Repeater) {
072: if (id.equals("length")) {
073: return true;
074: }
075: } else if (delegate instanceof MultiValueField) {
076: if (id.equals("length")) {
077: return true;
078: }
079: } else if (delegate != null) {
080: Widget sub = delegate.getWidget(id);
081: if (sub != null) {
082: return true;
083: }
084: }
085: return super .has(id, start);
086: }
087:
088: public boolean has(int index, Scriptable start) {
089: if (delegate instanceof Repeater) {
090: Repeater repeater = (Repeater) delegate;
091: return index >= 0 && index < repeater.getSize();
092: }
093: if (delegate instanceof MultiValueField) {
094: Object[] values = (Object[]) delegate.getValue();
095: return index >= 0 && index < values.length;
096: }
097: return super .has(index, start);
098: }
099:
100: public Object get(String id, Scriptable start) {
101: if (delegate instanceof Repeater) {
102: if (id.equals("length")) {
103: Repeater repeater = (Repeater) delegate;
104: return new Integer(repeater.getSize());
105: }
106: } else if (delegate instanceof MultiValueField) {
107: if (id.equals("length")) {
108: Object[] values = (Object[]) delegate.getValue();
109: return new Integer(values.length);
110: }
111: } else if (delegate != null) {
112: Widget sub = delegate.getWidget(id);
113: if (sub != null) {
114: if (sub instanceof Field || sub instanceof BooleanField
115: || sub instanceof AggregateField
116: || sub instanceof Output) {
117: return sub.getValue();
118: }
119: return wrap(sub);
120: }
121: }
122: return super .get(id, start);
123: }
124:
125: public Object get(int index, Scriptable start) {
126: if (delegate instanceof Repeater) {
127: Repeater repeater = (Repeater) delegate;
128: if (index >= 0) {
129: while (index >= repeater.getSize()) {
130: repeater.addRow();
131: }
132: return wrap(repeater.getRow(index));
133: }
134: }
135: if (delegate instanceof MultiValueField) {
136: Object[] values = (Object[]) delegate.getValue();
137: if (index >= 0 && index < values.length) {
138: return values[index];
139: } else {
140: return NOT_FOUND;
141: }
142: }
143: return super .get(index, start);
144: }
145:
146: public void delete(String id) {
147: super .delete(id);
148: }
149:
150: public void delete(int index) {
151: if (delegate instanceof Repeater) {
152: Repeater repeater = (Repeater) delegate;
153: if (index >= 0 && index < repeater.getSize()) {
154: repeater.removeRow(index);
155: return;
156: }
157: } else if (delegate instanceof MultiValueField) {
158: MultiValueField field = (MultiValueField) delegate;
159: Object[] values = (Object[]) field.getValue();
160: if (values != null && values.length > index) {
161: Object[] newValues = new Object[values.length - 1];
162: int i;
163: for (i = 0; i < index; i++) {
164: newValues[i] = values[i];
165: }
166: i++;
167: for (; i < values.length; i++) {
168: newValues[i - 1] = values[i];
169: }
170: field.setValues(newValues);
171: }
172: return;
173: }
174: super .delete(index);
175: }
176:
177: public void put(String id, Scriptable start, Object value) {
178: if (delegate instanceof Repeater) {
179: if (id.equals("length")) {
180: int len = (int) Context.toNumber(value);
181: Repeater repeater = (Repeater) delegate;
182: int size = repeater.getSize();
183: if (size > len) {
184: while (repeater.getSize() > len) {
185: repeater.removeRow(repeater.getSize() - 1);
186: }
187: } else {
188: for (int i = size; i < len; ++i) {
189: repeater.addRow();
190: }
191: }
192: }
193: } else if (delegate != null) {
194: Widget sub = delegate.getWidget(id);
195: if (sub instanceof Field) {
196: Field field = (Field) sub;
197: value = unwrap(value);
198: if (value instanceof Double) {
199: // make woody accept a JS Number
200: Class typeClass = field.getFieldDefinition()
201: .getDatatype().getTypeClass();
202: if (typeClass == long.class
203: || typeClass == Long.class) {
204: value = new Long(((Number) value).longValue());
205: } else if (typeClass == int.class
206: || typeClass == Integer.class) {
207: value = new Integer(((Number) value).intValue());
208: } else if (typeClass == float.class
209: || typeClass == Float.class) {
210: value = new Float(((Number) value).floatValue());
211: } else if (typeClass == short.class
212: || typeClass == Short.class) {
213: value = new Short(((Number) value).shortValue());
214: }
215: }
216: field.setValue(value);
217: return;
218: } else if (sub instanceof BooleanField) {
219: BooleanField field = (BooleanField) sub;
220: value = unwrap(value);
221: field.setValue(value);
222: } else if (sub instanceof Output) {
223: Output field = (Output) sub;
224: value = unwrap(value);
225: field.setValue(value);
226: } else if (sub instanceof Repeater) {
227: Repeater repeater = (Repeater) sub;
228: if (value instanceof NativeArray) {
229: NativeArray arr = (NativeArray) value;
230: Object length = getProperty(arr, "length");
231: int len = ((Number) length).intValue();
232: for (int i = repeater.getSize(); i >= len; --i) {
233: repeater.removeRow(i);
234: }
235: for (int i = 0; i < len; i++) {
236: Object elemValue = getProperty(arr, i);
237: if (elemValue instanceof Scriptable) {
238: Scriptable s = (Scriptable) elemValue;
239: Object[] ids = s.getIds();
240: ScriptableWidget wid = wrap(repeater
241: .getRow(i));
242: for (int j = 0; j < ids.length; j++) {
243: String idStr = ids[j].toString();
244: wid.put(idStr, wid, getProperty(s,
245: idStr));
246: }
247: }
248: }
249: return;
250: }
251: } else if (sub instanceof MultiValueField) {
252: MultiValueField field = (MultiValueField) sub;
253: Object[] values = null;
254: if (value instanceof NativeArray) {
255: NativeArray arr = (NativeArray) value;
256: Object length = getProperty(arr, "length");
257: int len = ((Number) length).intValue();
258: values = new Object[len];
259: for (int i = 0; i < len; i++) {
260: Object elemValue = getProperty(arr, i);
261: values[i] = unwrap(elemValue);
262: }
263: } else if (value instanceof Object[]) {
264: values = (Object[]) value;
265: }
266: field.setValues(values);
267: } else {
268: if (value instanceof Scriptable) {
269: Scriptable s = (Scriptable) value;
270: Object[] ids = s.getIds();
271: ScriptableWidget wid = wrap(sub);
272: for (int j = 0; j < ids.length; j++) {
273: String idStr = ids[j].toString();
274: wid.put(idStr, wid, getProperty(s, idStr));
275: }
276: return;
277: }
278: }
279: }
280: super .put(id, start, value);
281: }
282:
283: public String jsGet_id() {
284: return delegate.getId();
285: }
286:
287: public Object jsGet_parent() {
288: if (delegate != null) {
289: return wrap(delegate.getParent());
290: }
291: return Undefined.instance;
292: }
293:
294: public boolean jsFunction_equals(Object other) {
295: if (other instanceof ScriptableWidget) {
296: ScriptableWidget otherWidget = (ScriptableWidget) other;
297: return delegate.equals(otherWidget.delegate);
298: }
299: return false;
300: }
301:
302: public void jsFunction_remove(int index) {
303: delete(index);
304: }
305:
306: }
|