/* JavaCC grammar for the SLING-5449 content repository 
 * initialization language
 * See https://javacc.java.net/doc/docindex.html for the JavaCC docs
 * and http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm for the FAQ
 */
 
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.*;

/*
 * 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" >
|   < ON: "on" >
|   < REMOVE: "remove" >
|   < ALLOW: "allow" >
|   < DENY: "deny" >
|   < FOR: "for" >
|   < CREATE: "create" >
|   < DELETE: "delete" >
|   < DISABLE: "disable" >
|   < SERVICE: "service" >
|   < MIXIN: "mixin" >
|   < PATH: "path" >
|   < END: "end" >
|   < REPOSITORY: "repository" >
|   < USER: "user" >
|   < NODETYPES: "nodetypes" >
|   < REGISTER: "register" >
|   < NAMESPACE: "namespace" >
|   < WITH: "with" >
|   < PASSWORD: "password" >
|   < START_TEXTBLOCK: "<<===" > : TEXTBLOCK
|   < LPAREN: "(" >
|   < RPAREN: ")" >
|   < LCURLY: "{" >
|   < RCURLY: "}" >
|   < COMMA: "," >
|   < DQUOTE: "\"" >
|   < COLON: ":" >
|   < STAR: "*" >
|   < EQUALS: "=" >
|   < RESTRICTION: "restriction" >
|   < ACL_OPTIONS: "ACLOptions" >

/* 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"] | ["-"] | ["_"] | ["."] | ["@"] | [":"] | ["+"] | ["/"]) * >
|   < 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)
        | setAclRepository(result)
        | createPathStatement(result)
        | registerNamespaceStatement(result)
        | registerNodetypesStatement(result)
        | createUserStatement(result)
        | deleteUserStatement(result)
        | disableServiceUserStatement(result)
        | blankLine() 
    ) * 
    <EOF>
    
    { return result; }
}

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

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

String withPathStatement() :
{
    Token t = null;
}
{
    /* accept relative (string) or absolute path */
    <WITH> <PATH> ( t=<STRING> | t=<PATH_STRING> )
    { return t.image; }
}

void serviceUserStatement(List<Operation> result) :
{
    Token t;
    List<String> principals;
    String path = null;
}
{
    (t=<CREATE> | t=<DELETE>) 
    <SERVICE> <USER> 
    principals = principalsList() 
    ( path = withPathStatement() ) ?
    (<EOL> | <EOF>)
    
    {
        for(String principal : principals) {
            if(CREATE == t.kind) {
                result.add(new CreateServiceUser(principal, path));
            } 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> pathsList() :
{
    Token t = null;
    List<String> paths = new ArrayList<String>();
}
{
    t = <PATH_STRING> { paths.add(t.image); } 
    ( <COMMA> t = <PATH_STRING> { paths.add(t.image); } )* 
    { return paths; }
}

void createPathStatement(List<Operation> result) :
{
    CreatePath cp = null;
    String defaultPrimaryType = null;
    Token t1 = null;
    Token t2 = null;
    List<String> t3 = null;
}
{
    <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;
        }
    ) +
    
    (<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) | 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() :
{}
{
    ( 
        <REMOVE>        { return new AclLine(AclLine.Action.REMOVE); }
        | ( <ALLOW>     { return new AclLine(AclLine.Action.ALLOW); } )
        | ( <DENY>      { return new AclLine(AclLine.Action.DENY); } )    
    ) 
}

void userPrivilegesLine(List<AclLine> lines) :
{
    AclLine line;
    List<String> tmp;
    List<RestrictionClause> restrictions;
}
{
    line = privilegesLineOperation()
    tmp = namespacedItemsList() { 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) : 
{
    AclLine line;
    List<String> tmp;
    List<RestrictionClause> restrictions;
}
{
    line = privilegesLineOperation()
    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() 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) | blankLine() ) +
    <END> 
    ( <EOL> | <EOF> )
    
    {
        result.add(new SetAclPrincipals(principals, lines, aclOptions));
    }
}

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

    {
        result.add(new RegisterNamespace(prefix.image, uri.image)); 
    }
    
    (<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 createUserStatement(List<Operation> result) :
{
    Token user = null;
    Token encoding = null;
    Token password = null;
    String path = null;
}
{
    <CREATE> <USER> 
    ( user = <STRING> )
    ( path = 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),
            path
        ));
    }
}

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

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

void disableServiceUserStatement(List<Operation> result) :
{
    Token user = null;
    Token msg = null;
}
{
    <DISABLE> <SERVICE> <USER> 
    ( user = <STRING> )
    ( <COLON> msg = <QUOTED> )
    {
        result.add(new DisableServiceUser(user.image, msg == null ? null : msg.image));
    }
}
