Index: /trunk/grails-app/i18n/messages.properties
===================================================================
--- /trunk/grails-app/i18n/messages.properties	(revision 299)
+++ /trunk/grails-app/i18n/messages.properties	(revision 300)
@@ -1,7 +1,7 @@
 asset.tree.import.success=Asset tree imported.
 asset.tree.import.failure=Could not create asset tree from supplied file, failed on line {0}.
-asset.tree.import.file.over.max.size=Supplied file is greater than max size of {0} Mbytes.
+asset.tree.import.file.over.max.size=Supplied file is greater than max size of {0} {1}.
 asset.tree.import.file.not.supplied=No file supplied.
-asset.tree.import.no.header=The supplied file does not have the correct headers, please see the template file.
+asset.tree.import.no.header=The supplied file does not have the correct header lines, please see the template file.
 
 asset.copy.method.required=Please select a copy method for sub items.
Index: /trunk/grails-app/services/CsvService.groovy
===================================================================
--- /trunk/grails-app/services/CsvService.groovy	(revision 299)
+++ /trunk/grails-app/services/CsvService.groovy	(revision 300)
@@ -19,6 +19,6 @@
             def result = [:]
 
-            def megaByteMultiplier = 1000 * 1000
-            def fileMaxSize = 10 * megaByteMultiplier //Mb
+            def kByteMultiplier = 1000
+            def fileMaxSize = 500 * kByteMultiplier
 
             def multiPartFile = request.getFile('file')
@@ -38,13 +38,33 @@
 
             if (multiPartFile.getSize() > fileMaxSize)
-                return fail(code: "asset.tree.import.file.over.max.size", args: [fileMaxSize/megaByteMultiplier])
-
+                return fail(code: "asset.tree.import.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
+
+            def columnIndex = 0
+            def numberOfColumns = 0
+            def maxNumberOfColumns = 20
+
+            // Get first line.
             def line = reader.readNext()
             def lineNumber = 1
 
-            def header = ["Site", "Section", "Asset", "Sub Asset", "Functional Assembly", "Sub Assembly Group"]
-
-            if(line != header)
+            // Check for header line 1.
+            if(line != templateHeaderLine1) {
+                log.error "Failed to find header line 1. "
+                log.error "Required: " + templateHeaderLine1.toString()
+                log.error "Supplied: " + line.toString()
                 return fail(code: "asset.tree.import.no.header")
+            }
+
+            // Get second line.
+            line = reader.readNext()
+            lineNumber ++
+
+            // Check for header line 2.
+            if(line != templateHeaderLine2) {
+                log.error "Failed to find header line 2. "
+                log.error "Required: " + templateHeaderLine2.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "asset.tree.import.no.header")
+            }
 
             log.info "Import checks passed, start processing asset file."
@@ -55,36 +75,140 @@
 
             def siteInstance
+            def departmentInstance
             def sectionInstance
             def assetInstance
+            def assetSubItemInstance
+            def parentItem
 
             while(line) {
-                def lineSize = line.size()
-    //             log.info lineNumber+ "(" + lineSize + ")" + " : " + line
-
-                if(line[0]) {
-                        if( !Site.findByName(line[0]) )
-                            siteInstance = new Site(name: line[0])
-                            if(!siteInstance.save())
+                columnIndex = 0
+                numberOfColumns = Math.min( line.size(), maxNumberOfColumns )
+
+                if( (columnIndex+2) > numberOfColumns ) {
+                    line = reader.readNext()
+                    lineNumber ++
+                    continue
+                }
+
+                if(line[columnIndex]) {
+                    siteInstance = Site.findByName(line[columnIndex])
+                    if(!siteInstance) {
+                        log.info "Creating site: " + line[columnIndex]
+                        siteInstance = new Site(name: line[columnIndex],
+                                                                    description: line[++columnIndex])
+                        if(!siteInstance.save()) {
+                            log.error "Failed to create site on line: " + line[--columnIndex] + "(" + lineNumber + ")"
+                            return fail(code: "asset.tree.import.failure", args: [lineNumber])
+                        }
+                    }
+                    else log.info "Existing site: " + siteInstance
+
+                    columnIndex++
+                    if( (columnIndex+2) > numberOfColumns ) {
+                        line = reader.readNext()
+                        lineNumber ++
+                        continue
+                    }
+
+                    if(line[columnIndex]) {
+                        departmentInstance = Department.findByName(line[columnIndex])
+                        if(!departmentInstance) {
+                            departmentInstance = new Department(name: line[columnIndex],
+                                                                                                    description: line[++columnIndex],
+                                                                                                    site: siteInstance)
+                            if(!departmentInstance.save()) {
+                                log.error "Failed to create department on line: " + line[--columnIndex] + "(" + lineNumber + ")"
                                 return fail(code: "asset.tree.import.failure", args: [lineNumber])
-                }
-                else continue
-
-                if(line[1]) {
-                        if( !Section.findByName(line[1]) )
-                           sectionInstance =  new Section(name: line[1],
-                                                                                site: siteInstance)
-                            if(!sectionInstance.save())
-                                return fail(code: "asset.tree.import.failure", args: [lineNumber])
-                }
-                else continue
-
-                if(line[2]) {
-                        if( !Asset.findByName(line[2]) )
-                            assetInstance = new Asset(name: line[2],
-                                                                        section: sectionInstance)
-                            if(!sectionInstance.save())
-                                return fail(code: "asset.tree.import.failure", args: [lineNumber])
-                }
-                else continue
+                            }
+                        }
+
+                        columnIndex++
+                        if( (columnIndex+2) > numberOfColumns ) {
+                            line = reader.readNext()
+                            lineNumber ++
+                            continue
+                        }
+
+                        if(line[columnIndex]) {
+                            sectionInstance = Section.findByName(line[columnIndex])
+                            if(!sectionInstance) {
+                                sectionInstance =  new Section(name: line[columnIndex],
+                                                                                        description: line[++columnIndex],
+                                                                                        site: siteInstance,
+                                                                                        department: departmentInstance)
+                                if(!sectionInstance.save()) {
+                                    log.error "Failed to create section on line: " + line[--columnIndex] + "(" + lineNumber + ")"
+                                    return fail(code: "asset.tree.import.failure", args: [lineNumber])
+                                }
+                            }
+
+                            columnIndex++
+                            if( (columnIndex+2) > numberOfColumns ) {
+                                line = reader.readNext()
+                                lineNumber ++
+                                continue
+                            }
+
+                            if(line[columnIndex]) {
+                                assetInstance = Asset.findByName(line[columnIndex])
+                                if(!assetInstance) {
+                                    assetInstance = new Asset(name: line[columnIndex],
+                                                                                    description: line[++columnIndex],
+                                                                                    section: sectionInstance)
+                                    if(!assetInstance.save()) {
+                                        log.error "Failed to create asset on line: " + line[--columnIndex] + "(" + lineNumber + ")"
+                                        return fail(code: "asset.tree.import.failure", args: [lineNumber])
+                                    }
+                                }
+
+                                columnIndex++
+                                if( (columnIndex+2) > numberOfColumns ) {
+                                    line = reader.readNext()
+                                    lineNumber ++
+                                    continue
+                                }
+
+                                if(line[columnIndex]) {
+                                    assetSubItemInstance = AssetSubItem.findByName(line[columnIndex])
+                                    if(!assetSubItemInstance) {
+                                        assetSubItemInstance = new AssetSubItem(name: line[columnIndex],
+                                                                                                                    description: line[++columnIndex])
+                                        if(!assetInstance.save()) {
+                                            log.error "Failed to create assetSubItem on line: " + line[--columnIndex] + "(" + lineNumber + ")"
+                                            return fail(code: "asset.tree.import.failure", args: [lineNumber])
+                                        }
+                                    }
+
+                                    assetInstance.addToAssetSubItems(assetSubItemInstance)
+
+                                    columnIndex++
+                                    if( (columnIndex+2) > numberOfColumns ) {
+                                        line = reader.readNext()
+                                        lineNumber ++
+                                        continue
+                                    }
+
+                                    while( (columnIndex+2) < numberOfColumns ) {
+
+                                        if(line[columnIndex]) {
+                                            parentItem = assetSubItemInstance
+                                            assetSubItemInstance = new AssetSubItem(name: line[columnIndex],
+                                                                                                                        description: line[++columnIndex],
+                                                                                                                        parentItem: parentItem)
+                                            if(!assetInstance.save()) {
+                                                log.error "Failed to create assetSubItem on line: " + line[--columnIndex] + "(" + lineNumber + ")"
+                                                return fail(code: "asset.tree.import.failure", args: [lineNumber])
+                                            }
+                                        }
+                                        else break
+
+                                        columnIndex++
+                                    } // while()
+
+                                } // AssetSubItem L1
+                            } // Asset
+                        } // Section
+                    } // Department
+                } // Site
 
                 line = reader.readNext()
@@ -109,12 +233,8 @@
         CSVWriter writer = new CSVWriter(sw)
 
-        //Header
-        def header = ["Site", "Section", "Asset", "Sub Asset", "Functional Assembly", "Sub Assembly Group"]
-        def blankLine = []
-        def noteLine = ["Note: the header is required, start by replacing this line."]
-
-        writer.writeNext(header as String[])
-        writer.writeNext(blankLine as String[])
-        writer.writeNext(noteLine as String[])
+        writer.writeNext(templateHeaderLine1 as String[])
+        writer.writeNext(templateHeaderLine2 as String[])
+        writer.writeNext()
+        writer.writeNext("Note: the header lines are required, start by replacing this line.")
 
         writer.close()
@@ -212,3 +332,11 @@
     } // end buildAssetTree
 
+    private getTemplateHeaderLine1() {
+            ["Site", "", "Department", "", "Section", "","Asset", "", "Sub Asset", "", "Functional Assembly", "", "Sub Assembly Group", "", "SubItem", ""]
+    }
+
+    private getTemplateHeaderLine2() {
+            (["Name", "Description"])*8
+    }
+
 } // end class
