/*
  *
  *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
  *  *
  *  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  *  you may not use this file except in compliance with the License.
  *  *  You may obtain a copy of the License at
  *  *
  *  *       http://www.apache.org/licenses/LICENSE-2.0
  *  *
  *  *  Unless required by applicable law or agreed to in writing, software
  *  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  *  See the License for the specific language governing permissions and
  *  *  limitations under the License.
  *  *
  *  * For more information: http://www.orientechnologies.com
  *
  */
package com.orientechnologies.orient.core.command.script;

import java.lang.reflect.Method;
import java.util.*;

/**
 * Script utility class
 * 
 * @see OCommandScript
 * @author Luca Garulli
 * 
 */
public class OCommandExecutorUtility {
  private static Method java8MethodIsArray;
  private static Method java8MethodValues;

  /**
   * Manages cross compiler compatibility issues.
   * 
   * @param result
   *          Result to transform
   * @return
   */
  public static Object transformResult(Object result) {
    // PATCH BY MAT ABOUT NASHORN RETURNING VALUE FOR ARRAYS.
    if (result!=null && result.getClass().getName().contains("nashorn") && result instanceof Map) {
      try {
        if (isActuallyAnArray(result)) {
          List<?> partial = new ArrayList(((Map) result).values());
          List<Object> finalResult = new ArrayList<Object>();
          for (Object o : partial) {
            if (o instanceof Map) {
              Map<Object, Object> innerMap = (Map) o;
              Set<Object> keys = innerMap.keySet();
              Map<Object, Object> newMap = new LinkedHashMap<Object, Object>();
              for (Object key : keys) {
                newMap.put(key, transformResult(innerMap.get(key)));
              }
              finalResult.add(newMap.values());
            } else {
              finalResult.add(o);
            }
          }

          return finalResult;
        }else{
          Map<Object, Object> mapResult = (Map) result;
          List<Object> keys = new ArrayList<Object>(mapResult.keySet());
          for (Object key : keys) {
            mapResult.put(key, transformResult(mapResult.get(key)));
          }
          return mapResult;
        }
      } catch (Exception e) {
      }
    }

    return result;
  }

  private static boolean isActuallyAnArray(Object iObject) {
    try {
      return Boolean.TRUE.equals(Class.forName("jdk.nashorn.api.scripting.JSObject").getDeclaredMethod("isArray", null).invoke(iObject));
    }  catch(Exception e) {
      return false;
    }
  }
}

@@ -1062,49 +1062,169 @@
 ;%0A  
-private static Method java8MethodValues;%0A
+static %7B%0A   try %7B%0A     java8MethodIsArray = Class.forName(%22jdk.nashorn.api.scripting.JSObject%22).getDeclaredMethod(%22isArray%22,null);%0A   %7D catch(Exception e) %7B%7D%0A  %7D
 %0A  /
@@ -1418,168 +1418,160 @@
     
-// PATCH BY MAT ABOUT NASHORN RETURNING VALUE FOR ARRAYS.%0A    if (result!=null && result.getClass().getName().contains(%22nashorn%22) && result instanceof Map) %7B%0A  
+if (java8MethodIsArray == null %7C%7C !(result instanceof Map)) %7B %0A      return result;%0A    %7D%0A    // PATCH BY MAT ABOUT NASHORN RETURNING VALUE FOR ARRAYS.%0A
     
@@ -1572,26 +1572,24 @@
 .%0A    try %7B%0A
-  
       if (is
@@ -1586,33 +1586,51 @@
     if (
-isActuallyAnArray
+(Boolean) java8MethodIsArray.invoke
 (result)
@@ -1629,26 +1629,24 @@
 (result)) %7B%0A
-  
         List
@@ -1699,34 +1699,32 @@
 ues());%0A        
-  
 List%3CObject%3E fin
@@ -1759,34 +1759,32 @@
 ect%3E();%0A        
-  
 for (Object o : 
@@ -1808,446 +1808,43 @@
     
-  if (o instanceof Map) %7B%0A              Map%3CObject, Object%3E innerMap = (Map) o;%0A              Set%3CObject%3E keys = innerMap.keySet();%0A              Map%3CObject, Object%3E newMap = new LinkedHashMap%3CObject, Object%3E();%0A              for (Object key : keys) %7B%0A                newMap.put(key, transformResult(innerMap.get(key)));%0A              %7D%0A              finalResult.add(newMap.values());%0A            %7D else %7B%0A              final
+finalResult.add(transform
 Result
-.add
 (o)
+)
 ;%0A  
@@ -1853,29 +1853,10 @@
     
-    
 %7D%0A
-          %7D%0A%0A  
     
@@ -1889,15 +1889,15 @@
     
-  
 %7D
+ 
 else
+ 
 %7B%0A  
@@ -1902,18 +1902,16 @@
         
-  
 Map%3CObje
@@ -1944,26 +1944,24 @@
 ap) result;%0A
-  
         List
@@ -2023,26 +2023,24 @@
 ));%0A        
-  
 for (Object 
@@ -2049,26 +2049,24 @@
 y : keys) %7B%0A
-  
           ma
@@ -2124,30 +2124,26 @@
 ));%0A        
-  %7D%0A  
+%7D%0A
         retu
@@ -2158,30 +2158,26 @@
 sult;%0A      
-  %7D%0A  
+%7D%0A
     %7D catch 
@@ -2195,310 +2195,28 @@
 e) %7B
-%0A      %7D%0A    %7D%0A%0A    return result;%0A  %7D%0A%0A  private static boolean isActuallyAnArray(Object iObject) %7B%0A    try %7B%0A      return Boolean.TRUE.equals(Class.forName(%22jdk.nashorn.api.scripting.JSObject%22).getDeclaredMethod(%22isArray%22, null).invoke(iObject));%0A    %7D  catch(Exception e) %7B%0A      return false;%0A    %7D
+%7D%0A    return result;
 %0A  %7D

fix #2279