Added: 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/documentation/html.jsp
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/documentation/html.jsp?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/documentation/html.jsp
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/documentation/html.jsp
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,334 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+--%>
+
+<!DOCTYPE html>
+<%@ page session="false"%>
+<%@ page isELIgnored="false"%>
+<%@ page import="javax.jcr.*,org.apache.sling.api.resource.Resource"%>
+<%@ taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
+<sling:defineObjects />
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+
+<script type="text/javascript" src="../js/jsnodetypes.js"></script>
+
+<style type="text/css">
+#main {
+    border: 1px dashed;
+    margin: 0 auto;
+    padding: 10px;
+    width: 1000px;
+}
+input {
+       margin: 10px 0;
+}
+.label {
+       margin: 5px;
+}
+#ntNames {
+       white-space: pre-wrap;
+}
+#ntJson {
+       display: inline;
+}
+.code.block-code {
+       display: block;
+}
+.code {
+       border: 1px solid black;
+       display: inline-block;
+       vertical-align: top;
+       margin-top: 10px;
+}
+.code pre {
+       margin: 5px;
+}
+.nodeTypeMethods {
+       display: inline-block;
+       margin: 0 10px 10px;
+       width: 350px;
+}
+.doc {
+       margin-bottom: 15px;
+}
+.parameter {
+       margin-left: 10px;
+}
+
+</style>
+
+<script type="text/javascript">
+
+var settings = {"contextPath": "${pageContext.request.contextPath}"};
+var ntManager = new de.sandroboehme.NodeTypeManager(settings);
+
+function getNTNames(){
+       var ntNames = ntManager.getNodeTypeNames();
+       var ntNamesString = "[ ";
+       for (var ntNameIndex in ntNames) {
+               ntNamesString+= ntNames[ntNameIndex]
+               if (ntNameIndex != ntNames.length-1) {
+                       ntNamesString += ", ";
+               }
+       }
+       ntNamesString+= " ]";
+       document.getElementById("ntNames").innerHTML=ntNamesString;
+};
+
+function getNTJson(){
+       var ntName = document.getElementById("ntName").value;
+       return ntManager.getNodeType(ntName);
+};
+
+function loadNTJson(){
+       document.getElementById("ntJson").innerHTML=JSON.stringify(getNTJson(), 
null, 4);
+};
+function loadChildNodeDefs(){
+       var ntJson = getNTJson();
+       if (ntJson != null){
+               var allChildNodeDefs = ntJson.getAllChildNodeDefinitions();
+               
document.getElementById("ntMethodResult").innerHTML=JSON.stringify(allChildNodeDefs,
 null, 4);
+       }
+};
+function loadPropertyDefs(){
+       var ntJson = getNTJson();
+       if (ntJson != null){
+               var propertyDefs = ntJson.getAllPropertyDefinitions();
+               
document.getElementById("ntMethodResult").innerHTML=JSON.stringify(propertyDefs,
 null, 4);
+       }
+};
+function loadApplicableChildNodeTypes(){
+       var ntJson = getNTJson();
+       if (ntJson != null){
+               var includeMixins = 
document.getElementById("includeMixins").checked;
+               var applicableChildNodeTypes = 
ntJson.getApplicableCnTypesPerCnDef(includeMixins);
+               
document.getElementById("ntMethodResult").innerHTML=JSON.stringify(applicableChildNodeTypes,
 null, 4);
+       }
+};
+function canAddChildNode(){
+       var ntJson = getNTJson();
+       if (ntJson != null){
+               var nodeName = document.getElementById("nodeName").value;
+               var nodeTypeToAdd = 
document.getElementById("nodeTypeToAdd").value;
+               var canAddChildNode = ntJson.canAddChildNode(nodeName, 
ntManager.getNodeType(nodeTypeToAdd));
+               
document.getElementById("ntMethodResult").innerHTML=canAddChildNode;
+       }
+}
+function canAddProperty(){
+       var ntJson = getNTJson();
+       if (ntJson != null){
+               var propertyName = 
document.getElementById("propertyName").value;
+               var propertyType = 
document.getElementById("propertyType").value;
+               var canAddProperty = ntJson.canAddProperty(propertyName, 
propertyType);
+               
document.getElementById("ntMethodResult").innerHTML=canAddProperty;
+       }
+}
+</script>
+
+</head>
+<body>
+       <div id="main">
+               <h1><em>JSNodeTypes</em> - A JavaScript Node Types library for 
Apache Sling</h1>
+               <p>It uses Apache Sling to generate JavaScript object literals 
for JCR node types. Default binary values are converted to paths where they can 
be downloaded.</p>
+               <h2>Live Demo of the API</h2>
+               <p>Have a look at the simple source code of this page to see 
how it's done.</p>
+               <h3>Methods of the node type manager:</h3>
+               <div>
+                       <input id="ntNamesButton" type="button" 
value="ntManager.getNodeTypeNames();" onclick="getNTNames();"/>
+               </div>
+               <div class="block-code code">
+                       <pre id="ntNames">[]</pre>
+               </div>
+               
+               <div>
+                       <input id="ntButton" type="button" 
value="ntManager.getNodeType" onclick="loadNTJson();"/>
+                       (<input id="ntName" type="text" value="nt:version"/>);
+               </div>
+               <div>
+                       <div class="code">
+                               <pre id="ntJson">{}</pre>
+                       </div>
+               </div>
+               <h3>Methods of the node type object selected above:</h3>
+               <ul class="nodeTypeMethods">
+               <li>
+                       <input type="button" 
value="getAllChildNodeDefinitions();" onclick="loadChildNodeDefs();"/>
+                               <span class="doc">That method returns the 
<strong>child node definitions</strong> of the node type and those <strong>of 
all inherited node types</strong>.<br/>Definitions with the same name are not 
overwritten but aggregated. If they are equal they are only listed once.</span>
+                       </li>
+                       <li>
+                               <input type="button" 
value="getAllPropertyDefinitions();" onclick="loadPropertyDefs();"/>
+                               <span class="doc">That method returns the 
<strong>property definitions</strong> of the node type and those <strong>of all 
inherited node types</strong>.<br/>Definitions with the same name are not 
overwritten but aggregated. If they are equal they are only listed 
once.<br/></span>
+                       </li>
+                       <li><input type="button" value="canAddChildNode" 
onclick="canAddChildNode();"/>
+                                       (<input type="text" value="nodeName" 
id="nodeName" class="parameter"/>,
+                                       <span style="display:inline-block" 
class="parameter">ntManager.getNodeType(<input type="select" 
value="nodeTypeToAdd" id="nodeTypeToAdd" class="parameter"/>)</span>);
+                               <span class="doc"><br>That method returns 
`true` if a node with the specified node name and node type can be added as a 
child node of the current node type. The residual definitions and subtypes are 
considered.<br/>The <strong>first parameter is the string</strong> of the node 
name and the <strong>second parameter is a node type object</strong> (not a 
string).</span>
+                       </li>
+                       <li><input type="button" value="canAddProperty" 
onclick="canAddProperty();"/>
+                                       (<input type="text" 
value="propertyName" id="propertyName" class="parameter"/>, <input type="text" 
value="propertyType" id="propertyType" class="parameter"/>);
+                               <span class="doc"><br>That method returns 
`true` if a property with the specified name and type can be to the current 
node type. The residual definitions and undefined types are considered.<br/>The 
<strong>first parameter is the string</strong> of the property name and the 
<strong>second parameter is the property type</strong> (case 
insensitive).</span>
+                       </li>
+                       <li>
+                               <input type="button" 
value="getApplicableCnTypesPerCnDef()" 
onclick="loadApplicableChildNodeTypes();"/>
+                                       (<input type="checkbox" 
value="includeMixins" id="includeMixins" class="parameter"/> includeMixins);
+                               <span class="doc"><br>Returns all node types 
that can be used for child nodes of this node type and its super types.<br/>If 
a child node definition specifies multiple required primary types, only node 
types that are subtypes of all of them are applicable.</br>The keys on the 
first level are the names of the child node definitions. Its values / the keys 
on the second level contain the node type names and its values in turn contain 
the node type definition itself. The <strong>parameter is a boolean</strong> 
and specifies if mixin types should be included in the result.</span>
+                       </li>
+               </ul>
+               <div class="code">
+                       <pre id="ntMethodResult">{}</pre>
+               </div>
+               <h2>Use</h2>
+               <ol>
+                       <li>
+                               <p>Include the JavaScript file to your 
page:</p>                
+                               <div class="code">
+                                       <pre class="JavaScript">&lt;script 
type="text/javascript" 
src="/libs/jsnodetypes/js/jsnodetypes.js"&gt;&lt;/script&gt;</pre>
+                               </div>
+                       </li>
+                       <li>
+                               <p>Instantiate the NodeTypeManager:</p>
+                               <div class="code">
+                                       <pre class="JavaScript">// this works 
if your WAR is deployed under the root context '/'
+var ntManager = new de.sandroboehme.NodeTypeManager();
+                                       </pre>
+                               </div>
+                               <p>If your WAR is not deployed under the root 
context you have to specify it:</p>
+                               <div class="code">
+                                       <pre class="JavaScript">var settings = 
{"contextPath": "/yourContextPath"};
+var ntManager = new de.sandroboehme.NodeTypeManager(settings);
+                                       </pre>
+                               </div>
+                       </li>
+                       <li>
+                               <p>Use the NodeTypeManager instance like 
described above:</p>
+                               <div class="code">
+                                       <pre class="JavaScript">var 
nodeTypesArray = ntManager.getNodeTypeNames();
+var firstNodeType = ntManager.getNodeType(nodeTypesArray[0]);
+var allChildNodeDefs = firstNodeType.getAllChildNodeDefinitions();
+var allPropertyDefs = firstNodeType.getAllPropertyDefinitions();
+var canAddChildNode = firstNodeType.canAddChildNode("myNodeName", 
nodeTypesArray[1]);
+                                       </pre>
+                               </div>
+                       </li>
+               </ol>
+               <h2>Installation</h2>
+               <ol>
+                       <li>Add 
<pre>http://www.jcrbrowser.org/sling/obr/repository.xml</pre> to your OSGi 
Bundle repository in the Sling web console (/system/console/obr)</li>
+                       <li>In the resource 'J' navigate to 'jsNodeTypes' and 
'Deploy and Start' the bundle</li>
+                       <li>At 
<pre>/libs/jsnodetypes/content/documentation.html</pre> you should be able to 
see and use this page.</li> 
+                       <li>If you see the page: Congrats you successfully 
installed the jsNodeTypes library! In case you don't see it, please have a look 
at the next section to get it installed.</li> 
+               </ol>
+               <h2>Version History</h2>
+               <ul>
+                       <li><strong>4.0.1</strong>
+                               <ul>
+                                       <li><strong>Non backwards compatible 
change:</strong>Renamed getApplicableChildNodeTypes() to 
getApplicableCnTypesPerCnDef() to allow other similar methods and still have no 
overlapping meanings.</li>
+                               </ul>
+                       </li>
+                       <li><strong>3.0.2</strong>
+                               <ul>
+                                       <li>Fixed canAddChildNode() to check 
node name and node type combination and to return 'true' also for subtypes of a 
requiredPrimaryType.</li>
+                                       <li>Fixed canAddChildNode() to handle 
the protected property correctly</li>
+                                       <li>Added includeMixins parameter to 
getApplicableChildNodeTypes()</li>
+                                       <li>Added canAddProperty()</li>
+                               </ul>
+                       </li>
+                       <li><strong>3.0.1</strong>
+                               <ul>
+                                       <li>canAddChildNode(): checking if the 
provided node type is null</li>
+                               </ul>
+                       </li>
+                       <li><strong>3.0</strong>
+                               <ul>
+                                       <li>Rework of almost all of the runtime 
source code to remove the Google Gson dependency and use the sling.commons.json 
dependency instead as the latter it is already part of the Sling launchpad and 
Gson is not.</li>
+                                       <li>Added the new types of JCR 2.0: 
'weakReference', 'uri', 'undefined' and 'decimal' as types for default 
values.</li>
+                                       <li><strong>Non backwards compatible 
changes:</strong> Changed the format of the default values:
+                                               <ul>
+                                                       <li>The 'name' value 
can now be found with the 'name' key. Not with the 'string' key anymore.</li>
+                                                       <li>The 'path' value 
can now be found with the 'path' key. Not with the 'string' key anymore.</li>
+                                                       <li>The 'reference' 
value can now be found with the 'reference' key. Not with the 'string' key 
anymore.</li>
+                                                       <li>The format of the 
'date' value changed to provide more information from the Calendar object that 
is retrieved from the repository. Until this version the date value contained a 
JavaScript
+                                                       object like this: 
'{"year": 2012, "month": 1, "dayOfMonth": 1, "hourOfDay": 0, "minute": 0, 
"second": 0}' and now it is a String containing an ISO8601 date. E.g. 
"2012-02-01T00:00:00.000+01:00". 
+                                                       For the date ISO8601 
conversion the dependency to 'jackrabbit-jcr-commons' has been added which is 
already part of the sling launchpad. 
+                                                       </li>
+                                                       <li>Empty 
'declaredChildNodeDefinitions', 'declaredSupertypes' and 
'declaredPropertyDefinitions' are not part of the JSON output anymore.</li>
+                                               </ul>
+                                       </li>
+                               </ul>
+                       </li>
+                       <li><strong>2.0</strong>
+                               <ul>
+                                       <li>getApplicableChildNodeTypes() 
added</li>
+                                       <li><strong>Non backwards compatible 
changes:</strong> getAllChildNodeDefinitions() and getAllPropertyDefinitions() 
changed to now return definitions with the same name as well. But only if they 
differ in any other way.</li>
+                               </ul>
+                       </li>
+                       <li><strong>1.0</strong>
+                               <ul>
+                                       <li>Initial version</li>
+                               </ul>
+                       </li>
+               </ul>
+               <h2>Support</h2>
+               <p>
+               Bugs can be opened at the <a 
href="https://github.com/sandroboehme/jsNodeTypes/issues";>GitHub issue tracker 
for the project</a>. For questions I will be monitoring the Sling users mailing 
list (us...@sling.apache.org).
+               I'm always looking forward to your feedback. Even if it's 
critique :-)</p> 
+               <h2>Architecture</h2>
+               <p>The JavaScript NodeTypeManager is developed in an object 
oriented way. It is instantiated in its own namespace and then loads <a 
href="${pageContext.request.contextPath}/libs/jsnodetypes/content/nodetypes.json">all
 available node types from the server in the JSON format</a>.</p> 
+               <p>This is handled by the 
<code>de.sandroboehme.jsnodetypes.NodeTypesJSONServlet</code> at the server 
side. It</p> 
+               <ul>
+                       <li>reads the node types from the repository</li>
+                       <li>converts them to JSON</li>
+                       <li>replaces the default binary values with URL's where 
they can later be downloaded from</li>
+                       <li>removes the  <a 
href="${pageContext.request.contextPath}/libs/jsnodetypes/js/defaultNT/defaultNT.json">default
 values</a> to have smaller node type objects</li>
+                       <li>and returns the result back to the JavaScript 
client.</li>
+               </ul>
+               <p>When <code>ntManager.getNodeType(nodeTypeName)</code> is 
called at the client side, the defaults are added again and 
+               the methods are added to the JSON object / JavaScript object 
literal and are finally returned.
+               </p>
+               <p>The internal 'processNodeTypeGraph()' method in 
jsnodetype.js is the basis for the other methods as it collects the needed 
data.</p>
+               <h2>Tests</h2>
+               <p>All JavaScript tests and Java tests are run in the Maven 
test phase as usual.
+               <h3>JavaScript</h3>
+               <p>The JavaScript tests are implemented in 
<code>src/test/javascript/NodeTypesSpec.js</code> using <a 
href="http://pivotal.github.com/jasmine/";>Jasmine</a>. When you call <code>mvn 
jasmine:bdd</code> you can edit the tests and refresh the browser at 
<code>http://localhost:8234</code> to rerun the tests. 
+               <h3>Java</h3>
+               <p>The Java tests can be found in 
<code>src/test/java/de/sandroboehme/jsnodetypes</code>. They query the 
<code>de.sandroboehme.jsnodetypes.NodeTypesJSONServlet</code> while mocking the 
<code>javax.jcr.nodetype.NodeTypeManager</code> using <a 
href="http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html";>Mockito</a>.
+               The result is then compared to the expected values in the 
<code>src/test/resources/expectedNTJSON/*.json</code> files using 
<code>de.sandroboehme.jsnodetypes.testJSONAssert</code>. This class is actually 
copied from 
+               <code>org.apache.sling.commons.json.test.JSONAssert</code>. If 
somebody knows a better way to reuse this class please open an bug and let me 
know.
+               </p>
+               <h2>Build</h2>
+               <p>You can check out the sources from <a 
href="https://github.com/sandroboehme/jsNodeTypes";>https://github.com/sandroboehme/jsNodeTypes</a>
 and build them with Maven. Use<br>
+               <code>mvn install, mvn sling:install,  mvn deploy 
-DremoteOBR=http://admin:admin@localhost:8080/obr/repository.xml 
-DaltDeploymentRepository=local8080::default::dav:http://admin:admin@localhost:8080/obr
+               </code><br>
+               to install the library to your local Maven repo, mount the 
library sources to your running sling repo for a quicker development or deploy 
it to your local OSGi bundle repository to test the OSGi installation.
+               </p>
+               <h2>License</h2>
+               <p>This library is licensed under the terms of the <a 
href="http://www.apache.org/licenses/LICENSE-2.0.html";>Apache 2 license</a>.</p>
+               <h2>Compatibility</h2>
+               <p>This library has out of the box support for: IE 8.0 
standards mode, Firefox 20.0, Chrome 26.0, Opera 12.1 and Safari 5.1</p>
+               <h3>Support for older browser versions</h3>
+               <p>If you would like to support older browser versions you can 
download the <a 
href="https://raw.github.com/douglascrockford/JSON-js/master/json2.js";>json2.js 
script</a> and include it like that:</p>
+               <div class="code">
+                       <pre class="JavaScript">&lt;script 
type="text/javascript" src="/path/to/json2.js"&gt;&lt;/script&gt;</pre>
+               </div>
+       </div>
+</body>
+</html>

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/defaultNT/defaultNT.json
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/defaultNT/defaultNT.json?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/defaultNT/defaultNT.json
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/defaultNT/defaultNT.json
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,32 @@
+{
+    "mixin": false,
+    "orderableChildNodes": false,
+    "declaredSupertypes": [
+      "nt:base"
+    ],
+    "declaredPropertyDefinitions": [
+      {
+        "defaultValues": null,
+        "valueConstraints": null,
+        "requiredType": "String",
+        "multiple": false,
+        "autoCreated": false,
+        "mandatory": false,
+        "protected": false,
+        "onParentVersion": "COPY"
+      }
+    ],
+    "declaredChildNodeDefinitions": [
+      {
+        "allowsSameNameSiblings": false,
+        "defaultPrimaryType": null,
+        "requiredPrimaryTypes": [
+          "nt:base"
+        ],
+        "autoCreated": false,
+        "mandatory": false,
+        "protected": false,
+        "onParentVersion": "COPY"
+      }
+    ]
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/jsnodetypes.js
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/jsnodetypes.js?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/jsnodetypes.js
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/main/resources/SLING-INF/libs/jsnodetypes/js/jsnodetypes.js
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,501 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// creating the namespace
+var de = de || {};
+de.sandroboehme = de.sandroboehme || {};
+var sandroboehme = de.sandroboehme;
+/*
+ JSNodeTypes - The JavaScript Node Types library for Apache Sling
+
+ The documentation of the library can be found at:
+ http://www.jcrbrowser.org/sling/libs/jsnodetypes/content/documentation.html
+ 
+*/
+
+//defining the module
+de.sandroboehme.NodeTypeManager = (function() {
+
+       function NodeTypeManager(settingsParameter){
+               // copies the setting parameters to the object scope and 
configures the defaults
+               
+               var noSettingsProvided = typeof settingsParameter === 
'undefined' || settingsParameter == null;
+               var contextPath = (noSettingsProvided || typeof 
settingsParameter.contextPath === 'undefined') ? '' : 
settingsParameter.contextPath;
+               var defaultNTJsonURL = (noSettingsProvided || typeof 
settingsParameter.defaultNTJsonURL === 'undefined') ? 
contextPath+'/libs/jsnodetypes/js/defaultNT/defaultNT.json' : 
settingsParameter.defaultNTJsonURL;
+               this.defaultNTJson = getJson(defaultNTJsonURL);
+               this.nodeTypesJson = (noSettingsProvided || typeof 
settingsParameter.nodeTypesJson === 'undefined') ? 
getJson(contextPath+'/libs/jsnodetypes/content/nodetypes.json') : 
settingsParameter.nodeTypesJson;
+               initializeNodeTypes(this);
+       };
+       
+       function getJson(url){
+               var result;
+               var xhr = null;
+           if (window.XMLHttpRequest) {
+               xhr = new XMLHttpRequest();
+           } else if (window.ActiveXObject) { // Older IE.
+               xhr = new ActiveXObject("MSXML2.XMLHTTP.3.0");
+           }
+               xhr.open("GET", url, false/*not async*/);
+               if (typeof xhr.overrideMimeType != "undefined"){
+                       xhr.overrideMimeType("application/json");
+               }
+               xhr.onload = function (e) {
+                 if (xhr.readyState === 4) {
+                   if (xhr.status === 200) {
+                       result = JSON.parse(xhr.responseText);
+                   } else {
+                       console.error(xhr.statusText);
+                   }
+                 }
+               };
+               xhr.onerror = function (e) {
+                 console.error(xhr.statusText);
+               };
+               xhr.send(null);
+               return result;
+       }
+       
+       /* adding an indexOf function if it's not available */
+       if (!Array.prototype.indexOf) {
+           Array.prototype.indexOf = function (searchElement /*, fromIndex */ 
) {
+               "use strict";
+               if (this == null) {
+                   throw new TypeError();
+               }
+               var t = Object(this);
+               var len = t.length >>> 0;
+               if (len === 0) {
+                   return -1;
+               }
+               var n = 0;
+               if (arguments.length > 1) {
+                   n = Number(arguments[1]);
+                   if (n != n) { // shortcut for verifying if it's NaN
+                       n = 0;
+                   } else if (n != 0 && n != Infinity && n != -Infinity) {
+                       n = (n > 0 || -1) * Math.floor(Math.abs(n));
+                   }
+               }
+               if (n >= len) {
+                   return -1;
+               }
+               var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+               for (; k < len; k++) {
+                   if (k in t && t[k] === searchElement) {
+                       return k;
+                   }
+               }
+               return -1;
+           }
+       }
+       
+       /*
+        * Adds Object.keys if its not available.
+        * See 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+        */
+       if (!Object.keys) {
+                Object.keys = (function() {
+                        'use strict';
+                        var hasOwnProperty = Object.prototype.hasOwnProperty,
+                           hasDontEnumBug = !({ toString: null 
}).propertyIsEnumerable('toString'),
+                           dontEnums = [
+                             'toString',
+                             'toLocaleString',
+                             'valueOf',
+                             'hasOwnProperty',
+                             'isPrototypeOf',
+                             'propertyIsEnumerable',
+                             'constructor'
+                           ],
+                           dontEnumsLength = dontEnums.length;
+
+                       return function(obj) {
+                         if (typeof obj !== 'object' && (typeof obj !== 
'function' || obj === null)) {
+                           throw new TypeError('Object.keys called on 
non-object');
+                         }
+
+                         var result = [], prop, i;
+
+                         for (prop in obj) {
+                           if (hasOwnProperty.call(obj, prop)) {
+                             result.push(prop);
+                           }
+                         }
+
+                         if (hasDontEnumBug) {
+                           for (i = 0; i < dontEnumsLength; i++) {
+                             if (hasOwnProperty.call(obj, dontEnums[i])) {
+                               result.push(dontEnums[i]);
+                             }
+                           }
+                         }
+                         return result;
+                       };
+               }()); 
+       }
+
+       /*
+        * This function walks recursively through all parent node types and 
calls the processing function with the current node type
+        *  
+        * currentNodeType - the node type to retrieve the property defs from 
in this call 
+        * processingFunction - the function to call on every node type
+        * processedNodeTypes - is used to avoid cycles by checking if a node 
type has been processed already
+        * iterationProperty - the property of the nodeType that should be used 
for iteration e.g. 'declaredSupertypes'
+        */
+       function processNodeTypeGraph (currentNodeType, iterationProperty, 
processingFunction, processedNodeTypes){
+               if (currentNodeType == null || iterationProperty == null || 
iterationProperty==="" || processingFunction == null ) return;
+               var initialCall = typeof processedNodeTypes === 'undefined';
+               if (initialCall){
+                       processedNodeTypes = [];
+               }
+               
+               processingFunction(currentNodeType);
+
+               processedNodeTypes.push(currentNodeType.name);
+               
+               for (var supertypeIndex in currentNodeType[iterationProperty]) {
+                       newNodeTypeName = 
currentNodeType[iterationProperty][supertypeIndex];
+                       
+                       newNodeType = this.getNodeType(newNodeTypeName);
+                       
+                       /* 
+                        * skip the processing of node types that have already 
been processed
+                        */
+                       var notProcessedYet = 
processedNodeTypes.indexOf(newNodeTypeName) < 0;
+                       if (notProcessedYet){
+                               processNodeTypeGraph.call(this, newNodeType, 
iterationProperty, processingFunction, processedNodeTypes);
+                       }
+               }
+       };
+       
+       /*
+        * Sets the value of all properties of defaultNT.json to the 
corresponding undefined properties of the specified node type.
+        * E.g. if nt.declaredChildNodeDefinitions[2].allowsSameNameSiblings is 
undefined it is set to 
testNodeType.declaredChildNodeDefinitions[0].allowsSameNameSiblings
+        */
+       function setDefaults(nt){
+
+               if(typeof nt["declaredSupertypes"] === "undefined" && "nt:base" 
!= nt.name){
+                       nt["declaredSupertypes"] = 
this.defaultNTJson["declaredSupertypes"]; 
+               }
+               
+               // node type defaults
+               for(var propName in this.defaultNTJson){
+                       if (propName != "declaredPropertyDefinitions" && 
propName != "declaredChildNodeDefinitions"){
+                               setDefaultNTProps.call(this, propName);
+                       }
+               }
+               
+               // property definition defaults
+               for(var propName in 
this.defaultNTJson.declaredPropertyDefinitions[0]){
+                       /*
+                        * Sets the default values from all 
this.defaultNTJson.declaredPropertyDefinitions[0] properties
+                        * too all properties of all 
declaredPropertyDefinitions of 'nt'.
+                        */
+                       for (var propDefIndex in 
nt.declaredPropertyDefinitions){
+                               setDefaultPropDefProps.call(this, propDefIndex, 
propName);
+                       }
+               }
+               // child node definition defaults       
+               for(var propName in 
this.defaultNTJson.declaredChildNodeDefinitions[0]){
+                       /*
+                        * Sets the default values from all 
this.defaultNTJson.declaredChildNodeDefinitions[0] properties
+                        * too all properties of all 
declaredChildNodeDefinitions of 'nt'.
+                        */
+                       for (var childNodeDefIndex in 
nt.declaredChildNodeDefinitions){
+                               setDefaultChildNodeDefProps.call(this, 
childNodeDefIndex, propName);
+                       }
+               }
+               
+               function setDefaultNTProps(propName){
+                       if(typeof nt[propName] === "undefined") nt[propName] = 
this.defaultNTJson[propName]; 
+               }
+               
+               function setDefaultPropDefProps(index, propName){
+                       if(typeof 
nt.declaredPropertyDefinitions[index][propName] === "undefined") 
nt.declaredPropertyDefinitions[index][propName] = 
this.defaultNTJson.declaredPropertyDefinitions[0][propName]; 
+               }
+               
+               function setDefaultChildNodeDefProps(index, propName){
+                       if(typeof 
nt.declaredChildNodeDefinitions[index][propName] === "undefined") 
nt.declaredChildNodeDefinitions[index][propName] = 
this.defaultNTJson.declaredChildNodeDefinitions[0][propName]; 
+               }
+               
+       };
+       
+       NodeTypeManager.prototype.internalGetDefaultNodeType = function() {
+               return this.defaultNTJson;
+       };
+       
+       NodeTypeManager.prototype.getNodeTypeNames = function(name) {
+               var ntNames = [];
+               for (var ntJson in this.nodeTypesJson) {
+                       ntNames.push(ntJson);
+               }
+               return ntNames;
+       }
+               
+       NodeTypeManager.prototype.getNodeType = function(name) {
+               return this.nodeTypesJson[name];
+       }
+       
+       function initializeNodeTypes(that){
+               try {
+                       for (var ntIndex in Object.keys(that.nodeTypesJson)){
+                               var nodeTypeName = 
Object.keys(that.nodeTypesJson)[ntIndex];
+                               
+                               if (typeof that.nodeTypesJson[nodeTypeName] != 
"undefined") {
+                                       that.nodeTypesJson[nodeTypeName].name = 
nodeTypeName;
+               
+                                       /*
+                                        * Returns the child node definitions 
of the node type and those of all inherited node types.
+                                        * Definitions with the same child node 
name are returned if they differ in any other attribute.
+                                        */
+                                       
that.nodeTypesJson[nodeTypeName].getAllChildNodeDefinitions = function(){
+                                               var allCollectedChildNodeDefs = 
[];
+                                               var 
allCollectedChildNodeDefHashes = [];
+                                               processNodeTypeGraph.call(that, 
this, 'declaredSupertypes', function(currentNodeType){
+                                                       if 
(currentNodeType.declaredChildNodeDefinitions == null) return;
+                                                       for (var 
childNodeDefIndex in currentNodeType.declaredChildNodeDefinitions) {
+                                                               var 
childNodeDef = currentNodeType.declaredChildNodeDefinitions[childNodeDefIndex];
+                                                               var 
childNodeDefName = childNodeDef.name;
+                                                               var hashCode = 
childNodeDef.hashCode();
+                                                               // in case the 
child has the same child node definition as its parent (supertype)
+                                                               var processed = 
allCollectedChildNodeDefHashes.indexOf(hashCode) >= 0;
+                                                               if (!processed){
+                                                                       
allCollectedChildNodeDefHashes.push(hashCode);
+                                                                       
allCollectedChildNodeDefs.push(childNodeDef);
+                                                               }
+                                                       }
+                                               }); 
+                                               return 
allCollectedChildNodeDefs;
+                                       };
+                                       /*
+                                        * Returns the property definitions of 
the node type and those of all inherited node types.
+                                        * Definitions with the same property 
name are returned if they differ in any other attribute. 
+                                        */
+                                       
that.nodeTypesJson[nodeTypeName].getAllPropertyDefinitions = function(){
+                                               var allCollectedPropertyDefs = 
[];
+                                               var 
allCollectedPropertyDefHashes = [];
+                                               processNodeTypeGraph.call(that, 
this, 'declaredSupertypes', function(currentNodeType){
+                                                       if 
(currentNodeType.declaredPropertyDefinitions == null) return;
+                                                       for (var 
propertyDefIndex in currentNodeType.declaredPropertyDefinitions) {
+                                                               var propertyDef 
= currentNodeType.declaredPropertyDefinitions[propertyDefIndex];
+                                                               var 
propertyDefName = propertyDef.name;
+                                                               var hashCode = 
propertyDef.hashCode();
+                                                               // in case the 
child has the same property definition as its parent (supertype)
+                                                               var processed = 
allCollectedPropertyDefHashes.indexOf(hashCode) >= 0;
+                                                               if (!processed){
+                                                                       
allCollectedPropertyDefHashes.push(hashCode);
+                                                                       
allCollectedPropertyDefs.push(propertyDef);
+                                                               }
+                                                       }
+                                               });
+                                               return allCollectedPropertyDefs;
+                                       };
+               
+                                       /*
+                                        * Returns `true` if a node with the 
specified node name and node type can be added as a child node of the current 
node type. 
+                                        * 
+                                        * The first parameter is the string of 
the node name and 
+                                        * the second parameter is a node type 
object (not a string).
+                                        */
+                                       
that.nodeTypesJson[nodeTypeName].canAddChildNode = function(nodeName, 
nodeTypeToAdd){
+                                               if (nodeName==null || 
nodeTypeToAdd==null) return false;
+                                               var allChildNodeDefNames = [];
+                                               
processApplicableChildNodeTypes(that, this, function(cnDef, nodeTypeName){
+                                                       if (cnDef.name === 
nodeName) {
+                                                               
allChildNodeDefNames.push(nodeName);
+                                                       }
+                                               });
+                                               var canAddChildNode = false;
+                                               
processApplicableChildNodeTypes(that, this, function(cnDef, nodeTypeName){
+                                                       var 
noNonRisidualWithThatName = allChildNodeDefNames.indexOf(nodeName)<0;
+                                                       var nodeNameMatches = 
(nodeName === cnDef.name) || ("*" === cnDef.name && noNonRisidualWithThatName); 
+                                                       var 
canAddToCurrentCnDef = !cnDef.protected && nodeNameMatches && 
nodeTypeToAdd.name === nodeTypeName;
+                                                       canAddChildNode = 
canAddChildNode || canAddToCurrentCnDef; 
+                                               });
+                                               return canAddChildNode;
+                                       }
+               
+                                       /*
+                                        * Returns `true` if a property with 
the specified name and type can be to the current node type. 
+                                        * 
+                                        * The first parameter is the string of 
the property name and 
+                                        * the second parameter is the property 
type (case insensitive).
+                                        */
+                                       
that.nodeTypesJson[nodeTypeName].canAddProperty = function(propertyName, 
propertyType){
+                                               if (propertyName == null || 
propertyType == null) return false;
+                                               var allPropertyDefNames = [];
+                                               processNodeTypeGraph.call(that, 
this, 'declaredSupertypes', function(currentNodeType){
+                                                       if 
(currentNodeType.declaredPropertyDefinitions == null) return;
+                                                   for (var propDefIndex in 
currentNodeType.declaredPropertyDefinitions) {
+                                                               var propDef = 
currentNodeType.declaredPropertyDefinitions[propDefIndex];
+                                                               
allPropertyDefNames.push(propDef.name);
+                                                   }
+                                               }); 
+                                               var canAddProperty = false;
+                                               processNodeTypeGraph.call(that, 
this, 'declaredSupertypes', function(currentNodeType){
+                                                       if 
(currentNodeType.declaredPropertyDefinitions == null) return;
+                                                   for (var propDefIndex=0; 
canAddProperty === false && propDefIndex < 
currentNodeType.declaredPropertyDefinitions.length; propDefIndex++) {
+                                                               var propDef = 
currentNodeType.declaredPropertyDefinitions[propDefIndex];
+                                                               var 
noNonRisidualWithThatName = allPropertyDefNames.indexOf(propertyName)<0;
+                                                               var namesMatch 
= propDef.name === propertyName || ("*" === propDef.name && 
noNonRisidualWithThatName);
+                                                               var typesMatch 
= propDef.requiredType.toLowerCase() === propertyType.toLowerCase() || 
"undefined" === propDef.requiredType;
+                                                               var 
isNotProtected = !propDef.protected;
+                                                               canAddProperty 
= namesMatch && typesMatch && isNotProtected; 
+                                                   }
+                                               }); 
+                                               return canAddProperty;
+                                       };
+                                       
+                                       /*
+                                        * Returns all node types that can be 
used for child nodes of this node type and its super types.
+                                        * If a child node definition specifies 
multiple required primary types an applicable node type has
+                                        * to be a subtype of all of them. 
+                                        * The parameter is a boolean that 
specifies if mixins should be included or not. If no parameter is passed 'true' 
is assumed and mixins are
+                                        * returned as well.
+                                        */
+                                       
that.nodeTypesJson[nodeTypeName].getApplicableCnTypesPerCnDef = 
function(includeMixins){
+                                               var allApplChildNodeTypes = {};
+                                               
processApplicableChildNodeTypes(that, this, function(cnDef, nodeTypeName){
+                                                       var nodeType = 
that.getNodeType(nodeTypeName);
+                                                       if (typeof 
allApplChildNodeTypes[cnDef.name] === "undefined") {
+                                                               
allApplChildNodeTypes[cnDef.name] = {};
+                                                       }
+                                                       var includeAlsoMixins = 
typeof includeMixins === "undefined" || includeMixins;
+                                                       if (nodeType.mixin === 
true && includeAlsoMixins || !nodeType.mixin){
+                                                               
allApplChildNodeTypes[cnDef.name][nodeTypeName] = 
that.getNodeType(nodeTypeName);
+                                                       }
+                                               });
+                                               return allApplChildNodeTypes;
+                                       }
+                               };
+                               
+                               setDefaults.call(that, 
that.nodeTypesJson[nodeTypeName]);
+                               initializeChildNodeDefs.call(that);
+                               initializePropertyDefs.call(that);
+                       }
+               } catch (e){
+                       console.log("Error, the node types JSON is not an 
object"); 
+               };
+               function itemHashCode(item){
+                       var hash = "";
+                       hash += item.name;
+                       hash += item.autoCreated;
+                       hash += item.mandatory;
+                       hash += item.protected;
+                       hash += item.onParentVersion;
+                       return hash;
+               }
+
+               function initializeChildNodeDefs(){
+                       for (var childNodeDefIndex in 
that.nodeTypesJson[nodeTypeName].declaredChildNodeDefinitions) {
+                               var childNodeDef = 
that.nodeTypesJson[nodeTypeName].declaredChildNodeDefinitions[childNodeDefIndex];
+                               
+                               childNodeDef.hashCode = function (){
+                                       var hashCode = itemHashCode(this);
+                                       hashCode += this.allowsSameNameSiblings;
+                                       hashCode += this.defaultPrimaryType;
+                                       for (var reqPtIndex in 
this.requiredPrimaryTypes) {
+                                               hashCode += 
this.requiredPrimaryTypes[reqPtIndex];
+                                       }
+                                       return hashCode;
+                               }
+                       }
+               }
+
+               function initializePropertyDefs(){
+                       for (var propertyIndex in 
that.nodeTypesJson[nodeTypeName].declaredPropertyDefinitions) {
+                               var propertyDef = 
that.nodeTypesJson[nodeTypeName       
].declaredPropertyDefinitions[propertyIndex];
+                               
+                               propertyDef.hashCode = function (){
+                                       var hashCode = itemHashCode(this);
+                                       for (var defaultValueIndex in 
this.defaultValues) {
+                                               hashCode += 
this.defaultValues[defaultValueIndex];
+                                       }
+                                       for (var valueConstraintIndex in 
this.valueConstraints) {
+                                               hashCode += 
this.valueConstraints[valueConstraintIndex];
+                                       }
+                                       hashCode += this.requiredType;
+                                       hashCode += this.multiple;
+                                       return hashCode;
+                               }
+                       }
+               }
+               
+               /*
+                * Navigates to every node types' supertype and sets the 
subtype property there.
+                */
+               function addSubtypeRelation(nodeTypesJson){
+                       for (var nodeTypeName in nodeTypesJson) {
+                               nodeTypeJson = nodeTypesJson[nodeTypeName];
+                               for (var supertypeIndex in 
nodeTypeJson.declaredSupertypes) {
+                                       var supertypeName = 
nodeTypeJson.declaredSupertypes[supertypeIndex];
+                                       var supertype = 
this.getNodeType(supertypeName);
+                                       if (typeof supertype.subtypes === 
"undefined") {
+                                               supertype.subtypes = [];
+                                       }
+                                       supertype.subtypes.push(nodeTypeName);
+                               }
+                       }
+                       return nodeTypesJson;
+               }
+               addSubtypeRelation.call(that, that.nodeTypesJson);
+       }
+
+       
+       function processApplicableChildNodeTypes(ntManager, nodeType, 
functionToCall){
+               var cnDefs = nodeType.getAllChildNodeDefinitions();
+               for (var cnDefIndex in cnDefs) {
+                       var cnDef = cnDefs[cnDefIndex];
+                       var nodeTypesPerChildNodeDef = {};
+                       var reqChildNodeTypes = cnDef.requiredPrimaryTypes;
+                       for (var reqChildNodeTypeIndex in reqChildNodeTypes) {
+                               var childNodeTypeName = 
reqChildNodeTypes[reqChildNodeTypeIndex];
+                               var childNodeType = 
ntManager.getNodeType(childNodeTypeName);
+                               /* 
+                                * calls the function for every subtype of 
'childNodeType' but skips
+                                * node types that have already been processed 
(e.g. because of cycles)
+                                */
+                               processNodeTypeGraph.call(ntManager, 
childNodeType, 'subtypes', function(currentNodeType){
+                                       if (currentNodeType != null) {
+                                               // if 'true' the type has not 
yet been found in _one_of_the_ required primary type's subtype tree
+                                               // of the child node definition
+                                               var 
cnDefWithTypeNotYetProcessed = typeof 
nodeTypesPerChildNodeDef[currentNodeType.name] === "undefined";
+                                               // This increments the 
occurency count of a node type in the subtype hierarchy of a required primary 
type. 
+                                               
nodeTypesPerChildNodeDef[currentNodeType.name] = cnDefWithTypeNotYetProcessed ? 
1 : nodeTypesPerChildNodeDef[currentNodeType.name]+1; 
+                                       }
+                               }); 
+                               
+                       }
+                       for (var keyIndex in 
Object.keys(nodeTypesPerChildNodeDef)){
+                               var nodeTypeName = 
Object.keys(nodeTypesPerChildNodeDef)[keyIndex];
+                               /* 
+                                * If the type has been found in all iterations 
of the required primary types it means it is a subtype
+                                * of all of them and can be used for the child 
node definition.
+                                */
+                               var nodeTypeCountInThisChildNodeDef = 
nodeTypesPerChildNodeDef[nodeTypeName];
+                               var subtypeOfAllReqPrimaryTypes = 
nodeTypeCountInThisChildNodeDef === cnDef.requiredPrimaryTypes.length;
+                               if (subtypeOfAllReqPrimaryTypes){
+                                       functionToCall(cnDef, nodeTypeName);
+                               }
+                       }
+               }
+       }
+       
+       return NodeTypeManager;
+}());
\ No newline at end of file

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/ChildNodeDefGenerationTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/ChildNodeDefGenerationTest.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/ChildNodeDefGenerationTest.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/ChildNodeDefGenerationTest.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes;
+
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.servlet.ServletException;
+
+import org.apache.sling.commons.json.JSONException;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.sandroboehme.jsnodetypes.mock.MockNodeTypeGenerator;
+
+/**
+ * Tests if the servlet generates the combinations child node definitions in 
the correct JSON format. 
+ */
+public class ChildNodeDefGenerationTest extends MockNodeTypeGenerator{
+
+       @Before
+       public void setUp() throws RepositoryException, IOException{
+               super.setUp();
+       }
+       
+       @Test
+       public void testOneSimpleChildNodeDefinition() throws ServletException, 
IOException, JSONException{
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithChildNodeDefs");
+
+               NodeDefinition[] childNodeDefs = 
{getSimpleChildNodeDef("childNodeDef1")};
+               
when(ntWithChildNodeDefs.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               
assertEqualsWithServletResult("testOneSimpleChildNodeDefinition");
+       }
+       
+       @Test
+       public void testSimpleChildNodeDefinitions() throws ServletException, 
IOException, JSONException{
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithChildNodeDefs");
+
+               NodeDefinition childNodeDef1 = 
getSimpleChildNodeDef("childNodeDef1");
+               NodeDefinition childNodeDef2 = 
getSimpleChildNodeDef("childNodeDef2");
+               
+               NodeDefinition[] childNodeDefs = {childNodeDef1, childNodeDef2};
+               
when(ntWithChildNodeDefs.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testSimpleChildNodeDefinitions");
+       }
+       
+       @Test
+       public void testCompleteChildNodeDefinitions() throws ServletException, 
IOException, JSONException{
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithChildNodeDefs");
+
+               NodeDefinition childNodeDef1 = 
getCompleteChildNodeDef("childNodeDef1");
+               NodeDefinition childNodeDef2 = 
getCompleteChildNodeDef("childNodeDef2");
+               
+               NodeDefinition[] childNodeDefs = {childNodeDef1, childNodeDef2};
+               
when(ntWithChildNodeDefs.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               
assertEqualsWithServletResult("testCompleteChildNodeDefinitions");
+       }
+       
+       @Test
+       public void testResidualChildNodeDefinitions() throws JSONException, 
ServletException, IOException{
+               NodeType ntWithChildNOdeDefs = 
getSimpleNodeTypeWithName("ntWithChildNodeDefs");
+
+               NodeDefinition childNodeDef1 = getSimpleChildNodeDef("*");
+               NodeDefinition childNodeDef2 = getSimpleChildNodeDef("*");
+               NodeDefinition childNodeDef3 = 
getSimpleChildNodeDef("childNodeDef");
+               
+               NodeDefinition[] childNodeDefs = {childNodeDef1, childNodeDef2, 
childNodeDef3};
+               
when(ntWithChildNOdeDefs.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNOdeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               
assertEqualsWithServletResult("testResidualChildNodeDefinitions");
+       }
+
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/DefaultNodeTypeTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/DefaultNodeTypeTest.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/DefaultNodeTypeTest.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/DefaultNodeTypeTest.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.servlet.ServletException;
+
+import org.apache.sling.commons.json.JSONException;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.sandroboehme.jsnodetypes.mock.MockNodeTypeGenerator;
+
+/**
+ * Tests if the JSON is generated with the default values omitted.
+ */
+public class DefaultNodeTypeTest extends MockNodeTypeGenerator{
+       
+       @Before
+       public void setUp() throws RepositoryException, IOException{
+               super.setUp();
+       }
+
+       private String getDefaultNTJSON() throws IOException {
+               URL fileUri = 
MockNodeTypeGenerator.class.getResource("/SLING-INF/libs/jsnodetypes/js/defaultNT/defaultNT.json");
+               BufferedReader in = new BufferedReader(new 
FileReader(fileUri.getFile()));
+               String currentLine = null;
+               StringBuilder fileContent = new StringBuilder();
+               while ((currentLine = in.readLine()) != null) {
+                       fileContent.append(currentLine);
+               }
+               return fileContent.toString();
+       }
+
+       /**
+        * Simulates a node type in the repository that has only default values 
and checks if they are omitted in the generated
+        * JSON file. 
+        */
+       @Test
+       public void testIfDefaultsAreOmittedWithServlet() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType");
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+
+               NodeType ntBase = mock(NodeType.class);
+               when(ntBase.getName()).thenReturn("nt:base");
+
+               NodeDefinition childNodeDef1 = mock(NodeDefinition.class);
+               NodeType[] reqPrimaryTypes = { ntBase };
+               
when(childNodeDef1.getRequiredPrimaryTypes()).thenReturn(reqPrimaryTypes);
+               when(childNodeDef1.getName()).thenReturn("childNodeDef");
+               
+               NodeDefinition[] childNodeDefs = {childNodeDef1};
+               
when(nt1.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               String propertyName = "stringPropertyDef";
+               PropertyDefinition propertyDef = mock(PropertyDefinition.class);
+               
when(propertyDef.getRequiredType()).thenReturn(PropertyType.STRING);
+               when(propertyDef.getName()).thenReturn(propertyName);
+               
+               when(nt1.getDeclaredPropertyDefinitions()).thenReturn(new 
PropertyDefinition[]{propertyDef});
+
+               
assertEqualsWithServletResult("testIfDefaultsAreOmittedWithServlet");
+       }
+       
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/GenerationConstants.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/GenerationConstants.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/GenerationConstants.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/GenerationConstants.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ * Used by generators to generate the right content and by the test cases to 
compare if the right content has been returned.
+ *
+ */
+public class GenerationConstants {
+       
+       public static final String CONSTRAINT_STRING = ".*";
+       private static final DateFormat df = new 
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");          
+       private static Calendar maxDate = Calendar.getInstance();
+       static {
+               maxDate.clear();
+               maxDate.set(2012, 03, 01);
+       }
+       public static final String CONSTRAINT_DATE = 
df.format(maxDate.getTime());
+       public static final String CONSTRAINT_DOUBLE = "[,5]";
+       public static final String CONSTRAINT_LONG = "[,55]";
+       public static final String CONSTRAINT_BINARY = "[,1024]";
+       public static final String CONSTRAINT_BOOLEAN = "true";
+       public static final String CONSTRAINT_NAME = "myapp:myName";
+       public static final String CONSTRAINT_PATH = 
"/myapp:myName/myapp:myChildNode/*";
+       public static final String CONSTRAINT_REFERENCE = "nt:unstructured";
+       
+       
+       public static final Calendar DEFAULT_VALUE_CALENDAR = 
Calendar.getInstance();
+       static {
+               DEFAULT_VALUE_CALENDAR.clear();
+               DEFAULT_VALUE_CALENDAR.set(2012, 01, 01);       
+       }
+       public static final String DEFAULT_VALUE_BINARY = 
"/ntName/stringPropertyDef/Binary/true/true/true/true/VERSION/0.default_binary_value.bin";
+       public static final String DEFAULT_VALUE_STRING = "Default-String";
+       public static final String DEFAULT_VALUE_BINARY_0 = "A content";
+       public static final String DEFAULT_VALUE_BINARY_1 = "An other content";
+       public static final Double DEFAULT_VALUE_DOUBLE = new Double(2.2);
+       public static final Long DEFAULT_VALUE_LONG = new Long(2);
+       public static final Boolean DEFAULT_VALUE_BOOLEAN = Boolean.TRUE;
+       public static final String DEFAULT_VALUE_NAME = "myapp:myName";
+       public static final String DEFAULT_VALUE_PATH = 
"/myapp:myName/myapp:myChildNode/aSubChildNode";
+       public static final String DEFAULT_VALUE_REFERENCE = "nt:unstructured";
+
+       public static final String NODETYPE_REQ_PRIMARY_TYPE_NAME1 = 
"requiredPrimaryType1";
+       public static final String NODETYPE_REQ_PRIMARY_TYPE_NAME2 = 
"requiredPrimaryType2";
+
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/NodeTypeGenerationTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/NodeTypeGenerationTest.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/NodeTypeGenerationTest.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/NodeTypeGenerationTest.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.OnParentVersionAction;
+import javax.servlet.ServletException;
+
+import org.apache.sling.commons.json.JSONException;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.sandroboehme.jsnodetypes.mock.MockNodeTypeGenerator;
+
+/**
+ * Tests if the servlet generates the combinations node type definitions in 
the correct JSON format.
+ */
+public class NodeTypeGenerationTest extends MockNodeTypeGenerator{
+       
+       @Before
+       public void setUp() throws RepositoryException, IOException{
+               super.setUp();
+       }
+
+       @Test
+       public void testSupertypeList() throws JSONException, ServletException, 
IOException{
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType");
+               NodeType[] superTypes = 
{getSimpleNodeTypeWithName("superType1"), 
getSimpleNodeTypeWithName("superType2"), 
getSimpleNodeTypeWithName("superType3")};
+               when(nt1.getDeclaredSupertypes()).thenReturn(superTypes);
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testSupertypeList");
+       }
+
+       @Test
+       public void testOneSimpleNodeType() throws ServletException, 
IOException, JSONException {
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType");
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testOneSimpleNodeType");
+       }
+
+       @Test
+       public void testSimpleNodeTypes() throws ServletException, IOException, 
JSONException {
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType1");
+               NodeType nt2 = getSimpleNodeTypeWithName("testNodeType2");
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1, nt2);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.TRUE, Boolean.TRUE, Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testSimpleNodeTypes");
+       }
+
+       @Test
+       public void testNodeTypeWithEmptyName() throws ServletException, 
IOException, JSONException {
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType1");
+               NodeType nt2 = getSimpleNodeTypeWithName(null);
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1, nt2);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.TRUE, Boolean.TRUE, Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testNodeTypeWithEmptyName");
+       }
+
+       @Test
+       public void testCompleteNodeTypes() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               NodeType nt1 = getSimpleNodeTypeWithName("testNodeType");
+               NodeType[] superTypes = 
{getSimpleNodeTypeWithName("superType1"), 
getSimpleNodeTypeWithName("superType2"), 
getSimpleNodeTypeWithName("superType3")};
+               NodeType nt2 = getSimpleNodeTypeWithName(null);
+               when(nt1.getDeclaredSupertypes()).thenReturn(superTypes);
+               when(nodeTypeIterator.nextNodeType()).thenReturn(nt1, nt2);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.TRUE, Boolean.TRUE, Boolean.FALSE);
+
+
+               NodeDefinition childNodeDef1 = 
getCompleteChildNodeDef("childNodeDef1");
+               NodeDefinition childNodeDef2 = 
getCompleteChildNodeDef("childNodeDef2");
+               
+               NodeDefinition[] childNodeDefs = {childNodeDef1, childNodeDef2};
+               
when(nt1.getDeclaredChildNodeDefinitions()).thenReturn(childNodeDefs);
+
+               String propertyName = "stringPropertyDef";
+               PropertyDefinition propertyDef = mock(PropertyDefinition.class);
+               
when(propertyDef.getOnParentVersion()).thenReturn(OnParentVersionAction.VERSION);
+               when(propertyDef.getName()).thenReturn(propertyName);
+               
when(propertyDef.getRequiredType()).thenReturn(PropertyType.STRING);
+               when(propertyDef.getValueConstraints()).thenReturn( new 
String[]{GenerationConstants.CONSTRAINT_STRING});
+               when(propertyDef.isMultiple()).thenReturn(Boolean.TRUE);
+               when(propertyDef.isProtected()).thenReturn(Boolean.TRUE);
+               Value defaultValue = mock(Value.class);
+               when(defaultValue.getType()).thenReturn(PropertyType.STRING);
+               
when(defaultValue.getString()).thenReturn(GenerationConstants.DEFAULT_VALUE_STRING);
+               when(propertyDef.getDefaultValues()).thenReturn(new 
Value[]{defaultValue});
+               when(propertyDef.isAutoCreated()).thenReturn(Boolean.TRUE);
+               when(propertyDef.isMandatory()).thenReturn(Boolean.TRUE);
+               
+               when(nt1.getDeclaredPropertyDefinitions()).thenReturn(new 
PropertyDefinition[]{propertyDef});
+
+               assertEqualsWithServletResult("testCompleteNodeTypes");
+       }
+
+       public void testCompletePropertyDefinition(PropertyDefinition[] 
propertyDef) throws JSONException, ServletException, IOException, 
ValueFormatException, IllegalStateException, RepositoryException{
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithPropertyDefs");
+
+               
when(ntWithChildNodeDefs.getDeclaredPropertyDefinitions()).thenReturn(propertyDef);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testCompletePropertyDefinition");
+       }
+       
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/PropertyDefGenerationTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/PropertyDefGenerationTest.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/PropertyDefGenerationTest.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/PropertyDefGenerationTest.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes;
+
+import static 
de.sandroboehme.jsnodetypes.GenerationConstants.CONSTRAINT_STRING;
+import static 
de.sandroboehme.jsnodetypes.GenerationConstants.DEFAULT_VALUE_STRING;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.servlet.ServletException;
+
+import org.apache.sling.commons.json.JSONException;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.sandroboehme.jsnodetypes.mock.MockNodeTypeGenerator;
+
+
+/**
+ * Tests if the servlet generates the combinations property definitions in the 
correct JSON format.
+ */
+public class PropertyDefGenerationTest extends MockNodeTypeGenerator{
+
+       @Before
+       public void setUp() throws RepositoryException, IOException{
+               super.setUp();
+       }
+
+       @Test
+       public void testCompleteBinaryPropertyDefinition() throws 
JSONException, ServletException, IOException, ValueFormatException, 
IllegalStateException, RepositoryException{
+               String propertyName = "stringPropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteBinaryPropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteBinaryPropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteStringPropertyDefinition() throws 
JSONException, ServletException, IOException, ValueFormatException, 
IllegalStateException, RepositoryException{
+               String propertyName = "stringPropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteStringPropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteStringPropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteDatePropertyDefinition() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               String propertyName = "datePropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteDatePropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteDatePropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteDoublePropertyDefinition() throws 
JSONException, ServletException, IOException, ValueFormatException, 
IllegalStateException, RepositoryException{
+               String propertyName = "doublePropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteDoublePropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteDoublePropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteLongPropertyDefinition() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               String propertyName = "longPropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteLongPropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteLongPropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteBooleanPropertyDefinition() throws 
JSONException, ServletException, IOException, ValueFormatException, 
IllegalStateException, RepositoryException{
+               String propertyName = "booleanPropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteBooleanPropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteBooleanPropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteNamePropertyDefinition() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               String propertyName = "namePropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteNamePropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteNamePropertyDefinition");
+       }
+
+       @Test
+       public void testCompletePathPropertyDefinition() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               String propertyName = "pathPropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompletePathPropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompletePathPropertyDefinition");
+       }
+
+       @Test
+       public void testCompleteReferencePropertyDefinition() throws 
JSONException, ServletException, IOException, ValueFormatException, 
IllegalStateException, RepositoryException{
+               String propertyName = "referencePropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getCompleteReferencePropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testCompleteReferencePropertyDefinition");
+       }
+
+       public void testCompletePropertyDefinition(PropertyDefinition[] 
propertyDef, String filename) throws JSONException, ServletException, 
IOException, ValueFormatException, IllegalStateException, RepositoryException{
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithPropertyDefs");
+
+               
when(ntWithChildNodeDefs.getDeclaredPropertyDefinitions()).thenReturn(propertyDef);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult(filename);
+       }
+
+
+       @Test
+       public void testOneSimplePropertyDefinition() throws JSONException, 
ServletException, IOException, ValueFormatException, IllegalStateException, 
RepositoryException{
+               String propertyName = "simplePropertyDef";
+               PropertyDefinition[] propertyDef = 
{getPropertyGenerator().getSimplePropertyDef(propertyName)};
+               testCompletePropertyDefinition(propertyDef, 
"testOneSimplePropertyDefinition");
+       }
+
+       @Test
+       public void testTwoResidualPropertyDefinitions() throws 
ValueFormatException, IllegalStateException, RepositoryException, 
JSONException, ServletException, IOException{
+               //Is only be possible for multi valued property defs
+               PropertyDefinition[] residualPropertyDefs = 
{getPropertyGenerator().getCompleteStringPropertyDef("*"), 
getPropertyGenerator().getCompleteDatePropertyDef("*")};
+
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithPropertyDefs");
+
+               
when(ntWithChildNodeDefs.getDeclaredPropertyDefinitions()).thenReturn(residualPropertyDefs);
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               
assertEqualsWithServletResult("testTwoResidualPropertyDefinitions");
+       }
+
+       @Test
+       public void testMultipleDefaultValues() throws ValueFormatException, 
IllegalStateException, RepositoryException, JSONException, ServletException, 
IOException{
+               Value defaultValue1 = mock(Value.class);
+               
when(defaultValue1.getString()).thenReturn(DEFAULT_VALUE_STRING);
+               Value defaultValue2 = mock(Value.class);
+               
when(defaultValue2.getString()).thenReturn(DEFAULT_VALUE_STRING+"2");
+               PropertyDefinition propertyDef = 
getPropertyGenerator().getPropertyDef("stringProp", PropertyType.STRING, new 
String[]{CONSTRAINT_STRING}, new Value[] {defaultValue1, defaultValue2});
+
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithPropertyDefs");
+
+               
when(ntWithChildNodeDefs.getDeclaredPropertyDefinitions()).thenReturn(new 
PropertyDefinition[]{propertyDef});
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult("testMultipleDefaultValues");
+       }
+
+       @Test
+       public void testMultipleConstraints() throws ValueFormatException, 
IllegalStateException, RepositoryException, JSONException, ServletException, 
IOException{
+               PropertyDefinition propertyDef = 
getPropertyGenerator().getPropertyDef("stringProp", PropertyType.STRING, new 
String[]{"banana", "apple"}, null);
+
+               NodeType ntWithChildNodeDefs = 
getSimpleNodeTypeWithName("ntWithPropertyDefs");
+
+               
when(ntWithChildNodeDefs.getDeclaredPropertyDefinitions()).thenReturn(new 
PropertyDefinition[]{propertyDef});
+
+               
when(nodeTypeIterator.nextNodeType()).thenReturn(ntWithChildNodeDefs);
+               when(nodeTypeIterator.hasNext()).thenReturn(Boolean.TRUE, 
Boolean.FALSE);
+               
+               assertEqualsWithServletResult( "testMultipleConstraints");
+       }
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/downloaddefaultbinary/DownloadDefaultBinaryValueTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/downloaddefaultbinary/DownloadDefaultBinaryValueTest.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/downloaddefaultbinary/DownloadDefaultBinaryValueTest.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/downloaddefaultbinary/DownloadDefaultBinaryValueTest.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes.downloaddefaultbinary;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.ValueFormatException;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.servlets.HttpConstants;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.sandroboehme.jsnodetypes.GenerationConstants;
+import 
de.sandroboehme.jsnodetypes.downloaddefaultbinary.DownloadDefaultBinaryValueServlet;
+import de.sandroboehme.jsnodetypes.mock.MockPropertyDefGenerator;
+
+/**
+ * Tests the DownloadDefaultBinaryValueServlet
+ *
+ */
+public class DownloadDefaultBinaryValueTest {
+
+       // mock classes
+       private SlingHttpServletRequest request = null;
+       private SlingHttpServletResponse response = null;
+       private Resource resource = null;
+       private Node rootNode = null;
+       private Session session = null;
+       private Workspace workspace = null;
+       private NodeTypeManager ntManager = null;
+       private ByteArrayOutputStream outStream = null;
+       private ResourceResolver resourceResolver = null;
+       private MockPropertyDefGenerator propDefGenerator = null;
+
+       @Before
+       public void setUp() throws RepositoryException, IOException{
+               // create mocks
+               request = mock(SlingHttpServletRequest.class);
+               response = mock(SlingHttpServletResponse.class);
+               resourceResolver = mock(ResourceResolver.class);
+               resource = mock(Resource.class);
+               rootNode = mock(Node.class);
+               session = mock(Session.class);
+               workspace = mock(Workspace.class);
+               ntManager = mock(NodeTypeManager.class);
+               outStream = new ByteArrayOutputStream();
+               
+               // stubbing
+               when(request.getMethod()).thenReturn(HttpConstants.METHOD_GET);
+               
when(request.getResourceResolver()).thenReturn(resourceResolver);
+               when(resourceResolver.getResource("/")).thenReturn(resource);
+               when(resource.adaptTo(Node.class)).thenReturn(rootNode);
+               when(rootNode.getSession()).thenReturn(session);
+               when(session.getWorkspace()).thenReturn(workspace);
+               when(workspace.getNodeTypeManager()).thenReturn(ntManager);
+               when(response.getWriter()).thenReturn(new 
PrintWriter(outStream, true));
+               propDefGenerator = new MockPropertyDefGenerator();
+       }
+
+       private void invokeServletWithDifferentPropertyDefs() throws 
NoSuchNodeTypeException, RepositoryException,
+                       ValueFormatException, ServletException, IOException {
+               NodeType nodeType = mock(NodeType.class);
+               when(ntManager.getNodeType("ns:ntName")).thenReturn(nodeType);
+               PropertyDefinition[] propDefs = 
propDefGenerator.getDifferentPropertyDefinitions();
+               when(nodeType.getPropertyDefinitions()).thenReturn(propDefs);
+               DownloadDefaultBinaryValueServlet downloadServlet = new 
DownloadDefaultBinaryValueServlet();
+               downloadServlet.service(request, response);
+       }
+
+       private void invokeServletWithEqualPropertyDefs() throws 
NoSuchNodeTypeException, RepositoryException,
+                       ValueFormatException, ServletException, IOException {
+               NodeType nodeType = mock(NodeType.class);
+               when(ntManager.getNodeType("ns:ntName")).thenReturn(nodeType);
+               PropertyDefinition[] propDefs = 
propDefGenerator.getEqualPropertyDefinitions();
+               when(nodeType.getPropertyDefinitions()).thenReturn(propDefs);
+               DownloadDefaultBinaryValueServlet downloadServlet = new 
DownloadDefaultBinaryValueServlet();
+               downloadServlet.service(request, response);
+       }
+       
+       @Test
+       public void testSuccessfulSingleMatchWithIndex() throws 
ServletException, IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/true/version/1.default_binary_value.bin");
+               invokeServletWithDifferentPropertyDefs();
+               verify(response, never()).sendError(anyInt());
+               Assert.assertEquals(GenerationConstants.DEFAULT_VALUE_BINARY_1, 
new String(outStream.toByteArray()));
+       }
+       
+       @Test
+       public void testSuccessfulSingleMatchWithoutIndex() throws 
ServletException, IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/true/version/default_binary_value.bin");
+               invokeServletWithDifferentPropertyDefs();
+               verify(response, never()).sendError(anyInt());
+               Assert.assertEquals(GenerationConstants.DEFAULT_VALUE_BINARY_0, 
new String(outStream.toByteArray()));
+       }
+       
+       @Test
+       public void testSuccessfulShortenedSingleMatchWithoutIndex() throws 
ServletException, IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/false/default_binary_value.bin");
+               testDifferentPropertyDefsWithExpectedBinary0();
+
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/false/default_binary_value.bin");
+               testDifferentPropertyDefsWithExpectedBinary0();
+
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/false/default_binary_value.bin");
+               testDifferentPropertyDefsWithExpectedBinary0();
+               
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/boolean/default_binary_value.bin");
+               testDifferentPropertyDefsWithExpectedBinary0();
+
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef2/default_binary_value.bin");
+               testDifferentPropertyDefsWithExpectedBinary0();
+       }
+
+       private void testDifferentPropertyDefsWithExpectedBinary0() throws 
NoSuchNodeTypeException, RepositoryException,
+                       ValueFormatException, ServletException, IOException {
+               invokeServletWithDifferentPropertyDefs();
+               verify(response, never()).sendError(anyInt());
+               Assert.assertEquals(GenerationConstants.DEFAULT_VALUE_BINARY_0, 
new String(outStream.toByteArray()));
+       }
+       
+       @Test
+       public void testSuccessfulSingleMatchWithInvalidIndex() throws 
ServletException, IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/true/version/5.default_binary_value.bin");
+               invokeServletWithDifferentPropertyDefs();
+               verify(response).sendError(HttpServletResponse.SC_NOT_FOUND);
+       }
+       
+       @Test
+       public void testUnsuccessfulMultipleMatches() throws ServletException, 
IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/true/version/5.default_binary_value.bin");
+               invokeServletWithEqualPropertyDefs();
+               verify(response).sendError(HttpServletResponse.SC_NOT_FOUND);
+       }
+       
+       @Test
+       public void testUnsuccessfulNoMatches() throws ServletException, 
IOException, NoSuchNodeTypeException, RepositoryException {
+               
when(request.getRequestURI()).thenReturn("/ns:ntName/binPropDef/binary/true/true/true/true/ignore/default_binary_value.bin");
+               invokeServletWithDifferentPropertyDefs();
+               verify(response).sendError(HttpServletResponse.SC_NOT_FOUND);
+       }
+       
+
+}

Added: 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/mock/MockNodeTypeGenerator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/mock/MockNodeTypeGenerator.java?rev=1660179&view=auto
==============================================================================
--- 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/mock/MockNodeTypeGenerator.java
 (added)
+++ 
sling/trunk/contrib/commons/js/nodetypes/src/test/java/de/sandroboehme/jsnodetypes/mock/MockNodeTypeGenerator.java
 Mon Feb 16 18:14:21 2015
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package de.sandroboehme.jsnodetypes.mock;
+
+import static 
de.sandroboehme.jsnodetypes.GenerationConstants.NODETYPE_REQ_PRIMARY_TYPE_NAME1;
+import static 
de.sandroboehme.jsnodetypes.GenerationConstants.NODETYPE_REQ_PRIMARY_TYPE_NAME2;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.version.OnParentVersionAction;
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HttpConstants;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.json.JSONTokener;
+
+import de.sandroboehme.jsnodetypes.NodeTypesJSONServlet;
+import de.sandroboehme.jsnodetypes.test.JSONAssert;
+
+/**
+ * Generates NodeType mocks that will be returned when the servlet calles
+ * NodeTypeManager.getAllNodeTypes(). It also mocks request, response, output
+ * stream and so on to simulate the environment the servlet needs at runtime.
+ * 
+ */
+public class MockNodeTypeGenerator {
+
+       // mock classes
+       protected SlingHttpServletRequest request = null;
+       protected SlingHttpServletResponse response = null;
+       protected Resource resource = null;
+       protected Node currentNode = null;
+       protected Session session = null;
+       protected Workspace workspace = null;
+       protected NodeTypeManager ntManager = null;
+       protected NodeTypeIterator nodeTypeIterator = null;
+       protected ByteArrayOutputStream outStream = null;
+       private MockPropertyDefGenerator propertyGenerator = new 
MockPropertyDefGenerator();
+
+       public void setUp() throws RepositoryException, IOException {
+               // create mocks
+               request = mock(SlingHttpServletRequest.class);
+               response = mock(SlingHttpServletResponse.class);
+               resource = mock(Resource.class);
+               currentNode = mock(Node.class);
+               session = mock(Session.class);
+               workspace = mock(Workspace.class);
+               ntManager = mock(NodeTypeManager.class);
+               nodeTypeIterator = mock(NodeTypeIterator.class);
+               outStream = new ByteArrayOutputStream();
+
+               // stubbing
+               when(request.getResource()).thenReturn(resource);
+               when(request.getMethod()).thenReturn(HttpConstants.METHOD_GET);
+               when(response.getWriter()).thenReturn(new 
PrintWriter(outStream, true));
+               when(resource.adaptTo(Node.class)).thenReturn(currentNode);
+               when(currentNode.getSession()).thenReturn(session);
+               when(session.getWorkspace()).thenReturn(workspace);
+               when(workspace.getNodeTypeManager()).thenReturn(ntManager);
+               when(ntManager.getAllNodeTypes()).thenReturn(nodeTypeIterator);
+
+       }
+
+       public MockPropertyDefGenerator getPropertyGenerator() {
+               return this.propertyGenerator;
+       }
+
+       public NodeDefinition getSimpleChildNodeDef(String name) {
+               NodeDefinition childNodeDef1 = mock(NodeDefinition.class);
+               NodeType[] reqPrimaryTypes = { 
getSimpleNodeTypeWithName(NODETYPE_REQ_PRIMARY_TYPE_NAME1),
+                               
getSimpleNodeTypeWithName(NODETYPE_REQ_PRIMARY_TYPE_NAME2) };
+               
when(childNodeDef1.getRequiredPrimaryTypes()).thenReturn(reqPrimaryTypes);
+               when(childNodeDef1.getName()).thenReturn(name);
+               
when(childNodeDef1.getOnParentVersion()).thenReturn(OnParentVersionAction.COPY);
+               return childNodeDef1;
+       }
+
+       public NodeDefinition getCompleteChildNodeDef(String name) {
+               NodeDefinition childNodeDef1 = mock(NodeDefinition.class);
+               NodeType requiredPrimaryType1 = 
getSimpleNodeTypeWithName(NODETYPE_REQ_PRIMARY_TYPE_NAME1);
+               NodeType requiredPrimaryType2 = 
getSimpleNodeTypeWithName(NODETYPE_REQ_PRIMARY_TYPE_NAME2);
+               NodeType[] reqPrimaryTypes = { requiredPrimaryType1, 
requiredPrimaryType2 };
+               
when(childNodeDef1.getRequiredPrimaryTypes()).thenReturn(reqPrimaryTypes);
+               when(childNodeDef1.getName()).thenReturn(name);
+               
when(childNodeDef1.getOnParentVersion()).thenReturn(OnParentVersionAction.VERSION);
+               
when(childNodeDef1.getDefaultPrimaryType()).thenReturn(requiredPrimaryType1);
+               
when(childNodeDef1.allowsSameNameSiblings()).thenReturn(Boolean.TRUE);
+               when(childNodeDef1.isAutoCreated()).thenReturn(Boolean.TRUE);
+               when(childNodeDef1.isMandatory()).thenReturn(Boolean.TRUE);
+               when(childNodeDef1.isProtected()).thenReturn(Boolean.TRUE);
+               return childNodeDef1;
+       }
+
+       public void assertEqualsWithServletResult(String filename) throws 
JSONException, ServletException,
+                       IOException {
+               NodeTypesJSONServlet generationServlet = new 
NodeTypesJSONServlet();
+               generationServlet.service(request, response);
+               verify(response, never()).sendError(anyInt());
+               String resultingJSON = new String(outStream.toByteArray(), 
"utf-8");
+
+
+               String expectedNTJSON = getExpectedNTJSON(filename);
+               
+               JSONObject actualJsonObjectFromServlet = new JSONObject(new 
JSONTokener(resultingJSON));
+
+               JSONAssert.assertEquals("Actual JSON: " + resultingJSON + 
"\nExpected JSON: " + expectedNTJSON, new JSONObject(
+                               new JSONTokener(expectedNTJSON)), 
actualJsonObjectFromServlet);
+       }
+
+       protected String getExpectedNTJSON(String filename) throws IOException {
+               URL fileUri = 
MockNodeTypeGenerator.class.getResource("/expectedNTJSON/"+filename+".json");
+               BufferedReader in = new BufferedReader(new 
FileReader(fileUri.getFile()));
+               String currentLine = null;
+               StringBuilder fileContent = new StringBuilder();
+               while ((currentLine = in.readLine()) != null) {
+                       fileContent.append(currentLine);
+               }
+               return fileContent.toString();
+       }
+
+       public NodeType getSimpleNodeTypeWithName(String nodeTypeName) {
+               NodeType nt1 = mock(NodeType.class);
+               NodeType supertype = mock(NodeType.class);
+               when(supertype.getName()).thenReturn("nt:base");
+               NodeType[] supertypes = { supertype };
+               when(nt1.getDeclaredSupertypes()).thenReturn(supertypes);
+               when(nt1.getName()).thenReturn(nodeTypeName);
+               return nt1;
+       }
+}


Reply via email to