Index: rice-framework/krad-it/src/test/java/org/kuali/rice/krad/uif/RichMessageTest.java =================================================================== --- rice-framework/krad-it/src/test/java/org/kuali/rice/krad/uif/RichMessageTest.java (revision 41915) +++ rice-framework/krad-it/src/test/java/org/kuali/rice/krad/uif/RichMessageTest.java (working copy) @@ -572,9 +572,9 @@ * @param component */ private void performSimulatedLifecycle(Component component) { - component.performInitialization(view, model); - component.performApplyModel(view, model, view); - component.performFinalize(view, model, view); + component.performInitialization(model); + component.performApplyModel(model, view); + component.performFinalize(model, view); } /** Index: rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentExhibit.java =================================================================== --- rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentExhibit.java (revision 41915) +++ rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentExhibit.java (working copy) @@ -20,6 +20,7 @@ import org.kuali.rice.krad.uif.container.TabGroup; import org.kuali.rice.krad.uif.element.ContentElementBase; import org.kuali.rice.krad.uif.field.FieldGroup; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.uif.widget.SyntaxHighlighter; @@ -50,13 +51,13 @@ * @see Component#performInitialization(org.kuali.rice.krad.uif.view.View, Object) */ @Override - public void performInitialization(View view, Object model) { + public void performInitialization(Object model) { //Setup tabGroup List tabItems = new ArrayList(); tabItems.addAll(tabGroup.getItems()); tabItems.addAll(demoGroups); tabGroup.setItems(tabItems); - view.assignComponentIds(tabGroup); + ViewLifecycle.getActiveLifecycle().getView().assignComponentIds(tabGroup); //source code viewer setup if(demoSourceCode != null && !demoSourceCode.isEmpty()){ Index: rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentLibraryView.java =================================================================== --- rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentLibraryView.java (revision 41915) +++ rice-framework/krad-sampleapp/src/main/java/org/kuali/rice/krad/demo/uif/components/ComponentLibraryView.java (working copy) @@ -15,9 +15,21 @@ */ package org.kuali.rice.krad.demo.uif.components; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.kuali.rice.core.api.util.AbstractKeyValue; import org.kuali.rice.core.api.util.ConcreteKeyValue; import org.kuali.rice.core.api.util.KeyValue; import org.kuali.rice.krad.datadictionary.parse.BeanTag; @@ -32,25 +44,11 @@ import org.kuali.rice.krad.uif.element.Header; import org.kuali.rice.krad.uif.element.Message; import org.kuali.rice.krad.uif.field.InputField; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentFactory; import org.kuali.rice.krad.uif.view.FormView; -import org.kuali.rice.krad.uif.view.View; import org.springframework.util.StringUtils; -import javax.swing.text.StyleContext; -import java.io.File; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * View for the ComponentLibrary demo examples of Uif Components * @@ -87,8 +85,8 @@ * @see Component#performInitialization(org.kuali.rice.krad.uif.view.View, Object) */ @Override - public void performInitialization(View view, Object model) { - super.performInitialization(view, model); + public void performInitialization(Object model) { + super.performInitialization(model); MessageService messageService = KRADServiceLocatorWeb.getMessageService(); @@ -151,7 +149,7 @@ detailsItems.addAll(detailsGroup.getItems()); detailsItems.add(tabGroup); detailsGroup.setItems(detailsItems); - view.assignComponentIds(detailsGroup); + ViewLifecycle.getActiveLifecycle().getView().assignComponentIds(detailsGroup); //exhibit setup List sourceCode = new ArrayList(); @@ -166,7 +164,7 @@ if (this.getExampleSize() != null && (this.getExampleSize().equals(ExampleSize.LARGE) || this.getExampleSize().equals(ExampleSize.XLARGE))) { exhibit.getTabGroup().addStyleClass("demo-noTabs"); - Group headerRightGroup = view.getPage().getHeader().getRightGroup(); + Group headerRightGroup = ViewLifecycle.getActiveLifecycle().getView().getPage().getHeader().getRightGroup(); for (Component item : headerRightGroup.getItems()) { if (item instanceof InputField && ((InputField) item).getControl() instanceof MultiValueControl && item .getId().equals(this.getLargeExampleFieldId())) { Index: rice-framework/krad-service-impl/src/main/java/org/kuali/rice/krad/uif/service/impl/ViewServiceImpl.java =================================================================== --- rice-framework/krad-service-impl/src/main/java/org/kuali/rice/krad/uif/service/impl/ViewServiceImpl.java (revision 41915) +++ rice-framework/krad-service-impl/src/main/java/org/kuali/rice/krad/uif/service/impl/ViewServiceImpl.java (working copy) @@ -15,10 +15,12 @@ */ package org.kuali.rice.krad.uif.service.impl; +import java.util.List; +import java.util.Map; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Logger; -import org.apache.log4j.Priority; import org.kuali.rice.core.api.CoreApiServiceLocator; import org.kuali.rice.krad.datadictionary.validator.ValidationController; import org.kuali.rice.krad.service.DataDictionaryService; @@ -26,15 +28,11 @@ import org.kuali.rice.krad.uif.UifConstants.ViewStatus; import org.kuali.rice.krad.uif.UifConstants.ViewType; import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; -import org.kuali.rice.krad.uif.service.ViewHelperService; import org.kuali.rice.krad.uif.service.ViewService; import org.kuali.rice.krad.uif.service.ViewTypeService; import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.web.form.UifFormBase; -import java.util.List; -import java.util.Map; - /** * Implementation of ViewService * @@ -57,22 +55,12 @@ /** * @see org.kuali.rice.krad.uif.service.ViewService#getViewById(java.lang.String) */ - public View getViewById(String viewId) { + public View getViewById(final String viewId) { if (LOG.isDebugEnabled()) { LOG.debug("retrieving view instance for id: " + viewId); } - - View view = dataDictionaryService.getViewById(viewId); - if (view == null) { - LOG.warn("View not found for id: " + viewId); - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("Updating view status to CREATED for view: " + view.getId()); - } - view.setViewStatus(ViewStatus.CREATED); - } - - return view; + + return dataDictionaryService.getViewById(viewId); } /** @@ -94,9 +82,6 @@ View view = dataDictionaryService.getViewByTypeIndex(viewType, typeParameters); if (view == null) { LOG.warn("View not found for type: " + viewType); - } else { - LOG.debug("Updating view status to CREATED for view: " + view.getId()); - view.setViewStatus(ViewStatus.CREATED); } return view; @@ -118,54 +103,30 @@ } /** + * TODO: Consider moving this method to ViewLifecycle * @see org.kuali.rice.krad.uif.service.ViewService#buildView(org.kuali.rice.krad.uif.view.View, java.lang.Object, * java.util.Map) */ - public void buildView(View view, Object model, Map parameters) { - // get the configured helper service for the view - ViewHelperService helperService = view.getViewHelperService(); - - // populate view from request parameters - helperService.populateViewFromRequestParameters(view, parameters); - - // backup view request parameters on form for recreating lost views (session timeout) - ((UifFormBase) model).setViewRequestParameters(view.getViewRequestParameters()); - - // run view lifecycle - performViewLifecycle(view, model, parameters); - - // Validation of the page's beans - if (CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsBoolean( - UifConstants.VALIDATE_VIEWS_ONBUILD)) { - ValidationController validator = new ValidationController(true, true, true, true, false); - Log tempLogger = LogFactory.getLog(ViewServiceImpl.class); - validator.validate(view, tempLogger, false); - } - } - - /** - * Initializes a newly created View instance. Each component of the tree is invoked - * to perform setup based on its configuration. In addition helper service methods are invoked to - * perform custom initialization - * - * @param view - view instance to initialize - * @param model - object instance containing the view data - * @param parameters - Map of key values pairs that provide configuration for the View, this - * is generally comes from the request and can be the request parameter Map itself. Any parameters - * not valid for the View will be filtered out - */ - protected void performViewLifecycle(final View view, final Object model, final Map parameters) { - // get the configured helper service for the view - final ViewHelperService helperService = view.getViewHelperService(); - - helperService.encapsulateViewLifecycle(new Runnable(){ + public View buildView(View view, final Object model, final Map parameters) { + View builtView = ViewLifecycle.encapsulateLifecycle(view, new Runnable(){ @Override public void run() { + ViewLifecycle viewLifecycle = ViewLifecycle.getActiveLifecycle(); + View view = viewLifecycle.getView(); + + // populate view from request parameters + viewLifecycle.populateViewFromRequestParameters(parameters); + + // backup view request parameters on form for recreating lost + // views (session timeout) + ((UifFormBase) model).setViewRequestParameters(view + .getViewRequestParameters()); + // invoke initialize phase on the views helper service - if (LOG.isEnabledFor(Priority.INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("performing initialize phase for view: " + view.getId()); } - helperService.performInitialization(view, model); + viewLifecycle.performInitialization(model); // do indexing if (LOG.isDebugEnabled()) { @@ -180,25 +141,25 @@ view.setViewStatus(ViewStatus.INITIALIZED); // Apply Model Phase - if (LOG.isEnabledFor(Priority.INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("performing apply model phase for view: " + view.getId()); } - helperService.performApplyModel(view, model); + viewLifecycle.performApplyModel(model); // do indexing - if (LOG.isEnabledFor(Priority.INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("reindexing after apply model for view: " + view.getId()); } view.index(); // Finalize Phase - if (LOG.isEnabledFor(Priority.INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("performing finalize phase for view: " + view.getId()); } - helperService.performFinalize(view, model); + viewLifecycle.performFinalize(model); // do indexing - if (LOG.isEnabledFor(Priority.INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("processing final indexing for view: " + view.getId()); } view.index(); @@ -208,7 +169,17 @@ LOG.debug("Updating view status to FINAL for view: " + view.getId()); } view.setViewStatus(ViewStatus.FINAL); - }}); + }}).getView(); + + // Validation of the page's beans + if (CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsBoolean( + UifConstants.VALIDATE_VIEWS_ONBUILD)) { + ValidationController validator = new ValidationController(true, true, true, true, false); + Log tempLogger = LogFactory.getLog(ViewServiceImpl.class); + validator.validate(builtView, tempLogger, false); + } + + return builtView; } public ViewTypeService getViewTypeService(UifConstants.ViewType viewType) { Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/DataDictionary.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/DataDictionary.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/DataDictionary.java (working copy) @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.concurrent.Callable; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.collections.ListUtils; @@ -48,6 +49,7 @@ import org.kuali.rice.krad.service.LegacyDataAdapter; import org.kuali.rice.krad.uif.UifConstants; import org.kuali.rice.krad.uif.UifConstants.ViewType; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentBeanPostProcessor; import org.kuali.rice.krad.uif.util.ComponentFactory; import org.kuali.rice.krad.uif.util.UifBeanFactoryPostProcessor; @@ -194,56 +196,62 @@ * @param allowConcurrentValidation - indicates whether the indexing should occur on a different thread * or the same thread */ - public void performDictionaryPostProcessing(boolean allowConcurrentValidation) { - LOG.info( "Starting Data Dictionary Post Processing"); - timer.start("Spring Post Processing"); - PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); - propertyPlaceholderConfigurer.setProperties(ConfigContext.getCurrentContextConfig().getProperties()); - propertyPlaceholderConfigurer.postProcessBeanFactory(ddBeans); - - DictionaryBeanFactoryPostProcessor dictionaryBeanPostProcessor = new DictionaryBeanFactoryPostProcessor(this, - ddBeans); - dictionaryBeanPostProcessor.postProcessBeanFactory(); - timer.stop(); - timer.start("UIF Post Processing"); - // post processes UIF beans for pulling out expressions within property values - UifBeanFactoryPostProcessor factoryPostProcessor = new UifBeanFactoryPostProcessor(); - factoryPostProcessor.postProcessBeanFactory(ddBeans); - timer.stop(); - - timer.start("Instantiating DD Beans"); - ddBeans.preInstantiateSingletons(); - timer.stop(); - - // Allow the DD to perform final post processing in a controlled order - // Unlike the Spring post processor, we will only call for these operations on the - // "top-level" beans and have them call post processing actions on embedded DD objects, if needed - timer.start("DD Post Processing"); - for (DataObjectEntry entry : ddBeans.getBeansOfType(DataObjectEntry.class).values()) { - entry.dataDictionaryPostProcessing(); - } - for (DocumentEntry entry : ddBeans.getBeansOfType(DocumentEntry.class).values()) { - entry.dataDictionaryPostProcessing(); - } - timer.stop(); - - timer.start("Data Dictionary Indexing"); - ddIndex.run(); - timer.stop(); - - // The UIF defaulting must be done before the UIF indexing but after - // the main DD data object indexing - timer.start("UIF Defaulting"); - // Check if there are inquiry definitions for data objects - generateMissingInquiryDefinitions(); - // Check if there are lookup definitions for data objects - generateMissingLookupDefinitions(); - timer.stop(); + public void performDictionaryPostProcessing(final boolean allowConcurrentValidation) { + ViewLifecycle.encapsulateInitialization(new Callable() { + @Override + public Void call() throws Exception { + LOG.info("Starting Data Dictionary Post Processing"); + timer.start("Spring Post Processing"); + PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); + propertyPlaceholderConfigurer.setProperties(ConfigContext.getCurrentContextConfig().getProperties()); + propertyPlaceholderConfigurer.postProcessBeanFactory(ddBeans); + + DictionaryBeanFactoryPostProcessor dictionaryBeanPostProcessor = + new DictionaryBeanFactoryPostProcessor(DataDictionary.this, ddBeans); + dictionaryBeanPostProcessor.postProcessBeanFactory(); + timer.stop(); + timer.start("UIF Post Processing"); + // post processes UIF beans for pulling out expressions within property values + UifBeanFactoryPostProcessor factoryPostProcessor = new UifBeanFactoryPostProcessor(); + factoryPostProcessor.postProcessBeanFactory(ddBeans); + timer.stop(); + + timer.start("Instantiating DD Beans"); + ddBeans.preInstantiateSingletons(); + timer.stop(); + + // Allow the DD to perform final post processing in a controlled order + // Unlike the Spring post processor, we will only call for these operations on the + // "top-level" beans and have them call post processing actions on embedded DD objects, if needed + timer.start("DD Post Processing"); + for (DataObjectEntry entry : ddBeans.getBeansOfType(DataObjectEntry.class).values()) { + entry.dataDictionaryPostProcessing(); + } + for (DocumentEntry entry : ddBeans.getBeansOfType(DocumentEntry.class).values()) { + entry.dataDictionaryPostProcessing(); + } + timer.stop(); - timer.start("UIF Indexing"); - uifIndex.run(); - timer.stop(); - LOG.info( "Completed Data Dictionary Post Processing"); + timer.start("Data Dictionary Indexing"); + ddIndex.run(); + timer.stop(); + + // The UIF defaulting must be done before the UIF indexing but after + // the main DD data object indexing + timer.start("UIF Defaulting"); + // Check if there are inquiry definitions for data objects + generateMissingInquiryDefinitions(); + // Check if there are lookup definitions for data objects + generateMissingLookupDefinitions(); + timer.stop(); + + timer.start("UIF Indexing"); + uifIndex.run(); + timer.stop(); + LOG.info("Completed Data Dictionary Post Processing"); + return null; + } + }); } protected void generateMissingInquiryDefinitions() { @@ -328,42 +336,48 @@ } } - public void validateDD(boolean validateEbos) { - timer.start("Validation"); - DataDictionary.validateEBOs = validateEbos; - - Validator.resetErrorReport(); - - Map doBeans = ddBeans.getBeansOfType(DataObjectEntry.class); - for (DataObjectEntry entry : doBeans.values()) { - entry.completeValidation( new ValidationTrace() ); - } - - Map docBeans = ddBeans.getBeansOfType(DocumentEntry.class); - for (DocumentEntry entry : docBeans.values()) { - entry.completeValidation( new ValidationTrace() ); - } - - List errorReports = Validator.getErrorReports(); - if ( errorReports.size() > 0 ) { - boolean errors = false; - LOG.error( "***********************************************************"); - LOG.error( "ERRORS OR WARNINGS REPORTED UPON DATA DICTIONARY VALIDATION"); - LOG.error( "***********************************************************"); - for ( ErrorReport err : errorReports ) { - if ( err.isError() ) { - LOG.error(err.errorMessage()); - errors = true; - } else { - LOG.warn(err.errorMessage()); + public void validateDD(final boolean validateEbos) { + ViewLifecycle.encapsulateInitialization(new Callable() { + @Override + public Void call() throws Exception { + timer.start("Validation"); + DataDictionary.validateEBOs = validateEbos; + + Validator.resetErrorReport(); + + Map doBeans = ddBeans.getBeansOfType(DataObjectEntry.class); + for (DataObjectEntry entry : doBeans.values()) { + entry.completeValidation(new ValidationTrace()); } - } - if ( errors ) { - throw new DataDictionaryException( "Errors during DD validation, failing validation." ); - } - } - timer.stop(); + Map docBeans = ddBeans.getBeansOfType(DocumentEntry.class); + for (DocumentEntry entry : docBeans.values()) { + entry.completeValidation(new ValidationTrace()); + } + + List errorReports = Validator.getErrorReports(); + if (errorReports.size() > 0) { + boolean errors = false; + LOG.error("***********************************************************"); + LOG.error("ERRORS OR WARNINGS REPORTED UPON DATA DICTIONARY VALIDATION"); + LOG.error("***********************************************************"); + for (ErrorReport err : errorReports) { + if (err.isError()) { + LOG.error(err.errorMessage()); + errors = true; + } else { + LOG.warn(err.errorMessage()); + } + } + if (errors) { + throw new DataDictionaryException("Errors during DD validation, failing validation."); + } + } + + timer.stop(); + return null; + } + }); } public void validateDD() { @@ -685,7 +699,7 @@ * @param beanName - id or name for the bean definition * @return Object object instance created or the singleton being maintained */ - public Object getDictionaryObject(String beanName) { + public Object getDictionaryObject(final String beanName) { return ddBeans.getBean(beanName); } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/uif/UifDictionaryIndex.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/uif/UifDictionaryIndex.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/datadictionary/uif/UifDictionaryIndex.java (working copy) @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.Callable; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -29,9 +30,10 @@ import org.kuali.rice.krad.datadictionary.DefaultListableBeanFactory; import org.kuali.rice.krad.service.KRADServiceLocatorWeb; import org.kuali.rice.krad.uif.UifConstants; +import org.kuali.rice.krad.uif.UifConstants.ViewStatus; import org.kuali.rice.krad.uif.UifConstants.ViewType; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.service.ViewTypeService; -import org.kuali.rice.krad.uif.util.ComponentUtils; import org.kuali.rice.krad.uif.util.ViewModelUtils; import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.util.KRADConstants; @@ -51,7 +53,7 @@ */ public class UifDictionaryIndex implements Runnable { private static final Log LOG = LogFactory.getLog(UifDictionaryIndex.class); - + private static final int VIEW_CACHE_SIZE = 1000; private DefaultListableBeanFactory ddBeans; @@ -87,19 +89,47 @@ * @return View instance with the given id * @throws org.kuali.rice.krad.datadictionary.DataDictionaryException if view doesn't exist for id */ - public View getViewById(String viewId) { + public View getViewById(final String viewId) { + View view = getImmutableViewById(viewId); + + if ( LOG.isDebugEnabled() ) { + LOG.debug("Pulled view " + viewId + " from Cache. Cloning..." ); + } + + return ViewLifecycle.getMutableCopy(view); + } + + /** + * Gets a view instance from the pool or factory but does not replace the view, meant for view readonly + * access (not running the lifecycle but just checking configuration) + * + * @param viewId the unique id for the view + * @return View instance with the given id + */ + public View getImmutableViewById(String viewId) { View cachedView = viewCache.get(viewId); if ( cachedView == null ) { if ( LOG.isDebugEnabled() ) { LOG.debug( "View " + viewId + " not in cache - creating and storing to cache"); } - String beanName = viewBeanEntriesById.get(viewId); + final String beanName = viewBeanEntriesById.get(viewId); if (StringUtils.isBlank(beanName)) { throw new DataDictionaryException("Unable to find View with id: " + viewId); } - View newView = ddBeans.getBean(beanName, View.class); + View newView = ViewLifecycle.encapsulateInitialization(new Callable(){ + @Override + public View call() throws Exception { + View view = ddBeans.getBean(beanName, View.class); + + if (LOG.isDebugEnabled()) { + LOG.debug("Updating view status to CREATED for view: " + view.getId()); + } + + view.setViewStatus(ViewStatus.CREATED); + return view; + }}); boolean inDevMode = ConfigContext.getCurrentContextConfig().getBooleanProperty( KRADConstants.ConfigParameters.KRAD_DEV_MODE); @@ -108,36 +138,13 @@ synchronized (viewCache) { viewCache.put(viewId, newView); } + } else if ( LOG.isDebugEnabled() ) { + LOG.debug( "DEV MODE - View " + viewId + " will not be cached"); } - + cachedView = newView; - } else { - if ( LOG.isDebugEnabled() ) { - LOG.debug("Pulled view " + viewId + " from Cache. Cloning..." ); - } } - View clonedView = ComponentUtils.copy(cachedView); - - return clonedView; - } - - /** - * Gets a view instance from the pool or factory but does not replace the view, meant for view readonly - * access (not running the lifecycle but just checking configuration) - * - * @param viewId the unique id for the view - * @return View instance with the given id - */ - public View getImmutableViewById(String viewId) { - // check for preloaded view - View cachedView = viewCache.get(viewId); - // If not already cached, pull and cache as normal - // This makes the first call to this method more expensive, as it - // will get a cloned copy instead of the original from the cache - if ( cachedView == null ) { - return getViewById(viewId); - } return cachedView; } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/inquiry/InquirableImpl.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/inquiry/InquirableImpl.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/inquiry/InquirableImpl.java (working copy) @@ -328,7 +328,7 @@ } @Override - protected DataDictionaryService getDataDictionaryService() { + public DataDictionaryService getDataDictionaryService() { return KRADServiceLocatorWeb.getDataDictionaryService(); } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/lookup/LookupableImpl.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/lookup/LookupableImpl.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/lookup/LookupableImpl.java (working copy) @@ -43,6 +43,7 @@ import org.kuali.rice.krad.uif.element.Action; import org.kuali.rice.krad.uif.field.InputField; import org.kuali.rice.krad.uif.field.LookupInputField; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl; import org.kuali.rice.krad.uif.util.ComponentUtils; import org.kuali.rice.krad.uif.util.LookupInquiryUtils; @@ -91,7 +92,9 @@ * java.lang.Object) */ @Override - public void performInitialization(View view, Object model) { + public void performCustomViewInitialization(Object model) { + View view = ViewLifecycle.getActiveLifecycle().getView(); + if (!LookupView.class.isAssignableFrom(view.getClass())) { throw new IllegalArgumentException( "View class '" + view.getClass() + " is not assignable from the '" + LookupView.class + "'"); @@ -99,8 +102,6 @@ LookupView lookupView = (LookupView) view; setDataObjectClass(lookupView.getDataObjectClassName()); - - super.performInitialization(view, model); } /** Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/maintenance/MaintainableImpl.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/maintenance/MaintainableImpl.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/maintenance/MaintainableImpl.java (working copy) @@ -442,7 +442,7 @@ * */ @Override - protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine, + public void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine, boolean isValidLine) { super.processAfterAddLine(view, collectionGroup, model, addLine, isValidLine); @@ -489,7 +489,7 @@ * org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object, int) */ @Override - protected void processAfterDeleteLine(View view, CollectionGroup collectionGroup, Object model, int lineIndex) { + public void processAfterDeleteLine(View view, CollectionGroup collectionGroup, Object model, int lineIndex) { super.processAfterDeleteLine(view, collectionGroup, model, lineIndex); // Check for maintenance documents in edit but exclude notes and ad hoc recipients Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/Component.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/Component.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/Component.java (working copy) @@ -15,16 +15,16 @@ */ package org.kuali.rice.krad.uif.component; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean; import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; import org.kuali.rice.krad.uif.modifier.ComponentModifier; -import org.kuali.rice.krad.uif.view.View; +import org.kuali.rice.krad.uif.util.LifecycleElement; import org.kuali.rice.krad.uif.widget.Tooltip; -import java.io.Serializable; -import java.util.List; -import java.util.Map; - /** * Component defines basic properties and methods that all rendering element implement * @@ -52,7 +52,7 @@ * @see org.kuali.rice.krad.uif.field.Field * @see org.kuali.rice.krad.uif.widget.Widget */ -public interface Component extends UifDictionaryBean, Serializable, Ordered, ScriptEventSupport { +public interface Component extends UifDictionaryBean, LifecycleElement, Serializable, Ordered, ScriptEventSupport { /** * The unique id (within a given tree) for the component @@ -185,12 +185,11 @@ * once per component lifecycle and is invoked within the initialize phase of the view lifecylce. *

* - * @param view - view instance in which the component belongs * @param model - object instance containing the view data * @see org.kuali.rice.krad.uif.service.ViewHelperService#performInitialization(org.kuali.rice.krad.uif.view.View, * Object) */ - void performInitialization(View view, Object model); + void performInitialization(Object model); /** * Called after the initialize phase to perform conditional logic based on the model data @@ -200,11 +199,10 @@ * based on the given data *

* - * @param view - view instance to which the component belongs * @param model - Top level object containing the data (could be the form or a * top level business object, dto) */ - void performApplyModel(View view, Object model, Component parent); + void performApplyModel(Object model, Component parent); /** * The last phase before the view is rendered @@ -217,7 +215,7 @@ * @param model - top level object containing the data * @param parent - parent component */ - void performFinalize(View view, Object model, Component parent); + void performFinalize(Object model, Component parent); /** * List of components that are contained within the component and should be sent through Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/ComponentBase.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/ComponentBase.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/component/ComponentBase.java (working copy) @@ -18,9 +18,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.kuali.rice.krad.data.DataObjectUtils; @@ -31,9 +31,13 @@ import org.kuali.rice.krad.datadictionary.validator.Validator; import org.kuali.rice.krad.uif.CssConstants; import org.kuali.rice.krad.uif.control.ControlBase; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.modifier.ComponentModifier; import org.kuali.rice.krad.uif.util.CloneUtils; import org.kuali.rice.krad.uif.util.ExpressionUtils; +import org.kuali.rice.krad.uif.util.LifecycleAwareList; +import org.kuali.rice.krad.uif.util.LifecycleAwareMap; +import org.kuali.rice.krad.uif.util.LifecycleElement; import org.kuali.rice.krad.uif.util.ProcessLogger; import org.kuali.rice.krad.uif.util.ScriptUtils; import org.kuali.rice.krad.uif.view.ExpressionEvaluator; @@ -54,8 +58,20 @@ */ @BeanTag(name = "componentBase-bean", parent = "Uif-ComponentBase") public abstract class ComponentBase extends UifDictionaryBeanBase implements Component { + private static final long serialVersionUID = -4449335748129894350L; + private static final ThreadLocal TL_INITIALIZING = new ThreadLocal(); + + public static boolean isInitializing() { + return Boolean.TRUE.equals(TL_INITIALIZING.get()); + } + + /** + * Track mutability status. + */ + private boolean mutable; + private String id; private String baseId; private String template; @@ -105,6 +121,7 @@ private String cellWidth; private String style; + private List libraryCssClasses; private List cssClasses; private List additionalCssClasses; @@ -148,15 +165,13 @@ private List componentModifiers; - private Map templateOptions; + protected Map templateOptions; + private String templateOptionsJSString; @ReferenceCopy(newCollectionInstance = true) private transient Map context; - @ReferenceCopy - private transient Map unmodifiableContext; - private List propertyReplacers; private Map dataAttributes; @@ -182,20 +197,69 @@ disableSessionPersistence = false; forceSessionPersistence = false; - // TODO : lazy init - // DONE: refreshWhenChangedPropertyNames = new ArrayList(); - // DONE: additionalComponentsToRefresh = new ArrayList(); - // DONE: finalizeMethodAdditionalArguments = new ArrayList(); - // DONE: cellCssClasses = new ArrayList(); - // DONE: cssClasses = new ArrayList(); - // DONE: componentModifiers = new ArrayList(); - // DONE: templateOptions = new HashMap(); - // DONE: context = new HashMap(); - // DONE: propertyReplacers = new ArrayList(); - // DONE: dataAttributes = new HashMap(); - // TODO: KULRICE-8954 test for NPE + context = Collections.emptyMap(); + dataAttributes = Collections.emptyMap(); + templateOptions = Collections.emptyMap(); + + cssClasses = Collections.emptyList(); + libraryCssClasses = Collections.emptyList(); + additionalCssClasses = Collections.emptyList(); + } + + /** + * Check for mutability on the component before modifying state. + * + * @param legalDuringInitialization True if the operation is legal during view configuration, + * false if the operation is part of the component lifecycle. + * @throws IllegalStateException If the component is not mutable. + */ + public void checkMutable(boolean legalDuringInitialization) { + if (!ViewLifecycle.isActive()) { + throw new IllegalStateException("View context is not active"); + } + + if (ViewLifecycle.isCopyActive()) { + return; + } + + if (ViewLifecycle.isLifecycleActive() && !(mutable && ViewLifecycle.isMutable(this))) { + throw new IllegalStateException( + "Component " + getId() + " is immutable, use copy() to get a mutable instance"); + } - unmodifiableContext = context = Collections.emptyMap(); + if (ViewLifecycle.isInitializing() && !legalDuringInitialization) { + throw new IllegalStateException("View has not been fully initialized"); + } + } + + /** + * Determine if this layout manager is mutable. + * + *

+ * Most layout managers are immutable, and all are immutable expect during initialization + * and the during the view lifecycle. Those that have been copied within the view lifecycle, + * however, may be modified during the same lifecycle. + *

+ * + * @return True if the component is mutable. + */ + public boolean isMutable(boolean legalBeforeConfiguration) { + return (ViewLifecycle.isLifecycleActive() && mutable && ViewLifecycle.isMutable(this)) || + (ViewLifecycle.isInitializing() && legalBeforeConfiguration); + } + + /** + * Mark this component as mutable within the current view lifecycle. + * + * @param mutable True to allow component state to change within the current view lifecycle. + */ + public void allowModification() { + if (!ViewLifecycle.isLifecycleActive()) { + throw new IllegalStateException("View lifecycle is not active"); + } + + this.mutable = true; + ViewLifecycle.setMutable(this); } /** @@ -208,8 +272,9 @@ * @see org.kuali.rice.krad.uif.component.Component#performInitialization(org.kuali.rice.krad.uif.view.View, * java.lang.Object) */ - public void performInitialization(View view, Object model) { - + @Override + public void performInitialization(Object model) { + checkMutable(false); } /** @@ -223,7 +288,12 @@ * @see org.kuali.rice.krad.uif.component.Component#performApplyModel(org.kuali.rice.krad.uif.view.View, * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ - public void performApplyModel(View view, Object model, Component parent) { + @Override + public void performApplyModel(Object model, Component parent) { + checkMutable(false); + + View view = ViewLifecycle.getActiveLifecycle().getView(); + if (this.render && StringUtils.isNotEmpty(progressiveRender)) { // progressive anded with render, will not render at least one of the two are false ExpressionEvaluator expressionEvaluator = view.getViewHelperService().getExpressionEvaluator(); @@ -231,7 +301,7 @@ String adjustedProgressiveRender = expressionEvaluator.replaceBindingPrefixes(view, this, progressiveRender); - Boolean progRenderEval = (Boolean) expressionEvaluator.evaluateExpression(unmodifiableContext, + Boolean progRenderEval = (Boolean) expressionEvaluator.evaluateExpression(context, adjustedProgressiveRender); this.setRender(progRenderEval); @@ -250,8 +320,13 @@ * @see org.kuali.rice.krad.uif.component.Component#performFinalize(org.kuali.rice.krad.uif.view.View, * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ - public void performFinalize(View view, Object model, Component parent) { - ExpressionEvaluator expressionEvaluator = view.getViewHelperService().getExpressionEvaluator(); + @Override + public void performFinalize(Object model, Component parent) { + checkMutable(false); + + ViewLifecycle viewLifecycle = ViewLifecycle.getActiveLifecycle(); + View view = viewLifecycle.getView(); + ExpressionEvaluator expressionEvaluator = viewLifecycle.getHelper().getExpressionEvaluator(); // progressiveRender expression setup if (StringUtils.isNotEmpty(progressiveRender)) { @@ -435,6 +510,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setId(java.lang.String) */ public void setId(String id) { + checkMutable(true); this.id = id; } @@ -449,6 +525,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setBaseId(java.lang.String) */ public void setBaseId(String baseId) { + checkMutable(true); this.baseId = baseId; } @@ -464,6 +541,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setTemplate(java.lang.String) */ public void setTemplate(String template) { + checkMutable(true); this.template = template; } @@ -479,6 +557,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setTemplateName(java.lang.String) */ public void setTemplateName(String templateName) { + checkMutable(true); this.templateName = templateName; } @@ -494,6 +573,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setTitle(java.lang.String) */ public void setTitle(String title) { + checkMutable(true); this.title = title; } @@ -509,6 +589,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setHidden(boolean) */ public void setHidden(boolean hidden) { + checkMutable(true); this.hidden = hidden; } @@ -524,6 +605,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setReadOnly(boolean) */ public void setReadOnly(boolean readOnly) { + checkMutable(true); this.readOnly = readOnly; } @@ -539,6 +621,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRequired(java.lang.Boolean) */ public void setRequired(Boolean required) { + checkMutable(true); this.required = required; } @@ -554,6 +637,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRender(boolean) */ public void setRender(boolean render) { + checkMutable(true); this.render = render; } @@ -569,6 +653,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRetrieveViaAjax(boolean) */ public void setRetrieveViaAjax(boolean retrieveViaAjax) { + checkMutable(true); this.retrieveViaAjax = retrieveViaAjax; } @@ -584,6 +669,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setColSpan(int) */ public void setColSpan(int colSpan) { + checkMutable(true); this.colSpan = colSpan; } @@ -599,6 +685,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRowSpan(int) */ public void setRowSpan(int rowSpan) { + checkMutable(true); this.rowSpan = rowSpan; } @@ -613,6 +700,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setCellCssClasses(java.util.List) */ public void setCellCssClasses(List cellCssClasses) { + checkMutable(true); this.cellCssClasses = cellCssClasses; } @@ -620,6 +708,7 @@ * @see org.kuali.rice.krad.uif.component.Component#addCellCssClass(String) */ public void addCellCssClass(String cssClass) { + checkMutable(false); if (this.cellCssClasses == null) { this.cellCssClasses = new ArrayList(); } @@ -654,6 +743,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setCellStyle(java.lang.String) */ public void setCellStyle(String cellStyle) { + checkMutable(true); this.cellStyle = cellStyle; } @@ -668,6 +758,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setCellWidth(java.lang.String) */ public void setCellWidth(String cellWidth) { + checkMutable(true); this.cellWidth = cellWidth; } @@ -683,6 +774,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setAlign(java.lang.String) */ public void setAlign(String align) { + checkMutable(true); this.align = align; } @@ -698,6 +790,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setValign(java.lang.String) */ public void setValign(String valign) { + checkMutable(true); this.valign = valign; } @@ -713,6 +806,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setWidth(java.lang.String) */ public void setWidth(String width) { + checkMutable(true); this.width = width; } @@ -728,6 +822,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setStyle(java.lang.String) */ public void setStyle(String style) { + checkMutable(true); this.style = style; } @@ -742,6 +837,10 @@ * @return the library cssClasses */ public List getLibraryCssClasses() { + if (libraryCssClasses == Collections.EMPTY_LIST && isMutable(true)) { + libraryCssClasses = new LifecycleAwareList(this); + } + return libraryCssClasses; } @@ -751,7 +850,13 @@ * @param libraryCssClasses */ public void setLibraryCssClasses(List libraryCssClasses) { - this.libraryCssClasses = libraryCssClasses; + checkMutable(true); + + if (libraryCssClasses == null) { + this.libraryCssClasses = Collections.emptyList(); + } else { + this.libraryCssClasses = new LifecycleAwareList(this, libraryCssClasses); + } } /** @@ -759,14 +864,23 @@ */ @BeanTagAttribute(name = "cssClasses", type = BeanTagAttribute.AttributeType.LISTVALUE) public List getCssClasses() { - return this.cssClasses; + if (cssClasses == Collections.EMPTY_LIST && isMutable(true)) { + cssClasses = new LifecycleAwareList(this); + } + + return cssClasses; } /** * @see org.kuali.rice.krad.uif.component.Component#setCssClasses(java.util.List) */ public void setCssClasses(List cssClasses) { - this.cssClasses = cssClasses; + checkMutable(true); + if (cssClasses == null) { + this.cssClasses = Collections.emptyList(); + } else { + this.cssClasses = new LifecycleAwareList(this, cssClasses); + } } /** @@ -774,14 +888,23 @@ */ @BeanTagAttribute(name = "additionalCssClasses", type = BeanTagAttribute.AttributeType.LISTVALUE) public List getAdditionalCssClasses() { - return this.additionalCssClasses; + if (additionalCssClasses == Collections.EMPTY_LIST && isMutable(true)) { + additionalCssClasses = new LifecycleAwareList(this); + } + + return additionalCssClasses; } /** * @see org.kuali.rice.krad.uif.component.Component#setAdditionalCssClasses(java.util.List) */ public void setAdditionalCssClasses(List additionalCssClasses) { - this.additionalCssClasses = additionalCssClasses; + checkMutable(true); + if (additionalCssClasses == null) { + this.additionalCssClasses = Collections.emptyList(); + } else { + this.additionalCssClasses = new LifecycleAwareList(this, additionalCssClasses); + } } /** @@ -802,9 +925,15 @@ * @see org.kuali.rice.krad.uif.component.Component#addStyleClass(java.lang.String) */ public void addStyleClass(String styleClass) { - if (cssClasses == null) { - cssClasses = new LinkedList(); + checkMutable(false); + if (StringUtils.isEmpty(styleClass)) { + return; + } + + if (cssClasses.isEmpty()) { + setCssClasses(new ArrayList()); } + if (!cssClasses.contains(styleClass)) { cssClasses.add(styleClass); } @@ -814,6 +943,7 @@ * @see org.kuali.rice.krad.uif.component.Component#appendToStyle(java.lang.String) */ public void appendToStyle(String styleRules) { + checkMutable(false); if (style == null) { style = ""; } @@ -834,6 +964,7 @@ * @param finalizeMethodToCall */ public void setFinalizeMethodToCall(String finalizeMethodToCall) { + checkMutable(true); this.finalizeMethodToCall = finalizeMethodToCall; } @@ -851,6 +982,7 @@ * @param finalizeMethodAdditionalArguments */ public void setFinalizeMethodAdditionalArguments(List finalizeMethodAdditionalArguments) { + checkMutable(true); this.finalizeMethodAdditionalArguments = finalizeMethodAdditionalArguments; } @@ -868,6 +1000,7 @@ * @param finalizeMethodInvoker */ public void setFinalizeMethodInvoker(MethodInvokerConfig finalizeMethodInvoker) { + checkMutable(true); this.finalizeMethodInvoker = finalizeMethodInvoker; } @@ -883,6 +1016,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setSelfRendered(boolean) */ public void setSelfRendered(boolean selfRendered) { + checkMutable(true); this.selfRendered = selfRendered; } @@ -898,6 +1032,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRenderedHtmlOutput(java.lang.String) */ public void setRenderedHtmlOutput(String renderedHtmlOutput) { + checkMutable(true); this.renderedHtmlOutput = renderedHtmlOutput; } @@ -913,6 +1048,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setDisableSessionPersistence(boolean) */ public void setDisableSessionPersistence(boolean disableSessionPersistence) { + checkMutable(true); this.disableSessionPersistence = disableSessionPersistence; } @@ -928,6 +1064,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setForceSessionPersistence(boolean) */ public void setForceSessionPersistence(boolean forceSessionPersistence) { + checkMutable(true); this.forceSessionPersistence = forceSessionPersistence; } @@ -943,6 +1080,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setComponentSecurity(org.kuali.rice.krad.uif.component.ComponentSecurity) */ public void setComponentSecurity(ComponentSecurity componentSecurity) { + checkMutable(true); this.componentSecurity = componentSecurity; } @@ -968,6 +1106,7 @@ * @see org.kuali.rice.krad.uif.component.ComponentSecurity#setEditAuthz(boolean) */ public void setEditAuthz(Boolean editAuthz) { + checkMutable(true); initializeComponentSecurity(); this.componentSecurity.setEditAuthz(editAuthz); @@ -986,6 +1125,7 @@ * @see org.kuali.rice.krad.uif.component.ComponentSecurity#setViewAuthz(boolean) */ public void setViewAuthz(Boolean viewAuthz) { + checkMutable(true); initializeComponentSecurity(); this.componentSecurity.setViewAuthz(viewAuthz); @@ -1003,7 +1143,10 @@ * @see org.kuali.rice.krad.uif.component.Component#setComponentModifiers(java.util.List) */ public void setComponentModifiers(List componentModifiers) { - this.componentModifiers = componentModifiers; + checkMutable(true); + this.componentModifiers = componentModifiers == null + ? Collections. emptyList() + : Collections. unmodifiableList(componentModifiers); } /** @@ -1011,18 +1154,23 @@ */ @BeanTagAttribute(name = "context", type = BeanTagAttribute.AttributeType.MAPBEAN) public Map getContext() { - return this.unmodifiableContext; + if (context == Collections.EMPTY_MAP && isMutable(true)) { + context = new LifecycleAwareMap(this); + } + + return context; } /** * @see org.kuali.rice.krad.uif.component.Component#setContext(java.util.Map) */ public void setContext(Map context) { - if (context == null || context.isEmpty()) { - this.unmodifiableContext = this.context = Collections.emptyMap(); + checkMutable(true); + + if (context == null) { + this.context = Collections.emptyMap(); } else { - this.context = context; - this.unmodifiableContext = Collections.unmodifiableMap(this.context); + this.context = new LifecycleAwareMap(this, context); } } @@ -1031,13 +1179,13 @@ * java.lang.Object) */ public void pushObjectToContext(String objectName, Object object) { - if (this.context.isEmpty()) { - this.context = new HashMap(); - this.unmodifiableContext = Collections.unmodifiableMap(this.context); + checkMutable(false); + if (context == Collections.EMPTY_MAP && isMutable(true)) { + context = new LifecycleAwareMap(this); } pushToPropertyReplacerContext(objectName, object); - this.context.put(objectName, object); + context.put(objectName, object); } /* @@ -1045,6 +1193,7 @@ * PropertyReplacer object. Only checks for a list, map or component. */ protected void pushToPropertyReplacerContext(String objectName, Object object) { + checkMutable(false); List propertyReplacerComponents = getPropertyReplacerComponents(); if (propertyReplacerComponents != null) { for (Component replacerComponent : propertyReplacerComponents) { @@ -1057,15 +1206,15 @@ * @see org.kuali.rice.krad.uif.component.ComponentBase#pushAllToContext */ public void pushAllToContext(Map objects) { + checkMutable(false); if (objects == null || objects.isEmpty()) { return; } - if (this.context.isEmpty()) { - this.context = new HashMap(); - this.unmodifiableContext = Collections.unmodifiableMap(this.context); + if (context == Collections.EMPTY_MAP && isMutable(true)) { + context = new LifecycleAwareMap(this); } - + context.putAll(objects); List propertyReplacerComponents = getPropertyReplacerComponents(); @@ -1088,7 +1237,10 @@ * @see org.kuali.rice.krad.uif.component.Component#setPropertyReplacers(java.util.List) */ public void setPropertyReplacers(List propertyReplacers) { - this.propertyReplacers = propertyReplacers; + checkMutable(true); + this.propertyReplacers = propertyReplacers == null + ? Collections. emptyList() + : Collections. unmodifiableList(propertyReplacers); } /** @@ -1105,6 +1257,7 @@ * @param order */ public void setOrder(int order) { + checkMutable(true); this.order = order; } @@ -1120,6 +1273,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setToolTip(Tooltip) */ public void setToolTip(Tooltip toolTip) { + checkMutable(true); this.toolTip = toolTip; } @@ -1127,7 +1281,7 @@ * @see Component#getEventHandlerScript() */ public String getEventHandlerScript() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append(ScriptUtils.buildEventHandlerScript(getId(), "load", getOnLoadScript())); @@ -1168,6 +1322,7 @@ * @see ScriptEventSupport#setOnLoadScript(java.lang.String) */ public void setOnLoadScript(String onLoadScript) { + checkMutable(true); this.onLoadScript = onLoadScript; } @@ -1183,6 +1338,7 @@ * @see ScriptEventSupport#setOnDocumentReadyScript(java.lang.String) */ public void setOnDocumentReadyScript(String onDocumentReadyScript) { + checkMutable(true); this.onDocumentReadyScript = onDocumentReadyScript; } @@ -1198,6 +1354,7 @@ * @see ScriptEventSupport#setOnUnloadScript(java.lang.String) */ public void setOnUnloadScript(String onUnloadScript) { + checkMutable(true); this.onUnloadScript = onUnloadScript; } @@ -1213,6 +1370,7 @@ * @see ScriptEventSupport#setOnCloseScript(java.lang.String) */ public void setOnCloseScript(String onCloseScript) { + checkMutable(true); this.onCloseScript = onCloseScript; } @@ -1228,6 +1386,7 @@ * @see ScriptEventSupport#setOnBlurScript(java.lang.String) */ public void setOnBlurScript(String onBlurScript) { + checkMutable(true); this.onBlurScript = onBlurScript; } @@ -1243,6 +1402,7 @@ * @see ScriptEventSupport#setOnChangeScript(java.lang.String) */ public void setOnChangeScript(String onChangeScript) { + checkMutable(true); this.onChangeScript = onChangeScript; } @@ -1258,6 +1418,7 @@ * @see ScriptEventSupport#setOnClickScript(java.lang.String) */ public void setOnClickScript(String onClickScript) { + checkMutable(true); this.onClickScript = onClickScript; } @@ -1273,6 +1434,7 @@ * @see ScriptEventSupport#setOnDblClickScript(java.lang.String) */ public void setOnDblClickScript(String onDblClickScript) { + checkMutable(true); this.onDblClickScript = onDblClickScript; } @@ -1288,6 +1450,7 @@ * @see ScriptEventSupport#setOnFocusScript(java.lang.String) */ public void setOnFocusScript(String onFocusScript) { + checkMutable(true); this.onFocusScript = onFocusScript; } @@ -1303,6 +1466,7 @@ * @see ScriptEventSupport#setOnSubmitScript(java.lang.String) */ public void setOnSubmitScript(String onSubmitScript) { + checkMutable(true); this.onSubmitScript = onSubmitScript; } @@ -1318,6 +1482,7 @@ * @see ScriptEventSupport#setOnKeyPressScript(java.lang.String) */ public void setOnKeyPressScript(String onKeyPressScript) { + checkMutable(true); this.onKeyPressScript = onKeyPressScript; } @@ -1333,6 +1498,7 @@ * @see ScriptEventSupport#setOnKeyUpScript(java.lang.String) */ public void setOnKeyUpScript(String onKeyUpScript) { + checkMutable(true); this.onKeyUpScript = onKeyUpScript; } @@ -1348,6 +1514,7 @@ * @see ScriptEventSupport#setOnKeyDownScript(java.lang.String) */ public void setOnKeyDownScript(String onKeyDownScript) { + checkMutable(true); this.onKeyDownScript = onKeyDownScript; } @@ -1363,6 +1530,7 @@ * @see ScriptEventSupport#setOnMouseOverScript(java.lang.String) */ public void setOnMouseOverScript(String onMouseOverScript) { + checkMutable(true); this.onMouseOverScript = onMouseOverScript; } @@ -1378,6 +1546,7 @@ * @see ScriptEventSupport#setOnMouseOutScript(java.lang.String) */ public void setOnMouseOutScript(String onMouseOutScript) { + checkMutable(true); this.onMouseOutScript = onMouseOutScript; } @@ -1393,6 +1562,7 @@ * @see ScriptEventSupport#setOnMouseUpScript(java.lang.String) */ public void setOnMouseUpScript(String onMouseUpScript) { + checkMutable(true); this.onMouseUpScript = onMouseUpScript; } @@ -1408,6 +1578,7 @@ * @see ScriptEventSupport#setOnMouseDownScript(java.lang.String) */ public void setOnMouseDownScript(String onMouseDownScript) { + checkMutable(true); this.onMouseDownScript = onMouseDownScript; } @@ -1423,6 +1594,7 @@ * @see ScriptEventSupport#setOnMouseMoveScript(java.lang.String) */ public void setOnMouseMoveScript(String onMouseMoveScript) { + checkMutable(true); this.onMouseMoveScript = onMouseMoveScript; } @@ -1431,14 +1603,23 @@ */ @BeanTagAttribute(name = "templateOptions", type = BeanTagAttribute.AttributeType.MAPVALUE) public Map getTemplateOptions() { - return this.templateOptions; + if (templateOptions == Collections.EMPTY_MAP && isMutable(true)) { + templateOptions = new LifecycleAwareMap(this); + } + + return templateOptions; } /** * @see Component#setTemplateOptions(java.util.Map) */ public void setTemplateOptions(Map templateOptions) { - this.templateOptions = templateOptions; + checkMutable(true); + if (templateOptions == null) { + this.templateOptions = Collections.emptyMap(); + } else { + this.templateOptions = new LifecycleAwareMap(this, templateOptions); + } } /** @@ -1455,23 +1636,22 @@ } if (templateOptions == null) { - templateOptions = new HashMap(); + return "{}"; } + StringBuilder sb = new StringBuilder(); - sb.append("{"); - for (String optionKey : templateOptions.keySet()) { - String optionValue = templateOptions.get(optionKey); + for (Entry option : templateOptions.entrySet()) { if (sb.length() > 1) { sb.append(","); } - sb.append(optionKey); + sb.append(option.getKey()); sb.append(":"); - sb.append(ScriptUtils.convertToJsValue(optionValue)); + sb.append(ScriptUtils.convertToJsValue(option.getValue())); } sb.append("}"); @@ -1481,6 +1661,7 @@ @Override public void setTemplateOptionsJSString(String templateOptionsJSString) { + checkMutable(true); this.templateOptionsJSString = templateOptionsJSString; } @@ -1515,6 +1696,7 @@ * @param progressiveRender the progressiveRender to set. */ public void setProgressiveRender(String progressiveRender) { + checkMutable(true); this.progressiveRender = progressiveRender; } @@ -1549,6 +1731,7 @@ * @param conditionalRefresh the conditionalRefresh to set */ public void setConditionalRefresh(String conditionalRefresh) { + checkMutable(true); this.conditionalRefresh = conditionalRefresh; } @@ -1612,6 +1795,7 @@ * @param progressiveRenderViaAJAX the progressiveRenderViaAJAX to set. */ public void setProgressiveRenderViaAJAX(boolean progressiveRenderViaAJAX) { + checkMutable(true); this.progressiveRenderViaAJAX = progressiveRenderViaAJAX; } @@ -1638,6 +1822,7 @@ * @param progressiveRenderAndRefresh the progressiveRenderAndRefresh to set. */ public void setProgressiveRenderAndRefresh(boolean progressiveRenderAndRefresh) { + checkMutable(true); this.progressiveRenderAndRefresh = progressiveRenderAndRefresh; } @@ -1655,7 +1840,10 @@ * List) */ public void setRefreshWhenChangedPropertyNames(List refreshWhenChangedPropertyNames) { - this.refreshWhenChangedPropertyNames = refreshWhenChangedPropertyNames; + checkMutable(true); + this.refreshWhenChangedPropertyNames = refreshWhenChangedPropertyNames == null ? + Collections. emptyList() : + Collections. unmodifiableList(refreshWhenChangedPropertyNames); } /** @@ -1667,19 +1855,23 @@ } /** - * @see - * org.kuali.rice.krad.uif.component.Component#setAdditionalComponentsToRefresh(java.util.List - * ) + * @see org.kuali.rice.krad.uif.component.Component#setAdditionalComponentsToRefresh(java.util.List) */ public void setAdditionalComponentsToRefresh(List additionalComponentsToRefresh) { - this.additionalComponentsToRefresh = additionalComponentsToRefresh; + checkMutable(true); + this.additionalComponentsToRefresh = additionalComponentsToRefresh == null + ? Collections. emptyList() + : Collections. unmodifiableList(additionalComponentsToRefresh); + this.additionalComponentsToRefreshJs = null; } /** * @see org.kuali.rice.krad.uif.component.Component#getAdditionalComponentsToRefreshJs */ public String getAdditionalComponentsToRefreshJs() { - if (additionalComponentsToRefresh != null && !additionalComponentsToRefresh.isEmpty()) { + if (additionalComponentsToRefreshJs == null + && additionalComponentsToRefresh != null + && !additionalComponentsToRefresh.isEmpty()) { additionalComponentsToRefreshJs = ScriptUtils.convertStringListToJsArray( this.getAdditionalComponentsToRefresh()); } @@ -1698,6 +1890,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setRefreshedByAction(boolean) */ public void setRefreshedByAction(boolean refreshedByAction) { + checkMutable(true); this.refreshedByAction = refreshedByAction; } @@ -1712,6 +1905,7 @@ * @see Component#setDisclosedByAction(boolean) */ public void setDisclosedByAction(boolean disclosedByAction) { + checkMutable(true); this.disclosedByAction = disclosedByAction; } @@ -1737,6 +1931,7 @@ * @param refreshTimer */ public void setRefreshTimer(int refreshTimer) { + checkMutable(true); this.refreshTimer = refreshTimer; } @@ -1752,6 +1947,7 @@ * @see org.kuali.rice.krad.uif.component.Component#setResetDataOnRefresh(boolean) */ public void setResetDataOnRefresh(boolean resetDataOnRefresh) { + checkMutable(true); this.resetDataOnRefresh = resetDataOnRefresh; } @@ -1785,6 +1981,7 @@ * @param methodToCallOnRefresh */ public void setMethodToCallOnRefresh(String methodToCallOnRefresh) { + checkMutable(true); this.methodToCallOnRefresh = methodToCallOnRefresh; } @@ -1792,6 +1989,7 @@ * @param skipInTabOrder flag */ public void setSkipInTabOrder(boolean skipInTabOrder) { + checkMutable(true); this.skipInTabOrder = skipInTabOrder; } @@ -1819,6 +2017,10 @@ */ @BeanTagAttribute(name = "dataAttributes", type = BeanTagAttribute.AttributeType.MAPVALUE) public Map getDataAttributes() { + if (dataAttributes == Collections.EMPTY_MAP) { + dataAttributes = new LifecycleAwareMap(this); + } + return dataAttributes; } @@ -1829,7 +2031,12 @@ * @param dataAttributes the data attributes to set for this component */ public void setDataAttributes(Map dataAttributes) { - this.dataAttributes = dataAttributes; + checkMutable(true); + if (dataAttributes == null) { + this.dataAttributes = Collections.emptyMap(); + } else { + this.dataAttributes = new LifecycleAwareMap(this, dataAttributes); + } } /** @@ -1839,8 +2046,10 @@ * @param value value of the data attribute */ public void addDataAttribute(String key, String value) { - if (this.dataAttributes == null) { - this.dataAttributes = new HashMap(); + checkMutable(true); + + if (dataAttributes == Collections.EMPTY_MAP) { + dataAttributes = new LifecycleAwareMap(this); } dataAttributes.put(key, value); @@ -1895,6 +2104,7 @@ * @see Component#setPreRenderContent(String) */ public void setPreRenderContent(String preRenderContent) { + checkMutable(true); this.preRenderContent = preRenderContent; } @@ -1910,10 +2120,39 @@ * @see Component#setPostRenderContent(String) */ public void setPostRenderContent(String postRenderContent) { + checkMutable(true); this.postRenderContent = postRenderContent; } /** + * @see org.kuali.rice.krad.datadictionary.DictionaryBeanBase#copy() + */ + @SuppressWarnings("unchecked") + @Override + public T copy() { + if (!ViewLifecycle.isActive()) { + throw new IllegalStateException("View context is not active"); + } + + ComponentBase copy = null; + try { + copy = (ComponentBase) this.getClass().newInstance(); + } catch (InstantiationException e) { + throw new IllegalStateException("Failed to copy component", e); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Failed to copy component", e); + } + + if (ViewLifecycle.isLifecycleActive()) { + copy.allowModification(); + } + + copyProperties(copy); + + return (T) copy; + } + + /** * @see org.kuali.rice.krad.datadictionary.DictionaryBeanBase#copyProperties(Object) */ @Override @@ -2036,11 +2275,7 @@ componentCopy.setToolTip((Tooltip) this.toolTip.copy()); } - if (!this.context.isEmpty()) { - Map contextCopy = new HashMap(this.context); - - componentCopy.setContext(contextCopy); - } + componentCopy.setContext(new HashMap(this.context)); if (propertyReplacers != null) { List propertyReplacersCopy = new ArrayList(); Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/AccordionGroup.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/AccordionGroup.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/AccordionGroup.java (working copy) @@ -15,18 +15,17 @@ */ package org.kuali.rice.krad.uif.container; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.kuali.rice.krad.datadictionary.parse.BeanTag; import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; import org.kuali.rice.krad.datadictionary.parse.BeanTags; import org.kuali.rice.krad.uif.UifConstants; import org.kuali.rice.krad.uif.component.Component; -import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.uif.widget.Accordion; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - /** * Accordion group class used to stack groups by there header titles in an accordion layout */ @@ -58,8 +57,8 @@ * org.kuali.rice.krad.uif.component.Component) */ @Override - public void performFinalize(View view, Object model, Component parent) { - super.performFinalize(view, model, parent); + public void performFinalize(Object model, Component parent) { + super.performFinalize(model, parent); this.addDataAttribute(UifConstants.DataAttributes.TYPE, "Uif-AccordionGroup"); } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroup.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroup.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroup.java (working copy) @@ -33,6 +33,7 @@ import org.kuali.rice.krad.uif.element.Action; import org.kuali.rice.krad.uif.element.Message; import org.kuali.rice.krad.uif.field.DataField; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentFactory; import org.kuali.rice.krad.uif.util.ComponentUtils; import org.kuali.rice.krad.uif.view.View; @@ -190,11 +191,13 @@ * java.lang.Object) */ @Override - public void performInitialization(View view, Object model) { + public void performInitialization(Object model) { setFieldBindingObjectPath(getBindingInfo().getBindingObjectPath()); - super.performInitialization(view, model); + super.performInitialization(model); + View view = ViewLifecycle.getActiveLifecycle().getView(); + if (bindingInfo != null) { bindingInfo.setDefaults(view, getPropertyName()); } @@ -279,8 +282,8 @@ * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ @Override - public void performApplyModel(View view, Object model, Component parent) { - super.performApplyModel(view, model, parent); + public void performApplyModel(Object model, Component parent) { + super.performApplyModel(model, parent); // If we are using server paging, determine if a displayStart value has been set for this collection // and used that value as the displayStart @@ -293,6 +296,8 @@ } } + View view = ViewLifecycle.getActiveLifecycle().getView(); + // adds the script to the add line buttons to keep collection on the same page if (this.renderAddBlankLineButton) { if (this.addBlankLineAction == null) { Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroupBuilder.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroupBuilder.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/CollectionGroupBuilder.java (working copy) @@ -15,6 +15,13 @@ */ package org.kuali.rice.krad.uif.container; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.commons.collections.ListUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -36,6 +43,7 @@ import org.kuali.rice.krad.uif.field.InputField; import org.kuali.rice.krad.uif.field.RemoteFieldsHolder; import org.kuali.rice.krad.uif.layout.CollectionLayoutManager; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentUtils; import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; import org.kuali.rice.krad.uif.util.ScriptUtils; @@ -48,13 +56,6 @@ import org.kuali.rice.krad.util.KRADUtils; import org.kuali.rice.krad.web.form.UifFormBase; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * Builds out the {@code Field} instances for a collection group with a * series of steps that interact with the configured @@ -294,7 +295,6 @@ * @param lineIndex index of the line in the collection, or -1 if we are * building the add line */ - @SuppressWarnings("unchecked") protected void buildLine(View view, Object model, CollectionGroup collectionGroup, String bindingPath, List actions, boolean bindToForm, Object currentLine, int lineIndex) { CollectionLayoutManager layoutManager = (CollectionLayoutManager) collectionGroup.getLayoutManager(); @@ -971,7 +971,8 @@ // apply default values if a new line was created if (newLine != null) { - view.getViewHelperService().applyDefaultValuesForCollectionLine(view, model, collectionGroup, newLine); + ViewLifecycle.getActiveLifecycle() + .applyDefaultValuesForCollectionLine(view, model, collectionGroup, newLine); } } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/ContainerBase.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/ContainerBase.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/ContainerBase.java (working copy) @@ -15,9 +15,11 @@ */ package org.kuali.rice.krad.uif.container; +import java.util.ArrayList; +import java.util.List; + import org.apache.commons.lang.StringUtils; import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; -import org.kuali.rice.krad.datadictionary.validator.ErrorReport; import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; import org.kuali.rice.krad.uif.UifConstants; import org.kuali.rice.krad.uif.component.Component; @@ -26,15 +28,12 @@ import org.kuali.rice.krad.uif.element.Message; import org.kuali.rice.krad.uif.element.ValidationMessages; import org.kuali.rice.krad.uif.layout.LayoutManager; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentFactory; import org.kuali.rice.krad.uif.util.ComponentUtils; -import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.uif.widget.Help; import org.kuali.rice.krad.uif.widget.Tooltip; -import java.util.ArrayList; -import java.util.List; - /** * Base Container implementation which container implementations * can extend @@ -82,19 +81,19 @@ * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object) */ @Override - public void performInitialization(View view, Object model) { - super.performInitialization(view, model); + public void performInitialization(Object model) { + super.performInitialization(model); - sortItems(view, model); + sortItems(model); if ((StringUtils.isNotBlank(instructionalText) || (getPropertyExpression("instructionalText") != null)) && ( instructionalMessage == null)) { instructionalMessage = ComponentFactory.getInstructionalMessage(); - view.assignComponentIds(instructionalMessage); + ViewLifecycle.getActiveLifecycle().getView().assignComponentIds(instructionalMessage); } if (layoutManager != null) { - layoutManager.performInitialization(view, model, this); + layoutManager.performInitialization(model, this); } } @@ -103,8 +102,8 @@ * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ @Override - public void performApplyModel(View view, Object model, Component parent) { - super.performApplyModel(view, model, parent); + public void performApplyModel(Object model, Component parent) { + super.performApplyModel(model, parent); // setup summary message field if necessary if (instructionalMessage != null && StringUtils.isBlank(instructionalMessage.getMessageText())) { @@ -112,7 +111,7 @@ } if (layoutManager != null) { - layoutManager.performApplyModel(view, model, this); + layoutManager.performApplyModel(model, this); } } @@ -129,15 +128,15 @@ * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ @Override - public void performFinalize(View view, Object model, Component parent) { - super.performFinalize(view, model, parent); + public void performFinalize(Object model, Component parent) { + super.performFinalize(model, parent); if(header != null){ header.addDataAttribute(UifConstants.DataAttributes.HEADER_FOR, this.getId()); } if (layoutManager != null) { - layoutManager.performFinalize(view, model, this); + layoutManager.performFinalize(model, this); } } @@ -186,10 +185,9 @@ * @param view view instance containing the container * @param model model object containing the view data */ - protected void sortItems(View view, Object model) { + protected void sortItems(Object model) { // sort items list by the order property - List sortedItems = (List) ComponentUtils.sort(getItems(), - defaultItemPosition); + List sortedItems = ComponentUtils.sort(getItems(), defaultItemPosition); setItems(sortedItems); } Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/DialogGroup.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/DialogGroup.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/DialogGroup.java (working copy) @@ -24,6 +24,7 @@ import org.kuali.rice.krad.uif.control.MultiValueControl; import org.kuali.rice.krad.uif.field.InputField; import org.kuali.rice.krad.uif.field.MessageField; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ScriptUtils; import org.kuali.rice.krad.uif.view.View; @@ -101,14 +102,16 @@ * java.lang.Object) */ @Override - public void performInitialization(View view, Object model) { - super.performInitialization(view, model); + public void performInitialization(Object model) { + super.performInitialization(model); // move dialogGroup custom properties into the items property. // where they will be rendered by group.jsp List newItems = new ArrayList(); List items = getItems(); + View view = ViewLifecycle.getActiveLifecycle().getView(); + // do not add the custom properties if they are already present if (!(items.contains(prompt))) { view.assignComponentIds(prompt); @@ -147,8 +150,8 @@ * java.lang.Object, org.kuali.rice.krad.uif.component.Component) */ @Override - public void performApplyModel(View view, Object model, Component parent) { - super.performApplyModel(view, model, parent); + public void performApplyModel(Object model, Component parent) { + super.performApplyModel(model, parent); // set the messageTest to the promptText prompt.setMessageText(promptText); @@ -186,8 +189,8 @@ * @param parent parent component */ @Override - public void performFinalize(View view, Object model, Component parent) { - super.performFinalize(view, model, parent); + public void performFinalize(Object model, Component parent) { + super.performFinalize(model, parent); if (responseInputField != null) { String responseInputSelector = "#" + responseInputField.getId() + " [name='" + Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/Group.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/Group.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/Group.java (working copy) @@ -15,6 +15,12 @@ */ package org.kuali.rice.krad.uif.container; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.apache.commons.lang.StringUtils; import org.kuali.rice.krad.datadictionary.parse.BeanTag; import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; @@ -26,16 +32,9 @@ import org.kuali.rice.krad.uif.field.Field; import org.kuali.rice.krad.uif.field.FieldGroup; import org.kuali.rice.krad.uif.util.ComponentUtils; -import org.kuali.rice.krad.uif.view.View; import org.kuali.rice.krad.uif.widget.Disclosure; import org.kuali.rice.krad.uif.widget.Scrollpane; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - /** * Container that holds a list of Field or other Group * instances @@ -149,8 +148,8 @@ * java.lang.Object) */ @Override - public void performInitialization(View view, Object model) { - super.performInitialization(view, model); + public void performInitialization(Object model) { + super.performInitialization(model); for (Component component : getItems()) { // append group's field bind by name prefix (if set) to each Index: rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/LightTable.java =================================================================== --- rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/LightTable.java (revision 41915) +++ rice-framework/krad-web-framework/src/main/java/org/kuali/rice/krad/uif/container/LightTable.java (working copy) @@ -44,6 +44,7 @@ import org.kuali.rice.krad.uif.field.Field; import org.kuali.rice.krad.uif.field.FieldGroup; import org.kuali.rice.krad.uif.field.InputField; +import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; import org.kuali.rice.krad.uif.util.ComponentUtils; import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; import org.kuali.rice.krad.uif.view.ExpressionEvaluator; @@ -119,13 +120,13 @@ * expressionConversionMap */ @Override - public void performInitialization(View view, Object model) { - super.performInitialization(view, model); + public void performInitialization(Object model) { + super.performInitialization(model); richTable.setForceLocalJsonData(true); //init binding info if (bindingInfo != null) { - bindingInfo.setDefaults(view, getPropertyName()); + bindingInfo.setDefaults(ViewLifecycle.getActiveLifecycle().getView(), getPropertyName()); } //iterate over this collections items to initialize @@ -263,8 +264,8 @@ * performFinalize override corrects the binding path for the DataFields and turns off rendering on some components */ @Override - public void performFinalize(View view, Object model, Component parent) { - super.performFinalize(view, model, parent); + public void performFinalize(Object model, Component parent) { + super.performFinalize(model, parent); headerLabels = new ArrayList