001: /*
002: * Created on Nov 2, 2005
003: */
004: package uk.org.ponder.rsf.componentprocessor;
005:
006: import java.util.ArrayList;
007: import java.util.Iterator;
008: import java.util.List;
009:
010: import uk.org.ponder.rsf.components.ComponentList;
011: import uk.org.ponder.rsf.components.FixableComponent;
012: import uk.org.ponder.rsf.components.UIBound;
013: import uk.org.ponder.rsf.components.UIComponent;
014: import uk.org.ponder.rsf.components.UIContainer;
015: import uk.org.ponder.rsf.components.decorators.UIBoundDecorator;
016: import uk.org.ponder.rsf.components.decorators.UIDecorator;
017: import uk.org.ponder.rsf.view.View;
018: import uk.org.ponder.rsf.view.ViewReceiver;
019: import uk.org.ponder.saxalizer.SAXalizerMappingContext;
020: import uk.org.ponder.util.Logger;
021:
022: /**
023: * A request-scope bean which processes a component tree (view) after its
024: * production by the ViewGenerator, and before rendering by the ViewRender. This
025: * performs "fixups" as specified by a list of ComponentProcessor objects,
026: * including applying the system's form model, resolving URLs and any
027: * application-registered processing.
028: *
029: * @author Antranig Basman (antranig@caret.cam.ac.uk)
030: */
031: public class ViewProcessor {
032: private List frameworkprocessors;
033:
034: private List clientprocessors;
035:
036: public void setComponentProcessors(List processors) {
037: this .frameworkprocessors = processors;
038: }
039:
040: public void setClientComponentProcessors(List clientprocessors) {
041: this .clientprocessors = clientprocessors;
042: }
043:
044: // List of components found in the tree. We may
045: // not use the tree directly because of possible folding mutations.
046: private ComponentList worklist;
047:
048: private View view;
049:
050: private SAXalizerMappingContext mappingcontext;
051:
052: // This dependency is not set via RSAC since it would execute too early.
053: public void setView(View view) {
054: this .view = view;
055: }
056:
057: public View getProcessedView() {
058: performFixup();
059: return view;
060: }
061:
062: public void setMappingContext(SAXalizerMappingContext mappingcontext) {
063: this .mappingcontext = mappingcontext;
064: }
065:
066: private void performFixup() {
067: List processors = new ArrayList();
068: if (clientprocessors != null) {
069: processors.addAll(clientprocessors);
070: }
071: processors.addAll(frameworkprocessors);
072:
073: for (int procind = 0; procind < processors.size(); ++procind) {
074: ComponentProcessor proc = (ComponentProcessor) processors
075: .get(procind);
076: if (proc instanceof ViewReceiver) {
077: ((ViewReceiver) proc).setView(view);
078: }
079: }
080:
081: generateWorkList();
082: // ensure that the ID map is fully populated before any processors begin
083: // to execute, which may be dependent on it.
084: for (int compind = 0; compind < worklist.size(); ++compind) {
085: UIComponent child = worklist.componentAt(compind);
086: view.registerComponent(child);
087: }
088: OrphanFinder finder = new OrphanFinder();
089: for (int compind = 0; compind < worklist.size(); ++compind) {
090: UIComponent child = worklist.componentAt(compind);
091: for (int procind = 0; procind < processors.size(); ++procind) {
092: ComponentProcessor proc = (ComponentProcessor) processors
093: .get(procind);
094: try {
095: proc.processComponent(child);
096: } catch (Exception e) {
097: Logger.log.warn("Error processing component "
098: + child + " with ID " + child.getFullID(),
099: e);
100: }
101: }
102: finder.processComponent(child);
103: }
104: for (int compind = 0; compind < worklist.size(); ++compind) {
105: UIComponent this child = worklist.componentAt(compind);
106: if (this child instanceof FixableComponent) {
107: ((FixableComponent) this child).fixupComponent();
108: }
109: }
110: finder.report();
111: }
112:
113: private void generateWorkList() {
114: worklist = new ComponentList();
115: appendContainer(view.viewroot);
116: }
117:
118: private void appendComponent(UIBound toappend, String fullID) {
119: if (toappend != null) {
120: if (fullID != null) {
121: toappend.updateFullID(fullID);
122: }
123: worklist.add(toappend);
124: }
125: }
126:
127: private void appendContainer(UIContainer toappend) {
128: ComponentList this children = toappend.flattenChildren();
129: // add the actual children later, to ensure dependent components resolved
130: // first
131: // BUT we require at the very least that Forms are processed before their
132: // children, otherwise any work done by ContainmentFCF will NOT BE SEEN
133: // in time!
134: worklist.addAll(this children);
135:
136: for (int i = 0; i < this children.size(); ++i) {
137: UIComponent this child = this children.componentAt(i);
138: if (this child instanceof UIContainer) {
139: appendContainer((UIContainer) this child);
140: }
141: ComponentChildIterator children = new ComponentChildIterator(
142: this child, mappingcontext);
143: for (Iterator childit = children.iterator(); childit
144: .hasNext();) {
145: String childname = (String) childit.next();
146: appendComponent((UIBound) children
147: .locateBean(childname), this child.getFullID()
148: + "-" + childname);
149: }
150: if (this child.decorators != null) {
151: for (int j = 0; j < this child.decorators.size(); ++j) {
152: UIDecorator dec = this child.decorators
153: .decoratorAt(j);
154: if (dec instanceof UIBoundDecorator) {
155: appendComponent(((UIBoundDecorator) dec)
156: .acquireBound(), this child.getFullID()
157: + "-decorator" + i);
158: }
159: }
160: }
161: }
162:
163: }
164: }
|