001: /*
002: * Created on Oct 20, 2004
003: */
004: package uk.org.ponder.rsf.view.support;
005:
006: import java.util.ArrayList;
007: import java.util.HashMap;
008: import java.util.List;
009: import java.util.Map;
010:
011: import uk.org.ponder.booleanutil.BooleanGetter;
012: import uk.org.ponder.booleanutil.BooleanHolder;
013: import uk.org.ponder.rsf.content.ContentTypeReceiver;
014: import uk.org.ponder.rsf.content.ContentTypeReporter;
015: import uk.org.ponder.rsf.flow.errors.SilentRedirectException;
016: import uk.org.ponder.rsf.flow.jsfnav.DynamicNavigationCaseReporter;
017: import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReceiver;
018: import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter;
019: import uk.org.ponder.rsf.view.ComponentProducer;
020: import uk.org.ponder.rsf.view.DefaultView;
021: import uk.org.ponder.rsf.view.MappingViewResolver;
022: import uk.org.ponder.rsf.view.ViewComponentProducer;
023: import uk.org.ponder.rsf.view.ViewResolver;
024: import uk.org.ponder.rsf.viewstate.ViewParamsReceiver;
025: import uk.org.ponder.rsf.viewstate.ViewParamsReporter;
026: import uk.org.ponder.util.UniversalRuntimeException;
027:
028: /**
029: * A concrete implementation of ViewResolver which will resolve
030: * ComponentProducer requests into a fixed collection of configured beans, set
031: * up by the setViews() method. Can also fall back to a set of generic
032: * ViewResolvers should initial lookup fail. This is the default RSF
033: * ViewResolver - it is an application scope bean, although it collaborates with
034: * the AutoComponentProducerManager to accept request-scope producers.
035: *
036: * @author Antranig Basman (antranig@caret.cam.ac.uk)
037: *
038: */
039: public class ConcreteViewResolver implements MappingViewResolver {
040: // This key is used to identify a producer that *might* produce components
041: // in all views. Upgrade this architecture once we think a little more about
042: // how we might actually want to locate view templates and component
043: // producers relative to views (view IDs or in general, ViewParams)
044: public static final String ALL_VIEW_PRODUCER = " all views ";
045:
046: private Map views = new HashMap();
047:
048: private List resolvers = new ArrayList();
049: private BooleanGetter unknowniserror = new BooleanHolder(true);
050: private ViewParamsReceiver vpreceiver;
051: private NavigationCaseReceiver ncreceiver;
052: private ContentTypeReceiver ctreceiver;
053: private AutoComponentProducerManager automanager;
054:
055: public void setUnknownViewIsError(BooleanGetter unknowniserror) {
056: this .unknowniserror = unknowniserror;
057: }
058:
059: public void setViewParametersReceiver(ViewParamsReceiver vpreceiver) {
060: this .vpreceiver = vpreceiver;
061: }
062:
063: public void setNavigationCaseReceiver(
064: NavigationCaseReceiver ncreceiver) {
065: this .ncreceiver = ncreceiver;
066: }
067:
068: public void setContentTypeReceiver(ContentTypeReceiver ctreceiver) {
069: this .ctreceiver = ctreceiver;
070: }
071:
072: private List pendingviews = new ArrayList();
073:
074: // Apologies for this lack of abstraction. There is currently only one of
075: // these,
076: // and we do use it for two purposes...
077: public void setAutoComponentProducerManager(
078: AutoComponentProducerManager requestmanager) {
079: this .automanager = requestmanager;
080: pendingviews.addAll(requestmanager.getProducers());
081: }
082:
083: /**
084: * Sets a static list of ViewComponentProducers which will be used as a first
085: * pass to resolve requests for incoming views. Any plain ComponentProducers
086: * will be added as default producers to execute for all views.
087: */
088: public void setViews(List viewlist) {
089: pendingviews.addAll(viewlist);
090: }
091:
092: public void init() {
093: for (int i = 0; i < pendingviews.size(); ++i) {
094: ComponentProducer view = (ComponentProducer) pendingviews
095: .get(i);
096: // view.setMessageLocator(messagelocator);
097: String key = ALL_VIEW_PRODUCER;
098: if (view instanceof ViewComponentProducer) {
099: key = ((ViewComponentProducer) view).getViewID();
100: if (view instanceof ViewParamsReporter) {
101: ViewParamsReporter vpreporter = (ViewParamsReporter) view;
102: vpreceiver.setViewParamsExemplar(key, vpreporter
103: .getViewParameters());
104: }
105: if (view instanceof DefaultView) {
106: vpreceiver.setDefaultView(key);
107: }
108: if (view instanceof NavigationCaseReporter
109: && !(view instanceof DynamicNavigationCaseReporter)) {
110: ncreceiver.receiveNavigationCases(key,
111: ((NavigationCaseReporter) view)
112: .reportNavigationCases());
113: }
114: if (view instanceof ContentTypeReporter) {
115: ctreceiver.setContentType(key,
116: ((ContentTypeReporter) view)
117: .getContentType());
118: }
119: }
120: addView(key, view);
121: }
122: pendingviews.clear();
123: }
124:
125: /**
126: * Sets a list of slave ViewResolvers which will be polled in sequence should
127: * no static producer be registered, until the first which returns a non-null
128: * result for this view.
129: */
130: public void setViewResolvers(List resolvers) {
131: this .resolvers = resolvers;
132: }
133:
134: private void addView(String key, ComponentProducer view) {
135: List got = get(key);
136: if (got == null) {
137: got = new ArrayList();
138: views.put(key, got);
139: }
140: got.add(view);
141: }
142:
143: private List get(String key) {
144: return (List) views.get(key);
145: }
146:
147: public ComponentProducer mapProducer(Object tomap) {
148: return automanager.wrapProducer((ComponentProducer) tomap);
149: }
150:
151: public List getUnmappedProducers(String viewid) {
152: List specific = get(viewid);
153:
154: if (specific == null && resolvers != null) {
155: for (int i = 0; i < resolvers.size(); ++i) {
156: ViewResolver resolver = (ViewResolver) resolvers.get(i);
157: specific = resolver.getProducers(viewid);
158: if (specific != null)
159: break;
160: }
161: }
162: if (specific == null && unknowniserror.get() == Boolean.TRUE) {
163: throw UniversalRuntimeException.accumulate(
164: new SilentRedirectException(),
165: "No ViewComponentProducer is registered for view "
166: + viewid);
167: }
168: ArrayList togo = new ArrayList();
169: List allproducers = get(ALL_VIEW_PRODUCER);
170: if (allproducers != null) {
171: togo.addAll(allproducers);
172: }
173: if (specific != null) {
174: togo.addAll(specific);
175: }
176: return togo;
177: }
178:
179: public List getProducers(String viewid) {
180: List togo = getUnmappedProducers(viewid);
181: mapProducers(togo);
182: return togo;
183: }
184:
185: private void mapProducers(List producers) {
186: for (int i = 0; i < producers.size(); ++i) {
187: ComponentProducer producer = (ComponentProducer) producers
188: .get(i);
189: ComponentProducer ultimate = automanager
190: .wrapProducer(producer);
191: if (ultimate instanceof DynamicNavigationCaseReporter
192: && ultimate instanceof ViewComponentProducer) {
193: ncreceiver.receiveNavigationCases(
194: ((ViewComponentProducer) ultimate).getViewID(),
195: ((NavigationCaseReporter) ultimate)
196: .reportNavigationCases());
197: }
198: producers.set(i, ultimate);
199: }
200: }
201:
202: }
|