class AssetService {

    boolean transactional = false

    def saveCopy(params) {
        Asset.withTransaction { status ->
            def result = [:]

            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.assetInstance && m.field)
                    result.assetInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["Asset", params.id] ]
                return result
            }

            result.assetToCopy = Asset.get(params.assetToCopy?.id)
            if(!result.assetToCopy)
                return fail(code:"default.not.found")

            if(!params.copyMethod)
                fail(code:"asset.copy.method.required")

            result.assetInstance =  new Asset(params)

            if(result.assetInstance.hasErrors() || !result.assetInstance.save())
                return fail(code:"default.create.failure")

            def assetSubItemInstance1

            // Copy subItems from level 2 and bellow.
            def copyAssetSubItem = { assetSubItemToCopy, parentItem ->
                def assetSubItemInstance = new AssetSubItem(name: assetSubItemToCopy.name,
                                                                                            description: assetSubItemToCopy.description,
                                                                                            parentItem: parentItem)

                if(assetSubItemInstance.hasErrors() || !assetSubItemInstance.save())
                    return fail(field:"subItems", code:"default.create.failure")

                def i = 0
                for(assetSubItem in assetSubItemToCopy.subItems) {
                    call(assetSubItem, assetSubItemInstance)
                    // Protect against endless recurrsion.
                    i++
                    if(i > 100)
                        fail(code:"default.create.failure")
                    // Stop if an error is flagged.
                    if(result.error)
                        break
                }
            } //copyAssetSubItem

            // Copy the 1st level of subItems.
            def copyAssetSubItem1 = { assetSubItemToCopy ->
                assetSubItemInstance1 = new AssetSubItem(name: assetSubItemToCopy.name,
                                                                                        description: assetSubItemToCopy.description,
                                                                                        asset: result.assetInstance)

                if(assetSubItemInstance1.hasErrors() || !assetSubItemInstance1.save())
                    return fail(field:"assetSubItems", code:"default.create.failure")

                result.assetInstance.addToAssetSubItems(assetSubItemInstance1)

                def i = 0
                for(assetSubItem in assetSubItemToCopy.subItems) {
                    copyAssetSubItem(assetSubItem, assetSubItemInstance1)
                    // Protect against endless recurrsion.
                    i++
                    if(i > 100)
                        fail(code:"default.create.failure")
                    // Stop if an error is flagged.
                    if(result.error)
                        break
                }
            } //copyAssetSubItem1

            def linkAssetSubItem = { assetSubItemToLink ->
                result.assetInstance.addToAssetSubItems(assetSubItemToLink)
            }

            def i = 0
            for(assetSubItem in result.assetToCopy.assetSubItems) {

                if(params.copyMethod == "copy")
                    copyAssetSubItem1(assetSubItem)
                else
                    linkAssetSubItem(assetSubItem)
                // Protect against endless recurrsion.
                i++
                if(i > 100)
                    fail(code:"default.create.failure")
                // Stop if an error is flagged.
                if(result.error)
                    break
            }

            // Success or not.
            return result

        } //end withTransaction
    } // end saveCopySrvce

} // end class