/**
  * creates a node state for the given property def
  *
  * @param parent
  * @param propDef
  * @return
  * @throws RepositoryException
  */
 private VirtualNodeState createPropertyDefState(
     VirtualNodeState parent, QPropertyDefinition propDef, QNodeTypeDefinition ntDef, int n)
     throws RepositoryException {
   NodeId id =
       calculateStableId(
           ntDef.getName().toString()
               + "/"
               + NameConstants.JCR_PROPERTYDEFINITION.toString()
               + "/"
               + n);
   VirtualNodeState pState =
       createNodeState(
           parent, NameConstants.JCR_PROPERTYDEFINITION, id, NameConstants.NT_PROPERTYDEFINITION);
   // add properties
   if (!propDef.definesResidual()) {
     pState.setPropertyValue(NameConstants.JCR_NAME, InternalValue.create(propDef.getName()));
   }
   pState.setPropertyValue(
       NameConstants.JCR_AUTOCREATED, InternalValue.create(propDef.isAutoCreated()));
   pState.setPropertyValue(
       NameConstants.JCR_MANDATORY, InternalValue.create(propDef.isMandatory()));
   pState.setPropertyValue(
       NameConstants.JCR_ONPARENTVERSION,
       InternalValue.create(OnParentVersionAction.nameFromValue(propDef.getOnParentVersion())));
   pState.setPropertyValue(
       NameConstants.JCR_PROTECTED, InternalValue.create(propDef.isProtected()));
   pState.setPropertyValue(NameConstants.JCR_MULTIPLE, InternalValue.create(propDef.isMultiple()));
   pState.setPropertyValue(
       NameConstants.JCR_REQUIREDTYPE,
       InternalValue.create(PropertyType.nameFromValue(propDef.getRequiredType()).toUpperCase()));
   InternalValue[] defVals = InternalValue.create(propDef.getDefaultValues());
   // retrieve the property type from the first default value present with
   // the property definition. in case no default values are defined,
   // fallback to PropertyType.STRING in order to avoid creating a property
   // with type UNDEFINED which is illegal.
   int defValsType = PropertyType.STRING;
   if (defVals != null && defVals.length > 0) {
     defValsType = defVals[0].getType();
   }
   if (defVals != null) {
     pState.setPropertyValues(NameConstants.JCR_DEFAULTVALUES, defValsType, defVals);
   }
   QValueConstraint[] vc = propDef.getValueConstraints();
   InternalValue[] vals = new InternalValue[vc.length];
   for (int i = 0; i < vc.length; i++) {
     vals[i] = InternalValue.create(vc[i].getString());
   }
   pState.setPropertyValues(NameConstants.JCR_VALUECONSTRAINTS, PropertyType.STRING, vals);
   return pState;
 }
  /**
   * Creates a node type state
   *
   * @param parent
   * @param ntDef
   * @return
   * @throws RepositoryException
   */
  private VirtualNodeState createNodeTypeState(VirtualNodeState parent, QNodeTypeDefinition ntDef)
      throws RepositoryException {
    NodeId id = calculateStableId(ntDef.getName().toString());
    VirtualNodeState ntState =
        createNodeState(parent, ntDef.getName(), id, NameConstants.NT_NODETYPE);

    // add properties
    ntState.setPropertyValue(NameConstants.JCR_NODETYPENAME, InternalValue.create(ntDef.getName()));
    ntState.setPropertyValues(
        NameConstants.JCR_SUPERTYPES,
        PropertyType.NAME,
        InternalValue.create(ntDef.getSupertypes()));
    ntState.setPropertyValue(NameConstants.JCR_ISMIXIN, InternalValue.create(ntDef.isMixin()));
    ntState.setPropertyValue(
        NameConstants.JCR_HASORDERABLECHILDNODES,
        InternalValue.create(ntDef.hasOrderableChildNodes()));
    if (ntDef.getPrimaryItemName() != null) {
      ntState.setPropertyValue(
          NameConstants.JCR_PRIMARYITEMNAME, InternalValue.create(ntDef.getPrimaryItemName()));
    }

    // add property defs
    QPropertyDefinition[] propDefs = ntDef.getPropertyDefs();
    for (int i = 0; i < propDefs.length; i++) {
      VirtualNodeState pdState = createPropertyDefState(ntState, propDefs[i], ntDef, i);
      ntState.addChildNodeEntry(NameConstants.JCR_PROPERTYDEFINITION, pdState.getNodeId());
      // add as hard reference
      ntState.addStateReference(pdState);
    }

    // add child node defs
    QNodeDefinition[] cnDefs = ntDef.getChildNodeDefs();
    for (int i = 0; i < cnDefs.length; i++) {
      VirtualNodeState cnState = createChildNodeDefState(ntState, cnDefs[i], ntDef, i);
      ntState.addChildNodeEntry(NameConstants.JCR_CHILDNODEDEFINITION, cnState.getNodeId());
      // add as hard reference
      ntState.addStateReference(cnState);
    }

    return ntState;
  }
 /**
  * creates a node state for the given child node def
  *
  * @param parent
  * @param cnDef
  * @return
  * @throws RepositoryException
  */
 private VirtualNodeState createChildNodeDefState(
     VirtualNodeState parent, QNodeDefinition cnDef, QNodeTypeDefinition ntDef, int n)
     throws RepositoryException {
   NodeId id =
       calculateStableId(
           ntDef.getName().toString()
               + "/"
               + NameConstants.JCR_CHILDNODEDEFINITION.toString()
               + "/"
               + n);
   VirtualNodeState pState =
       createNodeState(
           parent,
           NameConstants.JCR_CHILDNODEDEFINITION,
           id,
           NameConstants.NT_CHILDNODEDEFINITION);
   // add properties
   if (!cnDef.definesResidual()) {
     pState.setPropertyValue(NameConstants.JCR_NAME, InternalValue.create(cnDef.getName()));
   }
   pState.setPropertyValue(
       NameConstants.JCR_AUTOCREATED, InternalValue.create(cnDef.isAutoCreated()));
   pState.setPropertyValue(NameConstants.JCR_MANDATORY, InternalValue.create(cnDef.isMandatory()));
   pState.setPropertyValue(
       NameConstants.JCR_ONPARENTVERSION,
       InternalValue.create(OnParentVersionAction.nameFromValue(cnDef.getOnParentVersion())));
   pState.setPropertyValue(NameConstants.JCR_PROTECTED, InternalValue.create(cnDef.isProtected()));
   pState.setPropertyValues(
       NameConstants.JCR_REQUIREDPRIMARYTYPES,
       PropertyType.NAME,
       InternalValue.create(cnDef.getRequiredPrimaryTypes()));
   if (cnDef.getDefaultPrimaryType() != null) {
     pState.setPropertyValue(
         NameConstants.JCR_DEFAULTPRIMARYTYPE,
         InternalValue.create(cnDef.getDefaultPrimaryType()));
   }
   pState.setPropertyValue(
       NameConstants.JCR_SAMENAMESIBLINGS, InternalValue.create(cnDef.allowsSameNameSiblings()));
   return pState;
 }