001 // Copyright 2004, 2005 The Apache Software Foundation 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 package org.apache.tapestry.enhance; 015 016 import org.apache.hivemind.ErrorLog; 017 import org.apache.hivemind.Location; 018 import org.apache.hivemind.service.MethodSignature; 019 import org.apache.tapestry.IComponent; 020 import org.apache.tapestry.event.PageDetachListener; 021 import org.apache.tapestry.spec.IComponentSpecification; 022 023 import java.lang.reflect.Modifier; 024 import java.util.Iterator; 025 026 027 /** 028 * Enhances the {@link org.apache.tapestry.IComponent#getClientId()} property. 029 */ 030 public class ClientIdPropertyWorker implements EnhancementWorker 031 { 032 private static final String PROPERTY_NAME = "clientId"; 033 034 private ErrorLog _errorLog; 035 036 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec) 037 { 038 Location location = spec.getLocation(); 039 040 Iterator i = op.findUnclaimedAbstractProperties().iterator(); 041 042 while (i.hasNext()) 043 { 044 String name = (String) i.next(); 045 046 if (name.equals(PROPERTY_NAME)) { 047 048 try 049 { 050 createProperty(op, name, location); 051 } 052 catch (Exception ex) 053 { 054 _errorLog.error( 055 EnhanceMessages.errorAddingProperty(name, op.getBaseClass(), ex), 056 location, 057 ex); 058 } 059 060 break; 061 } 062 } 063 } 064 065 private void createProperty(EnhancementOperation op, String name, Location location) 066 { 067 // This won't be null because its always for existing properties. 068 069 Class propertyType = op.getPropertyType(name); 070 071 String fieldName = "_$" + name; 072 String defaultFieldName = fieldName + "$defaultValue"; 073 074 op.addField(fieldName, propertyType); 075 op.addField(defaultFieldName, propertyType); 076 077 String methodName = op.getAccessorMethodName(name); 078 079 // Build special getter logic 080 // if the client id is null "peek" at the next possible unique id 081 082 StringBuffer str = new StringBuffer(); 083 084 str.append(" if(").append(fieldName).append(" == null){") 085 .append(" if (getPage() == null) { return null; }") 086 .append(" String tempId = getSpecifiedId();") 087 .append(" if (tempId == null) { return null; }") 088 .append(" return getPage().getRequestCycle().peekUniqueId(org.apache.tapestry.TapestryUtils#convertTapestryIdToNMToken(tempId));") 089 .append("} else { "); 090 091 // else return the existing clientId 092 093 str.append("return ").append(fieldName).append(";"); 094 str.append("}"); 095 096 op.addMethod( 097 Modifier.PUBLIC, 098 new MethodSignature(propertyType, methodName, null, null), 099 str.toString(), 100 location); 101 102 EnhanceUtils.createSimpleMutator(op, fieldName, name, propertyType, location); 103 104 // Copy the real attribute into the default attribute inside finish load 105 // (allowing a default value to be set inside finishLoad()). 106 107 op.extendMethodImplementation( 108 IComponent.class, 109 EnhanceUtils.FINISH_LOAD_SIGNATURE, 110 defaultFieldName + " = " + fieldName + ";"); 111 112 // On page detach, restore the attribute to its default value. 113 114 op.extendMethodImplementation( 115 PageDetachListener.class, 116 EnhanceUtils.PAGE_DETACHED_SIGNATURE, 117 fieldName + " = " + defaultFieldName + ";"); 118 119 // This is not all that necessary, but is proper. 120 121 op.claimProperty(name); 122 } 123 124 public void setErrorLog(ErrorLog errorLog) 125 { 126 _errorLog = errorLog; 127 } 128 }