001    // Copyright 2006-2007 Daniel Gredler
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package net.sf.beanform;
016    
017    import java.util.Map;
018    
019    import net.sf.beanform.prop.BeanProperty;
020    
021    import org.apache.hivemind.ApplicationRuntimeException;
022    import org.apache.tapestry.BaseComponent;
023    import org.apache.tapestry.IBinding;
024    import org.apache.tapestry.IComponent;
025    import org.apache.tapestry.IRequestCycle;
026    import org.apache.tapestry.components.Block;
027    import org.apache.tapestry.form.IFormComponent;
028    import org.apache.tapestry.form.IPropertySelectionModel;
029    
030    /**
031     * Superclass for low level BeanForm components which must be wrapped by
032     * a {@link BeanForm} component.
033     *
034     * @see BeanFormRows
035     * @see BeanFormLabel
036     * @see BeanFormField
037     * @see BeanFormButtons
038     *
039     * @author Daniel Gredler
040     */
041    public abstract class BeanFormComponent extends BaseComponent {
042    
043        final static String CUSTOM_FIELD_BLOCK_SUFFIX = "_BeanFieldBlock";
044        final static String CUSTOM_FIELD_SUFFIX = "_BeanField";
045    
046        final static String BINDING_OVERRIDE_SEPARATOR = "_";
047        final static String MODEL = "model";
048        final static String MODEL_SUFFIX = BINDING_OVERRIDE_SEPARATOR + MODEL;
049    
050        protected BeanForm getBeanForm() {
051            IRequestCycle cycle = this.getPage().getRequestCycle();
052            BeanForm beanForm = (BeanForm) cycle.getAttribute( BeanForm.BEAN_FORM_ATTRIBUTE );
053            if( beanForm == null ) throw new ApplicationRuntimeException( BeanFormMessages.noBeanForm( this ) );
054            return beanForm;
055        }
056    
057        protected boolean hasCustomField( BeanProperty property ) {
058            return ( this.getCustomFieldBlock( property ) != null &&
059                     this.getCustomField( property ) != null );
060        }
061    
062        protected Block getCustomFieldBlock( BeanProperty property ) {
063            String name = this.getCustomFieldBlockName( property );
064            return this.getSiblingComponent( name, Block.class );
065        }
066    
067        protected String getCustomFieldBlockName( BeanProperty property ) {
068            return this.getBeanForm().getId() + "_" + property.getName() + CUSTOM_FIELD_BLOCK_SUFFIX;
069        }
070    
071        protected IFormComponent getCustomField( BeanProperty property ) {
072            String name = this.getCustomFieldName( property );
073            return this.getSiblingComponent( name, IFormComponent.class );
074        }
075    
076        protected String getCustomFieldName( BeanProperty property ) {
077            return this.getBeanForm().getId() + "_" + property.getName() + CUSTOM_FIELD_SUFFIX;
078        }
079    
080        @SuppressWarnings( "unchecked" )
081        protected <T extends IComponent> T getSiblingComponent( String id, Class<T> clazz ) {
082            IComponent component = null;
083            IComponent container = this.getBeanForm().getContainer();
084            Map components = container.getComponents();
085            if( components.containsKey( id ) ) {
086                IComponent candidate = (IComponent) components.get( id );
087                if( clazz.isAssignableFrom( candidate.getClass() ) ) {
088                    component = candidate;
089                }
090                else {
091                    String msg = BeanFormMessages.componentUnexpectedType( candidate, clazz );
092                    throw new ApplicationRuntimeException( msg );
093                }
094            }
095            return (T) component;
096        }
097    
098        protected boolean hasPropertySelectionModel( BeanProperty prop, boolean useCache ) {
099            return this.getPropertySelectionModel( prop, useCache ) != null;
100        }
101    
102        protected IPropertySelectionModel getPropertySelectionModel( BeanProperty prop, boolean useCache ) {
103    
104            IBinding binding;
105            if( useCache ) binding = this.getBeanForm().getFieldBindingsFor( prop ).get( MODEL );
106            else binding = this.getBeanForm().getBinding( prop.getName() + MODEL_SUFFIX );
107    
108            IPropertySelectionModel model = null;
109            if( binding != null ) {
110                Object value = binding.getObject();
111                if( value instanceof IPropertySelectionModel ) {
112                    model = (IPropertySelectionModel) value;
113                }
114            }
115    
116            return model;
117        }
118    
119    }