001: /*
002: * Copyright 2006 Luca Garulli (luca.garulli@assetdata.it)
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.romaframework.aspect.view.echo2.component;
018:
019: import java.lang.reflect.InvocationTargetException;
020: import java.util.ArrayList;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import nextapp.echo2.app.Alignment;
026: import nextapp.echo2.app.Button;
027: import nextapp.echo2.app.Column;
028: import nextapp.echo2.app.Component;
029: import nextapp.echo2.app.ListBox;
030: import nextapp.echo2.app.Row;
031: import nextapp.echo2.app.event.ActionEvent;
032: import nextapp.echo2.app.event.ActionListener;
033: import nextapp.echo2.app.layout.CellLayoutData;
034: import nextapp.echo2.app.layout.ColumnLayoutData;
035: import nextapp.echo2.app.layout.RowLayoutData;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039: import org.romaframework.aspect.view.ViewAspect;
040: import org.romaframework.aspect.view.ViewConstants;
041: import org.romaframework.aspect.view.echo2.PatchHelper;
042: import org.romaframework.aspect.view.echo2.form.EntityFormHelper;
043: import org.romaframework.aspect.view.echo2.form.FormUtil;
044: import org.romaframework.aspect.view.echo2.look.LookAndFeelManager;
045: import org.romaframework.aspect.view.feature.ViewBaseFeatures;
046: import org.romaframework.aspect.view.form.ContentComponent;
047: import org.romaframework.core.config.RomaApplicationContext;
048: import org.romaframework.core.entity.ComposedEntity;
049: import org.romaframework.core.flow.ObjectContext;
050: import org.romaframework.core.schema.SchemaField;
051: import org.romaframework.core.schema.SchemaHelper;
052: import org.romaframework.core.validation.CustomValidation;
053:
054: import echopointng.ButtonEx;
055:
056: public abstract class DynaComponent extends AbstractContentComponent
057: implements ActionListener {
058:
059: protected boolean enabled;
060: protected String orientation = ViewConstants.ORIENTATION_HORIZONTAL;
061: protected List<?> objectList;
062: protected Component component;
063: protected Component frame;
064: protected Component commands;
065:
066: protected OPERATIONS operation;
067:
068: protected Button viewButton;
069: protected Button addButton;
070: protected Button editButton;
071: protected Button removeButton;
072: protected Button upButton;
073: protected Button downButton;
074:
075: protected enum OPERATIONS {
076: VIEW, ADD, EDIT, REMOVE, UP, DOWN
077: };
078:
079: private static Log log = LogFactory.getLog(DynaComponent.class);
080:
081: protected static final String VIEW_EVENT = "View";
082: protected static final String ADD_EVENT = "Add";
083: protected static final String EDIT_EVENT = "Edit";
084: protected static final String REMOVE_EVENT = "Remove";
085: protected static final String UP_EVENT = "Up";
086: protected static final String DOWN_EVENT = "Down";
087:
088: protected static final String VIEW_LABEL = "$view.label";
089: protected static final String VIEW_HINT = "$view.hint";
090: protected static final String ADD_LABEL = "$add.label";
091: protected static final String ADD_HINT = "$add.hint";
092: protected static final String EDIT_LABEL = "$edit.label";
093: protected static final String EDIT_HINT = "$edit.hint";
094: protected static final String REMOVE_LABEL = "$remove.label";
095: protected static final String REMOVE_HINT = "$remove.hint";
096: protected static final String UP_LABEL = "$up.label";
097: protected static final String UP_HINT = "$up.hint";
098: protected static final String DOWN_LABEL = "$down.label";
099: protected static final String DOWN_HINT = "$down.hint";
100:
101: public DynaComponent(ContentComponent iForm, Component iComponent) {
102: super (iForm);
103: enabled = false;
104: component = iComponent;
105:
106: layout();
107: }
108:
109: public Component getUnderlyingComponent() {
110: return component;
111: }
112:
113: public abstract Object getSelectedValue();
114:
115: public abstract Object[] getSelectedValues();
116:
117: public abstract int[] getSelectedIndices();
118:
119: @Override
120: public void setContent(Object iObjectList) {
121: super .setContent(iObjectList);
122:
123: if (iObjectList == null)
124: return;
125:
126: // FILL COLUMN VALUES
127: if (iObjectList instanceof List) {
128: // LIST
129: objectList = (List<?>) iObjectList;
130: } else {
131: // NOT ORDERABLE: HIDE UP/DOWN BUTTONS
132: if (upButton != null)
133: upButton.setVisible(false);
134: if (downButton != null)
135: downButton.setVisible(false);
136:
137: if (iObjectList instanceof Map)
138: // MAP: GET LIST BY VALUES
139: objectList = new ArrayList<Object>(
140: ((Map<?, ?>) iObjectList).values());
141: else if (iObjectList instanceof Set)
142: // SET: GET LIST
143: objectList = new ArrayList<Object>((Set<?>) iObjectList);
144: }
145:
146: // CREATE THE ASSOCIATION BETWEEN THE USER OBJECT AND THE FORM
147: ObjectContext.getInstance().createObjectFormAssociation(
148: objectList, null, this );
149: }
150:
151: @Override
152: public void bind(SchemaField iSchemaField, Object iValue) {
153: Object list = SchemaHelper.getFieldValue(iSchemaField,
154: containerComponent.getContent());
155:
156: if (list == null) {
157: log
158: .warn("[DynaComponent.bind] Cannot modify the underline collection since POJO attribute is null! Check the attribute: "
159: + iSchemaField.getEntity().getSchemaClass()
160: .getName()
161: + "."
162: + iSchemaField.getName());
163: return;
164: }
165:
166: Object entity = iValue;
167: if (entity instanceof ComposedEntity) {
168: entity = ((ComposedEntity<?>) entity).getEntity();
169: }
170:
171: if (operation == OPERATIONS.ADD || operation == OPERATIONS.EDIT) {
172: // EXECUTE VALIDATION AGAINST MAIN OBJECT
173: if (iValue instanceof CustomValidation)
174: ((CustomValidation) iValue).validate();
175:
176: // EXECUTE VALIDATION AGAINST ENTITY OBJECT
177: if (entity instanceof CustomValidation)
178: ((CustomValidation) entity).validate();
179: }
180:
181: if (operation == OPERATIONS.ADD)
182: SchemaHelper.insertElements(schemaField, containerComponent
183: .getContent(), new Object[] { iValue });
184:
185: if (list != objectList)
186: // UPDATE ALSO OBJECT LIST IF DIFFERENT. THIS IS THE CASE OF MAPS AND SETS
187: ((List<Object>) objectList).add(iValue);
188:
189: // REFRESH PROPERTY
190: ObjectContext.getInstance()
191: .refresh(containerComponent.getContent(),
192: iSchemaField.getName());
193: }
194:
195: public void render(ContentComponent iFormToRender) {
196: render();
197: }
198:
199: @Override
200: public void render() {
201: Class<?> classForStyle = schemaField.getEntity()
202: .getSchemaClass().getClazz();
203:
204: String styleName = (String) schemaField.getFeature(
205: ViewAspect.ASPECT_NAME, ViewBaseFeatures.STYLE);
206:
207: RomaApplicationContext.getInstance().getBean(
208: LookAndFeelManager.class).assignStyle(component,
209: classForStyle, schemaField.getName(), styleName);
210:
211: if (component instanceof ListBox) {
212: PatchHelper.containerExPatch(this , component);
213: }
214:
215: if (addButton != null)
216: RomaApplicationContext.getInstance().getBean(
217: LookAndFeelManager.class).assignStyle(addButton,
218: classForStyle, schemaField.getName(), "add");
219:
220: if (viewButton != null)
221: RomaApplicationContext.getInstance().getBean(
222: LookAndFeelManager.class).assignStyle(viewButton,
223: classForStyle, schemaField.getName(), "view");
224:
225: if (removeButton != null)
226: RomaApplicationContext.getInstance().getBean(
227: LookAndFeelManager.class).assignStyle(removeButton,
228: classForStyle, schemaField.getName(), "remove");
229:
230: if (editButton != null)
231: RomaApplicationContext.getInstance().getBean(
232: LookAndFeelManager.class).assignStyle(editButton,
233: classForStyle, schemaField.getName(), "edit");
234:
235: if (upButton != null)
236: RomaApplicationContext.getInstance().getBean(
237: LookAndFeelManager.class).assignStyle(upButton,
238: classForStyle, schemaField.getName(), "up");
239:
240: if (downButton != null)
241: RomaApplicationContext.getInstance().getBean(
242: LookAndFeelManager.class).assignStyle(downButton,
243: classForStyle, schemaField.getName(), "down");
244:
245: FormUtil
246: .setMetadata(component, containerComponent, schemaField);
247:
248: FormUtil.assignHint(component, (String) schemaField.getFeature(
249: ViewAspect.ASPECT_NAME, ViewBaseFeatures.DESCRIPTION));
250: }
251:
252: /**
253: * Disabled component hide action commands in list elements.
254: */
255: @Override
256: public void setEnabled(boolean iEnabled) {
257: if (enabled == iEnabled)
258: return;
259:
260: enabled = iEnabled;
261: layout();
262: }
263:
264: protected Button addButton(String iLabel, String iHint) {
265: Button button = new ButtonEx();
266: FormUtil.assignLabel(button, FormUtil.getLabel(getClass(),
267: iLabel));
268: FormUtil.assignHint(button, FormUtil
269: .getLabel(getClass(), iHint));
270: button.addActionListener(this );
271: commands.add(button);
272:
273: return button;
274: }
275:
276: protected void updateButtonStatus(Object[] iSelectedObjects) {
277: if (!enabled)
278: return;
279:
280: int selCount = iSelectedObjects != null ? iSelectedObjects.length
281: : 0;
282:
283: if (selCount == 0) {
284: viewButton.setEnabled(false);
285: editButton.setEnabled(false);
286: removeButton.setEnabled(false);
287: upButton.setEnabled(false);
288: downButton.setEnabled(false);
289: } else {
290: if (selCount == 1) {
291: viewButton.setEnabled(true);
292: editButton.setEnabled(true);
293: upButton.setEnabled(true);
294: downButton.setEnabled(true);
295: } else {
296: viewButton.setEnabled(false);
297: editButton.setEnabled(false);
298: upButton.setEnabled(false);
299: downButton.setEnabled(false);
300: }
301:
302: removeButton.setEnabled(true);
303: }
304: }
305:
306: public void setOrientation(String iOrientation) {
307: if (iOrientation.equals(orientation))
308: return;
309:
310: orientation = iOrientation;
311:
312: layout();
313: }
314:
315: protected void layout() {
316: if (getComponentCount() > 0)
317: remove(0);
318:
319: if (enabled) {
320: if (orientation
321: .equals(ViewConstants.ORIENTATION_HORIZONTAL))
322: frame = new Row();
323: else
324: frame = new Column();
325: add(frame);
326: } else
327: frame = this ;
328:
329: if (component != null) {
330: // ADD AGAIN THE COMPONENT PREVIOUSLY CREATED
331: frame.add(component);
332: }
333:
334: CellLayoutData layout = null;
335: if (enabled) {
336: if (orientation
337: .equals(ViewConstants.ORIENTATION_HORIZONTAL)) {
338: commands = new Column();
339: layout = new RowLayoutData();
340: } else {
341: commands = new Row();
342: layout = new ColumnLayoutData();
343: }
344: layout.setAlignment(new Alignment(Alignment.CENTER,
345: Alignment.BOTTOM));
346: commands.setLayoutData(layout);
347: frame.add(commands);
348:
349: addButton = addButton(ADD_LABEL, ADD_HINT);
350: viewButton = addButton(VIEW_LABEL, VIEW_HINT);
351: editButton = addButton(EDIT_LABEL, EDIT_HINT);
352: removeButton = addButton(REMOVE_LABEL, REMOVE_HINT);
353: upButton = addButton(UP_LABEL, UP_HINT);
354: downButton = addButton(DOWN_LABEL, DOWN_HINT);
355:
356: addButton.setEnabled(true);
357: viewButton.setEnabled(false);
358: editButton.setEnabled(false);
359: removeButton.setEnabled(false);
360: upButton.setEnabled(false);
361: downButton.setEnabled(false);
362: }
363: }
364:
365: public void actionPerformed(ActionEvent e) {
366: try {
367: Object[] selectedObjects = getSelectedValues();
368:
369: Object source = e.getSource();
370: if (source.equals(component)) {
371: // BIND THE SELECTION
372: getContainerComponent().bind(schemaField,
373: selectedObjects);
374:
375: updateButtonStatus(selectedObjects);
376: return;
377: } else if (source.equals(viewButton)) {
378: if (getSelectedValues().length == 0)
379: // NO SELECTION
380: return;
381:
382: Object selectedValue;
383: if (getContent() instanceof List) {
384: int index = getSelectedIndices()[0];
385: selectedValue = ((List<?>) getContent()).get(index);
386: } else
387: selectedValue = getSelectedValue();
388:
389: viewSelection(selectedValue);
390:
391: } else if (source.equals(addButton)) {
392: addNewEntry();
393:
394: } else if (source.equals(editButton)) {
395: if (getSelectedValues().length == 0)
396: // NO SELECTION
397: return;
398:
399: Object selectedValue;
400: if (getContent() instanceof List) {
401: int index = getSelectedIndices()[0];
402: selectedValue = ((List<?>) getContent()).get(index);
403: } else
404: selectedValue = getSelectedValue();
405:
406: editSelection(selectedValue);
407:
408: } else if (source.equals(removeButton)) {
409: if (getSelectedValues().length == 0)
410: // NO SELECTION
411: return;
412:
413: removeSelection(selectedObjects);
414: } else if (source.equals(upButton)) {
415: if (getSelectedValues().length == 0)
416: // NO SELECTION
417: return;
418:
419: moveSelection(selectedObjects[0], -1);
420: } else if (source.equals(downButton)) {
421: if (getSelectedValues().length == 0)
422: // NO SELECTION
423: return;
424:
425: moveSelection(selectedObjects[0], +1);
426: }
427: } catch (Throwable t) {
428: containerComponent.handleException(t);
429: }
430: }
431:
432: private void moveSelection(Object iSelection, int iDirection) {
433: int newPos = SchemaHelper.moveElement(getContent(), iSelection,
434: iDirection);
435: if (newPos > -1)
436: FormUtil.setComponentValue(this , getContent());
437: }
438:
439: protected void removeSelection(Object[] selectedObjects)
440: throws IllegalAccessException, InvocationTargetException {
441: String eventName = schemaField.getName() + REMOVE_EVENT;
442:
443: if (!SchemaHelper.invokeEvent(containerComponent, eventName)) {
444: // NO EVENT FOUND
445: }
446:
447: operation = OPERATIONS.REMOVE;
448:
449: Object newValue = SchemaHelper.removeElements(getContent(),
450: selectedObjects);
451:
452: if (newValue != null)
453: // COLLECTION OBJECT REPLACED (ARRAY CASES)
454: setContent(newValue);
455:
456: ObjectContext.getInstance().refresh(
457: containerComponent.getContent(), schemaField.getName());
458: }
459:
460: protected void editSelection(Object selectedValue)
461: throws IllegalAccessException, InvocationTargetException,
462: InstantiationException, Exception {
463: operation = OPERATIONS.EDIT;
464:
465: String eventName = schemaField.getName() + EDIT_EVENT;
466:
467: EntityFormHelper.edit(this , eventName,
468: (Class<?>) getSchemaField().getEmbeddedType(),
469: selectedValue);
470: }
471:
472: protected void addNewEntry() throws IllegalAccessException,
473: InvocationTargetException, InstantiationException,
474: Exception {
475: operation = OPERATIONS.ADD;
476:
477: String eventName = schemaField.getName() + ADD_EVENT;
478:
479: EntityFormHelper.add(this , eventName,
480: (Class<?>) getSchemaField().getEmbeddedType());
481: }
482:
483: protected void viewSelection(Object selectedValue)
484: throws IllegalAccessException, InvocationTargetException,
485: InstantiationException, Exception {
486: operation = OPERATIONS.VIEW;
487:
488: String eventName = schemaField.getName() + VIEW_EVENT;
489:
490: EntityFormHelper.view(this , eventName,
491: (Class<?>) getSchemaField().getEmbeddedType(),
492: selectedValue);
493: }
494: }
|