package org.openmole.core.implementation.tools;

import java.io.IOException;

import com.rits.cloning.Cloner;
import com.rits.cloning.IFastCloner;
import java.io.File;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.openmole.commons.exception.InternalProcessingError;
import org.openmole.commons.exception.MultipleException;
import org.openmole.commons.exception.UserBadDataError;
import org.openmole.core.implementation.data.Variable;
import org.openmole.core.implementation.internal.Activator;
import org.openmole.core.model.data.IVariable;


import static org.openmole.commons.tools.io.FileUtil.*;

public class ClonningService {

    
    public static IVariable clone(IVariable variable) throws InternalProcessingError, UserBadDataError {
        if (variable.getValue() == null || variable.getValue().getClass().isPrimitive()) {
            return variable;
        }
        
        Cloner cloner = new Cloner();
        final List<Throwable> exceptions = Collections.synchronizedList(new LinkedList<Throwable>());

        cloner.registerFastCloner(File.class, new IFastCloner() {

            @Override
            public Object clone(Object o, Cloner cloner, Map<Object, Object> map) throws IllegalAccessException {
                File toClone = (File) o;
                File cloned;
                try {
                    if (toClone.isDirectory()) {
                        cloned = Activator.getWorkspace().newTmpDir();
                    } else {
                        cloned = Activator.getWorkspace().newTmpFile();
                    }

                    copy(toClone, cloned);
                    return cloned;
                } catch (IOException ex) {
                    exceptions.add(ex);
                } catch (InternalProcessingError ex) {
                    exceptions.add(ex);
                }
                return null;
            }
        });

        Object val = cloner.deepClone(variable.getValue());

        if(!exceptions.isEmpty()) {
            throw new InternalProcessingError(new MultipleException(exceptions));
        }

        return new Variable(variable.getPrototype(), val);

       /* try {

            Iterable<File> files = FileMigrator.extractFilesFromVariable(variable);

            LocalFileCache localFileCache = new LocalFileCache();

            for (File f : files) {
                File toClone = f;
                File cloned;

                if (toClone.isDirectory()) {
                    cloned = Activator.getWorkspace().newTmpDir();
                } else {
                    cloned = Activator.getWorkspace().newTmpFile();
                }

                copy(toClone, cloned);
                localFileCache.fillInLocalFileCache(f, cloned);
            }

            IVariable ret = new Variable(variable.getPrototype(), cloner.deepClone(variable.getValue()));
            FileMigrator.initFilesInVariable(ret, localFileCache);

            return ret;

        } catch (IOException ex) {
            throw new InternalProcessingError(ex);
        } catch (StackOverflowError error) {
            throw new InternalProcessingError("Unable to clonne variable " + variable.getPrototype() + " , it is to big for the library.");
        }*/
    }
}

@@ -157,24 +157,82 @@
 va.io.File;%0A
+import java.math.BigDecimal;%0Aimport java.math.BigInteger;%0A
 import java.
@@ -905,16 +905,33 @@
 null %7C%7C 
+%0A                
 variable
@@ -966,16 +966,156 @@
 mitive()
+ %7C%7C%0A                variable.getValue().getClass() == BigDecimal.class %7C%7C%0A                variable.getValue().getClass() == BigInteger.class
 ) %7B%0A    
@@ -2164,24 +2164,137 @@
        %7D);%0A%0A
+        cloner.registerImmutable(BigDecimal.class);%0A        cloner.registerImmutable(BigInteger.class);%0A        %0A
         Obje

Add big decimal and big integer as immutables.