/*
 * Copyright 2012 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Eclipse Public License version 1.0, available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.jboss.forge.addon.parser.java;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.concurrent.Callable;

import org.jboss.forge.furnace.util.ClassLoaders;
import org.jboss.forge.parser.JavaParser;
import org.jboss.forge.parser.java.JavaClass;
import org.jboss.forge.parser.java.JavaSource;

/**
 * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
 */
public class JavaSourceFactoryImpl implements JavaSourceFactory
{
   /**
    * Open the given {@link File}, parsing its contents into a new {@link JavaClass} instance.
    */
   @Override
   public JavaSource<?> parse(final File data) throws FileNotFoundException
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<JavaSource<?>>()
         {
            @Override
            public JavaSource<?> call() throws Exception
            {
               return JavaParser.parse(data);
            }
         });
      }
      catch (FileNotFoundException e)
      {
         throw e;
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Read the given {@link InputStream} and parse the data into a new {@link JavaClass} instance.
    */
   @Override
   public JavaSource<?> parse(final InputStream data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<JavaSource<?>>()
         {
            @Override
            public JavaSource<?> call() throws Exception
            {
               return JavaParser.parse(data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Parse the given character array into a new {@link JavaClass} instance.
    */
   @Override
   public JavaSource<?> parse(final char[] data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<JavaSource<?>>()
         {
            @Override
            public JavaSource<?> call() throws Exception
            {
               return JavaParser.parse(data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Parse the given String data into a new {@link JavaClass} instance.
    */
   @Override
   public JavaSource<?> parse(final String data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<JavaSource<?>>()
         {
            @Override
            public JavaSource<?> call() throws Exception
            {
               return JavaParser.parse(data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Create a new empty {@link JavaClass} instance.
    */
   @Override
   public <T extends JavaSource<?>> T create(final Class<T> type)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<T>()
         {
            @Override
            public T call() throws Exception
            {
               return JavaParser.create(type);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Read the given {@link File} and parse its data into a new {@link JavaSource} instance of the given type.
    * 
    * @throws FileNotFoundException
    */
   @Override
   public <T extends JavaSource<?>> T parse(final Class<T> type, final File data) throws FileNotFoundException
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<T>()
         {
            @Override
            public T call() throws Exception
            {
               return JavaParser.parse(type, data);
            }
         });
      }
      catch (FileNotFoundException e)
      {
         throw e;
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Read the given {@link InputStream} and parse its data into a new {@link JavaSource} instance of the given type.
    */
   @Override
   public <T extends JavaSource<?>> T parse(final Class<T> type, final InputStream data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<T>()
         {
            @Override
            public T call() throws Exception
            {
               return JavaParser.parse(type, data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Read the given character array and parse its data into a new {@link JavaSource} instance of the given type.
    */
   @Override
   public <T extends JavaSource<?>> T parse(final Class<T> type, final char[] data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<T>()
         {
            @Override
            public T call() throws Exception
            {
               return JavaParser.parse(type, data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }

   /**
    * Read the given string and parse its data into a new {@link JavaSource} instance of the given type.
    */
   @Override
   public <T extends JavaSource<?>> T parse(final Class<T> type, final String data)
   {
      try
      {
         return ClassLoaders.executeIn(getClass().getClassLoader(), new Callable<T>()
         {
            @Override
            public T call() throws Exception
            {
               return JavaParser.parse(type, data);
            }
         });
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }
}
