getNodeBoundaries = function (node, initialNode) {
    var schemaKey = null;
    var arrayKey = null;
    var boundaries = {
      minItems: -1,
      maxItems: -1
    };
    initialNode = initialNode || node;

    if (node.view && node.view.array && (node !== initialNode)) {
      // New array level not linked to an array in the schema,
      // so no size constraints
      return boundaries;
    }

    if (node.key) {
      // Note the conversion to target the actual array definition in the
      // schema where minItems/maxItems may be defined. If we're still looking
      // at the initial node, the goal is to convert from:
      //  foo[0].bar[3].baz to foo[].bar[].baz
      // If we're not looking at the initial node, the goal is to look at the
      // closest array parent:
      //  foo[0].bar[3].baz to foo[].bar
      arrayKey = node.key.replace(/\[[0-9]+\]/g, '[]');
      if (node !== initialNode) {
        arrayKey = arrayKey.replace(/\[\][^\[\]]*$/, '');
      }
      schemaKey = getSchemaKey(
        node.ownerTree.formDesc.schema.properties,
        arrayKey
      );
      if (!schemaKey) return boundaries;
      return {
        minItems: schemaKey.minItems || schemaKey.minLength || -1,
        maxItems: schemaKey.maxItems || schemaKey.maxLength || -1
      };
    }
    else {
      _.each(node.children, function (child) {
        var subBoundaries = getNodeBoundaries(child, initialNode);
        if (subBoundaries.minItems !== -1) {
          if (boundaries.minItems !== -1) {
            boundaries.minItems = Math.max(
              boundaries.minItems,
              subBoundaries.minItems
            );
          }
          else {
            boundaries.minItems = subBoundaries.minItems;
          }
        }
        if (subBoundaries.maxItems !== -1) {
          if (boundaries.maxItems !== -1) {
            boundaries.maxItems = Math.min(
              boundaries.maxItems,
              subBoundaries.maxItems
            );
          }
          else {
            boundaries.maxItems = subBoundaries.maxItems;
          }
        }
      });
    }
    return boundaries;
  }
Returns the minimum/maximum number of items that an array field
is allowed to have according to the schema definition of the fields
it contains.

The function parses the schema definitions of the array items that
compose the current "array" node and returns the minimum value of
"maxItems" it encounters as the maximum number of items, and the
maximum value of "minItems" as the minimum number of items.

The function reports a -1 for either of the boundaries if the schema
does not put any constraint on the number of elements the current
array may have of if the current node is not an array.

Note that array boundaries should be defined in the JSON Schema using
"minItems" and "maxItems". The code also supports "minLength" and
"maxLength" as a fallback, mostly because it used to by mistake (see #22)
and because other people could make the same mistake.

@function
@return {Object} An object with properties "minItems" and "maxItems"
 that reports the corresponding number of items that the array may
 have (value is -1 when there is no constraint for that boundary)