// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/Constants.java
// public class Constants {
//     public static final String INGREDIENT = "INGREDIENT";
//     public static final String RECIPE = "RECIPE";
//     public static final String ALL = "ALL";
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/CookBookQuery.java
// public interface CookBookQuery {
//     boolean getAllFields();
//     List<String> getFields();
//     String getEntity();
//     List<String> getCriteria();
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/Dsql.java
// public class Dsql implements CookBookQuery{
//     private final Pattern queryPattern = Pattern.compile("GET (.*) FROM ([\\w]*)( MATCHING (.*))?");
// 
//     private final Matcher matcher;
// 
//     public static Dsql newInstance(String query){
//         return new Dsql(query);
//     }
// 
//     private Dsql(String query){
//         matcher=queryPattern.matcher(query);
//         if(!matcher.matches()){
//             throw new RuntimeException("Don't know how to process:"+query);
//         }
//     }
// 
//     @Override
//     public boolean getAllFields() {
//         return matcher.group(1).equals(Constants.ALL);
//     }
// 
//     @Override
//     public List<String> getFields() {
//         return Arrays.asList(matcher.group(1).split(","));
//     }
// 
//     @Override
//     public String getEntity() {
//         return matcher.group(2);
//     }
// 
//     @Override
//     public List<String> getCriteria() {
//         if(matcher.groupCount()==4 && matcher.group(4)!=null) {
//             return Arrays.asList(matcher.group(4).split(","));
//         }
//         return Collections.EMPTY_LIST;
//     }
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/DsqlParser.java
// @BuildParseTree
// public class DsqlParser extends BaseParser<Object>{
// 
//     public Rule Statement(){
//         return Sequence(
//                 String("GET"),
//                 Ch(' '),
//                 Fields(),
//                 Ch(' '),
//                 String("FROM"),
//                 Ch(' '),
//                 Entities(),
//                 Clause(),
//                 EOI
//         );
//     }
// 
//     public Rule Fields() {
//         return FirstOf(
//                 String("ALL"), OneOrMore(
//                         Sequence(
//                                 Field(), ZeroOrMore(Ch(','), Field()))
//                 )
//         );
//     }
// 
//     public Rule Entities(){
//         return FirstOf(String(Constants.INGREDIENT),String(Constants.RECIPE));
//     }
// 
//     public Rule Clause(){
//         return Optional(
//                 Sequence(
//                         Ch(' '),
//                         String("MATCHING"),
//                         Ch(' '),
//                         Sequence(
//                                 Comparison(),ZeroOrMore(Ch(','),Comparison())
//                         )
//                 )
//         );
//     }
// 
//     public Rule Field(){
//         return FirstOf(
//                 String("id"),
//                 String("created"),
//                 String("lastModified"),
//                 String("name"),
//                 String("quantity"),
//                 String("unit"),
//                 String("prepTime"),
//                 String("cookTime"),
//                 String("ingredients")
//         );
//     }
// 
// 
//     public Rule Comparison(){
//         return FirstOf(
//                 Sequence(AlphaNumeric(), Spacing(), Operator(),Spacing(), Field()), Sequence(Field(),Spacing(), Operator(),Spacing(), AlphaNumeric()));
//     }
// 
//     public Rule Operator(){
//         return FirstOf(
//                 String("=="),
//                 String("<>"),
//                 String(">"),
//                 String("<"),
//                 String(">="),
//                 String("<="),
//                 String("contains")
//         );
//     }
// 
//     public Rule AlphaNumeric(){
//         return OneOrMore(FirstOf(CharRange('a','z'),CharRange('0','9'))
//         );
//     }
// 
//     public Rule Spacing(){
//         return ZeroOrMore(Ch(' '));
//     }
// 
// }


import com.cookbook.tutorial.internal.dsql.Constants;
import com.cookbook.tutorial.internal.dsql.CookBookQuery;
import com.cookbook.tutorial.internal.dsql.Dsql;
import com.cookbook.tutorial.internal.dsql.DsqlParser;
import com.cookbook.tutorial.service.*;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.cxf.common.util.CollectionUtils;
import org.parboiled.Parboiled;
import org.parboiled.common.FileUtils;
import org.parboiled.parserunners.ReportingParseRunner;
import org.parboiled.support.ParsingResult;
import javax.jws.WebParam;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import java.lang.reflect.Type;
import java.util.*;

    @Override
    public List<CookBookEntity> addList(@WebParam(name = "entities", targetNamespace = "") List<CookBookEntity> entities)
            throws InvalidEntityException {
        for (CookBookEntity entity : entities) {
            create(entity);
        }
        return entities;
    }

    @Override
    public List<CookBookEntity> searchWithQuery(@WebParam(name = "query", targetNamespace = "") String query, @WebParam(name = "page", targetNamespace = "") Integer page,
            @WebParam(name = "pageSize", targetNamespace = "") Integer pageSize) throws InvalidRequestException {

        DsqlParser parser = Parboiled.createParser(DsqlParser.class);
        ParsingResult<?> result = new ReportingParseRunner(parser.Statement()).run(query);
        if (result.hasErrors()) {
            throw new InvalidRequestException(result.parseErrors.get(0).getErrorMessage());
        }
        List<CookBookEntity> searchResult = new ArrayList<>();
        CookBookQuery cookBookQuery = Dsql.newInstance(query);
        if(pageSize==null){
            throw new InvalidRequestException("Need to specify a page size");
        }
        Integer currentCount = 0;
        Integer skipCount = 0;
        Integer addedCount = 0;
        if(page!=null){
            skipCount=page*pageSize;
        }
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/Constants.java
// public class Constants {
//     public static final String INGREDIENT = "INGREDIENT";
//     public static final String RECIPE = "RECIPE";
//     public static final String ALL = "ALL";
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/CookBookQuery.java
// public interface CookBookQuery {
//     boolean getAllFields();
//     List<String> getFields();
//     String getEntity();
//     List<String> getCriteria();
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/Dsql.java
// public class Dsql implements CookBookQuery{
//     private final Pattern queryPattern = Pattern.compile("GET (.*) FROM ([\\w]*)( MATCHING (.*))?");
// 
//     private final Matcher matcher;
// 
//     public static Dsql newInstance(String query){
//         return new Dsql(query);
//     }
// 
//     private Dsql(String query){
//         matcher=queryPattern.matcher(query);
//         if(!matcher.matches()){
//             throw new RuntimeException("Don't know how to process:"+query);
//         }
//     }
// 
//     @Override
//     public boolean getAllFields() {
//         return matcher.group(1).equals(Constants.ALL);
//     }
// 
//     @Override
//     public List<String> getFields() {
//         return Arrays.asList(matcher.group(1).split(","));
//     }
// 
//     @Override
//     public String getEntity() {
//         return matcher.group(2);
//     }
// 
//     @Override
//     public List<String> getCriteria() {
//         if(matcher.groupCount()==4 && matcher.group(4)!=null) {
//             return Arrays.asList(matcher.group(4).split(","));
//         }
//         return Collections.EMPTY_LIST;
//     }
// }
// 
// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/dsql/DsqlParser.java
// @BuildParseTree
// public class DsqlParser extends BaseParser<Object>{
// 
//     public Rule Statement(){
//         return Sequence(
//                 String("GET"),
//                 Ch(' '),
//                 Fields(),
//                 Ch(' '),
//                 String("FROM"),
//                 Ch(' '),
//                 Entities(),
//                 Clause(),
//                 EOI
//         );
//     }
// 
//     public Rule Fields() {
//         return FirstOf(
//                 String("ALL"), OneOrMore(
//                         Sequence(
//                                 Field(), ZeroOrMore(Ch(','), Field()))
//                 )
//         );
//     }
// 
//     public Rule Entities(){
//         return FirstOf(String(Constants.INGREDIENT),String(Constants.RECIPE));
//     }
// 
//     public Rule Clause(){
//         return Optional(
//                 Sequence(
//                         Ch(' '),
//                         String("MATCHING"),
//                         Ch(' '),
//                         Sequence(
//                                 Comparison(),ZeroOrMore(Ch(','),Comparison())
//                         )
//                 )
//         );
//     }
// 
//     public Rule Field(){
//         return FirstOf(
//                 String("id"),
//                 String("created"),
//                 String("lastModified"),
//                 String("name"),
//                 String("quantity"),
//                 String("unit"),
//                 String("prepTime"),
//                 String("cookTime"),
//                 String("ingredients")
//         );
//     }
// 
// 
//     public Rule Comparison(){
//         return FirstOf(
//                 Sequence(AlphaNumeric(), Spacing(), Operator(),Spacing(), Field()), Sequence(Field(),Spacing(), Operator(),Spacing(), AlphaNumeric()));
//     }
// 
//     public Rule Operator(){
//         return FirstOf(
//                 String("=="),
//                 String("<>"),
//                 String(">"),
//                 String("<"),
//                 String(">="),
//                 String("<="),
//                 String("contains")
//         );
//     }
// 
//     public Rule AlphaNumeric(){
//         return OneOrMore(FirstOf(CharRange('a','z'),CharRange('0','9'))
//         );
//     }
// 
//     public Rule Spacing(){
//         return ZeroOrMore(Ch(' '));
//     }
// 
// }


// Path: soap-server/src/main/java/com/cookbook/tutorial/internal/service/CookBookDefaultBackEndImp.java
import com.cookbook.tutorial.internal.dsql.Constants;
import com.cookbook.tutorial.internal.dsql.CookBookQuery;
import com.cookbook.tutorial.internal.dsql.Dsql;
import com.cookbook.tutorial.internal.dsql.DsqlParser;
import com.cookbook.tutorial.service.*;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.cxf.common.util.CollectionUtils;
import org.parboiled.Parboiled;
import org.parboiled.common.FileUtils;
import org.parboiled.parserunners.ReportingParseRunner;
import org.parboiled.support.ParsingResult;
import javax.jws.WebParam;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import java.lang.reflect.Type;
import java.util.*;


    @Override
    public List<CookBookEntity> addList(@WebParam(name = "entities", targetNamespace = "") List<CookBookEntity> entities)
            throws InvalidEntityException {
        for (CookBookEntity entity : entities) {
            create(entity);
        }
        return entities;
    }

    @Override
    public List<CookBookEntity> searchWithQuery(@WebParam(name = "query", targetNamespace = "") String query, @WebParam(name = "page", targetNamespace = "") Integer page,
            @WebParam(name = "pageSize", targetNamespace = "") Integer pageSize) throws InvalidRequestException {

        DsqlParser parser = Parboiled.createParser(DsqlParser.class);
        ParsingResult<?> result = new ReportingParseRunner(parser.Statement()).run(query);
        if (result.hasErrors()) {
            throw new InvalidRequestException(result.parseErrors.get(0).getErrorMessage());
        }
        List<CookBookEntity> searchResult = new ArrayList<>();
        CookBookQuery cookBookQuery = Dsql.newInstance(query);
        if(pageSize==null){
            throw new InvalidRequestException("Need to specify a page size");
        }
        Integer currentCount = 0;
        Integer skipCount = 0;
        Integer addedCount = 0;
        if(page!=null){
            skipCount=page*pageSize;
        }
        if (cookBookQuery.getEntity().equals(Constants.INGREDIENT)) {