You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by mi...@apache.org on 2005/07/04 23:31:39 UTC

cvs commit: jakarta-tapestry/framework/src/java/org/apache/tapestry/components ForBean.java For.jwc IPrimaryKeyConverter.java Else.jwc If.jwc Conditional.jwc IfBean.java

mindbridge    2005/07/04 14:31:39

  Modified:    framework/src/java/org/apache/tapestry/components Else.jwc
                        If.jwc Conditional.jwc IfBean.java
  Added:       framework/src/java/org/apache/tapestry/components
                        ForBean.java For.jwc IPrimaryKeyConverter.java
  Log:
  Adding the For component and improving If/Else somewhat
  
  Revision  Changes    Path
  1.4       +4 -12     jakarta-tapestry/framework/src/java/org/apache/tapestry/components/Else.jwc
  
  Index: Else.jwc
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/Else.jwc,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Else.jwc	24 Jun 2005 02:03:58 -0000	1.3
  +++ Else.jwc	4 Jul 2005 21:31:38 -0000	1.4
  @@ -15,10 +15,9 @@
      limitations under the License.
   -->
   
  -<!DOCTYPE component-specification
  -      PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  -      "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
  -<!-- generated by Spindle, http://spindle.sourceforge.net -->
  +<!DOCTYPE component-specification PUBLIC 
  +  "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
  +  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
   
   <component-specification class="org.apache.tapestry.components.ElseBean" allow-body="yes" allow-informal-parameters="yes">
     
  @@ -27,17 +26,10 @@
     if the condition of the previous If component evaluates to false.
     </description>
       
  -  <parameter name="element" type="java.lang.String" direction="in" default-value="templateTag">
  +  <parameter name="element" default-binding="literal">
     	<description>
     	The element to emulate.
     	</description>
     </parameter>
     
  -  <parameter name="templateTag" type="java.lang.String" direction="auto" default-value="null">
  -    <description>
  -    The tag with which the component was inserted in its parent template.
  -    This parameter will be bound automatically by the framework.
  -    </description>
  -  </parameter>
  -  
   </component-specification>
  
  
  
  1.3       +8 -13     jakarta-tapestry/framework/src/java/org/apache/tapestry/components/If.jwc
  
  Index: If.jwc
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/If.jwc,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- If.jwc	21 Jun 2005 22:31:37 -0000	1.2
  +++ If.jwc	4 Jul 2005 21:31:38 -0000	1.3
  @@ -26,37 +26,32 @@
     if a condition is met.
     </description>
     
  -  <parameter name="condition" required="yes">
  +  <parameter name="condition" required="yes" default-binding="ognl">
       <description>
       The condition to evaluate.
       </description>
     </parameter>
     
  -  <parameter name="conditionValue">
  +  <parameter name="conditionValue" default-binding="ognl">
       <description>
       The value of the condition. During render this is obtained from
       the condition parameter. During rewind it is the submitted condition.
       </description>
     </parameter>
   
  -  <parameter name="listener"/>
  +  <parameter name="listener" default-binding="listener"/>
     
  -  <parameter name="formless" default-value="false">
  -    <description>
  -    Determines whether to avoid creating hidden fields within a form.
  -    </description>
  -  </parameter>
  -  
  -  <parameter name="element" default-value="templateTag">
  +  <parameter name="element" default-binding="literal">
     	<description>
     	The element to emulate.
     	</description>
     </parameter>
     
  -  <parameter name="templateTag" default-value="null">
  +  <parameter name="volatile" default-value="false" default-binding="ognl">
       <description>
  -    The tag with which the component was inserted in its parent template
  -    This parameter will be bound automatically by the framework.
  +    Only active in a form. Determines whether to avoid creating hidden fields within a form.
  +    Using this parameter may make the form structure different during render and rewind, 
  +    and cause exceptions as a result. Please use with caution.
       </description>
     </parameter>
     
  
  
  
  1.6       +1 -1      jakarta-tapestry/framework/src/java/org/apache/tapestry/components/Conditional.jwc
  
  Index: Conditional.jwc
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/Conditional.jwc,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Conditional.jwc	18 Apr 2005 17:06:36 -0000	1.5
  +++ Conditional.jwc	4 Jul 2005 21:31:38 -0000	1.6
  @@ -19,7 +19,7 @@
     "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
     "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
     
  -<component-specification class="org.apache.tapestry.components.Conditional">
  +<component-specification class="org.apache.tapestry.components.Conditional" deprecated="yes">
     <description>
     Conditionally emulates an element and its attributes (if element is specified) and/or includes a block of content if a condition is met.
     </description>
  
  
  
  1.4       +2 -2      jakarta-tapestry/framework/src/java/org/apache/tapestry/components/IfBean.java
  
  Index: IfBean.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/IfBean.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IfBean.java	25 Jun 2005 04:53:50 -0000	1.3
  +++ IfBean.java	4 Jul 2005 21:31:38 -0000	1.4
  @@ -38,7 +38,7 @@
       public abstract IBinding getConditionValueBinding();
       
       public abstract boolean getCondition();
  -    public abstract boolean getFormless();
  +    public abstract boolean getVolatile();
       public abstract String getElement();
       public abstract IActionListener getListener();
       
  @@ -97,7 +97,7 @@
       {
           boolean condition;
           
  -        if (form == null || getFormless()) { 
  +        if (form == null || getVolatile()) { 
               condition = getCondition();
           }
           else {
  
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java
  
  Index: ForBean.java
  ===================================================================
  // Copyright 2004, 2005 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.components;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.tapestry.IBinding;
  import org.apache.tapestry.IForm;
  import org.apache.tapestry.IMarkupWriter;
  import org.apache.tapestry.IRequestCycle;
  import org.apache.tapestry.Tapestry;
  import org.apache.tapestry.TapestryUtils;
  import org.apache.tapestry.coerce.ValueConverter;
  import org.apache.tapestry.form.AbstractFormComponent;
  import org.apache.tapestry.services.DataSqueezer;
  import org.apache.tapestry.services.ExpressionEvaluator;
  
  /**
   * @author mb
   */
  public abstract class ForBean extends AbstractFormComponent {
      private static final char DESC_VALUE = 'V';
  	private static final char DESC_PRIMARY_KEY = 'P';
  
  	// parameters
  	public abstract Object getSource();
  	public abstract Object getFullSource();
      public abstract String getElement();
      public abstract boolean getVolatile();
      public abstract Object getDefaultValue();
      public abstract String getPrimaryKey();
      public abstract IPrimaryKeyConverter getConverter();
      public abstract String getKeyExpression();
  
      // properties
      public abstract Map getPrimaryKeyMap();
      public abstract void setPrimaryKeyMap(Map primaryKeys);
      
      // injects
      public abstract DataSqueezer getDataSqueezer();
      public abstract ValueConverter getValueConverter();
      public abstract ExpressionEvaluator getExpressionEvaluator();
      
      
      private Object _value;
      private int _index;
      private boolean _rendering;
  	
      /**
       *  Gets the source binding and returns an {@link Iterator}
       *  representing
       *  the values identified by the source.  Returns an empty {@link Iterator}
       *  if the binding, or the binding value, is null.
       *
       *  <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
       *  the actual conversion.
       *
       **/
  
      protected Iterator getSourceData()
      {
  		Object source = getSource();
  		if (source == null)
  			return null;
      
      	Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(source, Iterator.class);
      	
      	return iteratorSource;
      }
  
      protected Iterator storeSourceData(IForm form, String name)
      {
      	Iterator iteratorSource = getSourceData();
  		if (iteratorSource == null)
  			return null;
      	
  		// extract primary keys from data
  		StringBuffer pkDesc = new StringBuffer();
  		List data = new ArrayList();
  		List pks = new ArrayList();
  		while (iteratorSource.hasNext()) {
  			Object value = iteratorSource.next();
  			data.add(value);
  			
  			Object pk = getPrimaryKeyFromValue(value);
  			if (pk == null) {
  				pk = value;
  				pkDesc.append(DESC_VALUE);
  			}
  			else
  				pkDesc.append(DESC_PRIMARY_KEY);
  			pks.add(pk);
  		}
  		
  		// store primary keys
          form.addHiddenValue(name, pkDesc.toString());
          for (Iterator it = pks.iterator(); it.hasNext();) {
  			Object pk = it.next();
  	    	try {
  				String stringRep = getDataSqueezer().squeeze(pk);
  				form.addHiddenValue(name, stringRep);
  			} catch (IOException ex) {
  	            throw new ApplicationRuntimeException(
  	                    Tapestry.format("For.unable-to-convert-value", pk),
  	                    this,
  	                    null,
  	                    ex);
  			}
  		}
  
      	return data.iterator();
      }
  
      protected Iterator getStoredData(IRequestCycle cycle, String name)
      {
          String[] submittedPrimaryKeys = cycle.getParameters(name);
          String pkDesc = submittedPrimaryKeys[0];
  
          // unsqueeze data
          List data = new ArrayList(submittedPrimaryKeys.length-1);
          List pks = new ArrayList(submittedPrimaryKeys.length-1);
          for (int i = 1; i < submittedPrimaryKeys.length; i++) {
          	String stringRep = submittedPrimaryKeys[i];
          	try {
  				Object value = getDataSqueezer().unsqueeze(stringRep);
  				data.add(value);
  				if (i <= pkDesc.length() && pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
  					pks.add(value);
  			} catch (IOException ex) {
  	            throw new ApplicationRuntimeException(
  	                    Tapestry.format("For.unable-to-convert-string", stringRep),
  	                    this,
  	                    null,
  	                    ex);
  			}
  		}
  
          // update the binding with the list of primary keys
      	IBinding primaryKeysBinding = getBinding("primaryKeys");
      	if (primaryKeysBinding != null)
      		primaryKeysBinding.setObject(pks);
          
      	// convert from primary keys to data
          for (int i = 0; i < data.size(); i++) {
          	if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY) {
          		Object pk = data.get(i);
          		Object value = getValueFromPrimaryKey(pk);
          		data.set(i, value);
          	}
  		}
          
          return data.iterator();
      }
      
      /**
       *  Gets the source binding and iterates through
       *  its values.  For each, it updates the value binding and render's its wrapped elements.
       *
       **/
  
      protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
      {
          // form may be null if component is not located in a form
          IForm form = (IForm) cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE);
  
          // If the cycle is rewinding, but not this particular form,
          // then do nothing (don't even render the body).
          boolean cycleRewinding = cycle.isRewinding();
          if (cycleRewinding && form != null && !form.isRewinding())
              return;
  
          boolean bInForm = (form != null && !getVolatile());
          
          String name = "";
          if (form != null)
              name = form.getElementId(this);
  
          // Get the data to be iterated upon. Store in form if needed.
          Iterator dataSource;
          if (!bInForm)
          	dataSource = getSourceData();
          else if (cycleRewinding)
          	dataSource = getStoredData(cycle, name);
          else 
          	dataSource = storeSourceData(form, name);
        	
          
          // Do not iterate if dataSource is null. 
          // The dataSource was either not convertable to Iterator, or was empty. 
          if (dataSource == null)
              return;
  
          String element = getElement();
  
          // Perform the iterations
          try
          {
              _index = 0;
              _rendering = true;
  
              while (dataSource.hasNext())
              {
              	// Get current value
                  _value = dataSource.next();
  
                  // Update output component parameters
              	IBinding indexBinding = getBinding("index");
              	if (indexBinding != null)
              		indexBinding.setObject(new Integer(_index));
  
              	IBinding valueBinding = getBinding("value");
              	if (valueBinding != null)
              		valueBinding.setObject(_value);
              	
                  // Render component
                  if (element != null)
                  {
                      writer.begin(element);
                      renderInformalParameters(writer, cycle);
                  }
  
                  renderBody(writer, cycle);
  
                  if (element != null)
                      writer.end();
  
                  _index++;
              }
          }
          finally
          {
              _rendering = false;
              _value = null;
          }
      }
  
      private Object restoreValue(IForm form, String name, Object primaryKey)
      {
      	return getValueFromPrimaryKey(primaryKey);
      }
      
      private void storeValue(IForm form, String name, Object value)
      {
      	Object convertedValue = getPrimaryKeyFromValue(value);
      	
          try
          {
          	String externalValue = getDataSqueezer().squeeze(convertedValue);
              form.addHiddenValue(name, externalValue);
          }
          catch (IOException ex)
          {
              throw new ApplicationRuntimeException(
                  Tapestry.format("For.unable-to-convert-value", value),
                  this,
                  null,
                  ex);
          }
      }
  
      private Object getPrimaryKeyFromValue(Object value) {
      	Object primaryKey = null;
      	
  		String keyExpression = getKeyExpression();
  		if (keyExpression != null)
  			primaryKey = getExpressionEvaluator().read(value, keyExpression);
  	
  		if (primaryKey == null) {
  	    	IPrimaryKeyConverter converter = getConverter();
  	    	if (converter != null)
  	    		primaryKey = converter.getPrimaryKey(value);
  		}
  
      	return primaryKey;
      }
      
      private Object getValueFromPrimaryKey(Object primaryKey) {
      	Object value = null;
  
      	if (value == null && getKeyExpression() != null) {
      		String keyExpression = getKeyExpression();
      		if (keyExpression != null) {
          		Map primaryKeys = getPrimaryKeyMap();
              	if (primaryKeys == null)
              		primaryKeys = initializePrimaryKeysFromSource(keyExpression);
              	value = primaryKeys.get(primaryKeys);
      		}
      	}
      	
      	if (value == null) {
  	    	IPrimaryKeyConverter converter = getConverter();
  	    	if (converter != null)
  	    		value = converter.getValue(primaryKey);
      	}
  
      	if (value == null)
      		value = getDefaultValue();
  
      	return value;
      }
      
      private Map initializePrimaryKeysFromSource(String keyExpression)
      {
      	Map primaryKeys = new HashMap();
      	
      	Object fullSource = getFullSource();
      	if (fullSource == null)
      		fullSource = getSource();
      	if (fullSource == null)
      		return primaryKeys;
      	
      	ExpressionEvaluator evaluator = getExpressionEvaluator();
      	
      	Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(fullSource, Iterator.class);
      	while (iteratorSource.hasNext()) {
      		Object value = iteratorSource.next();
          	Object primaryKey = evaluator.read(value, keyExpression);
          	if (primaryKey != null)
          		primaryKeys.put(primaryKey, value);
      	}
      	
      	setPrimaryKeyMap(primaryKeys);
      	return primaryKeys;
      }
      
      /**
       *  Returns the most recent value extracted from the source parameter.
       *
       *  @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
       *
       **/
  
      public final Object getValue()
      {
          if (!_rendering)
              throw Tapestry.createRenderOnlyPropertyException(this, "value");
    
          return _value;
      }
  
      /**
       *  The index number, within the {@link #getSource() source}, of the
       *  the current value.
       * 
       *  @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
       *
       *  @since 2.2
       * 
       **/
      
      public int getIndex()
      {
          if (!_rendering)
              throw Tapestry.createRenderOnlyPropertyException(this, "index");
          
          return _index;
      }
  
      public boolean isDisabled()
      {
          return false;
      }
  
  	// Do nothing in those methods, but make the JVM happy
      protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
      protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc
  
  Index: For.jwc
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!-- 
     Copyright 2005 The Apache Software Foundation
  
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
  
         http://www.apache.org/licenses/LICENSE-2.0
  
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
  -->
  
  <!DOCTYPE component-specification PUBLIC 
    "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
    "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
  
  <component-specification class="org.apache.tapestry.components.ForBean" allow-body="yes" allow-informal-parameters="yes">
      
    <description>
    Loops over a collection of source values.  May also emulate an element (like an Any
    component). If this component is placed in a Form, it will automatically store
    the collection in Hidden fields so that the structure of the page is preserved
    during a rewind even if the values in the source change.
    </description>
  	
    <parameter name="source" required="yes" default-binding="ognl">
      <description>
      The source of values, a Java collection or array.
      </description>
    </parameter>
    
    <parameter name="value" property="valueParameter" default-binding="ognl">
      <description>
      If provided, the parameter is updated with the current value on each iteration.
      </description>
    </parameter>
    
    <parameter name="index" property="indexParameter" default-binding="ognl">
      <description>
      If provided, the parameter is updated with the index of the loop on each iteration.
      </description>
    </parameter>
    
    <parameter name="element" default-binding="literal">
      <description>
      If provided, the component wraps its content with the requested element.
      Informal parameters become attributes of that element.
      </description>
    </parameter>
    
      
    <parameter name="keyExpression" default-binding="literal">
      <description>
      Only active in a form. An OGNL expression that returns the primary key of the iterated value. 
      The primary keys are stored in hidden fields during rendering and are loaded from the form
      during a rewind to ensure that the iterations remain the same.
      This is a simpler, but a less efficient alternative of the 'converter' parameter.
      If needed, please use in conjuction with 'fullSource' to reference objects 
      not currently present in 'source'.
      Also, use the 'defaultValue' parameter to define the object to be returned if
      a value corresponding to a particular primary key cannot be found.
      </description>
    </parameter>
      
    <parameter name="fullSource" default-binding="ognl">
      <description>
      Only active in a form and in combination with the 'keyExpression' parameter. 
      The objects provided by this parameter will be used to determine the values 
      referred to by the primary keys stored in the form. 
      If this parameter is not bound, 'source' is used instead.
      </description>
    </parameter>
    
    <parameter name="defaultValue" default-value="null" default-binding="ognl">
      <description>
      Only active in a form. The value to be used when no match for a given primary key is found. 
      </description>
    </parameter>
  
    <parameter name="converter" default-value="null" default-binding="ognl">
      <description>
      Only active in a form. Defines how the items iterated upon 
      will be stored in the form as hidden values and how the stored information will be 
      converted back to objects. 
      This interface allows only the primary key of the items to be stored, 
      rather than the whole item.
      </description>
    </parameter>
    
    <parameter name="primaryKeys" default-binding="ognl">
      <description>
      Only active in a form. If provided, the parameter is automatically updated 
      before a rewind with the list of primary keys stored in the form. 
      The parameter is updated right before the iterations begin in a rewind and 
      could be used to preload the relevant objects in a provided 'converter'.
      </description>
    </parameter>
    
    <parameter name="volatile" default-value="false" default-binding="ognl">
      <description>
      Only active in a form. Determines whether to avoid creating hidden fields within a form.
      Using this parameter may make the form structure different during render and rewind, 
      and cause exceptions as a result. Please use with caution.
      </description>
    </parameter>
    
    <inject property="dataSqueezer" object="service:tapestry.data.DataSqueezer"/>
    <inject property="valueConverter" object="service:tapestry.coerce.ValueConverter"/>
    <inject property="expressionEvaluator" object="service:tapestry.ognl.ExpressionEvaluator"/>
  
  </component-specification>
  
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/components/IPrimaryKeyConverter.java
  
  Index: IPrimaryKeyConverter.java
  ===================================================================
  // Copyright 2004, 2005 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.components;
  
  /**
   * An interface for converting an objects to their primary keys and back. 
   * Typically used to determine how to store a given object as a hidden 
   * value when rendering a form.
   * 
   * @author mb
   * @since 4.0
   */
  public interface IPrimaryKeyConverter
  {
      /**
       * Returns the primary key of the given value
       * 
       * @param objValue the value for which a primary key needs to be extracted
       * @return the primary key of the value
       */
      Object getPrimaryKey(Object value);
      
      /**
       * Returns the value corresponding the given primary key 
       *  
       * @param objPrimaryKey the primary key for which a value needs to be generated
       * @return the generated value corresponding to the given primary key
       */
      Object getValue(Object primaryKey); 
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org