/* JavaCC grammar for the SLING-5449 content repository 
 * initialization language
 * See https://javacc.github.io/javacc/ for the most recent docs,
 *   including links to grammar examples
 * See http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm for a FAQ from 2011
 * See also http://eriklievaart.com/web/javacc1.html (from 2014) for additional information
 */
 
options
{
    STATIC=false;
    LOOKAHEAD=3;
    //FORCE_LA_CHECK=true;
    //DEBUG_PARSER=true;
    //DEBUG_LOOKAHEAD=true;
}

PARSER_BEGIN(RepoInitParserImpl)

package org.apache.sling.repoinit.parser.impl;

import java.util.List;
import java.util.ArrayList;

import org.apache.sling.repoinit.parser.operations.*;
import org.apache.sling.repoinit.parser.impl.WithPathOptions;

/*
 * 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.
 */

public class RepoInitParserImpl 
{
}
PARSER_END(RepoInitParserImpl)

SKIP :
{
    " "
|   "\r"
|   "\t"
|   < COMMENT: "#" (~["\n"])* "\n" >
}

TOKEN:
{
    < SET: "set" >
|   < ACL: "ACL" >
|   < ACE: "ACE" >
|   < ON: "on" >
|   < TO: "to" >
|   < FROM: "from" >
|   < REMOVE: "remove" >
|   < ALLOW: "allow" >
|   < DENY: "deny" >
|   < FOR: "for" >
|   < CREATE: "create" >
|   < DELETE: "delete" >
|   < DISABLE: "disable" >
|   < SERVICE: "service" >
|   < ADD: "add" >
|   < MIXIN: "mixin" >
|   < PATH: "path" >
|   < END: "end" >
|   < REPOSITORY: "repository" >
|   < PRINCIPAL: "principal" >
|   < USER: "user" >
|   < GROUP: "group" >
|   < NODETYPES: "nodetypes" >
|   < REGISTER: "register" >
|   < NAMESPACE: "namespace" >
|   < PRIVILEGE: "privilege" >
|   < WITH: "with" >
|   < ABSTRACT: "abstract" >
|   < PASSWORD: "password" >
|   < START_TEXTBLOCK: "<<===" > : TEXTBLOCK
|   < LPAREN: "(" >
|   < RPAREN: ")" >
|   < LCURLY: "{" >
|   < RCURLY: "}" >
|   < MULTI: "[]" >
|   < COMMA: "," >
|   < DQUOTE: "\"" >
|   < COLON: ":" >
|   < STAR: "*" >
|   < EQUALS: "=" >
|   < RESTRICTION: "restriction" >
|   < ACL_OPTIONS: "ACLOptions" >
|   < PROPERTIES: "properties" >
|   < SETDEF: "default" >
|   < FORCED: "forced" >

/* The order of these fuzzy statements is important (first match wins?) */ 
|   < NAMESPACED_ITEM: (["a"-"z"] | ["A"-"Z"])+ ":" (["a"-"z"] | ["A"-"Z"])+ >
|   < PATH_STRING: "/" (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | ["-"] | ["_"] | ["."] | ["@"] | [":"] | ["+"] | ["/"]) * >
|   < PATH_REPOSITORY: ":repository" >
|   < STRING: (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | ["-"] | ["_"] | ["."] | ["/"] | [":"] | ["*"]) + >
|   < EOL: "\n" >
}

/* Found out about this syntax later - would make STRING etc. simpler */
TOKEN: {
<QUOTED: 
    <DQUOTE>
    (
         "\\" ~[]     // escaped chars
    |
        ~["\\","\""]  //any char but not backslash nor quote
    )* 
    <DQUOTE>
    > 
}

<TEXTBLOCK> SKIP : 
{
    "\r"
}

<TEXTBLOCK> TOKEN :
{
    < TEXT : ~[] > 
|   < END_TEXTBLOCK: "===>>" > : DEFAULT
} 

List<Operation> parse() :
{}
{
    { final List<Operation> result = new ArrayList<Operation>(); }
    
    ( 
        serviceUserStatement(result) 
        | setAclPaths(result) 
        | setAclPrincipals(result)
        | setAclPrincipalBased(result)
        | setAclRepository(result)
        | deleteAclPaths(result) 
        | deleteAclPrincipals(result)
        | deleteAclPrincipalBased(result)
        | removeAcePaths(result) 
        | removeAcePrincipals(result)
        | removeAcePrincipalBased(result)
        | createPathStatement(result)
        | registerNamespaceStatement(result)
        | registerNodetypesStatement(result)
        | registerPrivilegeStatement(result)
        | createGroupStatement(result)
        | deleteGroupStatement(result)
        | createUserStatement(result)
        | deleteUserStatement(result)
        | disableUserStatement(result)
        | addToGroupStatement(result)
        | removeFromGroupStatement(result)
        | setPropertiesStatement(result)
        | blankLine() 
    ) * 
    <EOF>
    
    { return result; }
}

void blankLine() :
{}
{
    <EOL>
}

List<String> principalsList() :
{
    Token t = null;
    List<String> principals = new ArrayList<String>(); 
}
{
    t = quotableString() { principals.add(t.image); } 
    ( <COMMA> t = quotableString() { principals.add(t.image); } )* 
    { return principals; }
}

WithPathOptions withPathStatement() :
{
    Token path = null;
    Token forced = null;
}
{
    /* accept relative (string) or absolute path */
    <WITH> (forced=<FORCED>)? <PATH> ( path=<STRING> | path=<PATH_STRING> )
    { return new WithPathOptions(path.image, forced != null); }
}

void serviceUserStatement(List<Operation> result) :
{
    Token t;
    List<String> principals;
    WithPathOptions wpopt = null;
}
{
    (t=<CREATE> | t=<DELETE>) 
    <SERVICE> <USER> 
    principals = principalsList() 
    ( wpopt = withPathStatement() ) ?
    (<EOL> | <EOF>)
    
    {
        for(String principal : principals) {
            if(CREATE == t.kind) {
                result.add(new CreateServiceUser(principal, wpopt));
            } else {
                result.add(new DeleteServiceUser(principal));
            }
        } 
    }
}

List<String> namespacedItemsList() :
{
    Token t = null;
    List<String> priv = new ArrayList<String>(); 
    
}
{
    t = <NAMESPACED_ITEM> { priv.add(t.image); } 
    ( <COMMA> t = <NAMESPACED_ITEM> { priv.add(t.image); } )* 
    { return priv; }
}

List<String> privilegesList() :
{
    Token t = null;
    List<String> priv = new ArrayList<String>();
}
{
    ( t=<NAMESPACED_ITEM> | t=<STRING> ) { priv.add(t.image); }
    ( <COMMA> ( t=<NAMESPACED_ITEM> | t=<STRING> ) { priv.add(t.image); } )*
    { return priv; }
}

String usernameList() :
{
    List<String> names = new ArrayList<String>();
    Token t = null;
}
{
    ( t = quotableString() ) { names.add(t.image); }
    // disable lists for now, not supported downstream
    // ( <COMMA> t = <STRING> { names.add(t.image); }) *

    {
        return String.join(",", names);
    }
}

String pathExpression() : 
{
    Token t = null;
    Token tf = null;
    String usernames = null;
    final StringBuilder sb = new StringBuilder();
}
{
    ( 
        tf = <STRING> <LPAREN> usernames = usernameList() <RPAREN> ( t = <PATH_STRING> ) ? 
        | ( t = <PATH_STRING> 
        | t = <PATH_REPOSITORY> )
    )
    { 
        if(tf != null) {
            sb.append(':').append(tf.image).append(':').append(usernames).append('#');
        }
        if(t != null) {
            sb.append(t.image);
        }
    }

    { return sb.toString(); }
}

List<String> pathsList() :
{
    String pathExpr = null;
    List<String> paths = new ArrayList<String>();
}
{
    ( pathExpr = pathExpression() ) { paths.add(pathExpr); }
    ( <COMMA> ( pathExpr = pathExpression() ) { paths.add(pathExpr); } )*
    { return paths; }
}

void createPathStatement(List<Operation> result) :
{
    CreatePath cp = null;
    String defaultPrimaryType = null;
    Token t1 = null;
    Token t2 = null;
    List<String> t3 = null;
    List<PropertyLine> lines = new ArrayList<PropertyLine>();
}
{
    <CREATE> <PATH> 
    ( <LPAREN> t1 = <NAMESPACED_ITEM> <RPAREN> { defaultPrimaryType = t1.image; } ) ?
    
    ( t1 = <PATH_STRING> ( <LPAREN> t2 = <NAMESPACED_ITEM> <RPAREN> ) ?
                         ( <LPAREN> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ?
                         ( <LPAREN> t2 = <NAMESPACED_ITEM> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ?
        {
            if(cp == null) {
                cp = new CreatePath(defaultPrimaryType);
            } 
            cp.addSegment(t1.image, t2 == null ? null : t2.image, t3);
            t2 = null;
            t3 = null;
        }
    ) +
    ( <WITH> <PROPERTIES> <EOL>
      ( propertyLine(lines) | blankLine() ) +
      {
        cp.setPropertyLines(lines);
      }
      <END>
    )?
    (<EOL> | <EOF>)
    
    { if(cp != null) result.add(cp); }
}

void setAclPaths(List<Operation> result) :
{
    List<String> paths;
    List<AclLine> lines = new ArrayList<AclLine>();
    List<String> aclOptions;
} 
{
    <SET> <ACL> <ON> paths  = pathsList() aclOptions=aclOptions() <EOL>
    ( removeStarLine(lines) | userPrivilegesLine(lines, true) | blankLine() ) +
    <END> 
    ( <EOL> | <EOF> )
    
    {
        result.add(new SetAclPaths(paths, lines, aclOptions));
    }
}

void removeStarLine(List<AclLine> lines) : 
{
    List<String> tmp = null;
    AclLine line = new AclLine(AclLine.Action.REMOVE_ALL);
}
{
    <REMOVE> <STAR> 
    (
        <FOR> tmp = principalsList() { line.setProperty(AclLine.PROP_PRINCIPALS, tmp); }
        
        | <ON> tmp = pathsList() { line.setProperty(AclLine.PROP_PATHS, tmp); }
    )     
    <EOL>
    
    {
        lines.add(line);
    }
}

AclLine privilegesLineOperation(boolean supportsRemoveAction) :
{  
}
{
    ( 
        <REMOVE>        { 
if (supportsRemoveAction) { 
    return new AclLine(AclLine.Action.REMOVE); 
} else { 
    throw new ParseException("REMOVE action not supported with 'remove acl' statements.");
}}
        | ( <ALLOW>     { return new AclLine(AclLine.Action.ALLOW); } )
        | ( <DENY>      { return new AclLine(AclLine.Action.DENY); } )    
    ) 
}

void userPrivilegesLine(List<AclLine> lines, boolean supportsRemoveAction) :
{
    AclLine line;
    List<String> tmp;
    List<RestrictionClause> restrictions;
}
{
    line = privilegesLineOperation(supportsRemoveAction)
    tmp = privilegesList() { line.setProperty(AclLine.PROP_PRIVILEGES, tmp); }
    <FOR>
    tmp = principalsList() { line.setProperty(AclLine.PROP_PRINCIPALS, tmp); }
    restrictions = restrictions()  { line.setRestrictions(restrictions); }
    <EOL>

    {   
        lines.add(line); 
    }
}
/**
 * A single restriction value
 */
void restrictionValue(List<String> values) :
{
   Token t;
}
{
   <COMMA> ( t=<STAR> | t=<NAMESPACED_ITEM> | t=<PATH_STRING> | t=<STRING> )
   {
       values.add(t.image);
   }
}

/**
 * A list of restriction values
 */
List<String> restrictionValues() :
{
    List<String> values = new ArrayList<String>();
}
{
    ( restrictionValue(values) ) *

    {
        return values;
    }

}


/**
 * A single restriction
 */
void restriction(List<RestrictionClause> restrictions) :
{
  Token restrictionProp;
  List<String> values;
}
{
  <RESTRICTION>
  <LPAREN> restrictionProp=<NAMESPACED_ITEM> values=restrictionValues()  <RPAREN>

  {
      restrictions.add(new RestrictionClause(restrictionProp.image,values));
  }
}

/**
 * A list of restrictions
 */
List<RestrictionClause> restrictions() :
{
    List<RestrictionClause> restrictions = new ArrayList<RestrictionClause>();
}
{
   ( restriction(restrictions) )*

   {
       return restrictions;
   }
}

void pathPrivilegesLine(List<AclLine> lines, boolean supportsRemoveAction) : 
{
    AclLine line;
    List<String> tmp;
    List<RestrictionClause> restrictions;
}
{
    line = privilegesLineOperation(supportsRemoveAction)
    tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_PRIVILEGES, tmp); } 
    <ON> tmp = pathsList() { line.setProperty(AclLine.PROP_PATHS, tmp); }
    ( <NODETYPES> tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_NODETYPES, tmp); }) ?
     restrictions = restrictions()  { line.setRestrictions(restrictions); }
    <EOL>
    
    {    
        lines.add(line); 
    }
}
void aclOption(List<String> options) :
{
   Token t;
}
{
    (t=<NAMESPACED_ITEM> | t=<STRING>)
    {
        options.add(t.image);
    }
}
List<String> aclOptions() :
{
    List<String> aclOptionList = new ArrayList<String>();
    Token t;
}
{
    ( <LPAREN> <ACL_OPTIONS> <EQUALS> aclOption(aclOptionList) ( <COMMA> aclOption(aclOptionList) )*  <RPAREN> )?

    {
       return aclOptionList;
    }
}

void setAclRepository(List<Operation> result) :
{
    List<AclLine> lines = new ArrayList<AclLine>();
    List<String> principals;
    List<String> privileges;
    List<String> aclOptions;
    AclLine line = null;

}
{
    <SET> <REPOSITORY> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL>
    (
        ( <REMOVE> <STAR> )
            {
                line = new AclLine(AclLine.Action.REMOVE_ALL);
                lines.add(line);
            }
        | ( line = privilegesLineOperation(true) privileges = namespacedItemsList() )
            {
                line.setProperty(AclLine.PROP_PRIVILEGES, privileges);
                lines.add(line);
            }
        | ( blankLine() )
    )+
    <END>
    ( <EOL> | <EOF> )

    {
        result.add(new SetAclPrincipals(principals, lines, aclOptions));
    }
}

void setAclPrincipals(List<Operation> result) :
{
    List <String> principals;
    List<AclLine> lines = new ArrayList<AclLine>();
    List<String> aclOptions;
}
{
    <SET> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL>
    ( removeStarLine(lines) | pathPrivilegesLine(lines, true) | blankLine() ) +
    <END> 
    ( <EOL> | <EOF> )
    
    {
        result.add(new SetAclPrincipals(principals, lines, aclOptions));
    }
}

void setAclPrincipalBased(List<Operation> result) :
{
    List <String> principals;
    List<AclLine> lines = new ArrayList<AclLine>();
    List<String> aclOptions;
}
{
    <SET> <PRINCIPAL> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL>
    ( removeStarLine(lines) | pathPrivilegesLine(lines, true) | blankLine() ) +
    <END>
    ( <EOL> | <EOF> )

    {
        result.add(new SetAclPrincipalBased(principals, lines, aclOptions));
    }
}

void removeAcePaths(List<Operation> result) :
{
    List<String> paths;
    List<AclLine> lines = new ArrayList<AclLine>();
} 
{
    <REMOVE> <ACE> <ON> paths  = pathsList()<EOL>
    ( userPrivilegesLine(lines, false) | blankLine() ) +
    <END> 
    ( <EOL> | <EOF> )
    
    {
    result.add(new RemoveAcePaths(paths, lines));
}
}

void removeAcePrincipals(List<Operation> result) :
{
    List <String> principals;
    List<AclLine> lines = new ArrayList<AclLine>();
}
{
    <REMOVE> <ACE> <FOR> principals = principalsList()<EOL>
    ( pathPrivilegesLine(lines, false) | blankLine() ) +
    <END> 
    ( <EOL> | <EOF> )
    
    {
    result.add(new RemoveAcePrincipals(principals, lines));
}
}

void removeAcePrincipalBased(List<Operation> result) :
{
    List <String> principals;
    List<AclLine> lines = new ArrayList<AclLine>();
}
{
    <REMOVE> <PRINCIPAL> <ACE> <FOR> principals = principalsList()<EOL>
    ( pathPrivilegesLine(lines, false) | blankLine() ) +
    <END>
    ( <EOL> | <EOF> )

    {
    result.add(new RemoveAcePrincipalBased(principals, lines));
}
}

void deleteAclPaths(List<Operation> result) :
{
    List<String> paths;
} 
{
    <DELETE> <ACL> <ON> paths  = pathsList()
    ( <EOL> | <EOF> )  
    {
        result.add(new DeleteAclPaths(paths));
    }
}

void deleteAclPrincipals(List<Operation> result) :
{
    List <String> principals;
}
{
    <DELETE> <ACL> <FOR> principals = principalsList()
    ( <EOL> | <EOF> )
    {
        result.add(new DeleteAclPrincipals(principals));
    }
}

void deleteAclPrincipalBased(List<Operation> result) :
{
    List <String> principals;
}
{
    <DELETE> <PRINCIPAL> <ACL> <FOR> principals = principalsList()
    ( <EOL> | <EOF> )
    {
        result.add(new DeleteAclPrincipalBased(principals));
    }
}

void registerNamespaceStatement(List<Operation> result) :
{
    Token prefix = null;
    Token uri;
}
{
    <REGISTER> <NAMESPACE> 
    <LPAREN> prefix = <STRING> <RPAREN> 
    uri = quotableString()

    {
        result.add(new RegisterNamespace(prefix.image, uri.image)); 
    }
    
    (<EOL> | <EOF>)
}

void registerPrivilegeStatement(List<Operation> result) :
{
    Token privilege;
    boolean isAbstract = false;
    List<String> aggregates = new ArrayList<String>();
}
{
    <REGISTER> ((<ABSTRACT>) {isAbstract = true;})? <PRIVILEGE> (privilege = <STRING> | privilege = <NAMESPACED_ITEM>) (<WITH> aggregates = privilegesList())?
    {
        result.add(new RegisterPrivilege(privilege.image, isAbstract, aggregates));
    }
    (<EOL> | <EOF>)
}

void textBlock(StringBuilder b) : 
{
    Token t;
}
{
    <START_TEXTBLOCK>
    ( t = <TEXT> { b.append(t.image); } )*
    <END_TEXTBLOCK>
}

void registerNodetypesStatement(List<Operation> result) :
{
    StringBuilder b = new StringBuilder();
}
{
    <REGISTER> <NODETYPES> <EOL> 
    textBlock(b) 
    (<EOL> | <EOF>)
    {
        result.add(new RegisterNodetypes(b.toString()));
    }
}

void createGroupStatement(List<Operation> result) :
{
    Token group = null;
    Token encoding = null;
    WithPathOptions wpopt = null;
}
{
    <CREATE> <GROUP> 
    ( group = quotableString() )
    ( wpopt = withPathStatement() ) ?

    {
        result.add(new CreateGroup(group.image, wpopt));
    }
}

void deleteGroupStatement(List<Operation> result) :
{
    Token group = null;
}
{
    <DELETE> <GROUP> 
    ( group = quotableString() )

    {
        result.add(new DeleteGroup(group.image));
    }
}

void createUserStatement(List<Operation> result) :
{
    Token user = null;
    Token encoding = null;
    Token password = null;
    WithPathOptions wpopt = null;
}
{
    <CREATE> <USER> 
    ( user = <STRING> )
    ( wpopt = withPathStatement() ) ?
    ( <WITH> <PASSWORD> ( <LCURLY> encoding = <STRING> <RCURLY> )? password = <STRING> )?

    {
        result.add(new CreateUser(user.image, 
            (encoding == null ? null : encoding.image), 
            (password == null ? null : password.image),
            wpopt
        ));
    }
}

void deleteUserStatement(List<Operation> result) :
{
    Token user = null;
}
{
    <DELETE> <USER> 
    ( user = <STRING> )

    {
        result.add(new DeleteUser(user.image));
    }
}

Token quotedString() :
{
    Token t = null;
}
{
    ( t = <QUOTED> )
    {
        // Remove start/end quotes + escaping backslash for double quotes
        final String unescaped = t.image.trim()
            .replaceAll("^\"|\"$", "")
            .replaceAll("\\\\\"", "\"")
            .replaceAll("\\\\\\\\", "\\\\")
        ;
        return new Token(t.kind, unescaped);
    }
}

void disableUserStatement(List<Operation> result) :
{
    Token user = null;
    Token msg = null;
    Token isServiceUser = null;
}
{
    <DISABLE> ( isServiceUser = <SERVICE> )? <USER>
    ( user = <STRING> )
    ( <COLON> msg = quotedString() )
    {
        DisableServiceUser dsu = new DisableServiceUser(user.image, msg.image);
        dsu.setServiceUser(isServiceUser != null);
        result.add(dsu);
    }
}

void addToGroupStatement(List<Operation> result) :
{
    List <String> members;
    Token t;
    Token group = null;
}
{
    <ADD>
    members =  principalsList()
    <TO> <GROUP>
    group = quotableString()

    {
        result.add(new AddGroupMembers(members, group.image));
    }
}

void removeFromGroupStatement(List<Operation> result) :
{
    List <String> members;
    Token t;
    Token group = null;
}
{
    <REMOVE>
    members =  principalsList()
    <FROM> <GROUP>
    group = quotableString()

    {
        result.add(new RemoveGroupMembers(members, group.image));
    }
}

Token quotableString() :
{
    Token t = null;
}
{
    (t = <STRING> | t = quotedString() ) { return t; }
}

Token propertyValue() :
{
    Token t = null;
}
{
    (t = <STRING> | t = quotedString() | t = <PATH_STRING> | t = <NAMESPACED_ITEM> ) { return t; }
}

List<String> propertyValuesList() :
{
    Token t = null;
    List<String> values = new ArrayList<String>();
}
{
    (( t = propertyValue() ) { values.add(t.image); })?
    ( <COMMA> ( t = propertyValue() ) { values.add(t.image); } )*
    { return values; }
}

void propertyLine(List<PropertyLine> lines) :
{
    Token name = null;
    Token type = null;
    List<String> values;
    Token t = null;
    boolean isDefault = false;
}
{
    (t = <SET> | t = <SETDEF> {isDefault = true;} )
    ( name = <STRING> | name = <NAMESPACED_ITEM>)
    ( <LCURLY> ( type = <STRING> ) <RCURLY> | <LCURLY> ( type = <STRING> ) <MULTI> <RCURLY> )?
    <TO> ( values = propertyValuesList() )
    <EOL>
    {
        lines.add(new PropertyLine(name.image, type == null ? null : type.image, values, isDefault));
    }
}

void setPropertiesStatement(List<Operation> result) :
{
    List<PropertyLine> lines = new ArrayList<PropertyLine>();
    List<String> paths;
}
{
    <SET> <PROPERTIES> <ON>  ( paths  = pathsList() ) <EOL>
    ( propertyLine(lines) | blankLine() ) +
    <END>
    ( <EOL> | <EOF> )
    {
        result.add(new SetProperties(paths, lines));
    }
}