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 015 package org.apache.tapestry.enhance; 016 017 import java.util.Iterator; 018 019 import org.apache.hivemind.ErrorLog; 020 import org.apache.hivemind.Location; 021 import org.apache.tapestry.IComponent; 022 import org.apache.tapestry.event.PageDetachListener; 023 import org.apache.tapestry.spec.IComponentSpecification; 024 025 /** 026 * No, this class isn't abstract ... this worker locates abstract properties in the base component 027 * class and provides a concrete implementation for them in the enhanced class. 028 * 029 * @author Howard M. Lewis Ship 030 * @since 4.0 031 */ 032 public class AbstractPropertyWorker implements EnhancementWorker 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 try 047 { 048 createProperty(op, name, location); 049 } 050 catch (Exception ex) 051 { 052 _errorLog.error( 053 EnhanceMessages.errorAddingProperty(name, op.getBaseClass(), ex), 054 location, 055 ex); 056 } 057 } 058 } 059 060 private void createProperty(EnhancementOperation op, String name, Location location) 061 { 062 // This won't be null because its always for existing properties. 063 064 Class propertyType = op.getPropertyType(name); 065 066 String fieldName = "_$" + name; 067 String defaultFieldName = fieldName + "$defaultValue"; 068 069 op.addField(fieldName, propertyType); 070 op.addField(defaultFieldName, propertyType); 071 072 EnhanceUtils.createSimpleAccessor(op, fieldName, name, propertyType, location); 073 EnhanceUtils.createSimpleMutator(op, fieldName, name, propertyType, location); 074 075 // Copy the real attribute into the default attribute inside finish load 076 // (allowing a default value to be set inside finishLoad()). 077 078 op.extendMethodImplementation( 079 IComponent.class, 080 EnhanceUtils.FINISH_LOAD_SIGNATURE, 081 defaultFieldName + " = " + fieldName + ";"); 082 083 // On page detach, restore the attribute to its default value. 084 085 op.extendMethodImplementation( 086 PageDetachListener.class, 087 EnhanceUtils.PAGE_DETACHED_SIGNATURE, 088 fieldName + " = " + defaultFieldName + ";"); 089 090 // This is not all that necessary, but is proper. 091 092 op.claimProperty(name); 093 } 094 095 public void setErrorLog(ErrorLog errorLog) 096 { 097 _errorLog = errorLog; 098 } 099 }