docs: protected void parseNodeAttributes( TokenStream tokens,
                                          JcrNodeDefinitionTemplate childDefn,
                                          JcrNodeTypeTemplate nodeType ) throws ConstraintViolationException {
          boolean autoCreated = false;
          boolean mandatory = false;
          boolean isProtected = false;
          boolean sns = false;
          String onParentVersion = "COPY";
          while (true) {
              if (tokens.canConsumeAnyOf("AUTOCREATED", "AUT", "A")) {
                  tokens.canConsume('?');
                  autoCreated = true;
              } else if (tokens.canConsumeAnyOf("MANDATORY", "MAN", "M")) {
                  tokens.canConsume('?');
                  mandatory = true;
              } else if (tokens.canConsumeAnyOf("PROTECTED", "PRO", "P")) {
                  tokens.canConsume('?');
                  isProtected = true;
              } else if (tokens.canConsumeAnyOf("SNS", "*")) { // standard JCR 2.0 keywords for SNS ...
                  tokens.canConsume('?');
                  sns = true;
              } else if (tokens.canConsumeAnyOf("MULTIPLE", "MUL", "*")) { // from pre-JCR 2.0 ref impl
                  Position pos = tokens.previousPosition();
                  int line = pos.getLine();
                  int column = pos.getColumn();
                  throw new ParsingException(tokens.previousPosition(),
                                             CndI18n.multipleKeywordNotValidInJcr2CndFormat.text(line, column));
              } else if (tokens.matchesAnyOf(VALID_ON_PARENT_VERSION)) {
                  onParentVersion = tokens.consume();
                  tokens.canConsume('?');
              } else if (tokens.matches("OPV")) {
                  // variant on-parent-version
                  onParentVersion = tokens.consume();
                  tokens.canConsume('?');
              } else if (tokens.canConsumeAnyOf("PRIMARYITEM", "PRIMARY", "PRI", "!")) {
                  Position pos = tokens.previousPosition();
                  int line = pos.getLine();
                  int column = pos.getColumn();
                  throw new ParsingException(tokens.previousPosition(),
                                             CndI18n.primaryKeywordNotValidInJcr2CndFormat.text(line, column));
              } else if (tokens.matches(CndTokenizer.VENDOR_EXTENSION)) {
                  List<Property> properties = new LinkedList<Property>();
                  parseVendorExtensions(tokens, properties);
                  applyVendorExtensions(childDefn, properties);
              } else {
                  break;
              }
          }
          childDefn.setAutoCreated(autoCreated);
          childDefn.setMandatory(mandatory);
          childDefn.setProtected(isProtected);
          childDefn.setOnParentVersion(OnParentVersionAction.valueFromName(onParentVersion.toUpperCase(Locale.ROOT)));
          childDefn.setSameNameSiblings(sns);
      }