/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.jsmodule.application; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.Validate; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.globant.katari.core.application.Command; import com.globant.katari.core.application.JsonRepresentation; import com.globant.katari.jsmodule.view.ContentModuleServlet; import com.globant.katari.jsmodule.domain.BundleCache; import com.globant.katari.jsmodule.domain.DependenciesBundler; import com.globant.katari.jsmodule.domain.DependenciesResolver; /** Returns the list of dependencies for a given list of files. * * This command resolves all the transitive dependencies for a list of * javascript files. In debug mode, it returns the list of files. In non-debug * mode, it bundles the files and makes the bundle available to the * ContentModuleServlet (through the BundleCache). * * Bundled content will be server from the path * /com/globant/katari/jsmodule/bundle relative to this module, by the * ContentModuleServlet. * * @author ivan.bedecarats@globant.com */ public class ResolveDependenciesCommand implements Command<JsonRepresentation> { /** * The Dependencies Resolver, it's never null. */ private DependenciesResolver resolver; /** * If it's true means the application is running in debug mode, false * otherwise. */ private boolean debugMode; /** * Contains a Map with the cache of the bundled files. It's never null. */ private BundleCache cache; /** * The list of files whose dependencies are going to be fetched, it's never * null. */ private List<String> files; /** Constructs a new {@link ResolveDependenciesCommand} to list the files * dependencies. * @param theResolver The {@link DependenciesResolver} used to resolve the * dependencies of the given list of files. Cannot be null. * @param theCache The {@link BundleCache} contains a Map with the cache of * the bundled files. Cannot be null. * @param theDebugMode If it's true means the application is running in debug * mode, false otherwise. */ public ResolveDependenciesCommand(final DependenciesResolver theResolver, final BundleCache theCache, final boolean theDebugMode) { Validate.notNull(theResolver, "The dependencies resolver cannot be null."); Validate.notNull(theCache, "The Bundle Cache cannot be null."); resolver = theResolver; debugMode = theDebugMode; cache = theCache; } /** * Lists the dependency file paths for the given list of file paths. * * @return A {@link JsonRepresentation} with the following structure: * * <pre> * * If the application is running in debug mode, then it'll return the list of * dependency files: * * [{ * "js" : [{/com/globant/katari/jsmodule/testfile/jquery.js, * /com/globant/katari/jsmodule/testfile/jquery-ui.js * }] * }] * * If the application is not running in debug mode, there are 2 possible * scenarios: * * The list of files were already bundled in a single .js file and cached in * the {@link BundleCache}. * The list of files were never bundled in a single .js file and hence not * cached in the {@link BundleCache}. * In both cases, the key of the bundled file which is cached in the * {@link BundleCache} for the given files will be returned in "js" * {@link JSONArray} of the {@link JsonRepresentation}: * [{ * "js" : [{30171d9260a024d0e87201555b450617.js * }] * }] * </pre> * Please note that the "js" array in the above {@link JsonRepresentation} was * filled with dummy values. */ public JsonRepresentation execute() { List<String> dependenciesFound = new LinkedList<String>(); // We sort here the files to guarantee that the sort order is the same in // debug and non-debug modes. Collections.sort(files); if (!debugMode) { String bundledName = cache.findKey(files); if (bundledName == null) { List<String> dependencies = resolver.resolve(files); DependenciesBundler depBundler = new DependenciesBundler(); String bundledFileContent = depBundler.bundleFiles(dependencies); bundledName = cache.store(files, bundledFileContent); } dependenciesFound.add(ContentModuleServlet.BUNDLE_PATH + bundledName); } else { dependenciesFound = resolver.resolve(files); } JSONArray jsJsonDependencies = new JSONArray(); for (String dependency : dependenciesFound) { jsJsonDependencies.put(dependency); } JSONObject jsonDependencies = new JSONObject(); try { jsonDependencies.put("js", jsJsonDependencies); return new JsonRepresentation(jsonDependencies); } catch (JSONException e) { throw new RuntimeException("Error generating JSON", e); } } /** Sets the list of files whose dependencies are going to be fetched. * @param theFiles The list of files whose dependencies are going to be * fetched. It's never null. */ public void setFiles(final List<String> theFiles) { Validate.notNull(theFiles, "The files cannot be null."); files = theFiles; } }