/*
 * Copyright 2012 Oracle Corporation. All Rights Reserved.
 *
 * 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.
 */
package com.fatwire.gst.foundation.groovy.context;

import groovy.lang.GroovyClassLoader;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.codehaus.groovy.control.MultipleCompilationErrorsException;
import org.junit.Test;

import com.fatwire.gst.foundation.controller.action.Factory;
import com.fatwire.gst.foundation.test.MockICS;

/**
 * @author dolf
 * 
 */
public class GroovyFactoryTest {

    /**
     * Test method for
     * {@link com.fatwire.gst.foundation.controller.action.support.BaseFactory#getObject(java.lang.String, java.lang.Class)}
     * .
     */
    @Test
    public void testGetObject() {

        MockICS ics = new MockICS();
        GroovyClassLoader gcl = new GroovyClassLoader();

        gcl.addClasspath("./src/test/groovy");

        GroovyFactory factory = new GroovyFactory(ics, gcl);
        List<?> list = factory.getObject("foo", List.class);
        org.junit.Assert.assertNotNull(list);

    }

    @Test
    public void testGetObject_bad_source() {

        MockICS ics = new MockICS();
        GroovyClassLoader gcl = new GroovyClassLoader();

        gcl.addClasspath("./src/test/bad-groovy");
        try {

            GroovyFactory factory = new GroovyFactory(ics, gcl);
            factory.getObject("foo", List.class);
        } catch (MultipleCompilationErrorsException e) {

            return;
        }
        org.junit.Assert.fail("should not have reached beyond the exception");

    }

    @Test
    public void testGetObject_no_method() {

        MockICS ics = new MockICS();
        GroovyClassLoader gcl = new GroovyClassLoader();

        gcl.addClasspath("./src/test/groovy");

        GroovyFactory factory = new GroovyFactory(ics, gcl);
        Collection<?> list = factory.getObject("foo", Collection.class);
        org.junit.Assert.assertNull(list);

    }

    @Test
    public void testGetObject_from_root() {

        MockICS ics = new MockICS();
        Factory root = new Factory() {

            @SuppressWarnings("unchecked")
            @Override
            public <T> T getObject(String name, Class<T> type) {
                return (T) ((Collection.class.isAssignableFrom(type)) ? Arrays.asList("tomato", "salad") : null);

            }

        };

        GroovyClassLoader gcl = new GroovyClassLoader();

        gcl.addClasspath("./src/test/groovy");

        GroovyFactory factory = new GroovyFactory(ics, gcl, root);
        Collection<?> list = factory.getObject("foobar", Collection.class);
        org.junit.Assert.assertNotNull(list);
        org.junit.Assert.assertEquals(2, list.size());

    }
}

@@ -707,16 +707,44 @@
 oader;%0A%0A
+import java.util.ArrayList;%0A
 import j
@@ -811,16 +811,60 @@
 il.List;
+%0Aimport java.util.Map;%0Aimport java.util.Set;
 %0A%0Aimport
@@ -2435,34 +2435,23 @@
         
-Collection%3C?%3E list
+Map map
  = facto
@@ -2470,26 +2470,19 @@
 (%22foo%22, 
-Collection
+Map
 .class);
@@ -2514,28 +2514,27 @@
 .assertNull(
-list
+map
 );%0A%0A    %7D%0A%0A 
@@ -2790,15 +2790,127 @@
 %3CT%3E 
-type) %7B
+c) %7B%0A                ArrayList al = new ArrayList();%0A                al.add(%22tomato%22);%0A                al.add(%22salad%22);
 %0A   
@@ -2935,26 +2935,20 @@
 n (T) ((
-Collection
+List
 .class.i
@@ -2967,50 +2967,16 @@
 rom(
-type
+c
 )) ? 
-Arrays.asList(%22tomato%22, %22salad%22) 
+al
 : nu
@@ -3211,97 +3211,1028 @@
 list
- = factory.getObject(%22foobar%22, Collection.class);%0A        org.junit.Assert.assertNotNull(
+;%0A%0A        // first check to see if we get the item back from the ObjectFactory classloader.%0A        list = factory.getObject(%22foobar1%22, List.class);%0A        org.junit.Assert.assertNotNull(%22Getting object from the ObjectFactory%22, list);%0A        org.junit.Assert.assertEquals(%22Getting object from the ObjectFactory%22, 0, list.size());%0A%0A        // now request a Set, which won't be returned from ObjectFactory, and it can't be returned from the local factory%0A        list = factory.getObject(%22foobar2%22, Set.class);%0A        org.junit.Assert.assertNull(%22Request a Set, which neither factory can return%22, list);%0A%0A        // requesting the collection will return the entry in the ObjectFactory because the returned List is a Collection%0A        // so instead request a Set, which won't be returned by ObjectFactory.%0A        list = factory.getObject(%22foobar3%22, Collection.class);%0A        org.junit.Assert.assertNotNull(%22Request a collection, which both factories can return - we expect the ObjectFactory one to take precedence%22, 
 list
@@ -4272,17 +4272,17 @@
 tEquals(
-2
+0
 , list.s
@@ -4286,20 +4286,338 @@
 t.size());%0A%0A
+        // request an array list, which ObjectFactory can't return but the root factory can return%0A        list = factory.getObject(%22foobar4%22, ArrayList.class);%0A        org.junit.Assert.assertNotNull(%22Request an ArrayList which only the root can return.%22, list);%0A        org.junit.Assert.assertEquals(2, list.size());%0A
     %7D%0A%7D%0A

Clean up factory tests to better address returning subclasses and superclasses of requested objects.