With your code Bob (I had to piece it together from your site, so I'm
posting the basic decorator here) I simply created
abstractDecorator.cfc:

<cfcomponent displayname="abstractDecorator" output="false"
extends="transfer.com.TransferDecorator">

    <cffunction name="configure" access="private" returntype="void"
hint="I am like init() but for decorators">
        <cfset variables.myInstance = StructNew() />
        <cfset variables.myInstance.CleanseInput = true />
    </cffunction>

<cffunction name="populate" access="public" output="false"
returntype="void" hint="Populates the object with values from the
argumemnts">
    <cfargument name="args" type="any" required="yes" />
    <cfargument name="FieldList" type="any" required="no" default="" /
>

    <cfset var theFieldList = "" />
    <cfset var TransferMetadata = getTransfer().getTransferMetaData
(getClassName()) />
    <cfset var Properties = TransferMetadata.getPropertyIterator() />
    <cfset var theProperty = 0 />
    <cfset var varName = 0 />
    <cfset var varType = 0 />
    <cfset var varValue = 0 />
    <cfset var CompType = 0 />
    <cfset var hasIterator = false />
    <cfset var theIterator = 0 />
    <cfset var theComposition = 0 />
    <cfset var ChildClass = 0 />
    <cfset var ChildPKName = 0 />
    <cfset var theChild = 0 />

<cfloop condition="#Properties.hasnext()#">
    <cfset theProperty = Properties.next() />
    <cfset varName = theProperty.getName() />
    <cfset varType = theProperty.getType() />
    <cfif NOT ListLen(arguments.FieldList) OR ListFindNoCase
(arguments.FieldList,varName)>
        <cfif varName EQ "LastUpdateTimestamp" AND varType EQ "Date">
            <cfset setLastUpdateTimestamp(Now()) />
        <cfelseif Right(varName,4) EQ "Flag" AND varType EQ "Numeric">
            <cfif StructKeyExists(arguments.args,varName)>
                <cfset varValue = Val(arguments.args[varName]) />
            <cfelse>
                <cfset varValue = 0 />
            </cfif>
            <cfinvoke component="#this#" method="set#varName#">
                <cfinvokeargument name="#varName#" value="#varValue#" /
>
            </cfinvoke>
        <cfelseif StructKeyExists(arguments.args,varName)>
            <cfset varValue = arguments.args[varName] />
            <cfif variables.myInstance.CleanseInput>
                <cfset varValue = HTMLEditFormat(varValue) />
            </cfif>
            <cfif IsValid(varType,varValue)>
                <cfinvoke component="#this#" method="set#varName#">
                    <cfinvokeargument name="#varName#"
value="#varValue#" />
                </cfinvoke>
            <cfelseif theProperty.getIsNullable() AND NOT Len(varValue)
>
                <cfinvoke component="#this#"
method="set#varName#Null" />
            <cfelse>
                <cfinvoke component="#this#"
method="setInvalid_#varName#">
                    <cfinvokeargument name="1" value="#varValue#" />
                </cfinvoke>
                <cfset ArrayAppend(arguments.args.Errors,"The contents
of the " & varName & " field must be a valid " & varType & " value.") /
>
            </cfif>
        </cfif>
    </cfif>
</cfloop>

<cfloop list="ManyToOne,ParentOneToMany" index="CompType">
    <cfinvoke component="#TransferMetadata#" method="has#CompType#"
returnvariable="hasIterator" />
    <cfif hasIterator>
        <cfinvoke component="#TransferMetadata#"
method="get#CompType#Iterator" returnvariable="theIterator" />
        <cfloop condition="#theIterator.hasnext()#">
            <cfset theComposition = theIterator.next() />
            <cfset varName = theComposition.getName() />
            <cfset ChildClass = theComposition.getLink().getTo() />
            <cfset ChildPKName = theComposition.getLink().getToObject
().getPrimaryKey().getName() />
            <cfif StructKeyExists(arguments.args,ChildPKName)>
                <cfset varValue = arguments.args[ChildPKName] />
                <cfset theChild = getTransfer().get
(ChildClass,varValue) />
                <cfif theChild.getIsPersisted()>
                    <cfif CompType CONTAINS "Parent">
                        <cfset varName = "Parent" &
theComposition.getLink().getToObject().getObjectName() />
                    </cfif>
                    <cfinvoke component="#this#"
method="set#varName#">
                        <cfinvokeargument name="transfer"
value="#theChild#" />
                    </cfinvoke>
                </cfif>
            </cfif>
        </cfloop>
    </cfif>
</cfloop>

</cffunction>

<cffunction name="onMissingMethod" access="public" output="false"
returntype="Any" hint="Very useful!">
    <cfargument name="missingMethodName" type="any" required="true" />
    <cfargument name="missingMethodArguments" type="any"
required="true" />

    <cfset var varName = 0 />
    <cfset var ReturnValue = "" />

    <cfif Left(arguments.missingMethodName,Len("setInvalid_")) EQ
"setInvalid_" AND StructKeyExists(arguments.missingMethodArguments,"1")
>
        <cfset varName = ReplaceNoCase
(arguments.missingMethodName,"setInvalid_","") & "_Invalid" />
        <cfset variables.myInstance[varName] =
arguments.missingMethodArguments.1 />
    <cfelseif Left(arguments.missingMethodName,Len("getInvalid_")) EQ
"getInvalid_">
        <cfset varName = ReplaceNoCase
(arguments.missingMethodName,"getInvalid_","") & "_Invalid" />
        <cfif StructKeyExists(variables.myInstance,varName)>
            <cfset ReturnValue = variables.myInstance[varName] />
        </cfif>
    </cfif>
    <cfreturn ReturnValue />
</cffunction>

<cffunction name="copyToStruct" access="public" output="false"
returntype="void" hint="Copies data from the TO into a Struct">
    <cfargument name="theStruct" type="any" required="false"
default="#StructNew()#" hint="A struct to receive the data" />
    <cfargument name="Overwrite" type="any" required="false"
default="true" hint="Should existing values in the struct be
overwritten?" />

    <!--- Get the MetaData and Properties --->
    <cfset var TransferMetadata = getTransfer().getTransferMetaData
(getClassName()) />
    <cfset var Properties = TransferMetadata.getPropertyIterator() />
    <cfset var PrimaryKey = TransferMetadata.getPrimaryKey() />
    <cfset var theProperty = 0 />
    <cfset var varName = 0 />
    <cfset var varType = 0 />
    <cfset var varValue = 0 />
    <cfset var i = 0 />

    <!--- Put the Id into the Struct --->
    <cfset varName = PrimaryKey.getName() />
    <cfinvoke component="#this#" method="get#varName#"
returnvariable="varValue" />
    <!--- Need cftry because if overwrite is false an error can be
thrown --->
    <cftry>
        <cfset StructInsert
(arguments.theStruct,varName,varValue,arguments.Overwrite) />
        <cfcatch type="any"></cfcatch>
    </cftry>
    <!--- Put the properties into the theStruct --->
    <cfloop condition="#Properties.hasnext()#">
        <cfset theProperty = Properties.next() />
        <cfset varName = theProperty.getName() />
        <cfinvoke component="#this#" method="get#varName#"
returnvariable="varValue" />
        <cftry>
            <cfset StructInsert
(arguments.theStruct,varName,varValue,arguments.Overwrite) />
            <cfcatch type="any"></cfcatch>
        </cftry>
    </cfloop>
    <!--- Add the extra properties into the Struct --->
    <cfif IsDefined("variables.myInstance.ExtraProperties") AND IsArray
(variables.myInstance.ExtraProperties) AND ArrayLen
(variables.myInstance.ExtraProperties)>
        <cfloop from="1" to="#ArrayLen
(variables.myInstance.ExtraProperties)#" index="i">
            <cfinvoke component="#this#"
method="get#variables.myInstance.ExtraProperties[i]#"
returnvariable="varValue" />
            <cftry>
                <cfset StructInsert
(arguments.theStruct,variables.myInstance.ExtraProperties
[i],varValue,arguments.Overwrite) />
                <cfcatch type="any"></cfcatch>
            </cftry>
        </cfloop>
    </cfif>
</cffunction>

</cfcomponent>

I then had my regular decorators for each object (such as
components.decorators.post for my "posts.post" Transfer object) extend
this abstractDecorator, so:

<cfcomponent displayname="post" output="false"
extends="components.decorators.abstractDecorator">
        <cfproperty name="postID" type="numeric" default="" />
        <cfproperty name="postTitle" type="string" default="" />
</cfcomponent>

Now I can simply do:

                post1 = instance.Transfer.get("posts.post", rc.postID);
                post2 = instance.Transfer.new("posts.post");
                tempTO = structNew();
                post1.copyToStruct(tempTO);
                post2.populate(tempTO);
                instance.Transfer.save(post2);

This effectively makes a copy of post1 to post2 and saves it.

Excellent work Bob and thank you!

On Nov 5, 2:00 pm, Bob Silverberg <[email protected]> wrote:
> Hmm, I've never even heard of listColumns().  If it were me, I'd use the
> metadata that Transfer makes available for just this purpose. In case you
> didn't see it, here's a link to a post I did about using Transfer's metadata
> to create your own implementation of 
> getMemento():http://www.silverwareconsulting.com/index.cfm/2008/6/17/Using-Transfe...
>
> Cheers,
> Bob
>
>
>
>
>
> On Thu, Nov 5, 2009 at 4:40 PM, Jim Rising <[email protected]> wrote:
> > what about listColumns() ?
>
> >     <cffunction name="copyTransferObject" output="false" hint="I copy one
> > transfer object to another">
> >         <cfargument name="aObject" required="true"
> > type="transfer.com.TransferObject">
> >         <cfargument name="bObject" required="true"
> > type="transfer.com.TransferObject">
> >         <cfset var aObject = arguments.aObject>
> >         <cfset var bObject = arguments.bObject>
>
> >         <cfset bColumns = bObject.listColumns()>
> >         <cfloop list="#bColumns#" index="columnName">
> >             <cfset getter = "aObject.get#columnName#()">
> >             <cfset columnValue =  Evaluate(getter)>
> >             <cfset setter = 'bObject.set#columnName#("#columnValue#")'>
> >             <cfset Evaluate(setter)>
> >         </cfloop>
> >         <cfreturn bObject />
> >     </cffunction>
>
> > On Thu, Nov 5, 2009 at 3:23 PM, Bob Silverberg 
> > <[email protected]>wrote:
>
> >> I'm sure Mark will correct me if I'm mistaken, but I don't think you
> >> should be calling setTransferObject() in your code.  I'm guessing you could
> >> get yourself into all kinds of trouble.
>
> >> On Thu, Nov 5, 2009 at 3:26 PM, John Watson <[email protected]> wrote:
>
> >>> I'm actually running into issues of losing my decorator methods after
> >>> using the setTransferObject(TO). I haven't had time to debug yet (as this 
> >>> is
> >>> not a production app yet).
>
> >>> I do this inside a "myDecoratedObject" called someobject:
>
> >>> <cfset TO = getTransfer().readByPropertyMap("myDecoratedObject",filter)
> >>> />
> >>> <cfif TO.getIsPersisted()>
> >>>   <cfset setTransferObject(TO) />
> >>> <cfelse>
> >>>  <!--- code that initializes this object based on the filter and saves it
> >>> --->
> >>> </cfif>
>
> >>> After running this code, randomly (haven't investigated yet; believe it
> >>> somehow related to my filter). "someobject" loses all of its decorator
> >>> methods until I clear the transfer cache.
>
> >>> Bob, I read your blog post:
>
> >>>http://www.silverwareconsulting.com/index.cfm/2008/7/22/How-I-Use-Tra...
> >>> And i think I will try that out whenever I go back to working on my
> >>> project. Thanks for the tip!
>
> >>> Mark, any plans for implementing something similar?
>
> >>> Thanks,
> >>> John
>
> >>> On Thu, Nov 5, 2009 at 12:11, Jim Rising <[email protected]>wrote:
>
> >>>> Mark,
>
> >>>> Thanks. I'll look into it a bit further.
>
> >>>> -jim
>
> >>>> On Thu, Nov 5, 2009 at 1:14 PM, Mark Mandel <[email protected]>wrote:
>
> >>>>> Probably because you are using a variety of undocumented badness :o(
>
> >>>>> getMemento() , switching out the inner object if a Decorator... all
> >>>>> sounds pretty bad if you ask me.
>
> >>>>> I think Bob's approach of using his memento function is probably the
> >>>>> way to go.
>
> >>>>> Mark
>
> >>>>> On Fri, Nov 6, 2009 at 6:07 AM, Jim Rising 
> >>>>> <[email protected]>wrote:
>
> >>>>>> ok... so here is what I did in my decorator:
>
> >>>>>>     <cffunction name="copyContentTemplate">
> >>>>>>         <cfargument name="contentTemplate"
> >>>>>> type="transfer.com.transferObject" required="true">
> >>>>>> <cfset var contentTemplate = arguments.contentTemplate>
> >>>>>>         <cfset var content = getTransfer().get("content.Content", "")>
>
> >>>>>>         <cfset content = setTransferObject(contentTemplate)>
> >>>>>>     </cffunction>
>
> >>>>>> now... this does seem to copy a 'contentTemplate' TO into a 'content'
> >>>>>> TO without any issues, but when i attempt to save using the following:
>
> >>>>>>     <cffunction name="saveContent" access="public" returntype="any">
> >>>>>>         <cfargument name="content" type="transfer.com.transferObject"
> >>>>>> required="true">
> >>>>>>         <cfset var content = arguments.content>
>
> >>>>>>         <cfset getTransfer().save(content)>
>
> >>>>>>     </cffunction>
>
> >>>>>> the object does not save.
>
> >>>>>> any ideas?
>
> >>>>>> -jim
>
> >>>>>> On Thu, Oct 29, 2009 at 11:21 AM, John Watson 
> >>>>>> <[email protected]>wrote:
>
> >>>>>>> Someone who knows a little more detail about how the caching works
> >>>>>>> may say what I suggest is a bad a idea, but here's a method I've used 
> >>>>>>> with
> >>>>>>> no issues yet.
>
> >>>>>>> Inside the decorator I've used the TO.setTransferObject(otherTO)
> >>>>>>> method. Though both the setting object and the TO object are both the 
> >>>>>>> same
> >>>>>>> (IE: content/content).
>
> >>>>>>> Another idea may be to use setMemento(mementoStruct)
>
> >>>>>>> John
>
> >>>>>>> On Thu, Oct 29, 2009 at 09:10, Jim Rising 
> >>>>>>> <[email protected]>wrote:
>
> >>>>>>>> I'm needing to copy one TO to another TO, and wondered if anyone had
> >>>>>>>> any ideas on the best way to do that? Basically I have one TO that 
> >>>>>>>> needs to
> >>>>>>>> serve as a 'template' of another.
>
> >>>>>>>> Example:
>
> >>>>>>>> I have a TO called 'contentTemplate' and another called 'content'.
> >>>>>>>> I want to be able to create a 'content' object from the
> >>>>>>>> 'contentTemplate' object.
>
> >>>>>>>> I'm thinking I will need to just get / set everything between each
> >>>>>>>> of them, but was hoping I would have another option available.
>
> >>>>>>>> Thanks!
> >>>>>>>> --
> >>>>>>>> Jim Rising
> >>>>>>>> Serial Entrepreneur
> >>>>>>>> Software Engineer
> >>>>>>>> Web Developer
>
> >>>>>>>> "Knowledge work requires both autonomy and accountability."
>
> >>>>>> --
> >>>>>> Jim Rising
> >>>>>> Serial Entrepreneur
> >>>>>> Software Engineer
> >>>>>> Web Developer
>
> >>>>>> "Knowledge work requires both autonomy and accountability."
>
> >>>>> --
> >>>>> E: [email protected]
> >>>>> T:http://www.twitter.com/neurotic
> >>>>> W:www.compoundtheory.com
>
> >>>> --
> >>>> Jim Rising
> >>>> Serial Entrepreneur
> >>>> Software Engineer
> >>>> Web Developer
>
> >>>> "Knowledge work requires both autonomy and accountability."
>
> >> --
> >> Bob Silverberg
> >>www.silverwareconsulting.com
>
> > --
> > Jim Rising
> > Serial Entrepreneur
> > Software Engineer
> > Web Developer
>
> > "Knowledge work requires both autonomy and accountability."
>
> --
> Bob Silverbergwww.silverwareconsulting.com
--~--~---------~--~----~------------~-------~--~----~
Before posting questions to the group please read:
http://groups.google.com/group/transfer-dev/web/how-to-ask-support-questions-on-transfer

You received this message because you are subscribed to the Google Groups 
"transfer-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/transfer-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to