You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sh...@apache.org on 2016/09/19 06:27:04 UTC

[1/8] incubator-atlas git commit: ATLAS-712 Support getTrait() API (svimal2106 via shwethags)

Repository: incubator-atlas
Updated Branches:
  refs/heads/master e8a148497 -> 71e0e09b9


ATLAS-712 Support getTrait() API (svimal2106 via shwethags)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/dd0b051e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/dd0b051e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/dd0b051e

Branch: refs/heads/master
Commit: dd0b051ec58ca292fca1862701e1089ad408e18d
Parents: e8a1484
Author: Shwetha GS <ss...@hortonworks.com>
Authored: Mon Sep 19 10:46:34 2016 +0530
Committer: Shwetha GS <ss...@hortonworks.com>
Committed: Mon Sep 19 10:46:34 2016 +0530

----------------------------------------------------------------------
 .../main/java/org/apache/atlas/AtlasClient.java | 39 +++++++++
 release-log.txt                                 |  1 +
 .../atlas/services/DefaultMetadataService.java  |  7 +-
 .../service/DefaultMetadataServiceTest.java     |  7 +-
 .../apache/atlas/services/MetadataService.java  |  3 +-
 .../atlas/web/resources/EntityResource.java     | 83 ++++++++++++++++++++
 .../web/resources/EntityJerseyResourceIT.java   | 32 ++++++++
 7 files changed, 162 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/client/src/main/java/org/apache/atlas/AtlasClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/atlas/AtlasClient.java b/client/src/main/java/org/apache/atlas/AtlasClient.java
index 5ed79bc..6c13ec8 100755
--- a/client/src/main/java/org/apache/atlas/AtlasClient.java
+++ b/client/src/main/java/org/apache/atlas/AtlasClient.java
@@ -100,6 +100,9 @@ public class AtlasClient {
     public static final String URI_NAME_LINEAGE = "lineage/hive/table";
     public static final String URI_LINEAGE = "lineage/";
     public static final String URI_TRAITS = "traits";
+    public static final String TRAITS = "traits";
+    public static final String TRAIT_DEFINITIONS = "traitDefinitions";
+
 
     public static final String QUERY = "query";
     public static final String LIMIT = "limit";
@@ -492,6 +495,8 @@ public class AtlasClient {
         ADD_TRAITS(BASE_URI + URI_ENTITY, HttpMethod.POST, Response.Status.CREATED),
         DELETE_TRAITS(BASE_URI + URI_ENTITY, HttpMethod.DELETE, Response.Status.OK),
         LIST_TRAITS(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK),
+        GET_ALL_TRAIT_DEFINITIONS(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK),
+        GET_TRAIT_DEFINITION(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK),
 
         //Search operations
         SEARCH(BASE_URI + URI_SEARCH, HttpMethod.GET, Response.Status.OK),
@@ -987,6 +992,40 @@ public class AtlasClient {
         return extractResults(jsonResponse, AtlasClient.RESULTS, new ExtractOperation<String, String>());
     }
 
+    /**
+     * Get all trait definitions for an entity
+     * @param guid GUID of the entity
+     * @return List<String> trait definitions of the traits associated to the entity
+     * @throws AtlasServiceException
+     */
+    public List<Struct> listTraitDefinitions(final String guid) throws AtlasServiceException{
+        JSONObject jsonResponse = callAPI(API.GET_ALL_TRAIT_DEFINITIONS, null, guid, TRAIT_DEFINITIONS);
+        List<JSONObject> traitDefList = extractResults(jsonResponse, AtlasClient.RESULTS, new ExtractOperation<JSONObject, JSONObject>());
+        ArrayList<Struct> traitStructList = new ArrayList<>();
+        for(JSONObject traitDef:traitDefList){
+            Struct traitStruct = InstanceSerialization.fromJsonStruct(traitDef.toString(), true);
+            traitStructList.add(traitStruct);
+        }
+        return traitStructList;
+    }
+
+    /**
+     * Get trait definition for a given entity and traitname
+     * @param guid GUID of the entity
+     * @param traitName
+     * @return trait definition
+     * @throws AtlasServiceException
+     */
+    public Struct getTraitDefinition(final String guid, final String traitName) throws AtlasServiceException{
+        JSONObject jsonResponse = callAPI(API.GET_TRAIT_DEFINITION, null, guid, TRAIT_DEFINITIONS, traitName);
+
+        try {
+            return InstanceSerialization.fromJsonStruct(jsonResponse.getString(AtlasClient.RESULTS), false);
+        }catch (JSONException e){
+            throw new AtlasServiceException(API.GET_TRAIT_DEFINITION, e);
+        }
+    }
+
     protected class ExtractOperation<T, U> {
         T extractElement(U element) throws JSONException {
             return (T) element;

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index f043a33..b11d7dc 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
 ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
 
 ALL CHANGES:
+ATLAS-712 Support getTrait() API (svimal2106 via shwethags)
 ATLAS-1173 Doc: Minor editorial bug in the example given for property atlas.server.ha.zookeeper.auth (yhemanth via shwethags)
 ATLAS-1133 Jetty Server start doesn't throw exception when user-credential.properties file is not found (nixonrodrigues,svimal2106 via kevalbhatt)
 ATLAS-1149 Changes to UI to sort the hive table schema based on "position" attribute of hive_column (Kalyanikashikar via kevalbhatt)

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
index 6a937f4..fdb749a 100755
--- a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
+++ b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
@@ -22,7 +22,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Provider;
-
 import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasException;
@@ -33,7 +32,6 @@ import org.apache.atlas.ha.HAConfiguration;
 import org.apache.atlas.listener.ActiveStateChangeHandler;
 import org.apache.atlas.listener.EntityChangeListener;
 import org.apache.atlas.listener.TypesChangeListener;
-import org.apache.atlas.query.QueryKeywords;
 import org.apache.atlas.query.QueryParser;
 import org.apache.atlas.repository.MetadataRepository;
 import org.apache.atlas.repository.RepositoryException;
@@ -77,7 +75,6 @@ import scala.collection.Set;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashSet;
@@ -701,12 +698,12 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
     }
 
     @Override
-    public String getTraitDefinition(String guid, final String traitName) throws AtlasException {
+    public IStruct getTraitDefinition(String guid, final String traitName) throws AtlasException {
         guid = ParamChecker.notEmpty(guid, "entity id");
 
         final ITypedReferenceableInstance instance = repository.getEntityDefinition(guid);
         IStruct struct = instance.getTrait(traitName);
-        return InstanceSerialization.toJson(struct, true);
+        return struct;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java b/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java
index 52dcfde..6782970 100644
--- a/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java
+++ b/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java
@@ -269,10 +269,9 @@ public class DefaultMetadataServiceTest {
         assertEquals(traits.get(0), PII);
 
         //getTrait
-        String traitDefinition = metadataService.getTraitDefinition(id, PII);
-        Struct traitResult = InstanceSerialization.fromJsonStruct(traitDefinition, true);
-        Assert.assertNotNull(traitResult);
-        assertEquals(traitResult.getValuesMap().size(), 0);
+        IStruct traitDefinition = metadataService.getTraitDefinition(id, PII);
+        Assert.assertNotNull(traitDefinition);
+        assertEquals(traitDefinition.getValuesMap().size(), 0);
 
         //delete trait
         metadataService.deleteTrait(id, PII);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/server-api/src/main/java/org/apache/atlas/services/MetadataService.java
----------------------------------------------------------------------
diff --git a/server-api/src/main/java/org/apache/atlas/services/MetadataService.java b/server-api/src/main/java/org/apache/atlas/services/MetadataService.java
index 60d8790..2351891 100644
--- a/server-api/src/main/java/org/apache/atlas/services/MetadataService.java
+++ b/server-api/src/main/java/org/apache/atlas/services/MetadataService.java
@@ -26,6 +26,7 @@ import org.apache.atlas.typesystem.ITypedReferenceableInstance;
 import org.apache.atlas.typesystem.ITypedStruct;
 import org.apache.atlas.typesystem.Referenceable;
 import org.apache.atlas.typesystem.Struct;
+import org.apache.atlas.typesystem.IStruct;
 import org.apache.atlas.typesystem.types.cache.TypeCache;
 import org.codehaus.jettison.json.JSONObject;
 
@@ -213,7 +214,7 @@ public interface MetadataService {
      * @return
      * @throws AtlasException
      */
-    String getTraitDefinition(String guid, String traitName) throws AtlasException;
+    IStruct getTraitDefinition(String guid, String traitName) throws AtlasException;
 
     /**
      * Deletes a given trait from an existing entity represented by a guid.

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
index 82016d0..bbf01a6 100755
--- a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
+++ b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
@@ -25,6 +25,7 @@ import org.apache.atlas.AtlasConstants;
 import org.apache.atlas.AtlasException;
 import org.apache.atlas.EntityAuditEvent;
 import org.apache.atlas.services.MetadataService;
+import org.apache.atlas.typesystem.IStruct;
 import org.apache.atlas.typesystem.Referenceable;
 import org.apache.atlas.typesystem.exception.EntityExistsException;
 import org.apache.atlas.typesystem.exception.EntityNotFoundException;
@@ -639,6 +640,88 @@ public class EntityResource {
     }
 
     /**
+     * Fetches the trait definitions of all the traits associated to the given entity
+     * @param guid globally unique identifier for the entity
+     */
+    @GET
+    @Path("{guid}/traitDefinitions")
+    @Produces(Servlets.JSON_MEDIA_TYPE)
+    public Response getTraitDefinitionsForEntity(@PathParam("guid") String guid){
+        AtlasPerfTracer perf = null;
+        try {
+            if(AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+                perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "EntityResource.getTraitDefinitionsForEntity(" + guid + ")");
+            }
+            LOG.debug("Fetching all trait definitions for entity={}", guid);
+            final String entityDefinition = metadataService.getEntityDefinition(guid);
+
+            Referenceable entity = InstanceSerialization.fromJsonReferenceable(entityDefinition, true);
+            JSONArray traits = new JSONArray();
+            for (String traitName : entity.getTraits()) {
+                IStruct trait = entity.getTrait(traitName);
+                traits.put(new JSONObject(InstanceSerialization.toJson(trait, true)));
+            }
+
+            JSONObject response = new JSONObject();
+            response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
+            response.put(AtlasClient.RESULTS, traits);
+            response.put(AtlasClient.COUNT, traits.length());
+
+            return Response.ok(response).build();
+        } catch (EntityNotFoundException e){
+            LOG.error("An entity with GUID={} does not exist", guid, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
+        } catch (AtlasException | IllegalArgumentException e) {
+            LOG.error("Unable to get trait definitions for entity {}", guid, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
+        } catch (Throwable e) {
+            LOG.error("Unable to get trait definitions for entity {}", guid, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
+        } finally {
+            AtlasPerfTracer.log(perf);
+        }
+
+    }
+
+    /**
+     * Fetches the trait definition for an entity given its guid and trait name
+     *
+     * @param guid globally unique identifier for the entity
+     * @param traitName name of the trait
+     */
+    @GET
+    @Path("{guid}/traitDefinitions/{traitName}")
+    @Produces(Servlets.JSON_MEDIA_TYPE)
+    public Response getTraitDefinitionForEntity(@PathParam("guid") String guid, @PathParam("traitName") String traitName){
+        AtlasPerfTracer perf = null;
+        try {
+            if(AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+                perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "EntityResource.getTraitDefinitionForEntity(" + guid + ", " + traitName + ")");
+            }
+            LOG.debug("Fetching trait definition for entity {} and trait name {}", guid, traitName);
+            final IStruct traitDefinition = metadataService.getTraitDefinition(guid, traitName);
+
+            JSONObject response = new JSONObject();
+            response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
+            response.put(AtlasClient.RESULTS, new JSONObject(InstanceSerialization.toJson(traitDefinition, true)));
+
+            return Response.ok(response).build();
+
+        } catch (EntityNotFoundException e){
+            LOG.error("An entity with GUID={} does not exist", guid, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
+        } catch (AtlasException | IllegalArgumentException e) {
+            LOG.error("Unable to get trait definition for entity {} and trait {}", guid, traitName, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
+        } catch (Throwable e) {
+            LOG.error("Unable to get trait definition for entity {} and trait {}", guid, traitName, e);
+            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
+        } finally {
+            AtlasPerfTracer.log(perf);
+        }
+    }
+
+    /**
      * Adds a new trait to an existing entity represented by a guid.
      *
      * @param guid globally unique identifier for the entity

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/dd0b051e/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
index a1988ef..ea86cc6 100755
--- a/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
@@ -87,6 +87,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
     private final String TABLE_NAME = "table" + randomString();
     private static final String ENTITIES = "api/atlas/entities";
     private static final String TRAITS = "traits";
+    private static final String TRAIT_DEFINITION = "traitDefinitions";
 
     private Referenceable tableInstance;
     private Id tableId;
@@ -526,6 +527,37 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
         assertEntityAudit(guid, EntityAuditEvent.EntityAuditAction.TAG_ADD);
     }
 
+    @Test(dependsOnMethods = "testSubmitEntity")
+    public void testgetTraitDefinitionForEntity() throws Exception{
+        traitName = "PII_Trait" + randomString();
+        HierarchicalTypeDefinition<TraitType> piiTrait =
+                TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of());
+        String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true);
+        LOG.debug("traitDefinitionAsJSON = " + traitDefinitionAsJSON);
+        createType(traitDefinitionAsJSON);
+
+        Struct traitInstance = new Struct(traitName);
+        String traitInstanceAsJSON = InstanceSerialization.toJson(traitInstance, true);
+        LOG.debug("traitInstanceAsJSON = " + traitInstanceAsJSON);
+
+        final String guid = tableId._getId();
+        ClientResponse clientResponse =
+                service.path(ENTITIES).path(guid).path(TRAITS).accept(Servlets.JSON_MEDIA_TYPE)
+                        .type(Servlets.JSON_MEDIA_TYPE)
+                        .method(HttpMethod.POST, ClientResponse.class, traitInstanceAsJSON);
+        Assert.assertEquals(clientResponse.getStatus(), Response.Status.CREATED.getStatusCode());
+
+        Struct traitDef = serviceClient.getTraitDefinition(guid, traitName);
+        System.out.println(traitDef.toString());
+        JSONObject responseAsJSON = new JSONObject(InstanceSerialization.toJson(traitDef, true));
+        Assert.assertEquals(responseAsJSON.get("typeName"), traitName);
+
+
+        List<Struct> allTraitDefs = serviceClient.listTraitDefinitions(guid);
+        System.out.println(allTraitDefs.toString());
+        Assert.assertEquals(allTraitDefs.size(), 9);
+    }
+
     @Test(dependsOnMethods = "testAddTrait")
     public void testAddExistingTrait() throws Exception {
         final String traitName = "PII_Trait" + randomString();


[3/8] incubator-atlas git commit: ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/require-handlebars-plugin/js/handlebars.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/require-handlebars-plugin/js/handlebars.js b/dashboardv2/public/js/require-handlebars-plugin/js/handlebars.js
deleted file mode 100644
index b62aa79..0000000
--- a/dashboardv2/public/js/require-handlebars-plugin/js/handlebars.js
+++ /dev/null
@@ -1,3103 +0,0 @@
-(function() {
-    /*
-
-    Copyright (C) 2011 by Yehuda Katz
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in
-    all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-    THE SOFTWARE.
-
-    */
-
-    // lib/handlebars/browser-prefix.js
-    var Handlebars = {};
-
-    (function(Handlebars, undefined) {;
-        // lib/handlebars/base.js
-
-        Handlebars.VERSION = "1.0.0-rc.3";
-        Handlebars.COMPILER_REVISION = 2;
-
-        Handlebars.REVISION_CHANGES = {
-            1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
-            2: '>= 1.0.0-rc.3'
-        };
-
-        Handlebars.helpers = {};
-        Handlebars.partials = {};
-
-        Handlebars.registerHelper = function(name, fn, inverse) {
-            if (inverse) {
-                fn.not = inverse;
-            }
-            this.helpers[name] = fn;
-        };
-
-        Handlebars.registerPartial = function(name, str) {
-            this.partials[name] = str;
-        };
-
-        Handlebars.registerHelper('helperMissing', function(arg) {
-            if (arguments.length === 2) {
-                return undefined;
-            } else {
-                throw new Error("Could not find property '" + arg + "'");
-            }
-        });
-
-        var toString = Object.prototype.toString,
-            functionType = "[object Function]";
-
-        Handlebars.registerHelper('blockHelperMissing', function(context, options) {
-            var inverse = options.inverse || function() {},
-                fn = options.fn;
-
-            var type = toString.call(context);
-
-            if (type === functionType) {
-                context = context.call(this);
-            }
-
-            if (context === true) {
-                return fn(this);
-            } else if (context === false || context == null) {
-                return inverse(this);
-            } else if (type === "[object Array]") {
-                if (context.length > 0) {
-                    return Handlebars.helpers.each(context, options);
-                } else {
-                    return inverse(this);
-                }
-            } else {
-                return fn(context);
-            }
-        });
-
-        Handlebars.K = function() {};
-
-        Handlebars.createFrame = Object.create || function(object) {
-            Handlebars.K.prototype = object;
-            var obj = new Handlebars.K();
-            Handlebars.K.prototype = null;
-            return obj;
-        };
-
-        Handlebars.logger = {
-            DEBUG: 0,
-            INFO: 1,
-            WARN: 2,
-            ERROR: 3,
-            level: 3,
-
-            methodMap: {
-                0: 'debug',
-                1: 'info',
-                2: 'warn',
-                3: 'error'
-            },
-
-            // can be overridden in the host environment
-            log: function(level, obj) {
-                if (Handlebars.logger.level <= level) {
-                    var method = Handlebars.logger.methodMap[level];
-                    if (typeof console !== 'undefined' && console[method]) {
-                        console[method].call(console, obj);
-                    }
-                }
-            }
-        };
-
-        Handlebars.log = function(level, obj) {
-            Handlebars.logger.log(level, obj);
-        };
-
-        Handlebars.registerHelper('each', function(context, options) {
-            var fn = options.fn,
-                inverse = options.inverse;
-            var i = 0,
-                ret = "",
-                data;
-
-            if (options.data) {
-                data = Handlebars.createFrame(options.data);
-            }
-
-            if (context && typeof context === 'object') {
-                if (context instanceof Array) {
-                    for (var j = context.length; i < j; i++) {
-                        if (data) {
-                            data.index = i;
-                        }
-                        ret = ret + fn(context[i], {
-                            data: data
-                        });
-                    }
-                } else {
-                    for (var key in context) {
-                        if (context.hasOwnProperty(key)) {
-                            if (data) {
-                                data.key = key;
-                            }
-                            ret = ret + fn(context[key], {
-                                data: data
-                            });
-                            i++;
-                        }
-                    }
-                }
-            }
-
-            if (i === 0) {
-                ret = inverse(this);
-            }
-
-            return ret;
-        });
-
-        Handlebars.registerHelper('if', function(context, options) {
-            var type = toString.call(context);
-            if (type === functionType) {
-                context = context.call(this);
-            }
-
-            if (!context || Handlebars.Utils.isEmpty(context)) {
-                return options.inverse(this);
-            } else {
-                return options.fn(this);
-            }
-        });
-
-        Handlebars.registerHelper('unless', function(context, options) {
-            return Handlebars.helpers['if'].call(this, context, {
-                fn: options.inverse,
-                inverse: options.fn
-            });
-        });
-
-        Handlebars.registerHelper('with', function(context, options) {
-            return options.fn(context);
-        });
-
-        Handlebars.registerHelper('log', function(context, options) {
-            var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
-            Handlebars.log(level, context);
-        });;
-    }(Handlebars));;
-    //>>excludeStart('excludeHbsParser', pragmas.excludeHbsParser)
-    // lib/handlebars/compiler/parser.js
-    /* Jison generated parser */
-    var handlebars = (function() {
-        var parser = {
-            trace: function trace() {},
-            yy: {},
-            symbols_: {
-                "error": 2,
-                "root": 3,
-                "program": 4,
-                "EOF": 5,
-                "simpleInverse": 6,
-                "statements": 7,
-                "statement": 8,
-                "openInverse": 9,
-                "closeBlock": 10,
-                "openBlock": 11,
-                "mustache": 12,
-                "partial": 13,
-                "CONTENT": 14,
-                "COMMENT": 15,
-                "OPEN_BLOCK": 16,
-                "inMustache": 17,
-                "CLOSE": 18,
-                "OPEN_INVERSE": 19,
-                "OPEN_ENDBLOCK": 20,
-                "path": 21,
-                "OPEN": 22,
-                "OPEN_UNESCAPED": 23,
-                "OPEN_PARTIAL": 24,
-                "partialName": 25,
-                "params": 26,
-                "hash": 27,
-                "DATA": 28,
-                "param": 29,
-                "STRING": 30,
-                "INTEGER": 31,
-                "BOOLEAN": 32,
-                "hashSegments": 33,
-                "hashSegment": 34,
-                "ID": 35,
-                "EQUALS": 36,
-                "PARTIAL_NAME": 37,
-                "pathSegments": 38,
-                "SEP": 39,
-                "$accept": 0,
-                "$end": 1
-            },
-            terminals_: {
-                2: "error",
-                5: "EOF",
-                14: "CONTENT",
-                15: "COMMENT",
-                16: "OPEN_BLOCK",
-                18: "CLOSE",
-                19: "OPEN_INVERSE",
-                20: "OPEN_ENDBLOCK",
-                22: "OPEN",
-                23: "OPEN_UNESCAPED",
-                24: "OPEN_PARTIAL",
-                28: "DATA",
-                30: "STRING",
-                31: "INTEGER",
-                32: "BOOLEAN",
-                35: "ID",
-                36: "EQUALS",
-                37: "PARTIAL_NAME",
-                39: "SEP"
-            },
-            productions_: [0, [3, 2],
-                [4, 2],
-                [4, 3],
-                [4, 2],
-                [4, 1],
-                [4, 1],
-                [4, 0],
-                [7, 1],
-                [7, 2],
-                [8, 3],
-                [8, 3],
-                [8, 1],
-                [8, 1],
-                [8, 1],
-                [8, 1],
-                [11, 3],
-                [9, 3],
-                [10, 3],
-                [12, 3],
-                [12, 3],
-                [13, 3],
-                [13, 4],
-                [6, 2],
-                [17, 3],
-                [17, 2],
-                [17, 2],
-                [17, 1],
-                [17, 1],
-                [26, 2],
-                [26, 1],
-                [29, 1],
-                [29, 1],
-                [29, 1],
-                [29, 1],
-                [29, 1],
-                [27, 1],
-                [33, 2],
-                [33, 1],
-                [34, 3],
-                [34, 3],
-                [34, 3],
-                [34, 3],
-                [34, 3],
-                [25, 1],
-                [21, 1],
-                [38, 3],
-                [38, 1]
-            ],
-            performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
-
-                var $0 = $$.length - 1;
-                switch (yystate) {
-                    case 1:
-                        return $$[$0 - 1];
-                        break;
-                    case 2:
-                        this.$ = new yy.ProgramNode([], $$[$0]);
-                        break;
-                    case 3:
-                        this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0]);
-                        break;
-                    case 4:
-                        this.$ = new yy.ProgramNode($$[$0 - 1], []);
-                        break;
-                    case 5:
-                        this.$ = new yy.ProgramNode($$[$0]);
-                        break;
-                    case 6:
-                        this.$ = new yy.ProgramNode([], []);
-                        break;
-                    case 7:
-                        this.$ = new yy.ProgramNode([]);
-                        break;
-                    case 8:
-                        this.$ = [$$[$0]];
-                        break;
-                    case 9:
-                        $$[$0 - 1].push($$[$0]);
-                        this.$ = $$[$0 - 1];
-                        break;
-                    case 10:
-                        this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1].inverse, $$[$0 - 1], $$[$0]);
-                        break;
-                    case 11:
-                        this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0 - 1].inverse, $$[$0]);
-                        break;
-                    case 12:
-                        this.$ = $$[$0];
-                        break;
-                    case 13:
-                        this.$ = $$[$0];
-                        break;
-                    case 14:
-                        this.$ = new yy.ContentNode($$[$0]);
-                        break;
-                    case 15:
-                        this.$ = new yy.CommentNode($$[$0]);
-                        break;
-                    case 16:
-                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
-                        break;
-                    case 17:
-                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
-                        break;
-                    case 18:
-                        this.$ = $$[$0 - 1];
-                        break;
-                    case 19:
-                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
-                        break;
-                    case 20:
-                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true);
-                        break;
-                    case 21:
-                        this.$ = new yy.PartialNode($$[$0 - 1]);
-                        break;
-                    case 22:
-                        this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1]);
-                        break;
-                    case 23:
-                        break;
-                    case 24:
-                        this.$ = [
-                            [$$[$0 - 2]].concat($$[$0 - 1]), $$[$0]
-                        ];
-                        break;
-                    case 25:
-                        this.$ = [
-                            [$$[$0 - 1]].concat($$[$0]), null
-                        ];
-                        break;
-                    case 26:
-                        this.$ = [
-                            [$$[$0 - 1]], $$[$0]
-                        ];
-                        break;
-                    case 27:
-                        this.$ = [
-                            [$$[$0]], null
-                        ];
-                        break;
-                    case 28:
-                        this.$ = [
-                            [new yy.DataNode($$[$0])], null
-                        ];
-                        break;
-                    case 29:
-                        $$[$0 - 1].push($$[$0]);
-                        this.$ = $$[$0 - 1];
-                        break;
-                    case 30:
-                        this.$ = [$$[$0]];
-                        break;
-                    case 31:
-                        this.$ = $$[$0];
-                        break;
-                    case 32:
-                        this.$ = new yy.StringNode($$[$0]);
-                        break;
-                    case 33:
-                        this.$ = new yy.IntegerNode($$[$0]);
-                        break;
-                    case 34:
-                        this.$ = new yy.BooleanNode($$[$0]);
-                        break;
-                    case 35:
-                        this.$ = new yy.DataNode($$[$0]);
-                        break;
-                    case 36:
-                        this.$ = new yy.HashNode($$[$0]);
-                        break;
-                    case 37:
-                        $$[$0 - 1].push($$[$0]);
-                        this.$ = $$[$0 - 1];
-                        break;
-                    case 38:
-                        this.$ = [$$[$0]];
-                        break;
-                    case 39:
-                        this.$ = [$$[$0 - 2], $$[$0]];
-                        break;
-                    case 40:
-                        this.$ = [$$[$0 - 2], new yy.StringNode($$[$0])];
-                        break;
-                    case 41:
-                        this.$ = [$$[$0 - 2], new yy.IntegerNode($$[$0])];
-                        break;
-                    case 42:
-                        this.$ = [$$[$0 - 2], new yy.BooleanNode($$[$0])];
-                        break;
-                    case 43:
-                        this.$ = [$$[$0 - 2], new yy.DataNode($$[$0])];
-                        break;
-                    case 44:
-                        this.$ = new yy.PartialNameNode($$[$0]);
-                        break;
-                    case 45:
-                        this.$ = new yy.IdNode($$[$0]);
-                        break;
-                    case 46:
-                        $$[$0 - 2].push($$[$0]);
-                        this.$ = $$[$0 - 2];
-                        break;
-                    case 47:
-                        this.$ = [$$[$0]];
-                        break;
-                }
-            },
-            table: [{
-                3: 1,
-                4: 2,
-                5: [2, 7],
-                6: 3,
-                7: 4,
-                8: 6,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 5],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                1: [3]
-            }, {
-                5: [1, 17]
-            }, {
-                5: [2, 6],
-                7: 18,
-                8: 6,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 19],
-                20: [2, 6],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                5: [2, 5],
-                6: 20,
-                8: 21,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 5],
-                20: [2, 5],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                17: 23,
-                18: [1, 22],
-                21: 24,
-                28: [1, 25],
-                35: [1, 27],
-                38: 26
-            }, {
-                5: [2, 8],
-                14: [2, 8],
-                15: [2, 8],
-                16: [2, 8],
-                19: [2, 8],
-                20: [2, 8],
-                22: [2, 8],
-                23: [2, 8],
-                24: [2, 8]
-            }, {
-                4: 28,
-                6: 3,
-                7: 4,
-                8: 6,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 5],
-                20: [2, 7],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                4: 29,
-                6: 3,
-                7: 4,
-                8: 6,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 5],
-                20: [2, 7],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                5: [2, 12],
-                14: [2, 12],
-                15: [2, 12],
-                16: [2, 12],
-                19: [2, 12],
-                20: [2, 12],
-                22: [2, 12],
-                23: [2, 12],
-                24: [2, 12]
-            }, {
-                5: [2, 13],
-                14: [2, 13],
-                15: [2, 13],
-                16: [2, 13],
-                19: [2, 13],
-                20: [2, 13],
-                22: [2, 13],
-                23: [2, 13],
-                24: [2, 13]
-            }, {
-                5: [2, 14],
-                14: [2, 14],
-                15: [2, 14],
-                16: [2, 14],
-                19: [2, 14],
-                20: [2, 14],
-                22: [2, 14],
-                23: [2, 14],
-                24: [2, 14]
-            }, {
-                5: [2, 15],
-                14: [2, 15],
-                15: [2, 15],
-                16: [2, 15],
-                19: [2, 15],
-                20: [2, 15],
-                22: [2, 15],
-                23: [2, 15],
-                24: [2, 15]
-            }, {
-                17: 30,
-                21: 24,
-                28: [1, 25],
-                35: [1, 27],
-                38: 26
-            }, {
-                17: 31,
-                21: 24,
-                28: [1, 25],
-                35: [1, 27],
-                38: 26
-            }, {
-                17: 32,
-                21: 24,
-                28: [1, 25],
-                35: [1, 27],
-                38: 26
-            }, {
-                25: 33,
-                37: [1, 34]
-            }, {
-                1: [2, 1]
-            }, {
-                5: [2, 2],
-                8: 21,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 19],
-                20: [2, 2],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                17: 23,
-                21: 24,
-                28: [1, 25],
-                35: [1, 27],
-                38: 26
-            }, {
-                5: [2, 4],
-                7: 35,
-                8: 6,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 19],
-                20: [2, 4],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                5: [2, 9],
-                14: [2, 9],
-                15: [2, 9],
-                16: [2, 9],
-                19: [2, 9],
-                20: [2, 9],
-                22: [2, 9],
-                23: [2, 9],
-                24: [2, 9]
-            }, {
-                5: [2, 23],
-                14: [2, 23],
-                15: [2, 23],
-                16: [2, 23],
-                19: [2, 23],
-                20: [2, 23],
-                22: [2, 23],
-                23: [2, 23],
-                24: [2, 23]
-            }, {
-                18: [1, 36]
-            }, {
-                18: [2, 27],
-                21: 41,
-                26: 37,
-                27: 38,
-                28: [1, 45],
-                29: 39,
-                30: [1, 42],
-                31: [1, 43],
-                32: [1, 44],
-                33: 40,
-                34: 46,
-                35: [1, 47],
-                38: 26
-            }, {
-                18: [2, 28]
-            }, {
-                18: [2, 45],
-                28: [2, 45],
-                30: [2, 45],
-                31: [2, 45],
-                32: [2, 45],
-                35: [2, 45],
-                39: [1, 48]
-            }, {
-                18: [2, 47],
-                28: [2, 47],
-                30: [2, 47],
-                31: [2, 47],
-                32: [2, 47],
-                35: [2, 47],
-                39: [2, 47]
-            }, {
-                10: 49,
-                20: [1, 50]
-            }, {
-                10: 51,
-                20: [1, 50]
-            }, {
-                18: [1, 52]
-            }, {
-                18: [1, 53]
-            }, {
-                18: [1, 54]
-            }, {
-                18: [1, 55],
-                21: 56,
-                35: [1, 27],
-                38: 26
-            }, {
-                18: [2, 44],
-                35: [2, 44]
-            }, {
-                5: [2, 3],
-                8: 21,
-                9: 7,
-                11: 8,
-                12: 9,
-                13: 10,
-                14: [1, 11],
-                15: [1, 12],
-                16: [1, 13],
-                19: [1, 19],
-                20: [2, 3],
-                22: [1, 14],
-                23: [1, 15],
-                24: [1, 16]
-            }, {
-                14: [2, 17],
-                15: [2, 17],
-                16: [2, 17],
-                19: [2, 17],
-                20: [2, 17],
-                22: [2, 17],
-                23: [2, 17],
-                24: [2, 17]
-            }, {
-                18: [2, 25],
-                21: 41,
-                27: 57,
-                28: [1, 45],
-                29: 58,
-                30: [1, 42],
-                31: [1, 43],
-                32: [1, 44],
-                33: 40,
-                34: 46,
-                35: [1, 47],
-                38: 26
-            }, {
-                18: [2, 26]
-            }, {
-                18: [2, 30],
-                28: [2, 30],
-                30: [2, 30],
-                31: [2, 30],
-                32: [2, 30],
-                35: [2, 30]
-            }, {
-                18: [2, 36],
-                34: 59,
-                35: [1, 60]
-            }, {
-                18: [2, 31],
-                28: [2, 31],
-                30: [2, 31],
-                31: [2, 31],
-                32: [2, 31],
-                35: [2, 31]
-            }, {
-                18: [2, 32],
-                28: [2, 32],
-                30: [2, 32],
-                31: [2, 32],
-                32: [2, 32],
-                35: [2, 32]
-            }, {
-                18: [2, 33],
-                28: [2, 33],
-                30: [2, 33],
-                31: [2, 33],
-                32: [2, 33],
-                35: [2, 33]
-            }, {
-                18: [2, 34],
-                28: [2, 34],
-                30: [2, 34],
-                31: [2, 34],
-                32: [2, 34],
-                35: [2, 34]
-            }, {
-                18: [2, 35],
-                28: [2, 35],
-                30: [2, 35],
-                31: [2, 35],
-                32: [2, 35],
-                35: [2, 35]
-            }, {
-                18: [2, 38],
-                35: [2, 38]
-            }, {
-                18: [2, 47],
-                28: [2, 47],
-                30: [2, 47],
-                31: [2, 47],
-                32: [2, 47],
-                35: [2, 47],
-                36: [1, 61],
-                39: [2, 47]
-            }, {
-                35: [1, 62]
-            }, {
-                5: [2, 10],
-                14: [2, 10],
-                15: [2, 10],
-                16: [2, 10],
-                19: [2, 10],
-                20: [2, 10],
-                22: [2, 10],
-                23: [2, 10],
-                24: [2, 10]
-            }, {
-                21: 63,
-                35: [1, 27],
-                38: 26
-            }, {
-                5: [2, 11],
-                14: [2, 11],
-                15: [2, 11],
-                16: [2, 11],
-                19: [2, 11],
-                20: [2, 11],
-                22: [2, 11],
-                23: [2, 11],
-                24: [2, 11]
-            }, {
-                14: [2, 16],
-                15: [2, 16],
-                16: [2, 16],
-                19: [2, 16],
-                20: [2, 16],
-                22: [2, 16],
-                23: [2, 16],
-                24: [2, 16]
-            }, {
-                5: [2, 19],
-                14: [2, 19],
-                15: [2, 19],
-                16: [2, 19],
-                19: [2, 19],
-                20: [2, 19],
-                22: [2, 19],
-                23: [2, 19],
-                24: [2, 19]
-            }, {
-                5: [2, 20],
-                14: [2, 20],
-                15: [2, 20],
-                16: [2, 20],
-                19: [2, 20],
-                20: [2, 20],
-                22: [2, 20],
-                23: [2, 20],
-                24: [2, 20]
-            }, {
-                5: [2, 21],
-                14: [2, 21],
-                15: [2, 21],
-                16: [2, 21],
-                19: [2, 21],
-                20: [2, 21],
-                22: [2, 21],
-                23: [2, 21],
-                24: [2, 21]
-            }, {
-                18: [1, 64]
-            }, {
-                18: [2, 24]
-            }, {
-                18: [2, 29],
-                28: [2, 29],
-                30: [2, 29],
-                31: [2, 29],
-                32: [2, 29],
-                35: [2, 29]
-            }, {
-                18: [2, 37],
-                35: [2, 37]
-            }, {
-                36: [1, 61]
-            }, {
-                21: 65,
-                28: [1, 69],
-                30: [1, 66],
-                31: [1, 67],
-                32: [1, 68],
-                35: [1, 27],
-                38: 26
-            }, {
-                18: [2, 46],
-                28: [2, 46],
-                30: [2, 46],
-                31: [2, 46],
-                32: [2, 46],
-                35: [2, 46],
-                39: [2, 46]
-            }, {
-                18: [1, 70]
-            }, {
-                5: [2, 22],
-                14: [2, 22],
-                15: [2, 22],
-                16: [2, 22],
-                19: [2, 22],
-                20: [2, 22],
-                22: [2, 22],
-                23: [2, 22],
-                24: [2, 22]
-            }, {
-                18: [2, 39],
-                35: [2, 39]
-            }, {
-                18: [2, 40],
-                35: [2, 40]
-            }, {
-                18: [2, 41],
-                35: [2, 41]
-            }, {
-                18: [2, 42],
-                35: [2, 42]
-            }, {
-                18: [2, 43],
-                35: [2, 43]
-            }, {
-                5: [2, 18],
-                14: [2, 18],
-                15: [2, 18],
-                16: [2, 18],
-                19: [2, 18],
-                20: [2, 18],
-                22: [2, 18],
-                23: [2, 18],
-                24: [2, 18]
-            }],
-            defaultActions: {
-                17: [2, 1],
-                25: [2, 28],
-                38: [2, 26],
-                57: [2, 24]
-            },
-            parseError: function parseError(str, hash) {
-                throw new Error(str);
-            },
-            parse: function parse(input) {
-                var self = this,
-                    stack = [0],
-                    vstack = [null],
-                    lstack = [],
-                    table = this.table,
-                    yytext = "",
-                    yylineno = 0,
-                    yyleng = 0,
-                    recovering = 0,
-                    TERROR = 2,
-                    EOF = 1;
-                this.lexer.setInput(input);
-                this.lexer.yy = this.yy;
-                this.yy.lexer = this.lexer;
-                this.yy.parser = this;
-                if (typeof this.lexer.yylloc == "undefined")
-                    this.lexer.yylloc = {};
-                var yyloc = this.lexer.yylloc;
-                lstack.push(yyloc);
-                var ranges = this.lexer.options && this.lexer.options.ranges;
-                if (typeof this.yy.parseError === "function")
-                    this.parseError = this.yy.parseError;
-
-                function popStack(n) {
-                    stack.length = stack.length - 2 * n;
-                    vstack.length = vstack.length - n;
-                    lstack.length = lstack.length - n;
-                }
-
-                function lex() {
-                    var token;
-                    token = self.lexer.lex() || 1;
-                    if (typeof token !== "number") {
-                        token = self.symbols_[token] || token;
-                    }
-                    return token;
-                }
-                var symbol, preErrorSymbol, state, action, a, r, yyval = {},
-                    p, len, newState, expected;
-                while (true) {
-                    state = stack[stack.length - 1];
-                    if (this.defaultActions[state]) {
-                        action = this.defaultActions[state];
-                    } else {
-                        if (symbol === null || typeof symbol == "undefined") {
-                            symbol = lex();
-                        }
-                        action = table[state] && table[state][symbol];
-                    }
-                    if (typeof action === "undefined" || !action.length || !action[0]) {
-                        var errStr = "";
-                        if (!recovering) {
-                            expected = [];
-                            for (p in table[state])
-                                if (this.terminals_[p] && p > 2) {
-                                    expected.push("'" + this.terminals_[p] + "'");
-                                }
-                            if (this.lexer.showPosition) {
-                                errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
-                            } else {
-                                errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
-                            }
-                            this.parseError(errStr, {
-                                text: this.lexer.match,
-                                token: this.terminals_[symbol] || symbol,
-                                line: this.lexer.yylineno,
-                                loc: yyloc,
-                                expected: expected
-                            });
-                        }
-                    }
-                    if (action[0] instanceof Array && action.length > 1) {
-                        throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
-                    }
-                    switch (action[0]) {
-                        case 1:
-                            stack.push(symbol);
-                            vstack.push(this.lexer.yytext);
-                            lstack.push(this.lexer.yylloc);
-                            stack.push(action[1]);
-                            symbol = null;
-                            if (!preErrorSymbol) {
-                                yyleng = this.lexer.yyleng;
-                                yytext = this.lexer.yytext;
-                                yylineno = this.lexer.yylineno;
-                                yyloc = this.lexer.yylloc;
-                                if (recovering > 0)
-                                    recovering--;
-                            } else {
-                                symbol = preErrorSymbol;
-                                preErrorSymbol = null;
-                            }
-                            break;
-                        case 2:
-                            len = this.productions_[action[1]][1];
-                            yyval.$ = vstack[vstack.length - len];
-                            yyval._$ = {
-                                first_line: lstack[lstack.length - (len || 1)].first_line,
-                                last_line: lstack[lstack.length - 1].last_line,
-                                first_column: lstack[lstack.length - (len || 1)].first_column,
-                                last_column: lstack[lstack.length - 1].last_column
-                            };
-                            if (ranges) {
-                                yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
-                            }
-                            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
-                            if (typeof r !== "undefined") {
-                                return r;
-                            }
-                            if (len) {
-                                stack = stack.slice(0, -1 * len * 2);
-                                vstack = vstack.slice(0, -1 * len);
-                                lstack = lstack.slice(0, -1 * len);
-                            }
-                            stack.push(this.productions_[action[1]][0]);
-                            vstack.push(yyval.$);
-                            lstack.push(yyval._$);
-                            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
-                            stack.push(newState);
-                            break;
-                        case 3:
-                            return true;
-                    }
-                }
-                return true;
-            }
-        };
-        /* Jison generated lexer */
-        var lexer = (function() {
-            var lexer = ({
-                EOF: 1,
-                parseError: function parseError(str, hash) {
-                    if (this.yy.parser) {
-                        this.yy.parser.parseError(str, hash);
-                    } else {
-                        throw new Error(str);
-                    }
-                },
-                setInput: function(input) {
-                    this._input = input;
-                    this._more = this._less = this.done = false;
-                    this.yylineno = this.yyleng = 0;
-                    this.yytext = this.matched = this.match = '';
-                    this.conditionStack = ['INITIAL'];
-                    this.yylloc = {
-                        first_line: 1,
-                        first_column: 0,
-                        last_line: 1,
-                        last_column: 0
-                    };
-                    if (this.options.ranges) this.yylloc.range = [0, 0];
-                    this.offset = 0;
-                    return this;
-                },
-                input: function() {
-                    var ch = this._input[0];
-                    this.yytext += ch;
-                    this.yyleng++;
-                    this.offset++;
-                    this.match += ch;
-                    this.matched += ch;
-                    var lines = ch.match(/(?:\r\n?|\n).*/g);
-                    if (lines) {
-                        this.yylineno++;
-                        this.yylloc.last_line++;
-                    } else {
-                        this.yylloc.last_column++;
-                    }
-                    if (this.options.ranges) this.yylloc.range[1]++;
-
-                    this._input = this._input.slice(1);
-                    return ch;
-                },
-                unput: function(ch) {
-                    var len = ch.length;
-                    var lines = ch.split(/(?:\r\n?|\n)/g);
-
-                    this._input = ch + this._input;
-                    this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
-                    //this.yyleng -= len;
-                    this.offset -= len;
-                    var oldLines = this.match.split(/(?:\r\n?|\n)/g);
-                    this.match = this.match.substr(0, this.match.length - 1);
-                    this.matched = this.matched.substr(0, this.matched.length - 1);
-
-                    if (lines.length - 1) this.yylineno -= lines.length - 1;
-                    var r = this.yylloc.range;
-
-                    this.yylloc = {
-                        first_line: this.yylloc.first_line,
-                        last_line: this.yylineno + 1,
-                        first_column: this.yylloc.first_column,
-                        last_column: lines ?
-                            (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
-                    };
-
-                    if (this.options.ranges) {
-                        this.yylloc.range = [r[0], r[0] + this.yyleng - len];
-                    }
-                    return this;
-                },
-                more: function() {
-                    this._more = true;
-                    return this;
-                },
-                less: function(n) {
-                    this.unput(this.match.slice(n));
-                },
-                pastInput: function() {
-                    var past = this.matched.substr(0, this.matched.length - this.match.length);
-                    return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
-                },
-                upcomingInput: function() {
-                    var next = this.match;
-                    if (next.length < 20) {
-                        next += this._input.substr(0, 20 - next.length);
-                    }
-                    return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
-                },
-                showPosition: function() {
-                    var pre = this.pastInput();
-                    var c = new Array(pre.length + 1).join("-");
-                    return pre + this.upcomingInput() + "\n" + c + "^";
-                },
-                next: function() {
-                    if (this.done) {
-                        return this.EOF;
-                    }
-                    if (!this._input) this.done = true;
-
-                    var token,
-                        match,
-                        tempMatch,
-                        index,
-                        col,
-                        lines;
-                    if (!this._more) {
-                        this.yytext = '';
-                        this.match = '';
-                    }
-                    var rules = this._currentRules();
-                    for (var i = 0; i < rules.length; i++) {
-                        tempMatch = this._input.match(this.rules[rules[i]]);
-                        if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
-                            match = tempMatch;
-                            index = i;
-                            if (!this.options.flex) break;
-                        }
-                    }
-                    if (match) {
-                        lines = match[0].match(/(?:\r\n?|\n).*/g);
-                        if (lines) this.yylineno += lines.length;
-                        this.yylloc = {
-                            first_line: this.yylloc.last_line,
-                            last_line: this.yylineno + 1,
-                            first_column: this.yylloc.last_column,
-                            last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
-                        };
-                        this.yytext += match[0];
-                        this.match += match[0];
-                        this.matches = match;
-                        this.yyleng = this.yytext.length;
-                        if (this.options.ranges) {
-                            this.yylloc.range = [this.offset, this.offset += this.yyleng];
-                        }
-                        this._more = false;
-                        this._input = this._input.slice(match[0].length);
-                        this.matched += match[0];
-                        token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
-                        if (this.done && this._input) this.done = false;
-                        if (token) return token;
-                        else return;
-                    }
-                    if (this._input === "") {
-                        return this.EOF;
-                    } else {
-                        return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
-                            text: "",
-                            token: null,
-                            line: this.yylineno
-                        });
-                    }
-                },
-                lex: function lex() {
-                    var r = this.next();
-                    if (typeof r !== 'undefined') {
-                        return r;
-                    } else {
-                        return this.lex();
-                    }
-                },
-                begin: function begin(condition) {
-                    this.conditionStack.push(condition);
-                },
-                popState: function popState() {
-                    return this.conditionStack.pop();
-                },
-                _currentRules: function _currentRules() {
-                    return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
-                },
-                topState: function() {
-                    return this.conditionStack[this.conditionStack.length - 2];
-                },
-                pushState: function begin(condition) {
-                    this.begin(condition);
-                }
-            });
-            lexer.options = {};
-            lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
-
-                var YYSTATE = YY_START
-                switch ($avoiding_name_collisions) {
-                    case 0:
-                        if (yy_.yytext.slice(-1) !== "\\") this.begin("mu");
-                        if (yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1), this.begin("emu");
-                        if (yy_.yytext) return 14;
-
-                        break;
-                    case 1:
-                        return 14;
-                        break;
-                    case 2:
-                        if (yy_.yytext.slice(-1) !== "\\") this.popState();
-                        if (yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1);
-                        return 14;
-
-                        break;
-                    case 3:
-                        yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 4);
-                        this.popState();
-                        return 15;
-                        break;
-                    case 4:
-                        this.begin("par");
-                        return 24;
-                        break;
-                    case 5:
-                        return 16;
-                        break;
-                    case 6:
-                        return 20;
-                        break;
-                    case 7:
-                        return 19;
-                        break;
-                    case 8:
-                        return 19;
-                        break;
-                    case 9:
-                        return 23;
-                        break;
-                    case 10:
-                        return 23;
-                        break;
-                    case 11:
-                        this.popState();
-                        this.begin('com');
-                        break;
-                    case 12:
-                        yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);
-                        this.popState();
-                        return 15;
-                        break;
-                    case 13:
-                        return 22;
-                        break;
-                    case 14:
-                        return 36;
-                        break;
-                    case 15:
-                        return 35;
-                        break;
-                    case 16:
-                        return 35;
-                        break;
-                    case 17:
-                        return 39;
-                        break;
-                    case 18:
-                        /*ignore whitespace*/
-                        break;
-                    case 19:
-                        this.popState();
-                        return 18;
-                        break;
-                    case 20:
-                        this.popState();
-                        return 18;
-                        break;
-                    case 21:
-                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(/\\"/g, '"');
-                        return 30;
-                        break;
-                    case 22:
-                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(/\\'/g, "'");
-                        return 30;
-                        break;
-                    case 23:
-                        yy_.yytext = yy_.yytext.substr(1);
-                        return 28;
-                        break;
-                    case 24:
-                        return 32;
-                        break;
-                    case 25:
-                        return 32;
-                        break;
-                    case 26:
-                        return 31;
-                        break;
-                    case 27:
-                        return 35;
-                        break;
-                    case 28:
-                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
-                        return 35;
-                        break;
-                    case 29:
-                        return 'INVALID';
-                        break;
-                    case 30:
-                        /*ignore whitespace*/
-                        break;
-                    case 31:
-                        this.popState();
-                        return 37;
-                        break;
-                    case 32:
-                        return 5;
-                        break;
-                }
-            };
-            lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|$)))/, /^(?:[\s\S]*?--\}\})/, /^(?:\{\{>)/, /^(?:\{\{#)/, /^(?:\{\{\/)/, /^(?:\{\{\^)/, /^(?:\{\{\s*else\b)/, /^(?:\{\{\{)/, /^(?:\{\{&)/, /^(?:\{\{!--)/, /^(?:\{\{![\s\S]*?\}\})/, /^(?:\{\{)/, /^(?:=)/, /^(?:\.(?=[} ]))/, /^(?:\.\.)/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}\}\})/, /^(?:\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@[a-zA-Z]+)/, /^(?:true(?=[}\s]))/, /^(?:false(?=[}\s]))/, /^(?:-?[0-9]+(?=[}\s]))/, /^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/, /^(?:\[[^\]]*\])/, /^(?:.)/, /^(?:\s+)/, /^(?:[a-zA-Z0-9_$-/]+)/, /^(?:$)/];
-            lexer.conditions = {
-                "mu": {
-                    "rules": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32],
-                    "inclusive": false
-                },
-                "emu": {
-                    "rules": [2],
-                    "inclusive": false
-                },
-                "com": {
-                    "rules": [3],
-                    "inclusive": false
-                },
-                "par": {
-                    "rules": [30, 31],
-                    "inclusive": false
-                },
-                "INITIAL": {
-                    "rules": [0, 1, 32],
-                    "inclusive": true
-                }
-            };
-            return lexer;
-        })()
-        parser.lexer = lexer;
-
-        function Parser() {
-            this.yy = {};
-        }
-        Parser.prototype = parser;
-        parser.Parser = Parser;
-        return new Parser;
-    })();;
-    // lib/handlebars/compiler/base.js
-
-    Handlebars.Parser = handlebars;
-
-    Handlebars.parse = function(input) {
-
-        // Just return if an already-compile AST was passed in.
-        if (input.constructor === Handlebars.AST.ProgramNode) {
-            return input;
-        }
-
-        Handlebars.Parser.yy = Handlebars.AST;
-        return Handlebars.Parser.parse(input);
-    };;
-    // lib/handlebars/compiler/ast.js
-    (function() {
-        Handlebars.AST = {};
-
-        Handlebars.AST.ProgramNode = function(statements, inverse) {
-            this.type = "program";
-            this.statements = statements;
-            if (inverse) {
-                this.inverse = new Handlebars.AST.ProgramNode(inverse);
-            }
-        };
-
-        Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
-            this.type = "mustache";
-            this.escaped = !unescaped;
-            this.hash = hash;
-
-            var id = this.id = rawParams[0];
-            var params = this.params = rawParams.slice(1);
-
-            // a mustache is an eligible helper if:
-            // * its id is simple (a single part, not `this` or `..`)
-            var eligibleHelper = this.eligibleHelper = id.isSimple;
-
-            // a mustache is definitely a helper if:
-            // * it is an eligible helper, and
-            // * it has at least one parameter or hash segment
-            this.isHelper = eligibleHelper && (params.length || hash);
-
-            // if a mustache is an eligible helper but not a definite
-            // helper, it is ambiguous, and will be resolved in a later
-            // pass or at runtime.
-        };
-
-        Handlebars.AST.PartialNode = function(partialName, context) {
-            this.type = "partial";
-            this.partialName = partialName;
-            this.context = context;
-        };
-
-        Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
-            var verifyMatch = function(open, close) {
-                if (open.original !== close.original) {
-                    throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
-                }
-            };
-
-            verifyMatch(mustache.id, close);
-            this.type = "block";
-            this.mustache = mustache;
-            this.program = program;
-            this.inverse = inverse;
-
-            if (this.inverse && !this.program) {
-                this.isInverse = true;
-            }
-        };
-
-        Handlebars.AST.ContentNode = function(string) {
-            this.type = "content";
-            this.string = string;
-        };
-
-        Handlebars.AST.HashNode = function(pairs) {
-            this.type = "hash";
-            this.pairs = pairs;
-        };
-
-        Handlebars.AST.IdNode = function(parts) {
-            this.type = "ID";
-            this.original = parts.join(".");
-
-            var dig = [],
-                depth = 0;
-
-            for (var i = 0, l = parts.length; i < l; i++) {
-                var part = parts[i];
-
-                if (part === ".." || part === "." || part === "this") {
-                    if (dig.length > 0) {
-                        throw new Handlebars.Exception("Invalid path: " + this.original);
-                    } else if (part === "..") {
-                        depth++;
-                    } else {
-                        this.isScoped = true;
-                    }
-                } else {
-                    dig.push(part);
-                }
-            }
-
-            this.parts = dig;
-            this.string = dig.join('.');
-            this.depth = depth;
-
-            // an ID is simple if it only has one part, and that part is not
-            // `..` or `this`.
-            this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
-
-            this.stringModeValue = this.string;
-        };
-
-        Handlebars.AST.PartialNameNode = function(name) {
-            this.type = "PARTIAL_NAME";
-            this.name = name;
-        };
-
-        Handlebars.AST.DataNode = function(id) {
-            this.type = "DATA";
-            this.id = id;
-        };
-
-        Handlebars.AST.StringNode = function(string) {
-            this.type = "STRING";
-            this.string = string;
-            this.stringModeValue = string;
-        };
-
-        Handlebars.AST.IntegerNode = function(integer) {
-            this.type = "INTEGER";
-            this.integer = integer;
-            this.stringModeValue = Number(integer);
-        };
-
-        Handlebars.AST.BooleanNode = function(bool) {
-            this.type = "BOOLEAN";
-            this.bool = bool;
-            this.stringModeValue = bool === "true";
-        };
-
-        Handlebars.AST.CommentNode = function(comment) {
-            this.type = "comment";
-            this.comment = comment;
-        };;
-    })();;
-    //>>excludeEnd('excludeHbsParser')
-    // lib/handlebars/utils.js
-
-    var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
-
-    Handlebars.Exception = function(message) {
-        var tmp = Error.prototype.constructor.apply(this, arguments);
-
-        // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
-        for (var idx = 0; idx < errorProps.length; idx++) {
-            this[errorProps[idx]] = tmp[errorProps[idx]];
-        }
-    };
-    Handlebars.Exception.prototype = new Error();
-
-    // Build out our basic SafeString type
-    Handlebars.SafeString = function(string) {
-        this.string = string;
-    };
-    Handlebars.SafeString.prototype.toString = function() {
-        return this.string.toString();
-    };
-
-    (function() {
-        var escape = {
-            "&": "&amp;",
-            "<": "&lt;",
-            ">": "&gt;",
-            '"': "&quot;",
-            "'": "&#x27;",
-            "`": "&#x60;"
-        };
-
-        var badChars = /[&<>"'`]/g;
-        var possible = /[&<>"'`]/;
-
-        var escapeChar = function(chr) {
-            return escape[chr] || "&amp;";
-        };
-
-        Handlebars.Utils = {
-            escapeExpression: function(string) {
-                // don't escape SafeStrings, since they're already safe
-                if (string instanceof Handlebars.SafeString) {
-                    return string.toString();
-                } else if (string == null || string === false) {
-                    return "";
-                }
-
-                if (!possible.test(string)) {
-                    return string;
-                }
-                return string.replace(badChars, escapeChar);
-            },
-
-            isEmpty: function(value) {
-                if (!value && value !== 0) {
-                    return true;
-                } else if (Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        };;
-    })();
-    // lib/handlebars/compiler/compiler.js
-
-    /*jshint eqnull:true*/
-    Handlebars.Compiler = function() {};
-    Handlebars.JavaScriptCompiler = function() {};
-
-    (function(Compiler, JavaScriptCompiler) {
-        // the foundHelper register will disambiguate helper lookup from finding a
-        // function in a context. This is necessary for mustache compatibility, which
-        // requires that context functions in blocks are evaluated by blockHelperMissing,
-        // and then proceed as if the resulting value was provided to blockHelperMissing.
-
-        Compiler.prototype = {
-            compiler: Compiler,
-
-            disassemble: function() {
-                var opcodes = this.opcodes,
-                    opcode, out = [],
-                    params, param;
-
-                for (var i = 0, l = opcodes.length; i < l; i++) {
-                    opcode = opcodes[i];
-
-                    if (opcode.opcode === 'DECLARE') {
-                        out.push("DECLARE " + opcode.name + "=" + opcode.value);
-                    } else {
-                        params = [];
-                        for (var j = 0; j < opcode.args.length; j++) {
-                            param = opcode.args[j];
-                            if (typeof param === "string") {
-                                param = "\"" + param.replace("\n", "\\n") + "\"";
-                            }
-                            params.push(param);
-                        }
-                        out.push(opcode.opcode + " " + params.join(" "));
-                    }
-                }
-
-                return out.join("\n");
-            },
-            equals: function(other) {
-                var len = this.opcodes.length;
-                if (other.opcodes.length !== len) {
-                    return false;
-                }
-
-                for (var i = 0; i < len; i++) {
-                    var opcode = this.opcodes[i],
-                        otherOpcode = other.opcodes[i];
-                    if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
-                        return false;
-                    }
-                    for (var j = 0; j < opcode.args.length; j++) {
-                        if (opcode.args[j] !== otherOpcode.args[j]) {
-                            return false;
-                        }
-                    }
-                }
-
-                len = this.children.length;
-                if (other.children.length !== len) {
-                    return false;
-                }
-                for (i = 0; i < len; i++) {
-                    if (!this.children[i].equals(other.children[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            guid: 0,
-
-            compile: function(program, options) {
-                this.children = [];
-                this.depths = {
-                    list: []
-                };
-                this.options = options;
-
-                // These changes will propagate to the other compiler components
-                var knownHelpers = this.options.knownHelpers;
-                this.options.knownHelpers = {
-                    'helperMissing': true,
-                    'blockHelperMissing': true,
-                    'each': true,
-                    'if': true,
-                    'unless': true,
-                    'with': true,
-                    'log': true
-                };
-                if (knownHelpers) {
-                    for (var name in knownHelpers) {
-                        this.options.knownHelpers[name] = knownHelpers[name];
-                    }
-                }
-
-                return this.program(program);
-            },
-
-            accept: function(node) {
-                return this[node.type](node);
-            },
-
-            program: function(program) {
-                var statements = program.statements,
-                    statement;
-                this.opcodes = [];
-
-                for (var i = 0, l = statements.length; i < l; i++) {
-                    statement = statements[i];
-                    this[statement.type](statement);
-                }
-                this.isSimple = l === 1;
-
-                this.depths.list = this.depths.list.sort(function(a, b) {
-                    return a - b;
-                });
-
-                return this;
-            },
-
-            compileProgram: function(program) {
-                var result = new this.compiler().compile(program, this.options);
-                var guid = this.guid++,
-                    depth;
-
-                this.usePartial = this.usePartial || result.usePartial;
-
-                this.children[guid] = result;
-
-                for (var i = 0, l = result.depths.list.length; i < l; i++) {
-                    depth = result.depths.list[i];
-
-                    if (depth < 2) {
-                        continue;
-                    } else {
-                        this.addDepth(depth - 1);
-                    }
-                }
-
-                return guid;
-            },
-
-            block: function(block) {
-                var mustache = block.mustache,
-                    program = block.program,
-                    inverse = block.inverse;
-
-                if (program) {
-                    program = this.compileProgram(program);
-                }
-
-                if (inverse) {
-                    inverse = this.compileProgram(inverse);
-                }
-
-                var type = this.classifyMustache(mustache);
-
-                if (type === "helper") {
-                    this.helperMustache(mustache, program, inverse);
-                } else if (type === "simple") {
-                    this.simpleMustache(mustache);
-
-                    // now that the simple mustache is resolved, we need to
-                    // evaluate it by executing `blockHelperMissing`
-                    this.opcode('pushProgram', program);
-                    this.opcode('pushProgram', inverse);
-                    this.opcode('emptyHash');
-                    this.opcode('blockValue');
-                } else {
-                    this.ambiguousMustache(mustache, program, inverse);
-
-                    // now that the simple mustache is resolved, we need to
-                    // evaluate it by executing `blockHelperMissing`
-                    this.opcode('pushProgram', program);
-                    this.opcode('pushProgram', inverse);
-                    this.opcode('emptyHash');
-                    this.opcode('ambiguousBlockValue');
-                }
-
-                this.opcode('append');
-            },
-
-            hash: function(hash) {
-                var pairs = hash.pairs,
-                    pair, val;
-
-                this.opcode('pushHash');
-
-                for (var i = 0, l = pairs.length; i < l; i++) {
-                    pair = pairs[i];
-                    val = pair[1];
-
-                    if (this.options.stringParams) {
-                        this.opcode('pushStringParam', val.stringModeValue, val.type);
-                    } else {
-                        this.accept(val);
-                    }
-
-                    this.opcode('assignToHash', pair[0]);
-                }
-                this.opcode('popHash');
-            },
-
-            partial: function(partial) {
-                var partialName = partial.partialName;
-                this.usePartial = true;
-
-                if (partial.context) {
-                    this.ID(partial.context);
-                } else {
-                    this.opcode('push', 'depth0');
-                }
-
-                this.opcode('invokePartial', partialName.name);
-                this.opcode('append');
-            },
-
-            content: function(content) {
-                this.opcode('appendContent', content.string);
-            },
-
-            mustache: function(mustache) {
-                var options = this.options;
-                var type = this.classifyMustache(mustache);
-
-                if (type === "simple") {
-                    this.simpleMustache(mustache);
-                } else if (type === "helper") {
-                    this.helperMustache(mustache);
-                } else {
-                    this.ambiguousMustache(mustache);
-                }
-
-                if (mustache.escaped && !options.noEscape) {
-                    this.opcode('appendEscaped');
-                } else {
-                    this.opcode('append');
-                }
-            },
-
-            ambiguousMustache: function(mustache, program, inverse) {
-                var id = mustache.id,
-                    name = id.parts[0],
-                    isBlock = program != null || inverse != null;
-
-                this.opcode('getContext', id.depth);
-
-                this.opcode('pushProgram', program);
-                this.opcode('pushProgram', inverse);
-
-                this.opcode('invokeAmbiguous', name, isBlock);
-            },
-
-            simpleMustache: function(mustache) {
-                var id = mustache.id;
-
-                if (id.type === 'DATA') {
-                    this.DATA(id);
-                } else if (id.parts.length) {
-                    this.ID(id);
-                } else {
-                    // Simplified ID for `this`
-                    this.addDepth(id.depth);
-                    this.opcode('getContext', id.depth);
-                    this.opcode('pushContext');
-                }
-
-                this.opcode('resolvePossibleLambda');
-            },
-
-            helperMustache: function(mustache, program, inverse) {
-                var params = this.setupFullMustacheParams(mustache, program, inverse),
-                    name = mustache.id.parts[0];
-
-                if (this.options.knownHelpers[name]) {
-                    this.opcode('invokeKnownHelper', params.length, name);
-                } else if (this.knownHelpersOnly) {
-                    throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
-                } else {
-                    this.opcode('invokeHelper', params.length, name);
-                }
-            },
-
-            ID: function(id) {
-                this.addDepth(id.depth);
-                this.opcode('getContext', id.depth);
-
-                var name = id.parts[0];
-                if (!name) {
-                    this.opcode('pushContext');
-                } else {
-                    this.opcode('lookupOnContext', id.parts[0]);
-                }
-
-                for (var i = 1, l = id.parts.length; i < l; i++) {
-                    this.opcode('lookup', id.parts[i]);
-                }
-            },
-
-            DATA: function(data) {
-                this.options.data = true;
-                this.opcode('lookupData', data.id);
-            },
-
-            STRING: function(string) {
-                this.opcode('pushString', string.string);
-            },
-
-            INTEGER: function(integer) {
-                this.opcode('pushLiteral', integer.integer);
-            },
-
-            BOOLEAN: function(bool) {
-                this.opcode('pushLiteral', bool.bool);
-            },
-
-            comment: function() {},
-
-            // HELPERS
-            opcode: function(name) {
-                this.opcodes.push({
-                    opcode: name,
-                    args: [].slice.call(arguments, 1)
-                });
-            },
-
-            declare: function(name, value) {
-                this.opcodes.push({
-                    opcode: 'DECLARE',
-                    name: name,
-                    value: value
-                });
-            },
-
-            addDepth: function(depth) {
-                if (isNaN(depth)) {
-                    throw new Error("EWOT");
-                }
-                if (depth === 0) {
-                    return;
-                }
-
-                if (!this.depths[depth]) {
-                    this.depths[depth] = true;
-                    this.depths.list.push(depth);
-                }
-            },
-
-            classifyMustache: function(mustache) {
-                var isHelper = mustache.isHelper;
-                var isEligible = mustache.eligibleHelper;
-                var options = this.options;
-
-                // if ambiguous, we can possibly resolve the ambiguity now
-                if (isEligible && !isHelper) {
-                    var name = mustache.id.parts[0];
-
-                    if (options.knownHelpers[name]) {
-                        isHelper = true;
-                    } else if (options.knownHelpersOnly) {
-                        isEligible = false;
-                    }
-                }
-
-                if (isHelper) {
-                    return "helper";
-                } else if (isEligible) {
-                    return "ambiguous";
-                } else {
-                    return "simple";
-                }
-            },
-
-            pushParams: function(params) {
-                var i = params.length,
-                    param;
-
-                while (i--) {
-                    param = params[i];
-
-                    if (this.options.stringParams) {
-                        if (param.depth) {
-                            this.addDepth(param.depth);
-                        }
-
-                        this.opcode('getContext', param.depth || 0);
-                        this.opcode('pushStringParam', param.stringModeValue, param.type);
-                    } else {
-                        this[param.type](param);
-                    }
-                }
-            },
-
-            setupMustacheParams: function(mustache) {
-                var params = mustache.params;
-                this.pushParams(params);
-
-                if (mustache.hash) {
-                    this.hash(mustache.hash);
-                } else {
-                    this.opcode('emptyHash');
-                }
-
-                return params;
-            },
-
-            // this will replace setupMustacheParams when we're done
-            setupFullMustacheParams: function(mustache, program, inverse) {
-                var params = mustache.params;
-                this.pushParams(params);
-
-                this.opcode('pushProgram', program);
-                this.opcode('pushProgram', inverse);
-
-                if (mustache.hash) {
-                    this.hash(mustache.hash);
-                } else {
-                    this.opcode('emptyHash');
-                }
-
-                return params;
-            }
-        };
-
-        var Literal = function(value) {
-            this.value = value;
-        };
-
-        JavaScriptCompiler.prototype = {
-            // PUBLIC API: You can override these methods in a subclass to provide
-            // alternative compiled forms for name lookup and buffering semantics
-            nameLookup: function(parent, name /* , type*/ ) {
-                if (/^[0-9]+$/.test(name)) {
-                    return parent + "[" + name + "]";
-                } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
-                    return parent + "." + name;
-                } else {
-                    return parent + "['" + name + "']";
-                }
-            },
-
-            appendToBuffer: function(string) {
-                if (this.environment.isSimple) {
-                    return "return " + string + ";";
-                } else {
-                    return {
-                        appendToBuffer: true,
-                        content: string,
-                        toString: function() {
-                            return "buffer += " + string + ";";
-                        }
-                    };
-                }
-            },
-
-            initializeBuffer: function() {
-                return this.quotedString("");
-            },
-
-            namespace: "Handlebars",
-            // END PUBLIC API
-
-            compile: function(environment, options, context, asObject) {
-                this.environment = environment;
-                this.options = options || {};
-
-                Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
-
-                this.name = this.environment.name;
-                this.isChild = !!context;
-                this.context = context || {
-                    programs: [],
-                    environments: [],
-                    aliases: {}
-                };
-
-                this.preamble();
-
-                this.stackSlot = 0;
-                this.stackVars = [];
-                this.registers = {
-                    list: []
-                };
-                this.compileStack = [];
-                this.inlineStack = [];
-
-                this.compileChildren(environment, options);
-
-                var opcodes = environment.opcodes,
-                    opcode;
-
-                this.i = 0;
-
-                for (l = opcodes.length; this.i < l; this.i++) {
-                    opcode = opcodes[this.i];
-
-                    if (opcode.opcode === 'DECLARE') {
-                        this[opcode.name] = opcode.value;
-                    } else {
-                        this[opcode.opcode].apply(this, opcode.args);
-                    }
-                }
-
-                return this.createFunctionContext(asObject);
-            },
-
-            nextOpcode: function() {
-                var opcodes = this.environment.opcodes;
-                return opcodes[this.i + 1];
-            },
-
-            eat: function() {
-                this.i = this.i + 1;
-            },
-
-            preamble: function() {
-                var out = [];
-
-                if (!this.isChild) {
-                    var namespace = this.namespace;
-                    var copies = "helpers = helpers || " + namespace + ".helpers;";
-                    if (this.environment.usePartial) {
-                        copies = copies + " partials = partials || " + namespace + ".partials;";
-                    }
-                    if (this.options.data) {
-                        copies = copies + " data = data || {};";
-                    }
-                    out.push(copies);
-                } else {
-                    out.push('');
-                }
-
-                if (!this.environment.isSimple) {
-                    out.push(", buffer = " + this.initializeBuffer());
-                } else {
-                    out.push("");
-                }
-
-                // track the last context pushed into place to allow skipping the
-                // getContext opcode when it would be a noop
-                this.lastContext = 0;
-                this.source = out;
-            },
-
-            createFunctionContext: function(asObject) {
-                var locals = this.stackVars.concat(this.registers.list);
-
-                if (locals.length > 0) {
-                    this.source[1] = this.source[1] + ", " + locals.join(", ");
-                }
-
-                // Generate minimizer alias mappings
-                if (!this.isChild) {
-                    for (var alias in this.context.aliases) {
-                        this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
-                    }
-                }
-
-                if (this.source[1]) {
-                    this.source[1] = "var " + this.source[1].substring(2) + ";";
-                }
-
-                // Merge children
-                if (!this.isChild) {
-                    this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
-                }
-
-                if (!this.environment.isSimple) {
-                    this.source.push("return buffer;");
-                }
-
-                var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
-
-                for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {
-                    params.push("depth" + this.environment.depths.list[i]);
-                }
-
-                // Perform a second pass over the output to merge content when possible
-                var source = this.mergeSource();
-
-                if (!this.isChild) {
-                    var revision = Handlebars.COMPILER_REVISION,
-                        versions = Handlebars.REVISION_CHANGES[revision];
-                    source = "this.compilerInfo = [" + revision + ",'" + versions + "'];\n" + source;
-                }
-
-                if (asObject) {
-                    params.push(source);
-
-                    return Function.apply(this, params);
-                } else {
-                    var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + source + '}';
-                    Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
-                    return functionSource;
-                }
-            },
-            mergeSource: function() {
-                // WARN: We are not handling the case where buffer is still populated as the source should
-                // not have buffer append operations as their final action.
-                var source = '',
-                    buffer;
-                for (var i = 0, len = this.source.length; i < len; i++) {
-                    var line = this.source[i];
-                    if (line.appendToBuffer) {
-                        if (buffer) {
-                            buffer = buffer + '\n    + ' + line.content;
-                        } else {
-                            buffer = line.content;
-                        }
-                    } else {
-                        if (buffer) {
-                            source += 'buffer += ' + buffer + ';\n  ';
-                            buffer = undefined;
-                        }
-                        source += line + '\n  ';
-                    }
-                }
-                return source;
-            },
-
-            // [blockValue]
-            //
-            // On stack, before: hash, inverse, program, value
-            // On stack, after: return value of blockHelperMissing
-            //
-            // The purpose of this opcode is to take a block of the form
-            // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
-            // replace it on the stack with the result of properly
-            // invoking blockHelperMissing.
-            blockValue: function() {
-                this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
-
-                var params = ["depth0"];
-                this.setupParams(0, params);
-
-                this.replaceStack(function(current) {
-                    params.splice(1, 0, current);
-                    return "blockHelperMissing.call(" + params.join(", ") + ")";
-                });
-            },
-
-            // [ambiguousBlockValue]
-            //
-            // On stack, before: hash, inverse, program, value
-            // Compiler value, before: lastHelper=value of last found helper, if any
-            // On stack, after, if no lastHelper: same as [blockValue]
-            // On stack, after, if lastHelper: value
-            ambiguousBlockValue: function() {
-                this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
-
-                var params = ["depth0"];
-                this.setupParams(0, params);
-
-                var current = this.topStack();
-                params.splice(1, 0, current);
-
-                // Use the options value generated from the invocation
-                params[params.length - 1] = 'options';
-
-                this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
-            },
-
-            // [appendContent]
-            //
-            // On stack, before: ...
-            // On stack, after: ...
-            //
-            // Appends the string value of `content` to the current buffer
-            appendContent: function(content) {
-                this.source.push(this.appendToBuffer(this.quotedString(content)));
-            },
-
-            // [append]
-            //
-            // On stack, before: value, ...
-            // On stack, after: ...
-            //
-            // Coerces `value` to a String and appends it to the current buffer.
-            //
-            // If `value` is truthy, or 0, it is coerced into a string and appended
-            // Otherwise, the empty string is appended
-            append: function() {
-                // Force anything that is inlined onto the stack so we don't have duplication
-                // when we examine local
-                this.flushInline();
-                var local = this.popStack();
-                this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
-                if (this.environment.isSimple) {
-                    this.source.push("else { " + this.appendToBuffer("''") + " }");
-                }
-            },
-
-            // [appendEscaped]
-            //
-            // On stack, before: value, ...
-            // On stack, after: ...
-            //
-            // Escape `value` and append it to the buffer
-            appendEscaped: function() {
-                this.context.aliases.escapeExpression = 'this.escapeExpression';
-
-                this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
-            },
-
-            // [getContext]
-            //
-            // On stack, before: ...
-            // On stack, after: ...
-            // Compiler value, after: lastContext=depth
-            //
-            // Set the value of the `lastContext` compiler value to the depth
-            getContext: function(depth) {
-                if (this.lastContext !== depth) {
-                    this.lastContext = depth;
-                }
-            },
-
-            // [lookupOnContext]
-            //
-            // On stack, before: ...
-            // On stack, after: currentContext[name], ...
-            //
-            // Looks up the value of `name` on the current context and pushes
-            // it onto the stack.
-            lookupOnContext: function(name) {
-                this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
-            },
-
-            // [pushContext]
-            //
-            // On stack, before: ...
-            // On stack, after: currentContext, ...
-            //
-            // Pushes the value of the current context onto the stack.
-            pushContext: function() {
-                this.pushStackLiteral('depth' + this.lastContext);
-            },
-
-            // [resolvePossibleLambda]
-            //
-            // On stack, before: value, ...
-            // On stack, after: resolved value, ...
-            //
-            // If the `value` is a lambda, replace it on the stack by
-            // the return value of the lambda
-            resolvePossibleLambda: function() {
-                this.context.aliases.functionType = '"function"';
-
-                this.replaceStack(function(current) {
-                    return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
-                });
-            },
-
-            // [lookup]
-            //
-            // On stack, before: value, ...
-            // On stack, after: value[name], ...
-            //
-            // Replace the value on the stack with the result of looking
-            // up `name` on `value`
-            lookup: function(name) {
-                this.replaceStack(function(current) {
-                    return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
-                });
-            },
-
-            // [lookupData]
-            //
-            // On stack, before: ...
-            // On stack, after: data[id], ...
-            //
-            // Push the result of looking up `id` on the current data
-            lookupData: function(id) {
-                this.push(this.nameLookup('data', id, 'data'));
-            },
-
-            // [pushStringParam]
-            //
-            // On stack, before: ...
-            // On stack, after: string, currentContext, ...
-            //
-            // This opcode is designed for use in string mode, which
-            // provides the string value of a parameter along with its
-            // depth rather than resolving it immediately.
-            pushStringParam: function(string, type) {
-                this.pushStackLiteral('depth' + this.lastContext);
-
-                this.pushString(type);
-
-                if (typeof string === 'string') {
-                    this.pushString(string);
-                } else {
-                    this.pushStackLiteral(string);
-                }
-            },
-
-            emptyHash: function() {
-                this.pushStackLiteral('{}');
-
-                if (this.options.stringParams) 

<TRUNCATED>


[7/8] incubator-atlas git commit: ATLAS-1098 Atlas allows creation of tag with name isa which causes exceptions during search (apoorvnaik via shwethags)

Posted by sh...@apache.org.
ATLAS-1098 Atlas allows creation of tag with name isa which causes exceptions during search (apoorvnaik via shwethags)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/c1081a49
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/c1081a49
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/c1081a49

Branch: refs/heads/master
Commit: c1081a49da3553f55b33edecb416de99c90d10b4
Parents: 7bb2709
Author: Shwetha GS <ss...@hortonworks.com>
Authored: Mon Sep 19 11:13:08 2016 +0530
Committer: Shwetha GS <ss...@hortonworks.com>
Committed: Mon Sep 19 11:13:08 2016 +0530

----------------------------------------------------------------------
 pom.xml                                         |  2 +-
 release-log.txt                                 |  1 +
 .../atlas/services/DefaultMetadataService.java  | 52 --------------------
 .../org/apache/atlas/query/QueryParser.scala    | 12 +++--
 .../org/apache/atlas/BaseRepositoryTest.java    |  5 +-
 .../GraphBackedDiscoveryServiceTest.java        |  3 ++
 6 files changed, 16 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 17660b5..ac5b042 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1737,7 +1737,7 @@
                         <exclude>**/users-credentials.properties</exclude>
                         <exclude>**/public/css/animate.min.css</exclude>
                         <exclude>**/public/css/bootstrap-sidebar.css</exclude>
-                        <exclude>**/public/js/require-handlebars-plugin/**</exclude>
+                        <exclude>**/public/js/external_lib/**</exclude>
                         <exclude>**/node_modules/**</exclude>
                         <!-- All the npm plugins are copied here, so exclude it -->
                         <exclude>**/public/js/libs/**</exclude>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index d53a866..f1ac7a7 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
 ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
 
 ALL CHANGES:
+ATLAS-1098 Atlas allows creation of tag with name "isa" which causes exceptions during search (apoorvnaik via shwethags)
 ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)
 ATLAS-712 Support getTrait() API (svimal2106 via shwethags)
 ATLAS-1173 Doc: Minor editorial bug in the example given for property atlas.server.ha.zookeeper.auth (yhemanth via shwethags)

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
index fdb749a..3550492 100755
--- a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
+++ b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
@@ -241,9 +241,6 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         typeDefinition = ParamChecker.notEmpty(typeDefinition, "type definition");
         TypesDef typesDef = validateTypeDefinition(typeDefinition);
 
-        // Also validate if the types being created are not keywords
-        validateIfNotKeyword(typesDef);
-
         try {
             final TypeSystem.TransientTypeSystem transientTypeSystem = typeSystem.createTransientTypeSystem(typesDef, isUpdate);
             final Map<String, IDataType> typesAdded = transientTypeSystem.getTypesAdded();
@@ -289,55 +286,6 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         }
     }
 
-    private void validateIfNotKeyword(TypesDef typesDef) throws AtlasException {
-        List<EnumTypeDefinition> enumDefs = typesDef.enumTypesAsJavaList();
-        List<StructTypeDefinition> structDefs = typesDef.structTypesAsJavaList();
-        List<HierarchicalTypeDefinition<ClassType>> classDefs = typesDef.classTypesAsJavaList();
-        List<HierarchicalTypeDefinition<TraitType>> traitDefs = typesDef.traitTypesAsJavaList();
-
-        // QueryParser has it's own set of keywords that should be avoided
-        Set<String> keywords = QueryParser.keywordCache().keySet();
-        boolean keywordCacheNotEmpty = null != keywords && !keywords.isEmpty();
-
-        if (keywordCacheNotEmpty) {
-            if (CollectionUtils.isNotEmpty(enumDefs)) {
-                // Check if any enum name is a keyword
-                for (EnumTypeDefinition enumDef : enumDefs) {
-                    if (keywords.contains(enumDef.name)) {
-                        throw new AtlasException("Enum definition name \"" + enumDef.name + "\" is a keyword");
-                    }
-                }
-            }
-
-            if (CollectionUtils.isNotEmpty(classDefs)){
-                // Check if any class name is a keyword
-                for (HierarchicalTypeDefinition<ClassType> classDef : classDefs) {
-                    if (keywords.contains(classDef.typeName)) {
-                        throw new AtlasException("Class definition name \"" + classDef.typeName + "\" is a keyword");
-                    }
-                }
-            }
-
-            if (CollectionUtils.isNotEmpty(structDefs)){
-                // Check if any struct name is a keyword
-                for (StructTypeDefinition structDef : structDefs) {
-                    if (keywords.contains(structDef.typeName)) {
-                        throw new AtlasException("StructType definition name \"" + structDef.typeName + "\" is a keyword");
-                    }
-                }
-            }
-
-            if (CollectionUtils.isNotEmpty(traitDefs)){
-                // Check if any trait name is a keyword
-                for (HierarchicalTypeDefinition<TraitType> traitDef : traitDefs) {
-                    if (keywords.contains(traitDef.typeName)) {
-                        throw new AtlasException("TraitType definition name \"" + traitDef.typeName + "\" is a keyword");
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * Return the definition for the given type.
      *

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/repository/src/main/scala/org/apache/atlas/query/QueryParser.scala
----------------------------------------------------------------------
diff --git a/repository/src/main/scala/org/apache/atlas/query/QueryParser.scala b/repository/src/main/scala/org/apache/atlas/query/QueryParser.scala
index 4d2429e..7074d74 100755
--- a/repository/src/main/scala/org/apache/atlas/query/QueryParser.scala
+++ b/repository/src/main/scala/org/apache/atlas/query/QueryParser.scala
@@ -387,6 +387,7 @@ class QueryLexer(val keywords: Seq[String], val delims: Seq[String]) extends Std
                 | floatConstant ^^ FloatLiteral
                 | dubConstant ^^ DoubleLiteral
                 | identifier ^^ processIdent
+                | quotedIdentifier ^^ Identifier
                 | string ^^ StringLit
                 | EofCh ^^^ EOF
                 | '\'' ~> failure("unclosed string literal")
@@ -398,10 +399,11 @@ class QueryLexer(val keywords: Seq[String], val delims: Seq[String]) extends Std
 
     override def identChar = letter | elem('_')
 
-    def identifier = identChar ~ (identChar | digit).* ^^ { case first ~ rest => (first :: rest).mkString} |
-        '`' ~> chrExcept('`', '\n', EofCh).* <~ '`' ^^ {
-            _ mkString ""
-        }
+    def identifier = identChar ~ (identChar | digit).* ^^ { case first ~ rest => (first :: rest).mkString}
+
+    def quotedIdentifier = '`' ~> chrExcept('`', '\n', EofCh).* <~ '`' ^^ {
+      _ mkString ""
+    }
 
     override def whitespace: Parser[Any] =
         (whitespaceChar
@@ -477,4 +479,4 @@ class QueryLexer(val keywords: Seq[String], val delims: Seq[String]) extends Std
                 allCaseVersions(s.tail, prefix + s.head.toUpper)
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/repository/src/test/java/org/apache/atlas/BaseRepositoryTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/BaseRepositoryTest.java b/repository/src/test/java/org/apache/atlas/BaseRepositoryTest.java
index 01c4bfa..500a305 100644
--- a/repository/src/test/java/org/apache/atlas/BaseRepositoryTest.java
+++ b/repository/src/test/java/org/apache/atlas/BaseRepositoryTest.java
@@ -174,8 +174,11 @@ public class BaseRepositoryTest {
 
         HierarchicalTypeDefinition<TraitType> logTraitDef = TypesUtil.createTraitTypeDef("Log Data", null);
 
+        HierarchicalTypeDefinition<TraitType> isaKeywordTraitDef = TypesUtil.createTraitTypeDef("isa", null);
+
         return TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.<StructTypeDefinition>of(),
-            ImmutableList.of(dimTraitDef, factTraitDef, piiTraitDef, metricTraitDef, etlTraitDef, jdbcTraitDef, logTraitDef),
+            ImmutableList.of(dimTraitDef, factTraitDef, piiTraitDef, metricTraitDef, etlTraitDef, jdbcTraitDef, logTraitDef,
+                    isaKeywordTraitDef),
             ImmutableList.of(dbClsDef, storageDescClsDef, columnClsDef, tblClsDef, loadProcessClsDef, viewClsDef, partClsDef, datasetSubTypeClsDef));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c1081a49/repository/src/test/java/org/apache/atlas/discovery/GraphBackedDiscoveryServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/discovery/GraphBackedDiscoveryServiceTest.java b/repository/src/test/java/org/apache/atlas/discovery/GraphBackedDiscoveryServiceTest.java
index 8a40110..40dc861 100755
--- a/repository/src/test/java/org/apache/atlas/discovery/GraphBackedDiscoveryServiceTest.java
+++ b/repository/src/test/java/org/apache/atlas/discovery/GraphBackedDiscoveryServiceTest.java
@@ -393,6 +393,9 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest {
                 {"Metric", 9},
                 {"PII", 8},
                 {"`Log Data`", 4},
+                // Not sure what the expected rows should be, but since we didn't assign or do anything with the created
+                // I assume it'll be zero
+                {"`isa`", 0},
 
                 /* Lineage queries are fired through ClosureQuery and are tested through HiveLineageJerseyResourceIt in webapp module.
                    Commenting out the below queries since DSL to Gremlin parsing/translation fails with lineage queries when there are array types


[2/8] incubator-atlas git commit: ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/require-handlebars-plugin/js/hbs.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/require-handlebars-plugin/js/hbs.js b/dashboardv2/public/js/require-handlebars-plugin/js/hbs.js
deleted file mode 100644
index 4aa054c..0000000
--- a/dashboardv2/public/js/require-handlebars-plugin/js/hbs.js
+++ /dev/null
@@ -1,490 +0,0 @@
-/**
- * @license Handlebars hbs 0.4.0 - Alex Sexton, but Handlebars has it's own licensing junk
- *
- * Available via the MIT or new BSD license.
- * see: http://github.com/jrburke/require-cs for details on the plugin this was based off of
- */
-
-/* Yes, deliciously evil. */
-/*jslint evil: true, strict: false, plusplus: false, regexp: false */
-/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
-define: false, process: false, window: false */
-define([
-    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
-    'handlebars', 'underscore', 'i18nprecompile', 'json2'
-    //>>excludeEnd('excludeHbs')
-], function(
-    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
-    Handlebars, _, precompile, JSON
-    //>>excludeEnd('excludeHbs')
-) {
-    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
-    var fs, getXhr,
-        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
-        fetchText = function() {
-            throw new Error('Environment unsupported.');
-        },
-        buildMap = [],
-        filecode = "w+",
-        templateExtension = "hbs",
-        customNameExtension = "@hbs",
-        devStyleDirectory = "/styles/",
-        buildStyleDirectory = "/demo-build/styles/",
-        helperDirectory = "template/helpers/",
-        i18nDirectory = "template/i18n/",
-        buildCSSFileName = "screen.build.css";
-
-    Handlebars.registerHelper('$', function() {
-        //placeholder for translation helper
-    });
-
-    if (typeof window !== "undefined" && window.navigator && window.document && !window.navigator.userAgent.match(/Node.js/)) {
-        // Browser action
-        getXhr = function() {
-            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
-            var xhr, i, progId;
-            if (typeof XMLHttpRequest !== "undefined") {
-                return new XMLHttpRequest();
-            } else {
-                for (i = 0; i < 3; i++) {
-                    progId = progIds[i];
-                    try {
-                        xhr = new ActiveXObject(progId);
-                    } catch (e) {}
-
-                    if (xhr) {
-                        progIds = [progId]; // so faster next time
-                        break;
-                    }
-                }
-            }
-
-            if (!xhr) {
-                throw new Error("getXhr(): XMLHttpRequest not available");
-            }
-
-            return xhr;
-        };
-
-        fetchText = function(url, callback) {
-            var prependComment = "<!--START: " + url + "--> == <!--END: " + url + "-->";
-            var xhr = getXhr();
-            xhr.open('GET', url, true);
-            xhr.onreadystatechange = function(evt) {
-                //Do not explicitly handle errors, those should be
-                //visible via console output in the browser.
-                if (xhr.readyState === 4) {
-                    callback(xhr.responseText);
-                    //TODO FIXME Gautam:Not working with backbone-forms when it does this : $($.trim(this.template(_.result(this, 'templateData'))));
-                    // callback(prependComment.replace('==',xhr.responseText));
-                }
-            };
-            xhr.send(null);
-        };
-
-    } else if (typeof process !== "undefined" &&
-        process.versions &&
-        !!process.versions.node) {
-        //Using special require.nodeRequire, something added by r.js.
-        fs = require.nodeRequire('fs');
-        fetchText = function(path, callback) {
-            var body = fs.readFileSync(path, 'utf8') || "";
-            // we need to remove BOM stuff from the file content
-            body = body.replace(/^\uFEFF/, '');
-            callback(body);
-        };
-    } else if (typeof java !== "undefined" && typeof java.io !== "undefined") {
-        fetchText = function(path, callback) {
-            var f = new java.io.File(path);
-            var is = new java.io.FileReader(f);
-            var reader = new java.io.BufferedReader(is);
-            var line;
-            var text = "";
-            while ((line = reader.readLine()) !== null) {
-                text += new String(line) + "\n";
-            }
-            reader.close();
-            callback(text);
-        };
-    }
-
-    var cache = {};
-    var fetchOrGetCached = function(path, callback) {
-        if (cache[path]) {
-            callback(cache[path]);
-        } else {
-            fetchText(path, function(data) {
-                cache[path] = data;
-                callback.call(this, data);
-            });
-        }
-    };
-    var styleList = [],
-        styleMap = {};
-    //>>excludeEnd('excludeHbs')
-
-    return {
-
-        get: function() {
-            return Handlebars;
-        },
-
-        write: function(pluginName, name, write) {
-
-            if ((name + customNameExtension) in buildMap) {
-                var text = buildMap[name + customNameExtension];
-                write.asModule(pluginName + "!" + name, text);
-            }
-        },
-
-        version: '0.4.0',
-
-        load: function(name, parentRequire, load, config) {
-            //>>excludeStart('excludeHbs', pragmas.excludeHbs)
-
-            var compiledName = name + customNameExtension,
-                disableI18n = (config.hbs && config.hbs.disableI18n),
-                partialDeps = [];
-
-            function recursiveNodeSearch(statements, res) {
-                _(statements).forEach(function(statement) {
-                    if (statement && statement.type && statement.type === 'partial') {
-                        res.push(statement.partialName.name);
-                    }
-                    if (statement && statement.program && statement.program.statements) {
-                        recursiveNodeSearch(statement.program.statements, res);
-                    }
-                    if (statement && statement.program && statement.program.inverse && statement.program.inverse.statements) {
-                        recursiveNodeSearch(statement.program.inverse.statements, res);
-                    }
-                });
-                return res;
-            }
-
-            // TODO :: use the parser to do this!
-            function findPartialDeps(nodes) {
-                var res = [];
-                if (nodes && nodes.statements) {
-                    res = recursiveNodeSearch(nodes.statements, []);
-                }
-                return _(res).unique();
-            }
-
-            // See if the first item is a comment that's json
-            function getMetaData(nodes) {
-                var statement, res, test;
-                if (nodes && nodes.statements) {
-                    statement = nodes.statements[0];
-                    if (statement && statement.type === "comment") {
-                        try {
-                            res = (statement.comment).replace(new RegExp('^[\\s]+|[\\s]+$', 'g'), '');
-                            test = JSON.parse(res);
-                            return res;
-                        } catch (e) {
-                            return "{}";
-                        }
-                    }
-                }
-                return "{}";
-            }
-
-            function composeParts(parts) {
-                if (!parts) {
-                    return [];
-                }
-                var res = [parts[0]],
-                    cur = parts[0],
-                    i;
-
-                for (i = 1; i < parts.length; ++i) {
-                    if (parts.hasOwnProperty(i)) {
-                        cur += "." + parts[i];
-                        res.push(cur);
-                    }
-                }
-                return res;
-            }
-
-            function recursiveVarSearch(statements, res, prefix, helpersres) {
-                prefix = prefix ? prefix + "." : "";
-
-                var newprefix = "",
-                    flag = false;
-
-                // loop through each statement
-                _(statements).forEach(function(statement) {
-                    var parts, part, sideways;
-
-                    // if it's a mustache block
-                    if (statement && statement.type && statement.type === 'mustache') {
-
-                        // If it has params, the first part is a helper or something
-                        if (!statement.params || !statement.params.length) {
-                            parts = composeParts(statement.id.parts);
-                            for (part in parts) {
-                                if (parts[part]) {
-                                    newprefix = parts[part] || newprefix;
-                                    res.push(prefix + parts[part]);
-                                }
-                            }
-                            res.push(prefix + statement.id.string);
-                        }
-
-                        var paramsWithoutParts = ['this', '.', '..', './..', '../..', '../../..'];
-
-                        // grab the params
-                        if (statement.params && typeof Handlebars.helpers[statement.id.string] === 'undefined') {
-                            _(statement.params).forEach(function(param) {
-                                if (_(paramsWithoutParts).contains(param.original) || param instanceof Handlebars.AST.StringNode || param instanceof Handlebars.AST.IntegerNode || param instanceof Handlebars.AST.BooleanNode) {
-                                    helpersres.push(statement.id.string);
-                                }
-
-                                parts = composeParts(param.parts);
-
-                                for (var part in parts) {
-                                    if (parts[part]) {
-                                        newprefix = parts[part] || newprefix;
-                                        helpersres.push(statement.id.string);
-                                        res.push(prefix + parts[part]);
-                                    }
-                                }
-                            });
-                        }
-                    }
-
-                    // If it's a meta block
-                    if (statement && statement.mustache) {
-                        recursiveVarSearch([statement.mustache], res, prefix + newprefix, helpersres);
-                    }
-
-                    // if it's a whole new program
-                    if (statement && statement.program && statement.program.statements) {
-                        sideways = recursiveVarSearch([statement.mustache], [], "", helpersres)[0] || "";
-                        if (statement.program.inverse && statement.program.inverse.statements) {
-                            recursiveVarSearch(statement.program.inverse.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres);
-                        }
-                        recursiveVarSearch(statement.program.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres);
-                    }
-                });
-                return res;
-            }
-
-            // This finds the Helper dependencies since it's soooo similar
-            function getExternalDeps(nodes) {
-                var res = [];
-                var helpersres = [];
-
-                if (nodes && nodes.statements) {
-                    res = recursiveVarSearch(nodes.statements, [], undefined, helpersres);
-                }
-
-                var defaultHelpers = ["helperMissing", "blockHelperMissing", "each", "if", "unless", "with"];
-
-                return {
-                    vars: _(res).chain().unique().map(function(e) {
-                        if (e === "") {
-                            return '.';
-                        }
-                        if (e.length && e[e.length - 1] === '.') {
-                            return e.substr(0, e.length - 1) + '[]';
-                        }
-                        return e;
-                    }).value(),
-                    helpers: _(helpersres).chain().unique().map(function(e) {
-                        if (_(defaultHelpers).contains(e)) {
-                            return undefined;
-                        }
-                        return e;
-                    }).compact().value()
-                };
-            }
-
-            function fetchAndRegister(langMap) {
-                fetchText(path, function(text) {
-                    // for some reason it doesn't include hbs _first_ when i don't add it here...
-                    var nodes = Handlebars.parse(text),
-                        deps = findPartialDeps(nodes),
-                        meta = getMetaData(nodes),
-                        extDeps = getExternalDeps(nodes),
-                        vars = extDeps.vars,
-                        helps = extDeps.helpers || [],
-                        depStr = deps.join("', 'hbs!").replace(/_/g, '/'),
-                        helpDepStr = config.hbs && config.hbs.disableHelpers ?
-                        "" : (function() {
-                            var i, paths = [],
-                                pathGetter = config.hbs && config.hbs.helperPathCallback ? config.hbs.helperPathCallback : function(name) {
-                                    return (config.hbs && config.hbs.helperDirectory ? config.hbs.helperDirectory : helperDirectory) + name;
-                                };
-
-                            for (i = 0; i < helps.length; i++) {
-                                paths[i] = "'" + pathGetter(helps[i], path) + "'"
-                            }
-                            return paths;
-                        })().join(','),
-                        debugOutputStart = "",
-                        debugOutputEnd = "",
-                        debugProperties = "",
-                        metaObj, head, linkElem;
-
-                    if (depStr) {
-                        depStr = ",'hbs!" + depStr + "'";
-                    }
-                    if (helpDepStr) {
-                        helpDepStr = "," + helpDepStr;
-                    }
-
-                    if (meta !== "{}") {
-                        try {
-                            metaObj = JSON.parse(meta);
-                            if (metaObj && metaObj.styles) {
-                                styleList = _.union(styleList, metaObj.styles);
-
-                                // In dev mode in the browser
-                                if (require.isBrowser && !config.isBuild) {
-                                    head = document.head || document.getElementsByTagName('head')[0];
-                                    _(metaObj.styles).forEach(function(style) {
-                                        if (!styleMap[style]) {
-                                            linkElem = document.createElement('link');
-                                            linkElem.href = config.baseUrl + devStyleDirectory + style + '.css';
-                                            linkElem.media = 'all';
-                                            linkElem.rel = 'stylesheet';
-                                            linkElem.type = 'text/css';
-                                            head.appendChild(linkElem);
-                                            styleMap[style] = linkElem;
-                                        }
-                                    });
-                                } else if (config.isBuild) {
-                                    (function() {
-                                        var fs = require.nodeRequire('fs'),
-                                            str = _(metaObj.styles).map(function(style) {
-                                                if (!styleMap[style]) {
-                                                    styleMap[style] = true;
-                                                    return "@import url(" + style + ".css);\n";
-                                                }
-                                                return "";
-                                            }).join("\n");
-
-                                        // I write out my import statements to a file in order to help me build stuff.
-                                        // Then I use a tool to inline my import statements afterwards. (you can run r.js on it too)
-                                        fs.open(__dirname + buildStyleDirectory + buildCSSFileName, filecode, '0666', function(e, id) {
-                                            fs.writeSync(id, str, null, encoding = 'utf8');
-                                            fs.close(id);
-                                        });
-                                        filecode = "a";
-                                    })();
-                                }
-                            }
-                        } catch (e) {
-                            console.log('error injecting styles');
-                        }
-                    }
-
-                    if (!config.isBuild && !config.serverRender) {
-                        debugOutputStart = "<!-- START - " + name + " -->";
-                        debugOutputEnd = "<!-- END - " + name + " -->";
-                        debugProperties = "t.meta = " + meta + ";\n" +
-                            "t.helpers = " + JSON.stringify(helps) + ";\n" +
-                            "t.deps = " + JSON.stringify(deps) + ";\n" +
-                            "t.vars = " + JSON.stringify(vars) + ";\n";
-                    }
-
-                    var mapping = disableI18n ? false : _.extend(langMap, config.localeMapping),
-                        configHbs = config.hbs || {},
-                        options = _.extend(configHbs.compileOptions || {}, {
-                            originalKeyFallback: configHbs.originalKeyFallback
-                        }),
-                        prec = precompile(text, mapping, options);
-
-                    text = "/* START_TEMPLATE */\n" +
-                        "define(['hbs','handlebars'" + depStr + helpDepStr + "], function( hbs, Handlebars ){ \n" +
-                        "var t = Handlebars.template(" + prec + ");\n" +
-                        "Handlebars.registerPartial('" + name.replace(/\//g, '_') + "', t);\n" +
-                        debugProperties +
-                        "return t;\n" +
-                        "});\n" +
-                        "/* END_TEMPLATE */\n";
-
-                    //Hold on to the transformed text if a build.
-                    if (config.isBuild) {
-                        buildMap[compiledName] = text;
-                    }
-
-                    //IE with conditional comments on cannot handle the
-                    //sourceURL trick, so skip it if enabled.
-                    /*@if (@_jscript) @else @*/
-                    if (!config.isBuild) {
-                        text += "\r\n//@ sourceURL=" + path;
-                    }
-                    /*@end@*/
-
-                    for (var i in deps) {
-                        if (deps.hasOwnProperty(i)) {
-                            deps[i] = 'hbs!' + deps[i].replace(/_/g, '/');
-                        }
-                    }
-
-                    if (!config.isBuild) {
-                        require(deps, function() {
-                            load.fromText(text);
-
-                            //Give result to load. Need to wait until the module
-                            //is fully parse, which will happen after this
-                            //execution.
-                            parentRequire([name], function(value) {
-                                load(value);
-                            });
-                        });
-                    } else {
-                        load.fromText(name, text);
-
-                        //Give result to load. Need to wait until the module
-                        //is fully parse, which will happen after this
-                        //execution.
-                        parentRequire([name], function(value) {
-                            load(value);
-                        });
-                    }
-
-                    if (config.removeCombined) {
-                        fs.unlinkSync(path);
-                    }
-                });
-            }
-
-            var path,
-                omitExtension = config.hbs && config.hbs.templateExtension === false;
-            if (omitExtension) {
-                path = parentRequire.toUrl(name);
-            } else {
-                path = parentRequire.toUrl(name + '.' + (config.hbs && config.hbs.templateExtension ? config.hbs.templateExtension : templateExtension));
-            }
-
-            if (disableI18n) {
-                fetchAndRegister(false);
-            } else {
-                // Workaround until jam is able to pass config info or we move i18n to a separate module.
-                // This logs a warning and disables i18n if there's an error loading the language file
-                var langMapPath = (config.hbs && config.hbs.i18nDirectory ? config.hbs.i18nDirectory : i18nDirectory) + (config.locale || "en_us") + '.json';
-                try {
-                    fetchOrGetCached(parentRequire.toUrl(langMapPath), function(langMap) {
-                        fetchAndRegister(JSON.parse(langMap));
-                    });
-                } catch (er) {
-                    // if there's no configuration at all, log a warning and disable i18n for this and subsequent templates
-                    if (!config.hbs) {
-                        console.warn('hbs: Error reading ' + langMapPath + ', disabling i18n. Ignore this if you\'re using jam, otherwise check your i18n configuration.\n');
-                        config.hbs = {
-                            disableI18n: true
-                        };
-                        fetchAndRegister(false);
-                    } else {
-                        throw er;
-
-                    }
-                }
-            }
-            //>>excludeEnd('excludeHbs')
-        }
-    };
-});
-/* END_hbs_PLUGIN */

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/require-handlebars-plugin/js/i18nprecompile.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/require-handlebars-plugin/js/i18nprecompile.js b/dashboardv2/public/js/require-handlebars-plugin/js/i18nprecompile.js
deleted file mode 100644
index 925ac39..0000000
--- a/dashboardv2/public/js/require-handlebars-plugin/js/i18nprecompile.js
+++ /dev/null
@@ -1,57 +0,0 @@
-//>>excludeStart('excludeAfterBuild', pragmas.excludeAfterBuild)
-define(['handlebars', "underscore"], function(Handlebars, _) {
-
-    function replaceLocaleStrings(ast, mapping, options) {
-        options = options || {};
-        mapping = mapping || {};
-        // Base set of things
-        if (ast && ast.type === "program" && ast.statements) {
-            _(ast.statements).forEach(function(statement, i) {
-                var newString = "<!-- i18n error -->";
-                // If it's a translation node
-                if (statement.type === "mustache" && statement.id && statement.id.original === "$") {
-
-                    if (statement.params.length && statement.params[0].string) {
-                        var key = statement.params[0].string;
-                        newString = mapping[key] || (options.originalKeyFallback ? key : newString);
-                    }
-                    ast.statements[i] = new Handlebars.AST.ContentNode(newString);
-                }
-                // If we need to recurse
-                else if (statement.program) {
-                    statement.program = replaceLocaleStrings(statement.program, mapping, options);
-                }
-            });
-            // Also cover the else blocks
-            if (ast.inverse) {
-                replaceLocaleStrings(ast.inverse, mapping, options);
-            }
-        }
-        return ast;
-    }
-
-    return function precompile(string, mapping, options) {
-        var ast, environment;
-
-        options = options || {};
-
-        if (!('data' in options)) {
-            options.data = true;
-        }
-
-        if (options.compat) {
-            options.useDepths = true;
-        }
-
-        ast = Handlebars.parse(string);
-
-        // avoid replacing locale if mapping is `false`
-        if (mapping !== false) {
-            ast = replaceLocaleStrings(ast, mapping, options);
-        }
-
-        environment = new Handlebars.Compiler().compile(ast, options);
-        return new Handlebars.JavaScriptCompiler().compile(environment, options);
-    };
-});
-//>>excludeEnd('excludeAfterBuild')

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/require-handlebars-plugin/js/json2.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/require-handlebars-plugin/js/json2.js b/dashboardv2/public/js/require-handlebars-plugin/js/json2.js
deleted file mode 100644
index c740001..0000000
--- a/dashboardv2/public/js/require-handlebars-plugin/js/json2.js
+++ /dev/null
@@ -1,351 +0,0 @@
-//>>excludeStart('excludeAfterBuild', pragmas.excludeAfterBuild)
-/*
-    http://www.JSON.org/json2.js
-    2011-10-19
-
-    Public Domain.
-
-    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
-    See http://www.JSON.org/js.html
-
-
-    This code should be minified before deployment.
-    See http://javascript.crockford.com/jsmin.html
-
-    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
-    NOT CONTROL.
-*/
-
-/*jslint evil: true, regexp: true */
-
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
-    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
-    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
-    lastIndex, length, parse, prototype, push, replace, slice, stringify,
-    test, toJSON, toString, valueOf
-*/
-
-(function(window) {
-
-    // Create a JSON object only if one does not already exist. We create the
-    // methods in a closure to avoid creating global variables.
-
-    // Return the window JSON element if it exists;
-    var JSON = window.JSON || {};
-
-    (function() {
-        'use strict';
-
-        function f(n) {
-            // Format integers to have at least two digits.
-            return n < 10 ? '0' + n : n;
-        }
-
-        if (typeof Date.prototype.toJSON !== 'function') {
-
-            Date.prototype.toJSON = function(key) {
-
-                return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' +
-                    f(this.getUTCMonth() + 1) + '-' +
-                    f(this.getUTCDate()) + 'T' +
-                    f(this.getUTCHours()) + ':' +
-                    f(this.getUTCMinutes()) + ':' +
-                    f(this.getUTCSeconds()) + 'Z' : null;
-            };
-
-            String.prototype.toJSON =
-                Number.prototype.toJSON =
-                Boolean.prototype.toJSON = function(key) {
-                    return this.valueOf();
-                };
-        }
-
-        var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            gap,
-            indent,
-            meta = { // table of character substitutions
-                '\b': '\\b',
-                '\t': '\\t',
-                '\n': '\\n',
-                '\f': '\\f',
-                '\r': '\\r',
-                '"': '\\"',
-                '\\': '\\\\'
-            },
-            rep;
-
-        function quote(string) {
-
-            // If the string contains no control characters, no quote characters, and no
-            // backslash characters, then we can safely slap some quotes around it.
-            // Otherwise we must also replace the offending characters with safe escape
-            // sequences.
-
-            escapable.lastIndex = 0;
-            return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
-                var c = meta[a];
-                return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-            }) + '"' : '"' + string + '"';
-        }
-
-        function str(key, holder) {
-
-            // Produce a string from holder[key].
-
-            var i, // The loop counter.
-                k, // The member key.
-                v, // The member value.
-                length,
-                mind = gap,
-                partial,
-                value = holder[key];
-
-            // If the value has a toJSON method, call it to obtain a replacement value.
-
-            if (value && typeof value === 'object' &&
-                typeof value.toJSON === 'function') {
-                value = value.toJSON(key);
-            }
-
-            // If we were called with a replacer function, then call the replacer to
-            // obtain a replacement value.
-
-            if (typeof rep === 'function') {
-                value = rep.call(holder, key, value);
-            }
-
-            // What happens next depends on the value's type.
-
-            switch (typeof value) {
-                case 'string':
-                    return quote(value);
-
-                case 'number':
-
-                    // JSON numbers must be finite. Encode non-finite numbers as null.
-
-                    return isFinite(value) ? String(value) : 'null';
-
-                case 'boolean':
-                case 'null':
-
-                    // If the value is a boolean or null, convert it to a string. Note:
-                    // typeof null does not produce 'null'. The case is included here in
-                    // the remote chance that this gets fixed someday.
-
-                    return String(value);
-
-                    // If the type is 'object', we might be dealing with an object or an array or
-                    // null.
-
-                case 'object':
-
-                    // Due to a specification blunder in ECMAScript, typeof null is 'object',
-                    // so watch out for that case.
-
-                    if (!value) {
-                        return 'null';
-                    }
-
-                    // Make an array to hold the partial results of stringifying this object value.
-
-                    gap += indent;
-                    partial = [];
-
-                    // Is the value an array?
-
-                    if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-                        // The value is an array. Stringify every element. Use null as a placeholder
-                        // for non-JSON values.
-
-                        length = value.length;
-                        for (i = 0; i < length; i += 1) {
-                            partial[i] = str(i, value) || 'null';
-                        }
-
-                        // Join all of the elements together, separated with commas, and wrap them in
-                        // brackets.
-
-                        v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
-                        gap = mind;
-                        return v;
-                    }
-
-                    // If the replacer is an array, use it to select the members to be stringified.
-
-                    if (rep && typeof rep === 'object') {
-                        length = rep.length;
-                        for (i = 0; i < length; i += 1) {
-                            if (typeof rep[i] === 'string') {
-                                k = rep[i];
-                                v = str(k, value);
-                                if (v) {
-                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                                }
-                            }
-                        }
-                    } else {
-
-                        // Otherwise, iterate through all of the keys in the object.
-
-                        for (k in value) {
-                            if (Object.prototype.hasOwnProperty.call(value, k)) {
-                                v = str(k, value);
-                                if (v) {
-                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                                }
-                            }
-                        }
-                    }
-
-                    // Join all of the member texts together, separated with commas,
-                    // and wrap them in braces.
-
-                    v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
-                    gap = mind;
-                    return v;
-            }
-        }
-
-        // If the JSON object does not yet have a stringify method, give it one.
-
-        if (typeof JSON.stringify !== 'function') {
-            JSON.stringify = function(value, replacer, space) {
-
-                // The stringify method takes a value and an optional replacer, and an optional
-                // space parameter, and returns a JSON text. The replacer can be a function
-                // that can replace values, or an array of strings that will select the keys.
-                // A default replacer method can be provided. Use of the space parameter can
-                // produce text that is more easily readable.
-
-                var i;
-                gap = '';
-                indent = '';
-
-                // If the space parameter is a number, make an indent string containing that
-                // many spaces.
-
-                if (typeof space === 'number') {
-                    for (i = 0; i < space; i += 1) {
-                        indent += ' ';
-                    }
-
-                    // If the space parameter is a string, it will be used as the indent string.
-
-                } else if (typeof space === 'string') {
-                    indent = space;
-                }
-
-                // If there is a replacer, it must be a function or an array.
-                // Otherwise, throw an error.
-
-                rep = replacer;
-                if (replacer && typeof replacer !== 'function' &&
-                    (typeof replacer !== 'object' ||
-                        typeof replacer.length !== 'number')) {
-                    throw new Error('JSON.stringify');
-                }
-
-                // Make a fake root object containing our value under the key of ''.
-                // Return the result of stringifying the value.
-
-                return str('', {
-                    '': value
-                });
-            };
-        }
-
-        // If the JSON object does not yet have a parse method, give it one.
-
-        if (typeof JSON.parse !== 'function') {
-            JSON.parse = function(text, reviver) {
-
-                // The parse method takes a text and an optional reviver function, and returns
-                // a JavaScript value if the text is a valid JSON text.
-
-                var j;
-
-                function walk(holder, key) {
-
-                    // The walk method is used to recursively walk the resulting structure so
-                    // that modifications can be made.
-
-                    var k, v, value = holder[key];
-                    if (value && typeof value === 'object') {
-                        for (k in value) {
-                            if (Object.prototype.hasOwnProperty.call(value, k)) {
-                                v = walk(value, k);
-                                if (v !== undefined) {
-                                    value[k] = v;
-                                } else {
-                                    delete value[k];
-                                }
-                            }
-                        }
-                    }
-                    return reviver.call(holder, key, value);
-                }
-
-                // Parsing happens in four stages. In the first stage, we replace certain
-                // Unicode characters with escape sequences. JavaScript handles many characters
-                // incorrectly, either silently deleting them, or treating them as line endings.
-
-                text = String(text);
-                cx.lastIndex = 0;
-                if (cx.test(text)) {
-                    text = text.replace(cx, function(a) {
-                        return '\\u' +
-                            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-                    });
-                }
-
-                // In the second stage, we run the text against regular expressions that look
-                // for non-JSON patterns. We are especially concerned with '()' and 'new'
-                // because they can cause invocation, and '=' because it can cause mutation.
-                // But just to be safe, we want to reject all unexpected forms.
-
-                // We split the second stage into 4 regexp operations in order to work around
-                // crippling inefficiencies in IE's and Safari's regexp engines. First we
-                // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-                // replace all simple value tokens with ']' characters. Third, we delete all
-                // open brackets that follow a colon or comma or that begin the text. Finally,
-                // we look to see that the remaining characters are only whitespace or ']' or
-                // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
-                if (/^[\],:{}\s]*$/
-                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
-                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
-                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-                    // In the third stage we use the eval function to compile the text into a
-                    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-                    // in JavaScript: it can begin a block or an object literal. We wrap the text
-                    // in parens to eliminate the ambiguity.
-
-                    j = eval('(' + text + ')');
-
-                    // In the optional fourth stage, we recursively walk the new structure, passing
-                    // each name/value pair to a reviver function for possible transformation.
-
-                    return typeof reviver === 'function' ? walk({
-                        '': j
-                    }, '') : j;
-                }
-
-                // If the text is not JSON parseable, then a SyntaxError is thrown.
-
-                throw new SyntaxError('JSON.parse');
-            };
-        }
-    }());
-
-    define(function() {
-        return JSON;
-    });
-    // otherwise just leave it alone
-
-}).call(this, this);
-//>>excludeEnd('excludeAfterBuild')

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
index 26d27b3..12e3a0a 100644
--- a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
@@ -17,7 +17,7 @@
 <!-- <div class="panel-heading">
     <h3 class="panel-title">Lineage</h3>
 </div> -->
-<div class="panel-body graph-bg" align="center">
+<div class="panel-body graph-bg resize-graph" align="center">
     <div class="graph" id="tree-container">
     </div>
     <div style="position:relative">

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
index 35f5811..4706ba3 100644
--- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
+++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
@@ -142,9 +142,13 @@ define(['require',
                             if (!this.name && collectionJSON[0].values.qualifiedName) {
                                 this.name = collectionJSON[0].values.qualifiedName;
                             }
+                            if (this.name && collectionJSON[0].typeName) {
+                                this.name = this.name + ' (' + collectionJSON[0].typeName + ')';
+                            }
                             if (!this.name && collectionJSON[0].typeName) {
                                 this.name = collectionJSON[0].typeName;
                             }
+
                             if (!this.name && this.id) {
                                 this.name = this.id;
                             }
@@ -153,7 +157,7 @@ define(['require',
                                 this.ui.title.show();
                                 var titleName = '<span>' + this.name + '</span>';
                                 if (this.readOnly) {
-                                    titleName += '<button title="Deleted" class="btn btn-atlasAction btn-atlas deleteBtn"><i class="fa fa-trash"></i> Deleted</button>'
+                                    titleName += '<button title="Deleted" class="btn btn-atlasAction btn-atlas deleteBtn"><i class="fa fa-trash"></i> Deleted</button>';
                                 }
                                 this.ui.title.html(titleName);
                             } else {

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/views/graph/LineageLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js b/dashboardv2/public/js/views/graph/LineageLayoutView.js
index 706848e..eebbd9f 100644
--- a/dashboardv2/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv2/public/js/views/graph/LineageLayoutView.js
@@ -24,7 +24,8 @@ define(['require',
     'utils/Utils',
     'dagreD3',
     'd3-tip',
-    'utils/Globals'
+    'utils/Globals',
+    'jquery-ui'
 ], function(require, Backbone, LineageLayoutViewtmpl, VLineageList, VEntity, Utils, dagreD3, d3Tip, Globals) {
     'use strict';
 
@@ -64,6 +65,7 @@ define(['require',
                 this.fetchGraphData();
                 this.data = {};
                 this.asyncFetchCounter = 0;
+
             },
             bindEvents: function() {
                 this.listenTo(this.inputCollection, 'reset', function() {
@@ -82,7 +84,15 @@ define(['require',
                 }, this);
             },
             onRender: function() {
+                var that = this;
                 this.$('.fontLoader').show();
+                this.$(".resize-graph").resizable({
+                    handles: ' s',
+                    minHeight: 355,
+                    stop: function(event, ui) {
+                        that.$('svg').height(($(this).height() - 5))
+                    },
+                });
                 this.g = new dagreD3.graphlib.Graph()
                     .setGraph({
                         nodesep: 50,
@@ -114,8 +124,15 @@ define(['require',
                     if (data && data.definition) {
                         if (data.definition.values) {
                             var values = data.definition.values;
-                            obj['label'] = values.name.trunc(20);
+                            obj['label'] = values.name;
+
                             obj['toolTiplabel'] = values.name;
+                            if (data.definition.typeName) {
+                                var temp = obj['label'] + ' (' + data.definition.typeName + ')'
+                                obj['label'] = temp;
+                                obj['toolTiplabel'] = temp;
+                            }
+                            obj['label'] = obj['label'].trunc(18);
                             obj['id'] = data.GUID;
                             if (values.queryText) {
                                 obj['queryText'] = values.queryText;
@@ -176,8 +193,14 @@ define(['require',
                     _.each(uniquNode, function(val, key) {
                         var obj = {};
                         if (vertices[val] && vertices[val].values) {
-                            obj['label'] = vertices[val].values.name.trunc(20);
+                            obj['label'] = vertices[val].values.name;
                             obj['toolTiplabel'] = vertices[val].values.name;
+                            if (vertices[val].values.vertexId && vertices[val].values.vertexId.values && vertices[val].values.vertexId.values.typeName) {
+                                var temp = obj['label'] + ' (' + vertices[val].values.vertexId.values.typeName + ')';
+                                obj['label'] = temp;
+                                obj['toolTiplabel'] = temp;
+                            }
+                            obj['label'] = obj['label'].trunc(18);
                             obj['id'] = val;
                             obj['class'] = "type-TOP";
                             obj['shape'] = "img";

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index b11d7dc..d53a866 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
 ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
 
 ALL CHANGES:
+ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)
 ATLAS-712 Support getTrait() API (svimal2106 via shwethags)
 ATLAS-1173 Doc: Minor editorial bug in the example given for property atlas.server.ha.zookeeper.auth (yhemanth via shwethags)
 ATLAS-1133 Jetty Server start doesn't throw exception when user-credential.properties file is not found (nixonrodrigues,svimal2106 via kevalbhatt)



[6/8] incubator-atlas git commit: ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)

Posted by sh...@apache.org.
ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/7bb2709d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/7bb2709d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/7bb2709d

Branch: refs/heads/master
Commit: 7bb2709d16694fb7957e2018532121474a810f14
Parents: dd0b051
Author: Shwetha GS <ss...@hortonworks.com>
Authored: Mon Sep 19 10:52:53 2016 +0530
Committer: Shwetha GS <ss...@hortonworks.com>
Committed: Mon Sep 19 10:52:53 2016 +0530

----------------------------------------------------------------------
 3party-licenses/jQuery-ui-LICENSE               |   43 +
 LICENSE                                         |    3 +
 dashboardv2/public/index.html                   |    1 +
 .../js/external_lib/jquery-ui/jquery-ui.min.css |    7 +
 .../js/external_lib/jquery-ui/jquery-ui.min.js  |    6 +
 .../require-handlebars-plugin/js/handlebars.js  | 3103 ++++++++++++++++++
 .../require-handlebars-plugin/js/hbs.js         |  490 +++
 .../js/i18nprecompile.js                        |   57 +
 .../require-handlebars-plugin/js/json2.js       |  351 ++
 dashboardv2/public/js/main.js                   |   14 +-
 .../require-handlebars-plugin/js/handlebars.js  | 3103 ------------------
 .../js/require-handlebars-plugin/js/hbs.js      |  490 ---
 .../js/i18nprecompile.js                        |   57 -
 .../js/require-handlebars-plugin/js/json2.js    |  351 --
 .../templates/graph/LineageLayoutView_tmpl.html |    2 +-
 .../views/detail_page/DetailPageLayoutView.js   |    6 +-
 .../public/js/views/graph/LineageLayoutView.js  |   29 +-
 release-log.txt                                 |    1 +
 18 files changed, 4103 insertions(+), 4011 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/3party-licenses/jQuery-ui-LICENSE
----------------------------------------------------------------------
diff --git a/3party-licenses/jQuery-ui-LICENSE b/3party-licenses/jQuery-ui-LICENSE
new file mode 100644
index 0000000..4819e54
--- /dev/null
+++ b/3party-licenses/jQuery-ui-LICENSE
@@ -0,0 +1,43 @@
+Copyright jQuery Foundation and other contributors, https://jquery.org/
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/jquery/jquery-ui
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code contained within the demos directory.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+All files located in the node_modules and external directories are
+externally maintained libraries used by this software which have their
+own licenses; we recommend you read them, as their terms may differ from
+the terms above.

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 032284e..0110fa9 100755
--- a/LICENSE
+++ b/LICENSE
@@ -232,4 +232,7 @@ WTFPL License.  For details, see 3party-licenses/require-handlebars-plugin-LICEN
 
 This product bundles json2.js (https://github.com/douglascrockford/JSON-js -
 Public Domain license) by Douglas Crockford
+
+This product bundles jQuery-ui.js, which is available under
+MIT License. For details, see 3party-licenses/jQuery-ui-LICENSE
 =======================================================================
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/index.html
----------------------------------------------------------------------
diff --git a/dashboardv2/public/index.html b/dashboardv2/public/index.html
index c43ca9a..a8f191a 100644
--- a/dashboardv2/public/index.html
+++ b/dashboardv2/public/index.html
@@ -41,6 +41,7 @@
     <link rel="stylesheet" href="js/libs/bootstrap/css/bootstrap.min.css">
     <link rel="stylesheet" href="js/libs/jquery-asBreadcrumbs/css/asBreadcrumbs.css">
     <link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600,600italic,700,700italic' rel='stylesheet' type='text/css'>
+    <link rel="stylesheet" type="text/css" href="js/external_lib/jquery-ui/jquery-ui.min.css">
     <link href="css/bootstrap-sidebar.css" rel="stylesheet">
     <link href="js/libs/font-awesome/css/font-awesome.min.css" rel="stylesheet">
     <link href="css/style.css" rel="stylesheet">

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css
new file mode 100644
index 0000000..76845f2
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.12.0 - 2016-08-25
+* http://jqueryui.com
+* Includes: core.css, resizable.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&ico
 nColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display
 :block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border
 :1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-ho
 ver a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highli
 ght a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui
 -widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon,.ui-state-default .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1
 -sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{b
 ackground-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{backg
 round-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arro
 wreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}
 .ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{
 background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{backgr
 ound-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position
 :-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-
 icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:
 -80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js
new file mode 100644
index 0000000..8951532
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.12.0 - 2016-08-25
+* http://jqueryui.com
+* Includes: widget.js, disable-selection.js, widgets/resizable.js, widgets/mouse.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.0";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].ap
 ply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.each(function(){var i,s=t.data(this,n);return"instance
 "===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&
 &this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t
 .widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disab
 led:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=thi
 s.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e
 ),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,t.fn.extend({disableSelection:func
 tion(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.0",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this
 .widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}}
 ,_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mou
 seDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.0",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},cont
 ainment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),lef
 t:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestro
 y();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,s
 w,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("<div>"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this.
 _handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height
 ()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,l=this._change[o];return this._updatePrevProperties(),l?(i=l.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proporti
 onallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,l,h=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,l=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,h.animate||this.element.css(t.extend(a,{top:l,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(
 ){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidt
 h=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalS
 ize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&c&&(t.top=l-e.minHeight),n&&c&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDi
 mensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:functio
 n(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.
 sizeDiff.width,l={width:i.size.width-r,height:i.size.height-a},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,c&&h?{top:c,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,l=t(this).resizable("instance"),h=l.options,c=l.element,u=h.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(l.containerElement=t(d),/document/.test(u)||u===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(documen
 t),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=l._num(e.css("padding"+s))}),l.containerOffset=e.offset(),l.containerPosition=e.position(),l.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=l.containerOffset,n=l.containerSize.height,o=l.containerSize.width,a=l._hasScroll(d,"left")?d.scrollWidth:o,r=l._hasScroll(d)?d.scrollHeight:n,l.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,l=a.containerOffset,h=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=l),h.left<(a._helper?l.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-l.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?l.left:0),h.
 top<(a._helper?l.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-l.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?l.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-l.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-l.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.widt
 h,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),l=a.outerWidth()-e.sizeDiff.width,h=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-
 a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&
 &e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,l="number"==typeof s.grid?[s.grid,s.grid]:s.grid,h=l[0]||1,c=l[1]||1,u=Math.round((n.width-o.width)/h)*h,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=l,_&&(p+=h),v&&(f+=c),g&&(p-=h),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-h)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-h>0?(i.size.width=p,i.position.left=a.left-u):(p=h-e.width,i.size.width=p,i.positio
 n.left=a.left+o.width-p))}}),t.ui.resizable});
\ No newline at end of file


[8/8] incubator-atlas git commit: ATLAS-1155 Errors in Eclipse when I bring in the latest code (davidrad via shwethags)

Posted by sh...@apache.org.
ATLAS-1155 Errors in Eclipse when I bring in the latest code (davidrad via shwethags)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/71e0e09b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/71e0e09b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/71e0e09b

Branch: refs/heads/master
Commit: 71e0e09b9d7c9f999741a71b4e779eb89a051760
Parents: c1081a4
Author: Shwetha GS <ss...@hortonworks.com>
Authored: Mon Sep 19 11:47:22 2016 +0530
Committer: Shwetha GS <ss...@hortonworks.com>
Committed: Mon Sep 19 11:47:22 2016 +0530

----------------------------------------------------------------------
 release-log.txt                                                  | 1 +
 .../atlas/discovery/graph/GraphBackedDiscoveryService.java       | 3 +--
 .../src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala | 4 ++++
 .../repository/graph/GraphBackedMetadataRepositoryTest.java      | 2 +-
 4 files changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/71e0e09b/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index f1ac7a7..88be4b6 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
 ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
 
 ALL CHANGES:
+ATLAS-1155 Errors in Eclipse when I bring in the latest code (davidrad via shwethags)
 ATLAS-1098 Atlas allows creation of tag with name "isa" which causes exceptions during search (apoorvnaik via shwethags)
 ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)
 ATLAS-712 Support getTrait() API (svimal2106 via shwethags)

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/71e0e09b/repository/src/main/java/org/apache/atlas/discovery/graph/GraphBackedDiscoveryService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/graph/GraphBackedDiscoveryService.java b/repository/src/main/java/org/apache/atlas/discovery/graph/GraphBackedDiscoveryService.java
index ef426e9..0c029bb 100755
--- a/repository/src/main/java/org/apache/atlas/discovery/graph/GraphBackedDiscoveryService.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/graph/GraphBackedDiscoveryService.java
@@ -150,8 +150,7 @@ public class GraphBackedDiscoveryService implements DiscoveryService {
         //If the final limit is 0, don't launch the query, return with 0 rows
         if (validatedExpression instanceof Expressions.LimitExpression
                 && ((Integer)((Expressions.LimitExpression) validatedExpression).limit().rawValue()) == 0) {
-            return new GremlinQueryResult(dslQuery, validatedExpression.dataType(),
-                    scala.collection.immutable.List.empty());
+            return new GremlinQueryResult(dslQuery, validatedExpression.dataType());
         }
 
         GremlinQuery gremlinQuery = new GremlinTranslator(validatedExpression, graphPersistenceStrategy).translate();

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/71e0e09b/repository/src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala
----------------------------------------------------------------------
diff --git a/repository/src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala b/repository/src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala
index 7de03c3..10d66a9 100755
--- a/repository/src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala
+++ b/repository/src/main/scala/org/apache/atlas/query/GremlinEvaluator.scala
@@ -33,6 +33,10 @@ import org.apache.atlas.query.Expressions._
 case class GremlinQueryResult(query: String,
                               resultDataType: IDataType[_],
                               rows: List[_]) {
+    def this(query: String,resultDataType: IDataType[_]) {
+      this(query,resultDataType,List.empty)
+    }
+  
     def toJson = JsonHelper.toJson(this)
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/71e0e09b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java
index 3ca1f78..2541541 100755
--- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java
@@ -188,7 +188,7 @@ public class GraphBackedMetadataRepositoryTest {
 
     private boolean assertEdge(String id, String typeName) throws Exception {
         TitanGraph graph = graphProvider.get();
-        Vertex vertex = graph.query().has(Constants.GUID_PROPERTY_KEY, id).vertices().iterator().next();
+        Vertex vertex = (Vertex)graph.query().has(Constants.GUID_PROPERTY_KEY, id).vertices().iterator().next();
         Iterable<Edge> edges = vertex.getEdges(Direction.OUT, Constants.INTERNAL_PROPERTY_KEY_PREFIX + typeName + ".ref");
         if (!edges.iterator().hasNext()) {
             ITypedReferenceableInstance entity = repositoryService.getEntityDefinition(id);


[5/8] incubator-atlas git commit: ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/handlebars.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/handlebars.js b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/handlebars.js
new file mode 100644
index 0000000..b62aa79
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/handlebars.js
@@ -0,0 +1,3103 @@
+(function() {
+    /*
+
+    Copyright (C) 2011 by Yehuda Katz
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+
+    */
+
+    // lib/handlebars/browser-prefix.js
+    var Handlebars = {};
+
+    (function(Handlebars, undefined) {;
+        // lib/handlebars/base.js
+
+        Handlebars.VERSION = "1.0.0-rc.3";
+        Handlebars.COMPILER_REVISION = 2;
+
+        Handlebars.REVISION_CHANGES = {
+            1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
+            2: '>= 1.0.0-rc.3'
+        };
+
+        Handlebars.helpers = {};
+        Handlebars.partials = {};
+
+        Handlebars.registerHelper = function(name, fn, inverse) {
+            if (inverse) {
+                fn.not = inverse;
+            }
+            this.helpers[name] = fn;
+        };
+
+        Handlebars.registerPartial = function(name, str) {
+            this.partials[name] = str;
+        };
+
+        Handlebars.registerHelper('helperMissing', function(arg) {
+            if (arguments.length === 2) {
+                return undefined;
+            } else {
+                throw new Error("Could not find property '" + arg + "'");
+            }
+        });
+
+        var toString = Object.prototype.toString,
+            functionType = "[object Function]";
+
+        Handlebars.registerHelper('blockHelperMissing', function(context, options) {
+            var inverse = options.inverse || function() {},
+                fn = options.fn;
+
+            var type = toString.call(context);
+
+            if (type === functionType) {
+                context = context.call(this);
+            }
+
+            if (context === true) {
+                return fn(this);
+            } else if (context === false || context == null) {
+                return inverse(this);
+            } else if (type === "[object Array]") {
+                if (context.length > 0) {
+                    return Handlebars.helpers.each(context, options);
+                } else {
+                    return inverse(this);
+                }
+            } else {
+                return fn(context);
+            }
+        });
+
+        Handlebars.K = function() {};
+
+        Handlebars.createFrame = Object.create || function(object) {
+            Handlebars.K.prototype = object;
+            var obj = new Handlebars.K();
+            Handlebars.K.prototype = null;
+            return obj;
+        };
+
+        Handlebars.logger = {
+            DEBUG: 0,
+            INFO: 1,
+            WARN: 2,
+            ERROR: 3,
+            level: 3,
+
+            methodMap: {
+                0: 'debug',
+                1: 'info',
+                2: 'warn',
+                3: 'error'
+            },
+
+            // can be overridden in the host environment
+            log: function(level, obj) {
+                if (Handlebars.logger.level <= level) {
+                    var method = Handlebars.logger.methodMap[level];
+                    if (typeof console !== 'undefined' && console[method]) {
+                        console[method].call(console, obj);
+                    }
+                }
+            }
+        };
+
+        Handlebars.log = function(level, obj) {
+            Handlebars.logger.log(level, obj);
+        };
+
+        Handlebars.registerHelper('each', function(context, options) {
+            var fn = options.fn,
+                inverse = options.inverse;
+            var i = 0,
+                ret = "",
+                data;
+
+            if (options.data) {
+                data = Handlebars.createFrame(options.data);
+            }
+
+            if (context && typeof context === 'object') {
+                if (context instanceof Array) {
+                    for (var j = context.length; i < j; i++) {
+                        if (data) {
+                            data.index = i;
+                        }
+                        ret = ret + fn(context[i], {
+                            data: data
+                        });
+                    }
+                } else {
+                    for (var key in context) {
+                        if (context.hasOwnProperty(key)) {
+                            if (data) {
+                                data.key = key;
+                            }
+                            ret = ret + fn(context[key], {
+                                data: data
+                            });
+                            i++;
+                        }
+                    }
+                }
+            }
+
+            if (i === 0) {
+                ret = inverse(this);
+            }
+
+            return ret;
+        });
+
+        Handlebars.registerHelper('if', function(context, options) {
+            var type = toString.call(context);
+            if (type === functionType) {
+                context = context.call(this);
+            }
+
+            if (!context || Handlebars.Utils.isEmpty(context)) {
+                return options.inverse(this);
+            } else {
+                return options.fn(this);
+            }
+        });
+
+        Handlebars.registerHelper('unless', function(context, options) {
+            return Handlebars.helpers['if'].call(this, context, {
+                fn: options.inverse,
+                inverse: options.fn
+            });
+        });
+
+        Handlebars.registerHelper('with', function(context, options) {
+            return options.fn(context);
+        });
+
+        Handlebars.registerHelper('log', function(context, options) {
+            var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
+            Handlebars.log(level, context);
+        });;
+    }(Handlebars));;
+    //>>excludeStart('excludeHbsParser', pragmas.excludeHbsParser)
+    // lib/handlebars/compiler/parser.js
+    /* Jison generated parser */
+    var handlebars = (function() {
+        var parser = {
+            trace: function trace() {},
+            yy: {},
+            symbols_: {
+                "error": 2,
+                "root": 3,
+                "program": 4,
+                "EOF": 5,
+                "simpleInverse": 6,
+                "statements": 7,
+                "statement": 8,
+                "openInverse": 9,
+                "closeBlock": 10,
+                "openBlock": 11,
+                "mustache": 12,
+                "partial": 13,
+                "CONTENT": 14,
+                "COMMENT": 15,
+                "OPEN_BLOCK": 16,
+                "inMustache": 17,
+                "CLOSE": 18,
+                "OPEN_INVERSE": 19,
+                "OPEN_ENDBLOCK": 20,
+                "path": 21,
+                "OPEN": 22,
+                "OPEN_UNESCAPED": 23,
+                "OPEN_PARTIAL": 24,
+                "partialName": 25,
+                "params": 26,
+                "hash": 27,
+                "DATA": 28,
+                "param": 29,
+                "STRING": 30,
+                "INTEGER": 31,
+                "BOOLEAN": 32,
+                "hashSegments": 33,
+                "hashSegment": 34,
+                "ID": 35,
+                "EQUALS": 36,
+                "PARTIAL_NAME": 37,
+                "pathSegments": 38,
+                "SEP": 39,
+                "$accept": 0,
+                "$end": 1
+            },
+            terminals_: {
+                2: "error",
+                5: "EOF",
+                14: "CONTENT",
+                15: "COMMENT",
+                16: "OPEN_BLOCK",
+                18: "CLOSE",
+                19: "OPEN_INVERSE",
+                20: "OPEN_ENDBLOCK",
+                22: "OPEN",
+                23: "OPEN_UNESCAPED",
+                24: "OPEN_PARTIAL",
+                28: "DATA",
+                30: "STRING",
+                31: "INTEGER",
+                32: "BOOLEAN",
+                35: "ID",
+                36: "EQUALS",
+                37: "PARTIAL_NAME",
+                39: "SEP"
+            },
+            productions_: [0, [3, 2],
+                [4, 2],
+                [4, 3],
+                [4, 2],
+                [4, 1],
+                [4, 1],
+                [4, 0],
+                [7, 1],
+                [7, 2],
+                [8, 3],
+                [8, 3],
+                [8, 1],
+                [8, 1],
+                [8, 1],
+                [8, 1],
+                [11, 3],
+                [9, 3],
+                [10, 3],
+                [12, 3],
+                [12, 3],
+                [13, 3],
+                [13, 4],
+                [6, 2],
+                [17, 3],
+                [17, 2],
+                [17, 2],
+                [17, 1],
+                [17, 1],
+                [26, 2],
+                [26, 1],
+                [29, 1],
+                [29, 1],
+                [29, 1],
+                [29, 1],
+                [29, 1],
+                [27, 1],
+                [33, 2],
+                [33, 1],
+                [34, 3],
+                [34, 3],
+                [34, 3],
+                [34, 3],
+                [34, 3],
+                [25, 1],
+                [21, 1],
+                [38, 3],
+                [38, 1]
+            ],
+            performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
+
+                var $0 = $$.length - 1;
+                switch (yystate) {
+                    case 1:
+                        return $$[$0 - 1];
+                        break;
+                    case 2:
+                        this.$ = new yy.ProgramNode([], $$[$0]);
+                        break;
+                    case 3:
+                        this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0]);
+                        break;
+                    case 4:
+                        this.$ = new yy.ProgramNode($$[$0 - 1], []);
+                        break;
+                    case 5:
+                        this.$ = new yy.ProgramNode($$[$0]);
+                        break;
+                    case 6:
+                        this.$ = new yy.ProgramNode([], []);
+                        break;
+                    case 7:
+                        this.$ = new yy.ProgramNode([]);
+                        break;
+                    case 8:
+                        this.$ = [$$[$0]];
+                        break;
+                    case 9:
+                        $$[$0 - 1].push($$[$0]);
+                        this.$ = $$[$0 - 1];
+                        break;
+                    case 10:
+                        this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1].inverse, $$[$0 - 1], $$[$0]);
+                        break;
+                    case 11:
+                        this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0 - 1].inverse, $$[$0]);
+                        break;
+                    case 12:
+                        this.$ = $$[$0];
+                        break;
+                    case 13:
+                        this.$ = $$[$0];
+                        break;
+                    case 14:
+                        this.$ = new yy.ContentNode($$[$0]);
+                        break;
+                    case 15:
+                        this.$ = new yy.CommentNode($$[$0]);
+                        break;
+                    case 16:
+                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
+                        break;
+                    case 17:
+                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
+                        break;
+                    case 18:
+                        this.$ = $$[$0 - 1];
+                        break;
+                    case 19:
+                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
+                        break;
+                    case 20:
+                        this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true);
+                        break;
+                    case 21:
+                        this.$ = new yy.PartialNode($$[$0 - 1]);
+                        break;
+                    case 22:
+                        this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1]);
+                        break;
+                    case 23:
+                        break;
+                    case 24:
+                        this.$ = [
+                            [$$[$0 - 2]].concat($$[$0 - 1]), $$[$0]
+                        ];
+                        break;
+                    case 25:
+                        this.$ = [
+                            [$$[$0 - 1]].concat($$[$0]), null
+                        ];
+                        break;
+                    case 26:
+                        this.$ = [
+                            [$$[$0 - 1]], $$[$0]
+                        ];
+                        break;
+                    case 27:
+                        this.$ = [
+                            [$$[$0]], null
+                        ];
+                        break;
+                    case 28:
+                        this.$ = [
+                            [new yy.DataNode($$[$0])], null
+                        ];
+                        break;
+                    case 29:
+                        $$[$0 - 1].push($$[$0]);
+                        this.$ = $$[$0 - 1];
+                        break;
+                    case 30:
+                        this.$ = [$$[$0]];
+                        break;
+                    case 31:
+                        this.$ = $$[$0];
+                        break;
+                    case 32:
+                        this.$ = new yy.StringNode($$[$0]);
+                        break;
+                    case 33:
+                        this.$ = new yy.IntegerNode($$[$0]);
+                        break;
+                    case 34:
+                        this.$ = new yy.BooleanNode($$[$0]);
+                        break;
+                    case 35:
+                        this.$ = new yy.DataNode($$[$0]);
+                        break;
+                    case 36:
+                        this.$ = new yy.HashNode($$[$0]);
+                        break;
+                    case 37:
+                        $$[$0 - 1].push($$[$0]);
+                        this.$ = $$[$0 - 1];
+                        break;
+                    case 38:
+                        this.$ = [$$[$0]];
+                        break;
+                    case 39:
+                        this.$ = [$$[$0 - 2], $$[$0]];
+                        break;
+                    case 40:
+                        this.$ = [$$[$0 - 2], new yy.StringNode($$[$0])];
+                        break;
+                    case 41:
+                        this.$ = [$$[$0 - 2], new yy.IntegerNode($$[$0])];
+                        break;
+                    case 42:
+                        this.$ = [$$[$0 - 2], new yy.BooleanNode($$[$0])];
+                        break;
+                    case 43:
+                        this.$ = [$$[$0 - 2], new yy.DataNode($$[$0])];
+                        break;
+                    case 44:
+                        this.$ = new yy.PartialNameNode($$[$0]);
+                        break;
+                    case 45:
+                        this.$ = new yy.IdNode($$[$0]);
+                        break;
+                    case 46:
+                        $$[$0 - 2].push($$[$0]);
+                        this.$ = $$[$0 - 2];
+                        break;
+                    case 47:
+                        this.$ = [$$[$0]];
+                        break;
+                }
+            },
+            table: [{
+                3: 1,
+                4: 2,
+                5: [2, 7],
+                6: 3,
+                7: 4,
+                8: 6,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 5],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                1: [3]
+            }, {
+                5: [1, 17]
+            }, {
+                5: [2, 6],
+                7: 18,
+                8: 6,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 19],
+                20: [2, 6],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                5: [2, 5],
+                6: 20,
+                8: 21,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 5],
+                20: [2, 5],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                17: 23,
+                18: [1, 22],
+                21: 24,
+                28: [1, 25],
+                35: [1, 27],
+                38: 26
+            }, {
+                5: [2, 8],
+                14: [2, 8],
+                15: [2, 8],
+                16: [2, 8],
+                19: [2, 8],
+                20: [2, 8],
+                22: [2, 8],
+                23: [2, 8],
+                24: [2, 8]
+            }, {
+                4: 28,
+                6: 3,
+                7: 4,
+                8: 6,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 5],
+                20: [2, 7],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                4: 29,
+                6: 3,
+                7: 4,
+                8: 6,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 5],
+                20: [2, 7],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                5: [2, 12],
+                14: [2, 12],
+                15: [2, 12],
+                16: [2, 12],
+                19: [2, 12],
+                20: [2, 12],
+                22: [2, 12],
+                23: [2, 12],
+                24: [2, 12]
+            }, {
+                5: [2, 13],
+                14: [2, 13],
+                15: [2, 13],
+                16: [2, 13],
+                19: [2, 13],
+                20: [2, 13],
+                22: [2, 13],
+                23: [2, 13],
+                24: [2, 13]
+            }, {
+                5: [2, 14],
+                14: [2, 14],
+                15: [2, 14],
+                16: [2, 14],
+                19: [2, 14],
+                20: [2, 14],
+                22: [2, 14],
+                23: [2, 14],
+                24: [2, 14]
+            }, {
+                5: [2, 15],
+                14: [2, 15],
+                15: [2, 15],
+                16: [2, 15],
+                19: [2, 15],
+                20: [2, 15],
+                22: [2, 15],
+                23: [2, 15],
+                24: [2, 15]
+            }, {
+                17: 30,
+                21: 24,
+                28: [1, 25],
+                35: [1, 27],
+                38: 26
+            }, {
+                17: 31,
+                21: 24,
+                28: [1, 25],
+                35: [1, 27],
+                38: 26
+            }, {
+                17: 32,
+                21: 24,
+                28: [1, 25],
+                35: [1, 27],
+                38: 26
+            }, {
+                25: 33,
+                37: [1, 34]
+            }, {
+                1: [2, 1]
+            }, {
+                5: [2, 2],
+                8: 21,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 19],
+                20: [2, 2],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                17: 23,
+                21: 24,
+                28: [1, 25],
+                35: [1, 27],
+                38: 26
+            }, {
+                5: [2, 4],
+                7: 35,
+                8: 6,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 19],
+                20: [2, 4],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                5: [2, 9],
+                14: [2, 9],
+                15: [2, 9],
+                16: [2, 9],
+                19: [2, 9],
+                20: [2, 9],
+                22: [2, 9],
+                23: [2, 9],
+                24: [2, 9]
+            }, {
+                5: [2, 23],
+                14: [2, 23],
+                15: [2, 23],
+                16: [2, 23],
+                19: [2, 23],
+                20: [2, 23],
+                22: [2, 23],
+                23: [2, 23],
+                24: [2, 23]
+            }, {
+                18: [1, 36]
+            }, {
+                18: [2, 27],
+                21: 41,
+                26: 37,
+                27: 38,
+                28: [1, 45],
+                29: 39,
+                30: [1, 42],
+                31: [1, 43],
+                32: [1, 44],
+                33: 40,
+                34: 46,
+                35: [1, 47],
+                38: 26
+            }, {
+                18: [2, 28]
+            }, {
+                18: [2, 45],
+                28: [2, 45],
+                30: [2, 45],
+                31: [2, 45],
+                32: [2, 45],
+                35: [2, 45],
+                39: [1, 48]
+            }, {
+                18: [2, 47],
+                28: [2, 47],
+                30: [2, 47],
+                31: [2, 47],
+                32: [2, 47],
+                35: [2, 47],
+                39: [2, 47]
+            }, {
+                10: 49,
+                20: [1, 50]
+            }, {
+                10: 51,
+                20: [1, 50]
+            }, {
+                18: [1, 52]
+            }, {
+                18: [1, 53]
+            }, {
+                18: [1, 54]
+            }, {
+                18: [1, 55],
+                21: 56,
+                35: [1, 27],
+                38: 26
+            }, {
+                18: [2, 44],
+                35: [2, 44]
+            }, {
+                5: [2, 3],
+                8: 21,
+                9: 7,
+                11: 8,
+                12: 9,
+                13: 10,
+                14: [1, 11],
+                15: [1, 12],
+                16: [1, 13],
+                19: [1, 19],
+                20: [2, 3],
+                22: [1, 14],
+                23: [1, 15],
+                24: [1, 16]
+            }, {
+                14: [2, 17],
+                15: [2, 17],
+                16: [2, 17],
+                19: [2, 17],
+                20: [2, 17],
+                22: [2, 17],
+                23: [2, 17],
+                24: [2, 17]
+            }, {
+                18: [2, 25],
+                21: 41,
+                27: 57,
+                28: [1, 45],
+                29: 58,
+                30: [1, 42],
+                31: [1, 43],
+                32: [1, 44],
+                33: 40,
+                34: 46,
+                35: [1, 47],
+                38: 26
+            }, {
+                18: [2, 26]
+            }, {
+                18: [2, 30],
+                28: [2, 30],
+                30: [2, 30],
+                31: [2, 30],
+                32: [2, 30],
+                35: [2, 30]
+            }, {
+                18: [2, 36],
+                34: 59,
+                35: [1, 60]
+            }, {
+                18: [2, 31],
+                28: [2, 31],
+                30: [2, 31],
+                31: [2, 31],
+                32: [2, 31],
+                35: [2, 31]
+            }, {
+                18: [2, 32],
+                28: [2, 32],
+                30: [2, 32],
+                31: [2, 32],
+                32: [2, 32],
+                35: [2, 32]
+            }, {
+                18: [2, 33],
+                28: [2, 33],
+                30: [2, 33],
+                31: [2, 33],
+                32: [2, 33],
+                35: [2, 33]
+            }, {
+                18: [2, 34],
+                28: [2, 34],
+                30: [2, 34],
+                31: [2, 34],
+                32: [2, 34],
+                35: [2, 34]
+            }, {
+                18: [2, 35],
+                28: [2, 35],
+                30: [2, 35],
+                31: [2, 35],
+                32: [2, 35],
+                35: [2, 35]
+            }, {
+                18: [2, 38],
+                35: [2, 38]
+            }, {
+                18: [2, 47],
+                28: [2, 47],
+                30: [2, 47],
+                31: [2, 47],
+                32: [2, 47],
+                35: [2, 47],
+                36: [1, 61],
+                39: [2, 47]
+            }, {
+                35: [1, 62]
+            }, {
+                5: [2, 10],
+                14: [2, 10],
+                15: [2, 10],
+                16: [2, 10],
+                19: [2, 10],
+                20: [2, 10],
+                22: [2, 10],
+                23: [2, 10],
+                24: [2, 10]
+            }, {
+                21: 63,
+                35: [1, 27],
+                38: 26
+            }, {
+                5: [2, 11],
+                14: [2, 11],
+                15: [2, 11],
+                16: [2, 11],
+                19: [2, 11],
+                20: [2, 11],
+                22: [2, 11],
+                23: [2, 11],
+                24: [2, 11]
+            }, {
+                14: [2, 16],
+                15: [2, 16],
+                16: [2, 16],
+                19: [2, 16],
+                20: [2, 16],
+                22: [2, 16],
+                23: [2, 16],
+                24: [2, 16]
+            }, {
+                5: [2, 19],
+                14: [2, 19],
+                15: [2, 19],
+                16: [2, 19],
+                19: [2, 19],
+                20: [2, 19],
+                22: [2, 19],
+                23: [2, 19],
+                24: [2, 19]
+            }, {
+                5: [2, 20],
+                14: [2, 20],
+                15: [2, 20],
+                16: [2, 20],
+                19: [2, 20],
+                20: [2, 20],
+                22: [2, 20],
+                23: [2, 20],
+                24: [2, 20]
+            }, {
+                5: [2, 21],
+                14: [2, 21],
+                15: [2, 21],
+                16: [2, 21],
+                19: [2, 21],
+                20: [2, 21],
+                22: [2, 21],
+                23: [2, 21],
+                24: [2, 21]
+            }, {
+                18: [1, 64]
+            }, {
+                18: [2, 24]
+            }, {
+                18: [2, 29],
+                28: [2, 29],
+                30: [2, 29],
+                31: [2, 29],
+                32: [2, 29],
+                35: [2, 29]
+            }, {
+                18: [2, 37],
+                35: [2, 37]
+            }, {
+                36: [1, 61]
+            }, {
+                21: 65,
+                28: [1, 69],
+                30: [1, 66],
+                31: [1, 67],
+                32: [1, 68],
+                35: [1, 27],
+                38: 26
+            }, {
+                18: [2, 46],
+                28: [2, 46],
+                30: [2, 46],
+                31: [2, 46],
+                32: [2, 46],
+                35: [2, 46],
+                39: [2, 46]
+            }, {
+                18: [1, 70]
+            }, {
+                5: [2, 22],
+                14: [2, 22],
+                15: [2, 22],
+                16: [2, 22],
+                19: [2, 22],
+                20: [2, 22],
+                22: [2, 22],
+                23: [2, 22],
+                24: [2, 22]
+            }, {
+                18: [2, 39],
+                35: [2, 39]
+            }, {
+                18: [2, 40],
+                35: [2, 40]
+            }, {
+                18: [2, 41],
+                35: [2, 41]
+            }, {
+                18: [2, 42],
+                35: [2, 42]
+            }, {
+                18: [2, 43],
+                35: [2, 43]
+            }, {
+                5: [2, 18],
+                14: [2, 18],
+                15: [2, 18],
+                16: [2, 18],
+                19: [2, 18],
+                20: [2, 18],
+                22: [2, 18],
+                23: [2, 18],
+                24: [2, 18]
+            }],
+            defaultActions: {
+                17: [2, 1],
+                25: [2, 28],
+                38: [2, 26],
+                57: [2, 24]
+            },
+            parseError: function parseError(str, hash) {
+                throw new Error(str);
+            },
+            parse: function parse(input) {
+                var self = this,
+                    stack = [0],
+                    vstack = [null],
+                    lstack = [],
+                    table = this.table,
+                    yytext = "",
+                    yylineno = 0,
+                    yyleng = 0,
+                    recovering = 0,
+                    TERROR = 2,
+                    EOF = 1;
+                this.lexer.setInput(input);
+                this.lexer.yy = this.yy;
+                this.yy.lexer = this.lexer;
+                this.yy.parser = this;
+                if (typeof this.lexer.yylloc == "undefined")
+                    this.lexer.yylloc = {};
+                var yyloc = this.lexer.yylloc;
+                lstack.push(yyloc);
+                var ranges = this.lexer.options && this.lexer.options.ranges;
+                if (typeof this.yy.parseError === "function")
+                    this.parseError = this.yy.parseError;
+
+                function popStack(n) {
+                    stack.length = stack.length - 2 * n;
+                    vstack.length = vstack.length - n;
+                    lstack.length = lstack.length - n;
+                }
+
+                function lex() {
+                    var token;
+                    token = self.lexer.lex() || 1;
+                    if (typeof token !== "number") {
+                        token = self.symbols_[token] || token;
+                    }
+                    return token;
+                }
+                var symbol, preErrorSymbol, state, action, a, r, yyval = {},
+                    p, len, newState, expected;
+                while (true) {
+                    state = stack[stack.length - 1];
+                    if (this.defaultActions[state]) {
+                        action = this.defaultActions[state];
+                    } else {
+                        if (symbol === null || typeof symbol == "undefined") {
+                            symbol = lex();
+                        }
+                        action = table[state] && table[state][symbol];
+                    }
+                    if (typeof action === "undefined" || !action.length || !action[0]) {
+                        var errStr = "";
+                        if (!recovering) {
+                            expected = [];
+                            for (p in table[state])
+                                if (this.terminals_[p] && p > 2) {
+                                    expected.push("'" + this.terminals_[p] + "'");
+                                }
+                            if (this.lexer.showPosition) {
+                                errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
+                            } else {
+                                errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
+                            }
+                            this.parseError(errStr, {
+                                text: this.lexer.match,
+                                token: this.terminals_[symbol] || symbol,
+                                line: this.lexer.yylineno,
+                                loc: yyloc,
+                                expected: expected
+                            });
+                        }
+                    }
+                    if (action[0] instanceof Array && action.length > 1) {
+                        throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
+                    }
+                    switch (action[0]) {
+                        case 1:
+                            stack.push(symbol);
+                            vstack.push(this.lexer.yytext);
+                            lstack.push(this.lexer.yylloc);
+                            stack.push(action[1]);
+                            symbol = null;
+                            if (!preErrorSymbol) {
+                                yyleng = this.lexer.yyleng;
+                                yytext = this.lexer.yytext;
+                                yylineno = this.lexer.yylineno;
+                                yyloc = this.lexer.yylloc;
+                                if (recovering > 0)
+                                    recovering--;
+                            } else {
+                                symbol = preErrorSymbol;
+                                preErrorSymbol = null;
+                            }
+                            break;
+                        case 2:
+                            len = this.productions_[action[1]][1];
+                            yyval.$ = vstack[vstack.length - len];
+                            yyval._$ = {
+                                first_line: lstack[lstack.length - (len || 1)].first_line,
+                                last_line: lstack[lstack.length - 1].last_line,
+                                first_column: lstack[lstack.length - (len || 1)].first_column,
+                                last_column: lstack[lstack.length - 1].last_column
+                            };
+                            if (ranges) {
+                                yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
+                            }
+                            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+                            if (typeof r !== "undefined") {
+                                return r;
+                            }
+                            if (len) {
+                                stack = stack.slice(0, -1 * len * 2);
+                                vstack = vstack.slice(0, -1 * len);
+                                lstack = lstack.slice(0, -1 * len);
+                            }
+                            stack.push(this.productions_[action[1]][0]);
+                            vstack.push(yyval.$);
+                            lstack.push(yyval._$);
+                            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+                            stack.push(newState);
+                            break;
+                        case 3:
+                            return true;
+                    }
+                }
+                return true;
+            }
+        };
+        /* Jison generated lexer */
+        var lexer = (function() {
+            var lexer = ({
+                EOF: 1,
+                parseError: function parseError(str, hash) {
+                    if (this.yy.parser) {
+                        this.yy.parser.parseError(str, hash);
+                    } else {
+                        throw new Error(str);
+                    }
+                },
+                setInput: function(input) {
+                    this._input = input;
+                    this._more = this._less = this.done = false;
+                    this.yylineno = this.yyleng = 0;
+                    this.yytext = this.matched = this.match = '';
+                    this.conditionStack = ['INITIAL'];
+                    this.yylloc = {
+                        first_line: 1,
+                        first_column: 0,
+                        last_line: 1,
+                        last_column: 0
+                    };
+                    if (this.options.ranges) this.yylloc.range = [0, 0];
+                    this.offset = 0;
+                    return this;
+                },
+                input: function() {
+                    var ch = this._input[0];
+                    this.yytext += ch;
+                    this.yyleng++;
+                    this.offset++;
+                    this.match += ch;
+                    this.matched += ch;
+                    var lines = ch.match(/(?:\r\n?|\n).*/g);
+                    if (lines) {
+                        this.yylineno++;
+                        this.yylloc.last_line++;
+                    } else {
+                        this.yylloc.last_column++;
+                    }
+                    if (this.options.ranges) this.yylloc.range[1]++;
+
+                    this._input = this._input.slice(1);
+                    return ch;
+                },
+                unput: function(ch) {
+                    var len = ch.length;
+                    var lines = ch.split(/(?:\r\n?|\n)/g);
+
+                    this._input = ch + this._input;
+                    this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
+                    //this.yyleng -= len;
+                    this.offset -= len;
+                    var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+                    this.match = this.match.substr(0, this.match.length - 1);
+                    this.matched = this.matched.substr(0, this.matched.length - 1);
+
+                    if (lines.length - 1) this.yylineno -= lines.length - 1;
+                    var r = this.yylloc.range;
+
+                    this.yylloc = {
+                        first_line: this.yylloc.first_line,
+                        last_line: this.yylineno + 1,
+                        first_column: this.yylloc.first_column,
+                        last_column: lines ?
+                            (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
+                    };
+
+                    if (this.options.ranges) {
+                        this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+                    }
+                    return this;
+                },
+                more: function() {
+                    this._more = true;
+                    return this;
+                },
+                less: function(n) {
+                    this.unput(this.match.slice(n));
+                },
+                pastInput: function() {
+                    var past = this.matched.substr(0, this.matched.length - this.match.length);
+                    return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
+                },
+                upcomingInput: function() {
+                    var next = this.match;
+                    if (next.length < 20) {
+                        next += this._input.substr(0, 20 - next.length);
+                    }
+                    return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
+                },
+                showPosition: function() {
+                    var pre = this.pastInput();
+                    var c = new Array(pre.length + 1).join("-");
+                    return pre + this.upcomingInput() + "\n" + c + "^";
+                },
+                next: function() {
+                    if (this.done) {
+                        return this.EOF;
+                    }
+                    if (!this._input) this.done = true;
+
+                    var token,
+                        match,
+                        tempMatch,
+                        index,
+                        col,
+                        lines;
+                    if (!this._more) {
+                        this.yytext = '';
+                        this.match = '';
+                    }
+                    var rules = this._currentRules();
+                    for (var i = 0; i < rules.length; i++) {
+                        tempMatch = this._input.match(this.rules[rules[i]]);
+                        if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+                            match = tempMatch;
+                            index = i;
+                            if (!this.options.flex) break;
+                        }
+                    }
+                    if (match) {
+                        lines = match[0].match(/(?:\r\n?|\n).*/g);
+                        if (lines) this.yylineno += lines.length;
+                        this.yylloc = {
+                            first_line: this.yylloc.last_line,
+                            last_line: this.yylineno + 1,
+                            first_column: this.yylloc.last_column,
+                            last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
+                        };
+                        this.yytext += match[0];
+                        this.match += match[0];
+                        this.matches = match;
+                        this.yyleng = this.yytext.length;
+                        if (this.options.ranges) {
+                            this.yylloc.range = [this.offset, this.offset += this.yyleng];
+                        }
+                        this._more = false;
+                        this._input = this._input.slice(match[0].length);
+                        this.matched += match[0];
+                        token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
+                        if (this.done && this._input) this.done = false;
+                        if (token) return token;
+                        else return;
+                    }
+                    if (this._input === "") {
+                        return this.EOF;
+                    } else {
+                        return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
+                            text: "",
+                            token: null,
+                            line: this.yylineno
+                        });
+                    }
+                },
+                lex: function lex() {
+                    var r = this.next();
+                    if (typeof r !== 'undefined') {
+                        return r;
+                    } else {
+                        return this.lex();
+                    }
+                },
+                begin: function begin(condition) {
+                    this.conditionStack.push(condition);
+                },
+                popState: function popState() {
+                    return this.conditionStack.pop();
+                },
+                _currentRules: function _currentRules() {
+                    return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
+                },
+                topState: function() {
+                    return this.conditionStack[this.conditionStack.length - 2];
+                },
+                pushState: function begin(condition) {
+                    this.begin(condition);
+                }
+            });
+            lexer.options = {};
+            lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
+
+                var YYSTATE = YY_START
+                switch ($avoiding_name_collisions) {
+                    case 0:
+                        if (yy_.yytext.slice(-1) !== "\\") this.begin("mu");
+                        if (yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1), this.begin("emu");
+                        if (yy_.yytext) return 14;
+
+                        break;
+                    case 1:
+                        return 14;
+                        break;
+                    case 2:
+                        if (yy_.yytext.slice(-1) !== "\\") this.popState();
+                        if (yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1);
+                        return 14;
+
+                        break;
+                    case 3:
+                        yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 4);
+                        this.popState();
+                        return 15;
+                        break;
+                    case 4:
+                        this.begin("par");
+                        return 24;
+                        break;
+                    case 5:
+                        return 16;
+                        break;
+                    case 6:
+                        return 20;
+                        break;
+                    case 7:
+                        return 19;
+                        break;
+                    case 8:
+                        return 19;
+                        break;
+                    case 9:
+                        return 23;
+                        break;
+                    case 10:
+                        return 23;
+                        break;
+                    case 11:
+                        this.popState();
+                        this.begin('com');
+                        break;
+                    case 12:
+                        yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);
+                        this.popState();
+                        return 15;
+                        break;
+                    case 13:
+                        return 22;
+                        break;
+                    case 14:
+                        return 36;
+                        break;
+                    case 15:
+                        return 35;
+                        break;
+                    case 16:
+                        return 35;
+                        break;
+                    case 17:
+                        return 39;
+                        break;
+                    case 18:
+                        /*ignore whitespace*/
+                        break;
+                    case 19:
+                        this.popState();
+                        return 18;
+                        break;
+                    case 20:
+                        this.popState();
+                        return 18;
+                        break;
+                    case 21:
+                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(/\\"/g, '"');
+                        return 30;
+                        break;
+                    case 22:
+                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(/\\'/g, "'");
+                        return 30;
+                        break;
+                    case 23:
+                        yy_.yytext = yy_.yytext.substr(1);
+                        return 28;
+                        break;
+                    case 24:
+                        return 32;
+                        break;
+                    case 25:
+                        return 32;
+                        break;
+                    case 26:
+                        return 31;
+                        break;
+                    case 27:
+                        return 35;
+                        break;
+                    case 28:
+                        yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
+                        return 35;
+                        break;
+                    case 29:
+                        return 'INVALID';
+                        break;
+                    case 30:
+                        /*ignore whitespace*/
+                        break;
+                    case 31:
+                        this.popState();
+                        return 37;
+                        break;
+                    case 32:
+                        return 5;
+                        break;
+                }
+            };
+            lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|$)))/, /^(?:[\s\S]*?--\}\})/, /^(?:\{\{>)/, /^(?:\{\{#)/, /^(?:\{\{\/)/, /^(?:\{\{\^)/, /^(?:\{\{\s*else\b)/, /^(?:\{\{\{)/, /^(?:\{\{&)/, /^(?:\{\{!--)/, /^(?:\{\{![\s\S]*?\}\})/, /^(?:\{\{)/, /^(?:=)/, /^(?:\.(?=[} ]))/, /^(?:\.\.)/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}\}\})/, /^(?:\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@[a-zA-Z]+)/, /^(?:true(?=[}\s]))/, /^(?:false(?=[}\s]))/, /^(?:-?[0-9]+(?=[}\s]))/, /^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/, /^(?:\[[^\]]*\])/, /^(?:.)/, /^(?:\s+)/, /^(?:[a-zA-Z0-9_$-/]+)/, /^(?:$)/];
+            lexer.conditions = {
+                "mu": {
+                    "rules": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32],
+                    "inclusive": false
+                },
+                "emu": {
+                    "rules": [2],
+                    "inclusive": false
+                },
+                "com": {
+                    "rules": [3],
+                    "inclusive": false
+                },
+                "par": {
+                    "rules": [30, 31],
+                    "inclusive": false
+                },
+                "INITIAL": {
+                    "rules": [0, 1, 32],
+                    "inclusive": true
+                }
+            };
+            return lexer;
+        })()
+        parser.lexer = lexer;
+
+        function Parser() {
+            this.yy = {};
+        }
+        Parser.prototype = parser;
+        parser.Parser = Parser;
+        return new Parser;
+    })();;
+    // lib/handlebars/compiler/base.js
+
+    Handlebars.Parser = handlebars;
+
+    Handlebars.parse = function(input) {
+
+        // Just return if an already-compile AST was passed in.
+        if (input.constructor === Handlebars.AST.ProgramNode) {
+            return input;
+        }
+
+        Handlebars.Parser.yy = Handlebars.AST;
+        return Handlebars.Parser.parse(input);
+    };;
+    // lib/handlebars/compiler/ast.js
+    (function() {
+        Handlebars.AST = {};
+
+        Handlebars.AST.ProgramNode = function(statements, inverse) {
+            this.type = "program";
+            this.statements = statements;
+            if (inverse) {
+                this.inverse = new Handlebars.AST.ProgramNode(inverse);
+            }
+        };
+
+        Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
+            this.type = "mustache";
+            this.escaped = !unescaped;
+            this.hash = hash;
+
+            var id = this.id = rawParams[0];
+            var params = this.params = rawParams.slice(1);
+
+            // a mustache is an eligible helper if:
+            // * its id is simple (a single part, not `this` or `..`)
+            var eligibleHelper = this.eligibleHelper = id.isSimple;
+
+            // a mustache is definitely a helper if:
+            // * it is an eligible helper, and
+            // * it has at least one parameter or hash segment
+            this.isHelper = eligibleHelper && (params.length || hash);
+
+            // if a mustache is an eligible helper but not a definite
+            // helper, it is ambiguous, and will be resolved in a later
+            // pass or at runtime.
+        };
+
+        Handlebars.AST.PartialNode = function(partialName, context) {
+            this.type = "partial";
+            this.partialName = partialName;
+            this.context = context;
+        };
+
+        Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
+            var verifyMatch = function(open, close) {
+                if (open.original !== close.original) {
+                    throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
+                }
+            };
+
+            verifyMatch(mustache.id, close);
+            this.type = "block";
+            this.mustache = mustache;
+            this.program = program;
+            this.inverse = inverse;
+
+            if (this.inverse && !this.program) {
+                this.isInverse = true;
+            }
+        };
+
+        Handlebars.AST.ContentNode = function(string) {
+            this.type = "content";
+            this.string = string;
+        };
+
+        Handlebars.AST.HashNode = function(pairs) {
+            this.type = "hash";
+            this.pairs = pairs;
+        };
+
+        Handlebars.AST.IdNode = function(parts) {
+            this.type = "ID";
+            this.original = parts.join(".");
+
+            var dig = [],
+                depth = 0;
+
+            for (var i = 0, l = parts.length; i < l; i++) {
+                var part = parts[i];
+
+                if (part === ".." || part === "." || part === "this") {
+                    if (dig.length > 0) {
+                        throw new Handlebars.Exception("Invalid path: " + this.original);
+                    } else if (part === "..") {
+                        depth++;
+                    } else {
+                        this.isScoped = true;
+                    }
+                } else {
+                    dig.push(part);
+                }
+            }
+
+            this.parts = dig;
+            this.string = dig.join('.');
+            this.depth = depth;
+
+            // an ID is simple if it only has one part, and that part is not
+            // `..` or `this`.
+            this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
+
+            this.stringModeValue = this.string;
+        };
+
+        Handlebars.AST.PartialNameNode = function(name) {
+            this.type = "PARTIAL_NAME";
+            this.name = name;
+        };
+
+        Handlebars.AST.DataNode = function(id) {
+            this.type = "DATA";
+            this.id = id;
+        };
+
+        Handlebars.AST.StringNode = function(string) {
+            this.type = "STRING";
+            this.string = string;
+            this.stringModeValue = string;
+        };
+
+        Handlebars.AST.IntegerNode = function(integer) {
+            this.type = "INTEGER";
+            this.integer = integer;
+            this.stringModeValue = Number(integer);
+        };
+
+        Handlebars.AST.BooleanNode = function(bool) {
+            this.type = "BOOLEAN";
+            this.bool = bool;
+            this.stringModeValue = bool === "true";
+        };
+
+        Handlebars.AST.CommentNode = function(comment) {
+            this.type = "comment";
+            this.comment = comment;
+        };;
+    })();;
+    //>>excludeEnd('excludeHbsParser')
+    // lib/handlebars/utils.js
+
+    var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+
+    Handlebars.Exception = function(message) {
+        var tmp = Error.prototype.constructor.apply(this, arguments);
+
+        // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
+        for (var idx = 0; idx < errorProps.length; idx++) {
+            this[errorProps[idx]] = tmp[errorProps[idx]];
+        }
+    };
+    Handlebars.Exception.prototype = new Error();
+
+    // Build out our basic SafeString type
+    Handlebars.SafeString = function(string) {
+        this.string = string;
+    };
+    Handlebars.SafeString.prototype.toString = function() {
+        return this.string.toString();
+    };
+
+    (function() {
+        var escape = {
+            "&": "&amp;",
+            "<": "&lt;",
+            ">": "&gt;",
+            '"': "&quot;",
+            "'": "&#x27;",
+            "`": "&#x60;"
+        };
+
+        var badChars = /[&<>"'`]/g;
+        var possible = /[&<>"'`]/;
+
+        var escapeChar = function(chr) {
+            return escape[chr] || "&amp;";
+        };
+
+        Handlebars.Utils = {
+            escapeExpression: function(string) {
+                // don't escape SafeStrings, since they're already safe
+                if (string instanceof Handlebars.SafeString) {
+                    return string.toString();
+                } else if (string == null || string === false) {
+                    return "";
+                }
+
+                if (!possible.test(string)) {
+                    return string;
+                }
+                return string.replace(badChars, escapeChar);
+            },
+
+            isEmpty: function(value) {
+                if (!value && value !== 0) {
+                    return true;
+                } else if (Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        };;
+    })();
+    // lib/handlebars/compiler/compiler.js
+
+    /*jshint eqnull:true*/
+    Handlebars.Compiler = function() {};
+    Handlebars.JavaScriptCompiler = function() {};
+
+    (function(Compiler, JavaScriptCompiler) {
+        // the foundHelper register will disambiguate helper lookup from finding a
+        // function in a context. This is necessary for mustache compatibility, which
+        // requires that context functions in blocks are evaluated by blockHelperMissing,
+        // and then proceed as if the resulting value was provided to blockHelperMissing.
+
+        Compiler.prototype = {
+            compiler: Compiler,
+
+            disassemble: function() {
+                var opcodes = this.opcodes,
+                    opcode, out = [],
+                    params, param;
+
+                for (var i = 0, l = opcodes.length; i < l; i++) {
+                    opcode = opcodes[i];
+
+                    if (opcode.opcode === 'DECLARE') {
+                        out.push("DECLARE " + opcode.name + "=" + opcode.value);
+                    } else {
+                        params = [];
+                        for (var j = 0; j < opcode.args.length; j++) {
+                            param = opcode.args[j];
+                            if (typeof param === "string") {
+                                param = "\"" + param.replace("\n", "\\n") + "\"";
+                            }
+                            params.push(param);
+                        }
+                        out.push(opcode.opcode + " " + params.join(" "));
+                    }
+                }
+
+                return out.join("\n");
+            },
+            equals: function(other) {
+                var len = this.opcodes.length;
+                if (other.opcodes.length !== len) {
+                    return false;
+                }
+
+                for (var i = 0; i < len; i++) {
+                    var opcode = this.opcodes[i],
+                        otherOpcode = other.opcodes[i];
+                    if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
+                        return false;
+                    }
+                    for (var j = 0; j < opcode.args.length; j++) {
+                        if (opcode.args[j] !== otherOpcode.args[j]) {
+                            return false;
+                        }
+                    }
+                }
+
+                len = this.children.length;
+                if (other.children.length !== len) {
+                    return false;
+                }
+                for (i = 0; i < len; i++) {
+                    if (!this.children[i].equals(other.children[i])) {
+                        return false;
+                    }
+                }
+
+                return true;
+            },
+
+            guid: 0,
+
+            compile: function(program, options) {
+                this.children = [];
+                this.depths = {
+                    list: []
+                };
+                this.options = options;
+
+                // These changes will propagate to the other compiler components
+                var knownHelpers = this.options.knownHelpers;
+                this.options.knownHelpers = {
+                    'helperMissing': true,
+                    'blockHelperMissing': true,
+                    'each': true,
+                    'if': true,
+                    'unless': true,
+                    'with': true,
+                    'log': true
+                };
+                if (knownHelpers) {
+                    for (var name in knownHelpers) {
+                        this.options.knownHelpers[name] = knownHelpers[name];
+                    }
+                }
+
+                return this.program(program);
+            },
+
+            accept: function(node) {
+                return this[node.type](node);
+            },
+
+            program: function(program) {
+                var statements = program.statements,
+                    statement;
+                this.opcodes = [];
+
+                for (var i = 0, l = statements.length; i < l; i++) {
+                    statement = statements[i];
+                    this[statement.type](statement);
+                }
+                this.isSimple = l === 1;
+
+                this.depths.list = this.depths.list.sort(function(a, b) {
+                    return a - b;
+                });
+
+                return this;
+            },
+
+            compileProgram: function(program) {
+                var result = new this.compiler().compile(program, this.options);
+                var guid = this.guid++,
+                    depth;
+
+                this.usePartial = this.usePartial || result.usePartial;
+
+                this.children[guid] = result;
+
+                for (var i = 0, l = result.depths.list.length; i < l; i++) {
+                    depth = result.depths.list[i];
+
+                    if (depth < 2) {
+                        continue;
+                    } else {
+                        this.addDepth(depth - 1);
+                    }
+                }
+
+                return guid;
+            },
+
+            block: function(block) {
+                var mustache = block.mustache,
+                    program = block.program,
+                    inverse = block.inverse;
+
+                if (program) {
+                    program = this.compileProgram(program);
+                }
+
+                if (inverse) {
+                    inverse = this.compileProgram(inverse);
+                }
+
+                var type = this.classifyMustache(mustache);
+
+                if (type === "helper") {
+                    this.helperMustache(mustache, program, inverse);
+                } else if (type === "simple") {
+                    this.simpleMustache(mustache);
+
+                    // now that the simple mustache is resolved, we need to
+                    // evaluate it by executing `blockHelperMissing`
+                    this.opcode('pushProgram', program);
+                    this.opcode('pushProgram', inverse);
+                    this.opcode('emptyHash');
+                    this.opcode('blockValue');
+                } else {
+                    this.ambiguousMustache(mustache, program, inverse);
+
+                    // now that the simple mustache is resolved, we need to
+                    // evaluate it by executing `blockHelperMissing`
+                    this.opcode('pushProgram', program);
+                    this.opcode('pushProgram', inverse);
+                    this.opcode('emptyHash');
+                    this.opcode('ambiguousBlockValue');
+                }
+
+                this.opcode('append');
+            },
+
+            hash: function(hash) {
+                var pairs = hash.pairs,
+                    pair, val;
+
+                this.opcode('pushHash');
+
+                for (var i = 0, l = pairs.length; i < l; i++) {
+                    pair = pairs[i];
+                    val = pair[1];
+
+                    if (this.options.stringParams) {
+                        this.opcode('pushStringParam', val.stringModeValue, val.type);
+                    } else {
+                        this.accept(val);
+                    }
+
+                    this.opcode('assignToHash', pair[0]);
+                }
+                this.opcode('popHash');
+            },
+
+            partial: function(partial) {
+                var partialName = partial.partialName;
+                this.usePartial = true;
+
+                if (partial.context) {
+                    this.ID(partial.context);
+                } else {
+                    this.opcode('push', 'depth0');
+                }
+
+                this.opcode('invokePartial', partialName.name);
+                this.opcode('append');
+            },
+
+            content: function(content) {
+                this.opcode('appendContent', content.string);
+            },
+
+            mustache: function(mustache) {
+                var options = this.options;
+                var type = this.classifyMustache(mustache);
+
+                if (type === "simple") {
+                    this.simpleMustache(mustache);
+                } else if (type === "helper") {
+                    this.helperMustache(mustache);
+                } else {
+                    this.ambiguousMustache(mustache);
+                }
+
+                if (mustache.escaped && !options.noEscape) {
+                    this.opcode('appendEscaped');
+                } else {
+                    this.opcode('append');
+                }
+            },
+
+            ambiguousMustache: function(mustache, program, inverse) {
+                var id = mustache.id,
+                    name = id.parts[0],
+                    isBlock = program != null || inverse != null;
+
+                this.opcode('getContext', id.depth);
+
+                this.opcode('pushProgram', program);
+                this.opcode('pushProgram', inverse);
+
+                this.opcode('invokeAmbiguous', name, isBlock);
+            },
+
+            simpleMustache: function(mustache) {
+                var id = mustache.id;
+
+                if (id.type === 'DATA') {
+                    this.DATA(id);
+                } else if (id.parts.length) {
+                    this.ID(id);
+                } else {
+                    // Simplified ID for `this`
+                    this.addDepth(id.depth);
+                    this.opcode('getContext', id.depth);
+                    this.opcode('pushContext');
+                }
+
+                this.opcode('resolvePossibleLambda');
+            },
+
+            helperMustache: function(mustache, program, inverse) {
+                var params = this.setupFullMustacheParams(mustache, program, inverse),
+                    name = mustache.id.parts[0];
+
+                if (this.options.knownHelpers[name]) {
+                    this.opcode('invokeKnownHelper', params.length, name);
+                } else if (this.knownHelpersOnly) {
+                    throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
+                } else {
+                    this.opcode('invokeHelper', params.length, name);
+                }
+            },
+
+            ID: function(id) {
+                this.addDepth(id.depth);
+                this.opcode('getContext', id.depth);
+
+                var name = id.parts[0];
+                if (!name) {
+                    this.opcode('pushContext');
+                } else {
+                    this.opcode('lookupOnContext', id.parts[0]);
+                }
+
+                for (var i = 1, l = id.parts.length; i < l; i++) {
+                    this.opcode('lookup', id.parts[i]);
+                }
+            },
+
+            DATA: function(data) {
+                this.options.data = true;
+                this.opcode('lookupData', data.id);
+            },
+
+            STRING: function(string) {
+                this.opcode('pushString', string.string);
+            },
+
+            INTEGER: function(integer) {
+                this.opcode('pushLiteral', integer.integer);
+            },
+
+            BOOLEAN: function(bool) {
+                this.opcode('pushLiteral', bool.bool);
+            },
+
+            comment: function() {},
+
+            // HELPERS
+            opcode: function(name) {
+                this.opcodes.push({
+                    opcode: name,
+                    args: [].slice.call(arguments, 1)
+                });
+            },
+
+            declare: function(name, value) {
+                this.opcodes.push({
+                    opcode: 'DECLARE',
+                    name: name,
+                    value: value
+                });
+            },
+
+            addDepth: function(depth) {
+                if (isNaN(depth)) {
+                    throw new Error("EWOT");
+                }
+                if (depth === 0) {
+                    return;
+                }
+
+                if (!this.depths[depth]) {
+                    this.depths[depth] = true;
+                    this.depths.list.push(depth);
+                }
+            },
+
+            classifyMustache: function(mustache) {
+                var isHelper = mustache.isHelper;
+                var isEligible = mustache.eligibleHelper;
+                var options = this.options;
+
+                // if ambiguous, we can possibly resolve the ambiguity now
+                if (isEligible && !isHelper) {
+                    var name = mustache.id.parts[0];
+
+                    if (options.knownHelpers[name]) {
+                        isHelper = true;
+                    } else if (options.knownHelpersOnly) {
+                        isEligible = false;
+                    }
+                }
+
+                if (isHelper) {
+                    return "helper";
+                } else if (isEligible) {
+                    return "ambiguous";
+                } else {
+                    return "simple";
+                }
+            },
+
+            pushParams: function(params) {
+                var i = params.length,
+                    param;
+
+                while (i--) {
+                    param = params[i];
+
+                    if (this.options.stringParams) {
+                        if (param.depth) {
+                            this.addDepth(param.depth);
+                        }
+
+                        this.opcode('getContext', param.depth || 0);
+                        this.opcode('pushStringParam', param.stringModeValue, param.type);
+                    } else {
+                        this[param.type](param);
+                    }
+                }
+            },
+
+            setupMustacheParams: function(mustache) {
+                var params = mustache.params;
+                this.pushParams(params);
+
+                if (mustache.hash) {
+                    this.hash(mustache.hash);
+                } else {
+                    this.opcode('emptyHash');
+                }
+
+                return params;
+            },
+
+            // this will replace setupMustacheParams when we're done
+            setupFullMustacheParams: function(mustache, program, inverse) {
+                var params = mustache.params;
+                this.pushParams(params);
+
+                this.opcode('pushProgram', program);
+                this.opcode('pushProgram', inverse);
+
+                if (mustache.hash) {
+                    this.hash(mustache.hash);
+                } else {
+                    this.opcode('emptyHash');
+                }
+
+                return params;
+            }
+        };
+
+        var Literal = function(value) {
+            this.value = value;
+        };
+
+        JavaScriptCompiler.prototype = {
+            // PUBLIC API: You can override these methods in a subclass to provide
+            // alternative compiled forms for name lookup and buffering semantics
+            nameLookup: function(parent, name /* , type*/ ) {
+                if (/^[0-9]+$/.test(name)) {
+                    return parent + "[" + name + "]";
+                } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
+                    return parent + "." + name;
+                } else {
+                    return parent + "['" + name + "']";
+                }
+            },
+
+            appendToBuffer: function(string) {
+                if (this.environment.isSimple) {
+                    return "return " + string + ";";
+                } else {
+                    return {
+                        appendToBuffer: true,
+                        content: string,
+                        toString: function() {
+                            return "buffer += " + string + ";";
+                        }
+                    };
+                }
+            },
+
+            initializeBuffer: function() {
+                return this.quotedString("");
+            },
+
+            namespace: "Handlebars",
+            // END PUBLIC API
+
+            compile: function(environment, options, context, asObject) {
+                this.environment = environment;
+                this.options = options || {};
+
+                Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
+
+                this.name = this.environment.name;
+                this.isChild = !!context;
+                this.context = context || {
+                    programs: [],
+                    environments: [],
+                    aliases: {}
+                };
+
+                this.preamble();
+
+                this.stackSlot = 0;
+                this.stackVars = [];
+                this.registers = {
+                    list: []
+                };
+                this.compileStack = [];
+                this.inlineStack = [];
+
+                this.compileChildren(environment, options);
+
+                var opcodes = environment.opcodes,
+                    opcode;
+
+                this.i = 0;
+
+                for (l = opcodes.length; this.i < l; this.i++) {
+                    opcode = opcodes[this.i];
+
+                    if (opcode.opcode === 'DECLARE') {
+                        this[opcode.name] = opcode.value;
+                    } else {
+                        this[opcode.opcode].apply(this, opcode.args);
+                    }
+                }
+
+                return this.createFunctionContext(asObject);
+            },
+
+            nextOpcode: function() {
+                var opcodes = this.environment.opcodes;
+                return opcodes[this.i + 1];
+            },
+
+            eat: function() {
+                this.i = this.i + 1;
+            },
+
+            preamble: function() {
+                var out = [];
+
+                if (!this.isChild) {
+                    var namespace = this.namespace;
+                    var copies = "helpers = helpers || " + namespace + ".helpers;";
+                    if (this.environment.usePartial) {
+                        copies = copies + " partials = partials || " + namespace + ".partials;";
+                    }
+                    if (this.options.data) {
+                        copies = copies + " data = data || {};";
+                    }
+                    out.push(copies);
+                } else {
+                    out.push('');
+                }
+
+                if (!this.environment.isSimple) {
+                    out.push(", buffer = " + this.initializeBuffer());
+                } else {
+                    out.push("");
+                }
+
+                // track the last context pushed into place to allow skipping the
+                // getContext opcode when it would be a noop
+                this.lastContext = 0;
+                this.source = out;
+            },
+
+            createFunctionContext: function(asObject) {
+                var locals = this.stackVars.concat(this.registers.list);
+
+                if (locals.length > 0) {
+                    this.source[1] = this.source[1] + ", " + locals.join(", ");
+                }
+
+                // Generate minimizer alias mappings
+                if (!this.isChild) {
+                    for (var alias in this.context.aliases) {
+                        this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
+                    }
+                }
+
+                if (this.source[1]) {
+                    this.source[1] = "var " + this.source[1].substring(2) + ";";
+                }
+
+                // Merge children
+                if (!this.isChild) {
+                    this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
+                }
+
+                if (!this.environment.isSimple) {
+                    this.source.push("return buffer;");
+                }
+
+                var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
+
+                for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {
+                    params.push("depth" + this.environment.depths.list[i]);
+                }
+
+                // Perform a second pass over the output to merge content when possible
+                var source = this.mergeSource();
+
+                if (!this.isChild) {
+                    var revision = Handlebars.COMPILER_REVISION,
+                        versions = Handlebars.REVISION_CHANGES[revision];
+                    source = "this.compilerInfo = [" + revision + ",'" + versions + "'];\n" + source;
+                }
+
+                if (asObject) {
+                    params.push(source);
+
+                    return Function.apply(this, params);
+                } else {
+                    var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + source + '}';
+                    Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
+                    return functionSource;
+                }
+            },
+            mergeSource: function() {
+                // WARN: We are not handling the case where buffer is still populated as the source should
+                // not have buffer append operations as their final action.
+                var source = '',
+                    buffer;
+                for (var i = 0, len = this.source.length; i < len; i++) {
+                    var line = this.source[i];
+                    if (line.appendToBuffer) {
+                        if (buffer) {
+                            buffer = buffer + '\n    + ' + line.content;
+                        } else {
+                            buffer = line.content;
+                        }
+                    } else {
+                        if (buffer) {
+                            source += 'buffer += ' + buffer + ';\n  ';
+                            buffer = undefined;
+                        }
+                        source += line + '\n  ';
+                    }
+                }
+                return source;
+            },
+
+            // [blockValue]
+            //
+            // On stack, before: hash, inverse, program, value
+            // On stack, after: return value of blockHelperMissing
+            //
+            // The purpose of this opcode is to take a block of the form
+            // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
+            // replace it on the stack with the result of properly
+            // invoking blockHelperMissing.
+            blockValue: function() {
+                this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+
+                var params = ["depth0"];
+                this.setupParams(0, params);
+
+                this.replaceStack(function(current) {
+                    params.splice(1, 0, current);
+                    return "blockHelperMissing.call(" + params.join(", ") + ")";
+                });
+            },
+
+            // [ambiguousBlockValue]
+            //
+            // On stack, before: hash, inverse, program, value
+            // Compiler value, before: lastHelper=value of last found helper, if any
+            // On stack, after, if no lastHelper: same as [blockValue]
+            // On stack, after, if lastHelper: value
+            ambiguousBlockValue: function() {
+                this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+
+                var params = ["depth0"];
+                this.setupParams(0, params);
+
+                var current = this.topStack();
+                params.splice(1, 0, current);
+
+                // Use the options value generated from the invocation
+                params[params.length - 1] = 'options';
+
+                this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
+            },
+
+            // [appendContent]
+            //
+            // On stack, before: ...
+            // On stack, after: ...
+            //
+            // Appends the string value of `content` to the current buffer
+            appendContent: function(content) {
+                this.source.push(this.appendToBuffer(this.quotedString(content)));
+            },
+
+            // [append]
+            //
+            // On stack, before: value, ...
+            // On stack, after: ...
+            //
+            // Coerces `value` to a String and appends it to the current buffer.
+            //
+            // If `value` is truthy, or 0, it is coerced into a string and appended
+            // Otherwise, the empty string is appended
+            append: function() {
+                // Force anything that is inlined onto the stack so we don't have duplication
+                // when we examine local
+                this.flushInline();
+                var local = this.popStack();
+                this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
+                if (this.environment.isSimple) {
+                    this.source.push("else { " + this.appendToBuffer("''") + " }");
+                }
+            },
+
+            // [appendEscaped]
+            //
+            // On stack, before: value, ...
+            // On stack, after: ...
+            //
+            // Escape `value` and append it to the buffer
+            appendEscaped: function() {
+                this.context.aliases.escapeExpression = 'this.escapeExpression';
+
+                this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
+            },
+
+            // [getContext]
+            //
+            // On stack, before: ...
+            // On stack, after: ...
+            // Compiler value, after: lastContext=depth
+            //
+            // Set the value of the `lastContext` compiler value to the depth
+            getContext: function(depth) {
+                if (this.lastContext !== depth) {
+                    this.lastContext = depth;
+                }
+            },
+
+            // [lookupOnContext]
+            //
+            // On stack, before: ...
+            // On stack, after: currentContext[name], ...
+            //
+            // Looks up the value of `name` on the current context and pushes
+            // it onto the stack.
+            lookupOnContext: function(name) {
+                this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
+            },
+
+            // [pushContext]
+            //
+            // On stack, before: ...
+            // On stack, after: currentContext, ...
+            //
+            // Pushes the value of the current context onto the stack.
+            pushContext: function() {
+                this.pushStackLiteral('depth' + this.lastContext);
+            },
+
+            // [resolvePossibleLambda]
+            //
+            // On stack, before: value, ...
+            // On stack, after: resolved value, ...
+            //
+            // If the `value` is a lambda, replace it on the stack by
+            // the return value of the lambda
+            resolvePossibleLambda: function() {
+                this.context.aliases.functionType = '"function"';
+
+                this.replaceStack(function(current) {
+                    return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
+                });
+            },
+
+            // [lookup]
+            //
+            // On stack, before: value, ...
+            // On stack, after: value[name], ...
+            //
+            // Replace the value on the stack with the result of looking
+            // up `name` on `value`
+            lookup: function(name) {
+                this.replaceStack(function(current) {
+                    return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
+                });
+            },
+
+            // [lookupData]
+            //
+            // On stack, before: ...
+            // On stack, after: data[id], ...
+            //
+            // Push the result of looking up `id` on the current data
+            lookupData: function(id) {
+                this.push(this.nameLookup('data', id, 'data'));
+            },
+
+            // [pushStringParam]
+            //
+            // On stack, before: ...
+            // On stack, after: string, currentContext, ...
+            //
+            // This opcode is designed for use in string mode, which
+            // provides the string value of a parameter along with its
+            // depth rather than resolving it immediately.
+            pushStringParam: function(string, type) {
+                this.pushStackLiteral('depth' + this.lastContext);
+
+                this.pushString(type);
+
+                if (typeof string === 'string') {
+                    this.pushString(string);
+                } else {
+                    this.pushStackLiteral(string);
+                }
+            },
+
+            emptyHash: function() {
+                this.pushStackLiteral('{}');
+


<TRUNCATED>


[4/8] incubator-atlas git commit: ATLAS-1142 Lineage UI Improvement (kevalbhatt via shwethags)

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/hbs.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/hbs.js b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/hbs.js
new file mode 100644
index 0000000..4aa054c
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/hbs.js
@@ -0,0 +1,490 @@
+/**
+ * @license Handlebars hbs 0.4.0 - Alex Sexton, but Handlebars has it's own licensing junk
+ *
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/require-cs for details on the plugin this was based off of
+ */
+
+/* Yes, deliciously evil. */
+/*jslint evil: true, strict: false, plusplus: false, regexp: false */
+/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
+define: false, process: false, window: false */
+define([
+    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
+    'handlebars', 'underscore', 'i18nprecompile', 'json2'
+    //>>excludeEnd('excludeHbs')
+], function(
+    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
+    Handlebars, _, precompile, JSON
+    //>>excludeEnd('excludeHbs')
+) {
+    //>>excludeStart('excludeHbs', pragmas.excludeHbs)
+    var fs, getXhr,
+        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
+        fetchText = function() {
+            throw new Error('Environment unsupported.');
+        },
+        buildMap = [],
+        filecode = "w+",
+        templateExtension = "hbs",
+        customNameExtension = "@hbs",
+        devStyleDirectory = "/styles/",
+        buildStyleDirectory = "/demo-build/styles/",
+        helperDirectory = "template/helpers/",
+        i18nDirectory = "template/i18n/",
+        buildCSSFileName = "screen.build.css";
+
+    Handlebars.registerHelper('$', function() {
+        //placeholder for translation helper
+    });
+
+    if (typeof window !== "undefined" && window.navigator && window.document && !window.navigator.userAgent.match(/Node.js/)) {
+        // Browser action
+        getXhr = function() {
+            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
+            var xhr, i, progId;
+            if (typeof XMLHttpRequest !== "undefined") {
+                return new XMLHttpRequest();
+            } else {
+                for (i = 0; i < 3; i++) {
+                    progId = progIds[i];
+                    try {
+                        xhr = new ActiveXObject(progId);
+                    } catch (e) {}
+
+                    if (xhr) {
+                        progIds = [progId]; // so faster next time
+                        break;
+                    }
+                }
+            }
+
+            if (!xhr) {
+                throw new Error("getXhr(): XMLHttpRequest not available");
+            }
+
+            return xhr;
+        };
+
+        fetchText = function(url, callback) {
+            var prependComment = "<!--START: " + url + "--> == <!--END: " + url + "-->";
+            var xhr = getXhr();
+            xhr.open('GET', url, true);
+            xhr.onreadystatechange = function(evt) {
+                //Do not explicitly handle errors, those should be
+                //visible via console output in the browser.
+                if (xhr.readyState === 4) {
+                    callback(xhr.responseText);
+                    //TODO FIXME Gautam:Not working with backbone-forms when it does this : $($.trim(this.template(_.result(this, 'templateData'))));
+                    // callback(prependComment.replace('==',xhr.responseText));
+                }
+            };
+            xhr.send(null);
+        };
+
+    } else if (typeof process !== "undefined" &&
+        process.versions &&
+        !!process.versions.node) {
+        //Using special require.nodeRequire, something added by r.js.
+        fs = require.nodeRequire('fs');
+        fetchText = function(path, callback) {
+            var body = fs.readFileSync(path, 'utf8') || "";
+            // we need to remove BOM stuff from the file content
+            body = body.replace(/^\uFEFF/, '');
+            callback(body);
+        };
+    } else if (typeof java !== "undefined" && typeof java.io !== "undefined") {
+        fetchText = function(path, callback) {
+            var f = new java.io.File(path);
+            var is = new java.io.FileReader(f);
+            var reader = new java.io.BufferedReader(is);
+            var line;
+            var text = "";
+            while ((line = reader.readLine()) !== null) {
+                text += new String(line) + "\n";
+            }
+            reader.close();
+            callback(text);
+        };
+    }
+
+    var cache = {};
+    var fetchOrGetCached = function(path, callback) {
+        if (cache[path]) {
+            callback(cache[path]);
+        } else {
+            fetchText(path, function(data) {
+                cache[path] = data;
+                callback.call(this, data);
+            });
+        }
+    };
+    var styleList = [],
+        styleMap = {};
+    //>>excludeEnd('excludeHbs')
+
+    return {
+
+        get: function() {
+            return Handlebars;
+        },
+
+        write: function(pluginName, name, write) {
+
+            if ((name + customNameExtension) in buildMap) {
+                var text = buildMap[name + customNameExtension];
+                write.asModule(pluginName + "!" + name, text);
+            }
+        },
+
+        version: '0.4.0',
+
+        load: function(name, parentRequire, load, config) {
+            //>>excludeStart('excludeHbs', pragmas.excludeHbs)
+
+            var compiledName = name + customNameExtension,
+                disableI18n = (config.hbs && config.hbs.disableI18n),
+                partialDeps = [];
+
+            function recursiveNodeSearch(statements, res) {
+                _(statements).forEach(function(statement) {
+                    if (statement && statement.type && statement.type === 'partial') {
+                        res.push(statement.partialName.name);
+                    }
+                    if (statement && statement.program && statement.program.statements) {
+                        recursiveNodeSearch(statement.program.statements, res);
+                    }
+                    if (statement && statement.program && statement.program.inverse && statement.program.inverse.statements) {
+                        recursiveNodeSearch(statement.program.inverse.statements, res);
+                    }
+                });
+                return res;
+            }
+
+            // TODO :: use the parser to do this!
+            function findPartialDeps(nodes) {
+                var res = [];
+                if (nodes && nodes.statements) {
+                    res = recursiveNodeSearch(nodes.statements, []);
+                }
+                return _(res).unique();
+            }
+
+            // See if the first item is a comment that's json
+            function getMetaData(nodes) {
+                var statement, res, test;
+                if (nodes && nodes.statements) {
+                    statement = nodes.statements[0];
+                    if (statement && statement.type === "comment") {
+                        try {
+                            res = (statement.comment).replace(new RegExp('^[\\s]+|[\\s]+$', 'g'), '');
+                            test = JSON.parse(res);
+                            return res;
+                        } catch (e) {
+                            return "{}";
+                        }
+                    }
+                }
+                return "{}";
+            }
+
+            function composeParts(parts) {
+                if (!parts) {
+                    return [];
+                }
+                var res = [parts[0]],
+                    cur = parts[0],
+                    i;
+
+                for (i = 1; i < parts.length; ++i) {
+                    if (parts.hasOwnProperty(i)) {
+                        cur += "." + parts[i];
+                        res.push(cur);
+                    }
+                }
+                return res;
+            }
+
+            function recursiveVarSearch(statements, res, prefix, helpersres) {
+                prefix = prefix ? prefix + "." : "";
+
+                var newprefix = "",
+                    flag = false;
+
+                // loop through each statement
+                _(statements).forEach(function(statement) {
+                    var parts, part, sideways;
+
+                    // if it's a mustache block
+                    if (statement && statement.type && statement.type === 'mustache') {
+
+                        // If it has params, the first part is a helper or something
+                        if (!statement.params || !statement.params.length) {
+                            parts = composeParts(statement.id.parts);
+                            for (part in parts) {
+                                if (parts[part]) {
+                                    newprefix = parts[part] || newprefix;
+                                    res.push(prefix + parts[part]);
+                                }
+                            }
+                            res.push(prefix + statement.id.string);
+                        }
+
+                        var paramsWithoutParts = ['this', '.', '..', './..', '../..', '../../..'];
+
+                        // grab the params
+                        if (statement.params && typeof Handlebars.helpers[statement.id.string] === 'undefined') {
+                            _(statement.params).forEach(function(param) {
+                                if (_(paramsWithoutParts).contains(param.original) || param instanceof Handlebars.AST.StringNode || param instanceof Handlebars.AST.IntegerNode || param instanceof Handlebars.AST.BooleanNode) {
+                                    helpersres.push(statement.id.string);
+                                }
+
+                                parts = composeParts(param.parts);
+
+                                for (var part in parts) {
+                                    if (parts[part]) {
+                                        newprefix = parts[part] || newprefix;
+                                        helpersres.push(statement.id.string);
+                                        res.push(prefix + parts[part]);
+                                    }
+                                }
+                            });
+                        }
+                    }
+
+                    // If it's a meta block
+                    if (statement && statement.mustache) {
+                        recursiveVarSearch([statement.mustache], res, prefix + newprefix, helpersres);
+                    }
+
+                    // if it's a whole new program
+                    if (statement && statement.program && statement.program.statements) {
+                        sideways = recursiveVarSearch([statement.mustache], [], "", helpersres)[0] || "";
+                        if (statement.program.inverse && statement.program.inverse.statements) {
+                            recursiveVarSearch(statement.program.inverse.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres);
+                        }
+                        recursiveVarSearch(statement.program.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres);
+                    }
+                });
+                return res;
+            }
+
+            // This finds the Helper dependencies since it's soooo similar
+            function getExternalDeps(nodes) {
+                var res = [];
+                var helpersres = [];
+
+                if (nodes && nodes.statements) {
+                    res = recursiveVarSearch(nodes.statements, [], undefined, helpersres);
+                }
+
+                var defaultHelpers = ["helperMissing", "blockHelperMissing", "each", "if", "unless", "with"];
+
+                return {
+                    vars: _(res).chain().unique().map(function(e) {
+                        if (e === "") {
+                            return '.';
+                        }
+                        if (e.length && e[e.length - 1] === '.') {
+                            return e.substr(0, e.length - 1) + '[]';
+                        }
+                        return e;
+                    }).value(),
+                    helpers: _(helpersres).chain().unique().map(function(e) {
+                        if (_(defaultHelpers).contains(e)) {
+                            return undefined;
+                        }
+                        return e;
+                    }).compact().value()
+                };
+            }
+
+            function fetchAndRegister(langMap) {
+                fetchText(path, function(text) {
+                    // for some reason it doesn't include hbs _first_ when i don't add it here...
+                    var nodes = Handlebars.parse(text),
+                        deps = findPartialDeps(nodes),
+                        meta = getMetaData(nodes),
+                        extDeps = getExternalDeps(nodes),
+                        vars = extDeps.vars,
+                        helps = extDeps.helpers || [],
+                        depStr = deps.join("', 'hbs!").replace(/_/g, '/'),
+                        helpDepStr = config.hbs && config.hbs.disableHelpers ?
+                        "" : (function() {
+                            var i, paths = [],
+                                pathGetter = config.hbs && config.hbs.helperPathCallback ? config.hbs.helperPathCallback : function(name) {
+                                    return (config.hbs && config.hbs.helperDirectory ? config.hbs.helperDirectory : helperDirectory) + name;
+                                };
+
+                            for (i = 0; i < helps.length; i++) {
+                                paths[i] = "'" + pathGetter(helps[i], path) + "'"
+                            }
+                            return paths;
+                        })().join(','),
+                        debugOutputStart = "",
+                        debugOutputEnd = "",
+                        debugProperties = "",
+                        metaObj, head, linkElem;
+
+                    if (depStr) {
+                        depStr = ",'hbs!" + depStr + "'";
+                    }
+                    if (helpDepStr) {
+                        helpDepStr = "," + helpDepStr;
+                    }
+
+                    if (meta !== "{}") {
+                        try {
+                            metaObj = JSON.parse(meta);
+                            if (metaObj && metaObj.styles) {
+                                styleList = _.union(styleList, metaObj.styles);
+
+                                // In dev mode in the browser
+                                if (require.isBrowser && !config.isBuild) {
+                                    head = document.head || document.getElementsByTagName('head')[0];
+                                    _(metaObj.styles).forEach(function(style) {
+                                        if (!styleMap[style]) {
+                                            linkElem = document.createElement('link');
+                                            linkElem.href = config.baseUrl + devStyleDirectory + style + '.css';
+                                            linkElem.media = 'all';
+                                            linkElem.rel = 'stylesheet';
+                                            linkElem.type = 'text/css';
+                                            head.appendChild(linkElem);
+                                            styleMap[style] = linkElem;
+                                        }
+                                    });
+                                } else if (config.isBuild) {
+                                    (function() {
+                                        var fs = require.nodeRequire('fs'),
+                                            str = _(metaObj.styles).map(function(style) {
+                                                if (!styleMap[style]) {
+                                                    styleMap[style] = true;
+                                                    return "@import url(" + style + ".css);\n";
+                                                }
+                                                return "";
+                                            }).join("\n");
+
+                                        // I write out my import statements to a file in order to help me build stuff.
+                                        // Then I use a tool to inline my import statements afterwards. (you can run r.js on it too)
+                                        fs.open(__dirname + buildStyleDirectory + buildCSSFileName, filecode, '0666', function(e, id) {
+                                            fs.writeSync(id, str, null, encoding = 'utf8');
+                                            fs.close(id);
+                                        });
+                                        filecode = "a";
+                                    })();
+                                }
+                            }
+                        } catch (e) {
+                            console.log('error injecting styles');
+                        }
+                    }
+
+                    if (!config.isBuild && !config.serverRender) {
+                        debugOutputStart = "<!-- START - " + name + " -->";
+                        debugOutputEnd = "<!-- END - " + name + " -->";
+                        debugProperties = "t.meta = " + meta + ";\n" +
+                            "t.helpers = " + JSON.stringify(helps) + ";\n" +
+                            "t.deps = " + JSON.stringify(deps) + ";\n" +
+                            "t.vars = " + JSON.stringify(vars) + ";\n";
+                    }
+
+                    var mapping = disableI18n ? false : _.extend(langMap, config.localeMapping),
+                        configHbs = config.hbs || {},
+                        options = _.extend(configHbs.compileOptions || {}, {
+                            originalKeyFallback: configHbs.originalKeyFallback
+                        }),
+                        prec = precompile(text, mapping, options);
+
+                    text = "/* START_TEMPLATE */\n" +
+                        "define(['hbs','handlebars'" + depStr + helpDepStr + "], function( hbs, Handlebars ){ \n" +
+                        "var t = Handlebars.template(" + prec + ");\n" +
+                        "Handlebars.registerPartial('" + name.replace(/\//g, '_') + "', t);\n" +
+                        debugProperties +
+                        "return t;\n" +
+                        "});\n" +
+                        "/* END_TEMPLATE */\n";
+
+                    //Hold on to the transformed text if a build.
+                    if (config.isBuild) {
+                        buildMap[compiledName] = text;
+                    }
+
+                    //IE with conditional comments on cannot handle the
+                    //sourceURL trick, so skip it if enabled.
+                    /*@if (@_jscript) @else @*/
+                    if (!config.isBuild) {
+                        text += "\r\n//@ sourceURL=" + path;
+                    }
+                    /*@end@*/
+
+                    for (var i in deps) {
+                        if (deps.hasOwnProperty(i)) {
+                            deps[i] = 'hbs!' + deps[i].replace(/_/g, '/');
+                        }
+                    }
+
+                    if (!config.isBuild) {
+                        require(deps, function() {
+                            load.fromText(text);
+
+                            //Give result to load. Need to wait until the module
+                            //is fully parse, which will happen after this
+                            //execution.
+                            parentRequire([name], function(value) {
+                                load(value);
+                            });
+                        });
+                    } else {
+                        load.fromText(name, text);
+
+                        //Give result to load. Need to wait until the module
+                        //is fully parse, which will happen after this
+                        //execution.
+                        parentRequire([name], function(value) {
+                            load(value);
+                        });
+                    }
+
+                    if (config.removeCombined) {
+                        fs.unlinkSync(path);
+                    }
+                });
+            }
+
+            var path,
+                omitExtension = config.hbs && config.hbs.templateExtension === false;
+            if (omitExtension) {
+                path = parentRequire.toUrl(name);
+            } else {
+                path = parentRequire.toUrl(name + '.' + (config.hbs && config.hbs.templateExtension ? config.hbs.templateExtension : templateExtension));
+            }
+
+            if (disableI18n) {
+                fetchAndRegister(false);
+            } else {
+                // Workaround until jam is able to pass config info or we move i18n to a separate module.
+                // This logs a warning and disables i18n if there's an error loading the language file
+                var langMapPath = (config.hbs && config.hbs.i18nDirectory ? config.hbs.i18nDirectory : i18nDirectory) + (config.locale || "en_us") + '.json';
+                try {
+                    fetchOrGetCached(parentRequire.toUrl(langMapPath), function(langMap) {
+                        fetchAndRegister(JSON.parse(langMap));
+                    });
+                } catch (er) {
+                    // if there's no configuration at all, log a warning and disable i18n for this and subsequent templates
+                    if (!config.hbs) {
+                        console.warn('hbs: Error reading ' + langMapPath + ', disabling i18n. Ignore this if you\'re using jam, otherwise check your i18n configuration.\n');
+                        config.hbs = {
+                            disableI18n: true
+                        };
+                        fetchAndRegister(false);
+                    } else {
+                        throw er;
+
+                    }
+                }
+            }
+            //>>excludeEnd('excludeHbs')
+        }
+    };
+});
+/* END_hbs_PLUGIN */

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/i18nprecompile.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/i18nprecompile.js b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/i18nprecompile.js
new file mode 100644
index 0000000..925ac39
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/i18nprecompile.js
@@ -0,0 +1,57 @@
+//>>excludeStart('excludeAfterBuild', pragmas.excludeAfterBuild)
+define(['handlebars', "underscore"], function(Handlebars, _) {
+
+    function replaceLocaleStrings(ast, mapping, options) {
+        options = options || {};
+        mapping = mapping || {};
+        // Base set of things
+        if (ast && ast.type === "program" && ast.statements) {
+            _(ast.statements).forEach(function(statement, i) {
+                var newString = "<!-- i18n error -->";
+                // If it's a translation node
+                if (statement.type === "mustache" && statement.id && statement.id.original === "$") {
+
+                    if (statement.params.length && statement.params[0].string) {
+                        var key = statement.params[0].string;
+                        newString = mapping[key] || (options.originalKeyFallback ? key : newString);
+                    }
+                    ast.statements[i] = new Handlebars.AST.ContentNode(newString);
+                }
+                // If we need to recurse
+                else if (statement.program) {
+                    statement.program = replaceLocaleStrings(statement.program, mapping, options);
+                }
+            });
+            // Also cover the else blocks
+            if (ast.inverse) {
+                replaceLocaleStrings(ast.inverse, mapping, options);
+            }
+        }
+        return ast;
+    }
+
+    return function precompile(string, mapping, options) {
+        var ast, environment;
+
+        options = options || {};
+
+        if (!('data' in options)) {
+            options.data = true;
+        }
+
+        if (options.compat) {
+            options.useDepths = true;
+        }
+
+        ast = Handlebars.parse(string);
+
+        // avoid replacing locale if mapping is `false`
+        if (mapping !== false) {
+            ast = replaceLocaleStrings(ast, mapping, options);
+        }
+
+        environment = new Handlebars.Compiler().compile(ast, options);
+        return new Handlebars.JavaScriptCompiler().compile(environment, options);
+    };
+});
+//>>excludeEnd('excludeAfterBuild')

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/json2.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/json2.js b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/json2.js
new file mode 100644
index 0000000..c740001
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/require-handlebars-plugin/js/json2.js
@@ -0,0 +1,351 @@
+//>>excludeStart('excludeAfterBuild', pragmas.excludeAfterBuild)
+/*
+    http://www.JSON.org/json2.js
+    2011-10-19
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+*/
+
+/*jslint evil: true, regexp: true */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+    lastIndex, length, parse, prototype, push, replace, slice, stringify,
+    test, toJSON, toString, valueOf
+*/
+
+(function(window) {
+
+    // Create a JSON object only if one does not already exist. We create the
+    // methods in a closure to avoid creating global variables.
+
+    // Return the window JSON element if it exists;
+    var JSON = window.JSON || {};
+
+    (function() {
+        'use strict';
+
+        function f(n) {
+            // Format integers to have at least two digits.
+            return n < 10 ? '0' + n : n;
+        }
+
+        if (typeof Date.prototype.toJSON !== 'function') {
+
+            Date.prototype.toJSON = function(key) {
+
+                return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' +
+                    f(this.getUTCMonth() + 1) + '-' +
+                    f(this.getUTCDate()) + 'T' +
+                    f(this.getUTCHours()) + ':' +
+                    f(this.getUTCMinutes()) + ':' +
+                    f(this.getUTCSeconds()) + 'Z' : null;
+            };
+
+            String.prototype.toJSON =
+                Number.prototype.toJSON =
+                Boolean.prototype.toJSON = function(key) {
+                    return this.valueOf();
+                };
+        }
+
+        var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+            escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+            gap,
+            indent,
+            meta = { // table of character substitutions
+                '\b': '\\b',
+                '\t': '\\t',
+                '\n': '\\n',
+                '\f': '\\f',
+                '\r': '\\r',
+                '"': '\\"',
+                '\\': '\\\\'
+            },
+            rep;
+
+        function quote(string) {
+
+            // If the string contains no control characters, no quote characters, and no
+            // backslash characters, then we can safely slap some quotes around it.
+            // Otherwise we must also replace the offending characters with safe escape
+            // sequences.
+
+            escapable.lastIndex = 0;
+            return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
+                var c = meta[a];
+                return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            }) + '"' : '"' + string + '"';
+        }
+
+        function str(key, holder) {
+
+            // Produce a string from holder[key].
+
+            var i, // The loop counter.
+                k, // The member key.
+                v, // The member value.
+                length,
+                mind = gap,
+                partial,
+                value = holder[key];
+
+            // If the value has a toJSON method, call it to obtain a replacement value.
+
+            if (value && typeof value === 'object' &&
+                typeof value.toJSON === 'function') {
+                value = value.toJSON(key);
+            }
+
+            // If we were called with a replacer function, then call the replacer to
+            // obtain a replacement value.
+
+            if (typeof rep === 'function') {
+                value = rep.call(holder, key, value);
+            }
+
+            // What happens next depends on the value's type.
+
+            switch (typeof value) {
+                case 'string':
+                    return quote(value);
+
+                case 'number':
+
+                    // JSON numbers must be finite. Encode non-finite numbers as null.
+
+                    return isFinite(value) ? String(value) : 'null';
+
+                case 'boolean':
+                case 'null':
+
+                    // If the value is a boolean or null, convert it to a string. Note:
+                    // typeof null does not produce 'null'. The case is included here in
+                    // the remote chance that this gets fixed someday.
+
+                    return String(value);
+
+                    // If the type is 'object', we might be dealing with an object or an array or
+                    // null.
+
+                case 'object':
+
+                    // Due to a specification blunder in ECMAScript, typeof null is 'object',
+                    // so watch out for that case.
+
+                    if (!value) {
+                        return 'null';
+                    }
+
+                    // Make an array to hold the partial results of stringifying this object value.
+
+                    gap += indent;
+                    partial = [];
+
+                    // Is the value an array?
+
+                    if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+                        // The value is an array. Stringify every element. Use null as a placeholder
+                        // for non-JSON values.
+
+                        length = value.length;
+                        for (i = 0; i < length; i += 1) {
+                            partial[i] = str(i, value) || 'null';
+                        }
+
+                        // Join all of the elements together, separated with commas, and wrap them in
+                        // brackets.
+
+                        v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
+                        gap = mind;
+                        return v;
+                    }
+
+                    // If the replacer is an array, use it to select the members to be stringified.
+
+                    if (rep && typeof rep === 'object') {
+                        length = rep.length;
+                        for (i = 0; i < length; i += 1) {
+                            if (typeof rep[i] === 'string') {
+                                k = rep[i];
+                                v = str(k, value);
+                                if (v) {
+                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                                }
+                            }
+                        }
+                    } else {
+
+                        // Otherwise, iterate through all of the keys in the object.
+
+                        for (k in value) {
+                            if (Object.prototype.hasOwnProperty.call(value, k)) {
+                                v = str(k, value);
+                                if (v) {
+                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                                }
+                            }
+                        }
+                    }
+
+                    // Join all of the member texts together, separated with commas,
+                    // and wrap them in braces.
+
+                    v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
+                    gap = mind;
+                    return v;
+            }
+        }
+
+        // If the JSON object does not yet have a stringify method, give it one.
+
+        if (typeof JSON.stringify !== 'function') {
+            JSON.stringify = function(value, replacer, space) {
+
+                // The stringify method takes a value and an optional replacer, and an optional
+                // space parameter, and returns a JSON text. The replacer can be a function
+                // that can replace values, or an array of strings that will select the keys.
+                // A default replacer method can be provided. Use of the space parameter can
+                // produce text that is more easily readable.
+
+                var i;
+                gap = '';
+                indent = '';
+
+                // If the space parameter is a number, make an indent string containing that
+                // many spaces.
+
+                if (typeof space === 'number') {
+                    for (i = 0; i < space; i += 1) {
+                        indent += ' ';
+                    }
+
+                    // If the space parameter is a string, it will be used as the indent string.
+
+                } else if (typeof space === 'string') {
+                    indent = space;
+                }
+
+                // If there is a replacer, it must be a function or an array.
+                // Otherwise, throw an error.
+
+                rep = replacer;
+                if (replacer && typeof replacer !== 'function' &&
+                    (typeof replacer !== 'object' ||
+                        typeof replacer.length !== 'number')) {
+                    throw new Error('JSON.stringify');
+                }
+
+                // Make a fake root object containing our value under the key of ''.
+                // Return the result of stringifying the value.
+
+                return str('', {
+                    '': value
+                });
+            };
+        }
+
+        // If the JSON object does not yet have a parse method, give it one.
+
+        if (typeof JSON.parse !== 'function') {
+            JSON.parse = function(text, reviver) {
+
+                // The parse method takes a text and an optional reviver function, and returns
+                // a JavaScript value if the text is a valid JSON text.
+
+                var j;
+
+                function walk(holder, key) {
+
+                    // The walk method is used to recursively walk the resulting structure so
+                    // that modifications can be made.
+
+                    var k, v, value = holder[key];
+                    if (value && typeof value === 'object') {
+                        for (k in value) {
+                            if (Object.prototype.hasOwnProperty.call(value, k)) {
+                                v = walk(value, k);
+                                if (v !== undefined) {
+                                    value[k] = v;
+                                } else {
+                                    delete value[k];
+                                }
+                            }
+                        }
+                    }
+                    return reviver.call(holder, key, value);
+                }
+
+                // Parsing happens in four stages. In the first stage, we replace certain
+                // Unicode characters with escape sequences. JavaScript handles many characters
+                // incorrectly, either silently deleting them, or treating them as line endings.
+
+                text = String(text);
+                cx.lastIndex = 0;
+                if (cx.test(text)) {
+                    text = text.replace(cx, function(a) {
+                        return '\\u' +
+                            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                    });
+                }
+
+                // In the second stage, we run the text against regular expressions that look
+                // for non-JSON patterns. We are especially concerned with '()' and 'new'
+                // because they can cause invocation, and '=' because it can cause mutation.
+                // But just to be safe, we want to reject all unexpected forms.
+
+                // We split the second stage into 4 regexp operations in order to work around
+                // crippling inefficiencies in IE's and Safari's regexp engines. First we
+                // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+                // replace all simple value tokens with ']' characters. Third, we delete all
+                // open brackets that follow a colon or comma or that begin the text. Finally,
+                // we look to see that the remaining characters are only whitespace or ']' or
+                // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+                if (/^[\],:{}\s]*$/
+                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+                    // In the third stage we use the eval function to compile the text into a
+                    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+                    // in JavaScript: it can begin a block or an object literal. We wrap the text
+                    // in parens to eliminate the ambiguity.
+
+                    j = eval('(' + text + ')');
+
+                    // In the optional fourth stage, we recursively walk the new structure, passing
+                    // each name/value pair to a reviver function for possible transformation.
+
+                    return typeof reviver === 'function' ? walk({
+                        '': j
+                    }, '') : j;
+                }
+
+                // If the text is not JSON parseable, then a SyntaxError is thrown.
+
+                throw new SyntaxError('JSON.parse');
+            };
+        }
+    }());
+
+    define(function() {
+        return JSON;
+    });
+    // otherwise just leave it alone
+
+}).call(this, this);
+//>>excludeEnd('excludeAfterBuild')

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/7bb2709d/dashboardv2/public/js/main.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js
index a1a9ae1..63dd71e 100644
--- a/dashboardv2/public/js/main.js
+++ b/dashboardv2/public/js/main.js
@@ -48,6 +48,9 @@ require.config({
             deps: ['underscore', 'jquery'],
             exports: 'Backbone'
         },
+        'jquery-ui': {
+            deps: ['jquery'],
+        },
         asBreadcrumbs: {
             deps: ['jquery'],
             exports: 'asBreadcrumbs'
@@ -120,13 +123,14 @@ require.config({
         'tmpl': 'templates',
         'noty': 'libs/noty/js/jquery.noty.packaged.min',
         'requirejs.text': 'libs/requirejs-text/text',
-        'handlebars': 'require-handlebars-plugin/js/handlebars',
-        'json2': 'require-handlebars-plugin/js/json2',
-        'hbs': 'require-handlebars-plugin/js/hbs',
-        'i18nprecompile': 'require-handlebars-plugin/js/i18nprecompile',
+        'handlebars': 'external_lib/require-handlebars-plugin/js/handlebars',
+        'json2': 'external_lib/require-handlebars-plugin/js/json2',
+        'hbs': 'external_lib/require-handlebars-plugin/js/hbs',
+        'i18nprecompile': 'external_lib/require-handlebars-plugin/js/i18nprecompile',
         'dagreD3': 'libs/dagre-d3/dagre-d3.min',
         'select2': 'libs/select2/select2.min',
-        'backgrid-select-all': 'libs/backgrid-select-all/backgrid-select-all.min'
+        'backgrid-select-all': 'libs/backgrid-select-all/backgrid-select-all.min',
+        'jquery-ui': 'external_lib/jquery-ui/jquery-ui.min',
     },
 
     /**