/*
 * (C) Copyright 2012, IBM Corporation
 *
 * 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.ibm.jaggr.service.impl.deps;

import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.JSSourceFile;
import com.google.javascript.rhino.Node;
import com.ibm.jaggr.service.resource.IResourceVisitor;

/**
 * This class implements the {@link Callable} interface to parse an AMD module
 * and extract the dependency information from the AMD module's define()
 * function. The dependency information thus obtained is used to update the
 * dependency array in the provided {@link DepTreeNode} and the node's
 * last-modified times are updated as well.
 */
final class DepParser implements Callable<URI> {
	static final Logger log = Logger.getLogger(DepParser.class.getName());
	static {
		Compiler.setLoggingLevel(Level.WARNING);
	}
	
	private final DepTreeNode treeNode;
	private final IResourceVisitor.Resource resource;

	/**
	 * Object constructor
	 * 
	 * @param treeNode
	 *            The node to be populated with the dependency list obtained
	 *            from jsFile
	 * @param resource
	 *            The resource to be parsed for dependencies
	 */
	DepParser(DepTreeNode treeNode, IResourceVisitor.Resource resource) {
		this.treeNode = treeNode;
		this.resource = resource;
	}

	/* (non-Javadoc)
	 * @see java.util.concurrent.Callable#call()
	 */
	public URI call() throws Exception {
		// Save original time stamp for dependency list
		long lastModifiedDep = treeNode.lastModifiedDep();
		long lastModified = resource.lastModified();
		// Parse the javascript code
		Compiler compiler = new Compiler();
		InputStream in = resource.getInputStream();
		Node node;
		try {
			node = compiler.parse(JSSourceFile.fromInputStream(resource.getURI().toString(), in));
		} catch (Exception e) {
			if (log.isLoggable(Level.WARNING)) {
				log.log(Level.WARNING, "Error occurred parsing " + resource.getURI().toString() + ": " + e.getMessage(), e);
			}
			throw e;
		} finally {
			in.close();
		}
		// walk the AST for the node looking for define calls
		// and pull out the required dependency list.
		ArrayList<String> deps = DepUtils.parseDependencies(node);
		String[] depArray = (deps == null) ? 
				new String[0] : deps.toArray(new String[deps.size()]);
		/*
		 * Determine if the dependency list has changed.  We keep track of 
		 * dependency list changes separate from code changes in general
		 * because a dependency list change necessitates invalidating all
		 * cached responses for the configs that reference this file, and
		 * we want to do this only when necessary.
		 */
		if (lastModifiedDep ==  -1 || !Arrays.equals(depArray, treeNode.getDepArray())) {
			lastModifiedDep = lastModified;
		}
		// update the dependency info in the node
		treeNode.setDependencies(depArray, 
				lastModified, lastModifiedDep);
		return resource.getURI();
	}
}

@@ -2481,19 +2481,26 @@
 ode node
+ = null
 ;%0D%0A
-
 %09%09try %7B%0D
@@ -2602,25 +2602,25 @@
  catch (
-Exception
+Throwable
  e) %7B%0D%0A%09
@@ -2783,21 +2783,8 @@
 %09%7D%0D%0A
-%09%09%09throw e;%0D%0A
 %09%09%7D 
@@ -2811,24 +2811,48 @@
 se();%0D%0A%09%09%7D%0D%0A
+%09%09if (node != null) %7B%0D%0A%09
 %09%09// walk th
@@ -2898,16 +2898,17 @@
 alls%0D%0A%09%09
+%09
 // and p
@@ -2946,16 +2946,17 @@
  list.%0D%0A
+%09
 %09%09ArrayL
@@ -3011,16 +3011,17 @@
 de);%0D%0A%09%09
+%09
 String%5B%5D
@@ -3051,16 +3051,17 @@
 ll) ? %0D%0A
+%09
 %09%09%09%09new 
@@ -3116,16 +3116,17 @@
 );%0D%0A
+%09
 %09%09/*%0D%0A%09%09
  * D
@@ -3121,16 +3121,17 @@
 %09%09/*%0D%0A%09%09
+%09
  * Deter
@@ -3193,16 +3193,17 @@
  of %0D%0A%09%09
+%09
  * depen
@@ -3260,16 +3260,17 @@
 eneral%0D%0A
+%09
 %09%09 * bec
@@ -3332,16 +3332,17 @@
  all%0D%0A%09%09
+%09
  * cache
@@ -3402,16 +3402,17 @@
  and%0D%0A%09%09
+%09
  * we wa
@@ -3447,16 +3447,17 @@
 ssary.%0D%0A
+%09
 %09%09 */%0D%0A%09
@@ -3453,24 +3453,25 @@
 %0D%0A%09%09%09 */%0D%0A%09%09
+%09
 if (lastModi
@@ -3544,16 +3544,17 @@
 ) %7B%0D%0A%09%09%09
+%09
 lastModi
@@ -3578,23 +3578,25 @@
 ified;%0D%0A
+%09
 %09%09%7D%0D%0A%09%09
+%09
 // updat
@@ -3632,16 +3632,17 @@
 node%0D%0A%09%09
+%09
 treeNode
@@ -3670,16 +3670,17 @@
 rray, %0D%0A
+%09
 %09%09%09%09last
@@ -3708,16 +3708,21 @@
 dDep);%0D%0A
+%09%09%7D%0D%0A
 %09%09return

refactor exception handling for parser