/*
 *  Copyright (C) 2010 reuillon
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openmole.core.implementation.tools;

import java.io.File;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.TreeSet;

import org.openmole.commons.exception.InternalProcessingError;
import org.openmole.commons.exception.UserBadDataError;
import org.openmole.core.model.data.IVariable;
import org.openmole.core.model.resource.ILocalFileCache;


/*TODO suport arrays and set*/
public class FileMigrator {

    public static void initFilesInVariable(IVariable variable, ILocalFileCache fileCache) {
        if (File.class.isAssignableFrom(variable.getPrototype().getType())) {
            initFile((IVariable<File>) variable, fileCache);
        } else {
            if (List.class.isAssignableFrom(variable.getPrototype().getType())) {
                initFilesInList(((IVariable<List>) variable).getValue(), fileCache);
            }
        }
    }

    public static void initFilesInVariables(Iterable<IVariable> context, ILocalFileCache fileCache) throws InternalProcessingError, UserBadDataError {
        for (IVariable v : context) {
            initFilesInVariable(v, fileCache);
        }
    }

    private static void initFilesInList(List list, ILocalFileCache fileCache) {
        ListIterator iterator = list.listIterator();

        while (iterator.hasNext()) {
            Object o = iterator.next();
            if (File.class.isAssignableFrom(o.getClass())) {
                File src = (File) o;
                File local = fileCache.getLocalFileCache(src);

                iterator.set(local);
            } else if (List.class.isAssignableFrom(o.getClass())) {
                initFilesInList((List) o, fileCache);
            }
        }

    }

    private static void initFile(IVariable<File> v, ILocalFileCache fileCache) {
        File src = v.getValue();
        File local = fileCache.getLocalFileCache(src);
        v.setValue(local);
    }

    public static Set<File> extractFilesFromVariable(IVariable variable) {
        Set<File> fileMap = new TreeSet<File>();
        if (File.class.isAssignableFrom(variable.getPrototype().getType())) {
            fileMap.add(((IVariable<File>) variable).getValue());
        } else {
            if (List.class.isAssignableFrom(variable.getPrototype().getType())) {
                extractFilesFromList(((IVariable<List>) variable).getValue(), fileMap);
            }
        }
        return fileMap;
    }

    public static Set<File> extractFilesFromVariables(Iterable<IVariable> context) {
        Set<File> fileMap = new TreeSet<File>();

        for (IVariable<?> v : context) {
            fileMap.addAll(extractFilesFromVariable(v));
        }
        return fileMap;
    }

    private static void extractFilesFromList(List list, Set<File> fileMap) {
        for (Object o : list) {
            if (File.class.isAssignableFrom(o.getClass())) {
                fileMap.add((File) o);
            } else {
                if (List.class.isAssignableFrom(o.getClass())) {
                    extractFilesFromList((List) o, fileMap);
                }
            }

        }
    }
}

@@ -757,24 +757,83 @@
 va.io.File;%0A
+import java.util.Collection;%0Aimport java.util.Collections;%0A
 import java.
@@ -1292,32 +1292,131 @@
 he fileCache) %7B%0A
+        Object variableContent = variable.getValue();%0A        if(variableContent == null) return;%0A%0A
         if (File
@@ -1447,39 +1447,32 @@
 variable
-.getPrototype().getType
+Content.getClass
 ())) %7B%0A 
@@ -1600,39 +1600,32 @@
 variable
-.getPrototype().getType
+Content.getClass
 ())) %7B%0A 
@@ -1656,32 +1656,20 @@
 InList((
-(IVariable%3C
 List
-%3E
 ) variab
@@ -1666,36 +1666,24 @@
 st) variable
-).getValue()
 , fileCache)
@@ -2806,24 +2806,145 @@
 variable) %7B%0A
+        Object variableContent = variable.getValue();%0A        if(variableContent == null) return Collections.EMPTY_SET;%0A%0A
         Set%3C
@@ -2976,24 +2976,25 @@
 et%3CFile%3E();%0A
+%0A
         if (
@@ -3029,39 +3029,32 @@
 variable
-.getPrototype().getType
+Content.getClass
 ())) %7B%0A 
@@ -3077,32 +3077,20 @@
 ap.add((
-(IVariable%3C
 File
-%3E
 ) variab
@@ -3096,20 +3096,8 @@
 ble)
-.getValue())
 ;%0A  
@@ -3167,31 +3167,24 @@
 able
-.getPrototype().getType
+Content.getClass
 ()))
@@ -3228,24 +3228,12 @@
 st((
-(IVariable%3C
 List
-%3E
 ) va
@@ -3242,20 +3242,15 @@
 able
-).getValue()
+Content
 , fi
@@ -3970,25 +3970,24 @@
           %7D%0A
-%0A
         %7D%0A  

Improve relayability and look at the type of the value and not the prototype.