Return-Path: X-Original-To: apmail-sling-commits-archive@www.apache.org Delivered-To: apmail-sling-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A7100CC7D for ; Fri, 14 Nov 2014 14:07:34 +0000 (UTC) Received: (qmail 63553 invoked by uid 500); 14 Nov 2014 14:07:34 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 63492 invoked by uid 500); 14 Nov 2014 14:07:34 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 63483 invoked by uid 99); 14 Nov 2014 14:07:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Nov 2014 14:07:34 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Nov 2014 14:07:29 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id EF25C2388B71; Fri, 14 Nov 2014 14:05:13 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1639641 [6/15] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/ engine/src/main/ engine/src/main/antlr4/ engine/src/main/antlr4/org/ engine/src/main/antlr4/org/apache/ engine/src/main/antlr4/org/apache/sling/ engine/src/... Date: Fri, 14 Nov 2014 14:05:03 -0000 To: commits@sling.apache.org From: bdelacretaz@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20141114140513.EF25C2388B71@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Patterns.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Patterns.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Patterns.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Patterns.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.api.ris.command; + +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant; + +/** + * Usual command patterns + */ +public class Patterns { + + private static final String ALWAYS_FALSE_VAR = "always_false"; + + /** + * Inserts a sequence of commands that will ignore the rest of the stream until + * the end stream sequence is inserted + * @param stream - the stream + */ + public static void beginStreamIgnore(PushStream stream) { + stream.emit(new VariableBinding.Start(ALWAYS_FALSE_VAR, BooleanConstant.FALSE)); + stream.emit(new Conditional.Start(ALWAYS_FALSE_VAR, true)); + } + + /** + * Inserts a sequence of commands that cancels stream ignore + * @param stream - the input stream + */ + public static void endStreamIgnore(PushStream stream) { + stream.emit(Conditional.END); + stream.emit(VariableBinding.END); + } + + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Procedure.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Procedure.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Procedure.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/Procedure.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,96 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.api.ris.command; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; + +/** + * Commands that delimitate a procedure + */ +public class Procedure { + + public static class Start implements Command { + + private String name; + private Set parameters; + + public Start(String name, Set parameters) { + this.name = name; + this.parameters = new HashSet(parameters); + } + + public String getName() { + return name; + } + + public Set getParameters() { + return Collections.unmodifiableSet(parameters); + } + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + } + + public static final End END = new End(); + + public static final class End implements Command { + + private End() { + } + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + } + + public static class Call implements Command { + + private final String templateVariable; + private final String argumentsVariable; + + public Call(String templateVariable, String argumentsVariable) { + this.templateVariable = templateVariable; + this.argumentsVariable = argumentsVariable; + } + + public String getTemplateVariable() { + return templateVariable; + } + + public String getArgumentsVariable() { + return argumentsVariable; + } + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + } + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/VariableBinding.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/VariableBinding.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/VariableBinding.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/api/ris/command/VariableBinding.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.api.ris.command; + +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; +import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode; +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; + +/** + * Marks the binding of a variable. Must have a corresponding binding end later in the stream + */ +public class VariableBinding { + + public static class Start implements Command { + private String variableName; + private ExpressionNode expression; + + public Start(String variableName, ExpressionNode expression) { + this.variableName = variableName; + this.expression = expression; + } + + public String getVariableName() { + return variableName; + } + + public ExpressionNode getExpression() { + return expression; + } + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + + @Override + public String toString() { + return "VariableBinding.Start{" + + "variableName='" + variableName + '\'' + + ", expression=" + expression + + '}'; + } + } + + public static final End END = new End(); + + public static final class End implements Command { + + private End() { + } + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + + @Override + public String toString() { + return "VariableBinding.End{}"; + } + } + + public static final class Global implements Command { + + private final String variableName; + private final ExpressionNode expressionNode; + + public Global(String variableName, ExpressionNode expressionNode) { + this.variableName = variableName; + this.expressionNode = expressionNode; + } + + public String getVariableName() { + return variableName; + } + + public ExpressionNode getExpression() { + return expressionNode; + } + + + @Override + public void accept(CommandVisitor visitor) { + visitor.visit(this); + } + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/common/DefaultPluginInvoke.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/common/DefaultPluginInvoke.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/common/DefaultPluginInvoke.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/common/DefaultPluginInvoke.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,111 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.common; + +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke; +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; + +/** + * Empty implementation for plugin invocation. Use this to implement + * methods selectively. + * @see org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin + */ +public class DefaultPluginInvoke implements PluginInvoke { + + @Override + public void beforeElement(PushStream stream, String tagName) { + + } + + @Override + public void beforeTagOpen(PushStream stream) { + + } + + @Override + public void beforeAttributes(PushStream stream) { + + } + + @Override + public void beforeAttribute(PushStream stream, String attributeName) { + + } + + @Override + public void beforeAttributeValue(PushStream stream, String attributeName, ExpressionNode attributeValue) { + + } + + @Override + public void afterAttributeValue(PushStream stream, String attributeName) { + + } + + @Override + public void afterAttribute(PushStream stream, String attributeName) { + + } + + @Override + public void onPluginCall(PushStream stream, PluginCallInfo callInfo, Expression expression) { + + } + + @Override + public void afterAttributes(PushStream stream) { + + } + + @Override + public void afterTagOpen(PushStream stream) { + + } + + @Override + public void beforeChildren(PushStream stream) { + + } + + @Override + public void afterChildren(PushStream stream) { + + } + + @Override + public void beforeTagClose(PushStream stream, boolean isSelfClosing) { + + } + + @Override + public void afterTagClose(PushStream stream, boolean isSelfClosing) { + + } + + @Override + public void afterElement(PushStream stream) { + + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/LoggingHandler.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/LoggingHandler.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/LoggingHandler.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/LoggingHandler.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.debug; + +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandHandler; + +/** + * Handler which logs all commands + */ +public final class LoggingHandler implements CommandHandler { + + public static final LoggingHandler INSTANCE = new LoggingHandler(); + + private final Logger LOG = LoggerFactory.getLogger(LoggingHandler.class); + + private LoggingHandler() { + } + + @Override + public void onEmit(Command command) { + LOG.info("Emitting {}", command); + } + + @Override + public void onError(String errorMessage) { + LOG.info("Error: {}", errorMessage); + } + + @Override + public void onDone() { + LOG.info("Finished"); + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/SanityChecker.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/SanityChecker.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/SanityChecker.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/debug/SanityChecker.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,167 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.debug; + +import java.util.Stack; + +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.BufferControl; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.Loop; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.Procedure; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandHandler; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandStream; +import org.apache.sling.scripting.sightly.compiler.api.ris.Command; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandHandler; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandStream; +import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.*; + +/** + * A visitor which checks a stream for correct closing of things + */ +public final class SanityChecker implements CommandVisitor, CommandHandler { + + private enum NestedType { + CONDITIONAL, VARIABLE_BIND, LOOP + } + + private final Stack stack = new Stack(); + private int bufferPushCount; + private boolean inProcedure; + + private SanityChecker() { + } + + public static void attachChecker(CommandStream commandStream) { + commandStream.addHandler(new SanityChecker()); + } + + @Override + public void onEmit(Command command) { + command.accept(this); + } + + @Override + public void onError(String errorMessage) { + throw new RuntimeException(errorMessage); + } + + @Override + public void onDone() { + if (!stack.isEmpty()) { + throw new IllegalStateException("Unclosed commands left"); + } + if (bufferPushCount > 0) { + throw new IllegalStateException("There are pushed buffer writers at stream end"); + } + } + + + @Override + public void visit(Conditional.Start conditionalStart) { + stack.push(NestedType.CONDITIONAL); + } + + @Override + public void visit(Conditional.End conditionalEnd) { + popCheck(NestedType.CONDITIONAL); + } + + @Override + public void visit(VariableBinding.Start variableBindingStart) { + stack.push(NestedType.VARIABLE_BIND); + } + + @Override + public void visit(VariableBinding.End variableBindingEnd) { + popCheck(NestedType.VARIABLE_BIND); + } + + @Override + public void visit(VariableBinding.Global globalAssignment) { + } + + @Override + public void visit(OutVariable outVariable) { + } + + @Override + public void visit(OutText outText) { + } + + @Override + public void visit(Loop.Start loopStart) { + stack.push(NestedType.LOOP); + } + + @Override + public void visit(Loop.End loopEnd) { + popCheck(NestedType.LOOP); + } + + @Override + public void visit(BufferControl.Push bufferPush) { + bufferPushCount++; + } + + @Override + public void visit(BufferControl.Pop bufferPop) { + if (bufferPushCount == 0) { + throw new IllegalStateException("There are more buffer pop commands than push"); + } + bufferPushCount--; + stack.push(NestedType.VARIABLE_BIND); + } + + @Override + public void visit(Procedure.Start startProcedure) { + if (inProcedure) { + throw new IllegalStateException("Cannot have nested procedures: " + startProcedure.getName()); + } + inProcedure = true; + } + + @Override + public void visit(Procedure.End endProcedure) { + if (!inProcedure) { + throw new IllegalStateException("Procedure closing is unmatched"); + } + inProcedure = false; + } + + @Override + public void visit(Procedure.Call procedureCall) { + } + + private void popCheck(NestedType nestedType) { + if (stack.isEmpty()) { + throw new IllegalStateException("Unbalanced command: " + nestedType); + } + NestedType top = stack.pop(); + if (top != nestedType) { + throw new IllegalStateException("Command closing is unmatched. Expected " + top + ", actual: " + nestedType); + } + } + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/AggregatePluginInvoke.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/AggregatePluginInvoke.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/AggregatePluginInvoke.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/AggregatePluginInvoke.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,153 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke; +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; + +import java.util.List; + +/** + * Plugin invoke which aggregates the behavior of several plugin invokes + */ +public class AggregatePluginInvoke implements PluginInvoke { + + private final List invokes; + + public AggregatePluginInvoke(List invokes) { + this.invokes = invokes; + } + + @Override + public void beforeElement(PushStream stream, String tagName) { + for (PluginInvoke invoke : invokes) { + invoke.beforeElement(stream, tagName); + } + } + + @Override + public void beforeTagOpen(PushStream stream) { + for (PluginInvoke invoke : invokes) { + invoke.beforeTagOpen(stream); + } + } + + @Override + public void beforeAttributes(PushStream stream) { + for (PluginInvoke invoke : invokes) { + invoke.beforeAttributes(stream); + } + } + + @Override + public void beforeAttribute(PushStream stream, String attributeName) { + for (PluginInvoke invoke : invokes) { + invoke.beforeAttribute(stream, attributeName); + } + } + + @Override + public void beforeAttributeValue(PushStream stream, String attributeName, ExpressionNode attributeValue) { + for (PluginInvoke invoke : invokes) { + invoke.beforeAttributeValue(stream, attributeName, attributeValue); + } + } + + @Override + public void afterAttributeValue(PushStream stream, String attributeName) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterAttributeValue(stream, attributeName); + } + } + + @Override + public void afterAttribute(PushStream stream, String attributeName) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterAttribute(stream, attributeName); + } + } + + @Override + public void onPluginCall(PushStream stream, PluginCallInfo callInfo, Expression expression) { + for (PluginInvoke invoke : invokes) { + invoke.onPluginCall(stream, callInfo, expression); + } + } + + @Override + public void afterAttributes(PushStream stream) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterAttributes(stream); + } + } + + @Override + public void afterTagOpen(PushStream stream) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterTagOpen(stream); + } + } + + @Override + public void beforeChildren(PushStream stream) { + for (PluginInvoke invoke : invokes) { + invoke.beforeChildren(stream); + } + } + + @Override + public void afterChildren(PushStream stream) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterChildren(stream); + } + } + + @Override + public void beforeTagClose(PushStream stream, boolean isSelfClosing) { + for (PluginInvoke invoke : invokes) { + invoke.beforeTagClose(stream, isSelfClosing); + } + } + + @Override + public void afterTagClose(PushStream stream, boolean isSelfClosing) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterTagClose(stream, isSelfClosing); + } + } + + @Override + public void afterElement(PushStream stream) { + for (int i = invokes.size() - 1; i >= 0; i--) { + PluginInvoke invoke = invokes.get(i); + invoke.afterElement(stream); + } + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/DefaultCompilerContext.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/DefaultCompilerContext.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/DefaultCompilerContext.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/DefaultCompilerContext.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import org.apache.sling.scripting.sightly.compiler.Syntax; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext; +import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext; +import org.apache.sling.scripting.sightly.compiler.util.SymbolGenerator; +import org.apache.sling.scripting.sightly.compiler.Syntax; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext; +import org.apache.sling.scripting.sightly.compiler.util.SymbolGenerator; + + +/** + * Default implementation for the compiler context + * @see org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin + */ +public class DefaultCompilerContext implements CompilerContext { + + private SymbolGenerator symbolGenerator; + private ExpressionWrapper expressionWrapper; + + DefaultCompilerContext(SymbolGenerator symbolGenerator, ExpressionWrapper wrapper) { + this.symbolGenerator = symbolGenerator; + this.expressionWrapper = wrapper; + } + + @Override + public String generateVariable(String hint) { + return symbolGenerator.next(hint); + } + + @Override + public Expression adjustToContext(Expression expression, MarkupContext context) { + if (!expression.getOptions().containsKey(Syntax.CONTEXT_OPTION)) { + return expressionWrapper.adjustToContext(expression, context); + } + return expression; + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ElementContext.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ElementContext.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ElementContext.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ElementContext.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,106 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ + +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke; + +/** + * Data structure used by {@link MarkupHandlerImpl} + */ +class ElementContext { + private final String tagName; + private final String openTagStartMarkup; + + private final List invokeList = new ArrayList(); + private final List> attributes = new ArrayList>(); + private PluginInvoke aggregateInvoke; + + public ElementContext(String tagName, String openTagStartMarkup) { + this.tagName = tagName; + this.openTagStartMarkup = openTagStartMarkup; + } + + public String getTagName() { + return tagName; + } + + public String getOpenTagStartMarkup() { + return openTagStartMarkup; + } + + public void addPlugin(PluginInvoke invoke, int priority) { + invokeList.add(new PrioritizedInvoke(invoke, priority)); + } + + public void addAttribute(String name, String value) { + attributes.add(new AbstractMap.SimpleEntry(name, value)); + } + + public void addPluginCall(String name, PluginCallInfo info, Expression expression) { + attributes.add(new AbstractMap.SimpleEntry(name, + new AbstractMap.SimpleEntry(info, expression))); + } + + public Iterable> getAttributes() { + return attributes; + } + + public PluginInvoke pluginInvoke() { + if (aggregateInvoke == null) { + Collections.sort(invokeList); + ArrayList result = new ArrayList(); + for (PrioritizedInvoke prioritizedInvoke : invokeList) { + result.add(prioritizedInvoke.invoke); + } + aggregateInvoke = new AggregatePluginInvoke(result); + } + return aggregateInvoke; + } + + + private static final class PrioritizedInvoke implements Comparable { + + private final PluginInvoke invoke; + private final int priority; + + private PrioritizedInvoke(PluginInvoke invoke, int priority) { + this.invoke = invoke; + this.priority = priority; + } + + @Override + public int compareTo(PrioritizedInvoke o) { + if (this.priority < o.priority) { + return -1; + } else if (this.priority == o.priority) { + return 0; + } + return 1; + } + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParser.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParser.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParser.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParser.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + + +/** + * Sightly expression parser service interface + * + * */ +public interface ExpressionParser { + + /** + * Parses the expression string. + * + * @param exprString as defined by the Sightly spec (http://apache.org) + * + * @return Parsed Expression object + * + * @throws NullPointerException is the given exprString is null + * @throws ParserException if an error occurs while parsing the expression + * */ + public Interpolation parseInterpolation(String exprString); + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParserImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParserImpl.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParserImpl.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionParserImpl.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import org.apache.sling.parser.expr.generated.SightlyLexer; +import org.apache.sling.parser.expr.generated.SightlyParser; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; + +public class ExpressionParserImpl implements ExpressionParser { + + public Interpolation parseInterpolation(String text) throws ParserException { + SightlyParser parser = createParser(text); + try { + return parser.interpolation().interp; + } catch (RecognitionException e) { + throw new ParserException(e); + } + } + + private SightlyParser createParser(String str) { + SightlyLexer lexer = new SightlyLexer(new ANTLRInputStream(str)); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + SightlyParser parser = new SightlyParser(tokenStream); + parser.removeErrorListeners(); + parser.addErrorListener(new SightlyParserErrorListener()); + return parser; + } + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionWrapper.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionWrapper.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionWrapper.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ExpressionWrapper.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,122 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.sling.scripting.sightly.compiler.Syntax; +import org.apache.sling.scripting.sightly.compiler.api.Filter; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperator; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant; +import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext; +import org.apache.sling.scripting.sightly.compiler.api.Filter; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant; + +/** + * This object wraps expressions in filter applications depending + * on options + */ +class ExpressionWrapper { + + private final List filters; + + ExpressionWrapper(Collection filters) { + this.filters = new ArrayList(); + this.filters.addAll(filters); + Collections.sort(this.filters); + } + + public Expression transform(Interpolation interpolation, MarkupContext markupContext) { + ArrayList nodes = new ArrayList(); + HashMap options = new HashMap(); + for (Fragment fragment : interpolation.getFragments()) { + if (fragment.isString()) { + nodes.add(new StringConstant(fragment.getText())); + } else { + Expression expression = fragment.getExpression(); + options.putAll(expression.getOptions()); + nodes.add(transformExpr(expression, markupContext).getRoot()); + } + } + ExpressionNode root = join(nodes); + if (interpolation.size() > 1 && options.containsKey(Syntax.CONTEXT_OPTION)) { + //context must not be calculated by merging + options.remove(Syntax.CONTEXT_OPTION); + } + return new Expression(root, options); + } + + private Expression applyFilters(Expression expression) { + Expression result = expression; + for (Filter filter : filters) { + result = filter.apply(result); + } + return result; + } + + public Expression adjustToContext(Expression expression, MarkupContext markupContext) { + if (expression.containsOption(Syntax.CONTEXT_OPTION)) { + return expression; + } + Map opt = addDefaultContext(Collections.emptyMap(), markupContext); + Expression result = applyFilters(new Expression(expression.getRoot(), opt)); + return expression.withNode(result.getRoot()); + } + + private ExpressionNode join(List nodes) { + if (nodes.isEmpty()) { + return StringConstant.EMPTY; + } + ExpressionNode root = nodes.get(0); + for (int i = 1; i < nodes.size(); i++) { + ExpressionNode node = nodes.get(i); + root = new BinaryOperation(BinaryOperator.CONCATENATE, root, node); + } + return root; + } + + private Expression transformExpr(Expression expression, MarkupContext markupContext) { + expression = addDefaultContext(expression, markupContext); + return applyFilters(expression); + } + + private Expression addDefaultContext(Expression expression, MarkupContext context) { + return new Expression(expression.getRoot(), addDefaultContext(expression.getOptions(), context)); + } + + private Map addDefaultContext(Map options, MarkupContext context) { + if (context == null || options.containsKey(Syntax.CONTEXT_OPTION)) { + return options; + } + HashMap newOptions = new HashMap(options); + newOptions.put(Syntax.CONTEXT_OPTION, new StringConstant(context.getName())); + return newOptions; + } + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Fragment.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Fragment.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Fragment.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Fragment.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,106 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; + +/** + * A segment in an interpolation. + */ +public interface Fragment { + + boolean isString(); + boolean isExpression(); + + Expression getExpression(); + String getText(); + + /** + * A fragment which is an expression. + */ + public static class Expr implements Fragment { + + private Expression expression; + + public Expr(Expression expression) { + this.expression = expression; + } + + @Override + public Expression getExpression() { + return expression; + } + + @Override + public String getText() { + throw new UnsupportedOperationException("Not a text fragment"); + } + + public boolean isString() { + return false; + } + + public boolean isExpression() { + return true; + } + + @Override + public String toString() { + return "Expr{" + + "expression=" + expression + + '}'; + } + } + + /** + * A text fragment. + */ + public static class Text implements Fragment { + private String text; + + public Text(String text) { + this.text = text; + } + + @Override + public String getText() { + return text; + } + + public boolean isString() { + return true; + } + + public boolean isExpression() { + return false; + } + + @Override + public Expression getExpression() { + throw new UnsupportedOperationException("Not an expression fragment"); + } + + @Override + public String toString() { + return "Text{" + + "text='" + text + '\'' + + '}'; + } + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Interpolation.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Interpolation.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Interpolation.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/Interpolation.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; + +/** + * A sequence with alternating string fragments and Sightly expressions. + * These result from parsing HTML attributes or string nodes. + * For instance "Hello ${World}!" would result in 3 fragments: + * "Hello ", ${World} and "!" + */ +public class Interpolation { + + //todo: this should be immutable to maintain the design consistent + + private List fragments = new ArrayList(); + + public void addFragment(Fragment fragment) { + fragments.add(fragment); + } + + public void addExpression(Expression expression) { + fragments.add(new Fragment.Expr(expression)); + } + + public void addText(String text) { + fragments.add(new Fragment.Text(text)); + } + + /** + * Get the number of fragments + * @return the number of fragments + */ + public int size() { + return fragments.size(); + } + + /** + * Return the fragment with the specified index + * @param index - the index of the fragments. must be less than the size of the interpolation + * @return - the specified fragment + * @throws IndexOutOfBoundsException - if the index is negative or greater or equal than size + */ + public Fragment getFragment(int index) { + return fragments.get(index); + } + + public Iterable getFragments() { + return fragments; + } + + @Override + public String toString() { + return "Interpolation{" + + "fragments=" + fragments + + '}'; + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/MarkupHandlerImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/MarkupHandlerImpl.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/MarkupHandlerImpl.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/MarkupHandlerImpl.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,405 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ + +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.Collection; +import java.util.Map; +import java.util.Stack; + +import org.apache.commons.lang.StringUtils; +import org.apache.sling.scripting.sightly.compiler.Syntax; +import org.apache.sling.scripting.sightly.compiler.api.Filter; +import org.apache.sling.scripting.sightly.compiler.api.MarkupHandler; +import org.apache.sling.scripting.sightly.compiler.api.expression.Expression; +import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperator; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant; +import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext; +import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext; +import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo; +import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable; +import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding; +import org.apache.sling.scripting.sightly.compiler.util.SymbolGenerator; +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; +import org.apache.sling.scripting.sightly.html.MarkupUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation for the markup handler + */ +public class MarkupHandlerImpl implements MarkupHandler { + + private static final Logger log = LoggerFactory.getLogger(MarkupHandlerImpl.class); + + private final PushStream stream; + private final SymbolGenerator symbolGenerator = new SymbolGenerator(); + private final ExpressionParser expressionParser = new ExpressionParserImpl(); + private final Map pluginRegistry; + private final CompilerContext compilerContext; + private final ExpressionWrapper expressionWrapper; + + private final Stack elementStack = new Stack(); + + public MarkupHandlerImpl(PushStream stream, Map pluginRegistry, Collection filters) { + this.stream = stream; + this.pluginRegistry = pluginRegistry; + this.expressionWrapper = new ExpressionWrapper(filters); + this.compilerContext = new DefaultCompilerContext(symbolGenerator, expressionWrapper); + } + + @Override + public void onOpenTagStart(String markup, String tagName) { + ElementContext context = new ElementContext(tagName, markup); + elementStack.push(context); + } + + @Override + public void onAttribute(String name, String value) { + ElementContext context = elementStack.peek(); + if (Syntax.isPluginAttribute(name)) { + handlePlugin(name, StringUtils.defaultString(value, ""), context); + } else { + context.addAttribute(name, value); + } + } + + @Override + public void onOpenTagEnd(String markup) { + ElementContext context = elementStack.peek(); + PluginInvoke invoke = context.pluginInvoke(); + invoke.beforeElement(stream, context.getTagName()); + invoke.beforeTagOpen(stream); + out(context.getOpenTagStartMarkup()); + invoke.beforeAttributes(stream); + traverseAttributes(context, invoke); + invoke.afterAttributes(stream); + out(markup); + invoke.afterTagOpen(stream); + invoke.beforeChildren(stream); + } + + private void traverseAttributes(ElementContext context, PluginInvoke invoke) { + for (Map.Entry attribute : context.getAttributes()) { + String attrName = attribute.getKey(); + Object contentObj = attribute.getValue(); + if (contentObj == null || contentObj instanceof String) { + String content = (String) contentObj; + emitAttribute(attrName, content, invoke); + } else if (contentObj instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) contentObj; + PluginCallInfo info = (PluginCallInfo) entry.getKey(); + Expression expression = (Expression) entry.getValue(); + invoke.onPluginCall(stream, info, expression); + } + } + } + + private void emitAttribute(String name, String content, PluginInvoke invoke) { + invoke.beforeAttribute(stream, name); + if (content == null) { + emitSimpleTextAttribute(name, null, invoke); + } else { + Interpolation interpolation = expressionParser.parseInterpolation(content); + String text = tryAsSimpleText(interpolation); + if (text != null) { + emitSimpleTextAttribute(name, text, invoke); + } else { + emitExpressionAttribute(name, interpolation, invoke); + } + } + invoke.afterAttribute(stream, name); + } + + private void emitSimpleTextAttribute(String name, String textValue, PluginInvoke invoke) { + emitAttributeStart(name); + invoke.beforeAttributeValue(stream, name, new StringConstant(textValue)); + if (textValue != null) { + emitAttributeValueStart(); + textValue = escapeQuotes(textValue); + out(textValue); + emitAttributeEnd(); + } + invoke.afterAttributeValue(stream, name); + } + + private String escapeQuotes(String textValue) { + return textValue.replace("\"", """); + } + + private void emitExpressionAttribute(String name, Interpolation interpolation, PluginInvoke invoke) { + interpolation = attributeChecked(name, interpolation); + if (interpolation.size() == 1) { + emitSingleFragment(name, interpolation, invoke); + } else { + emitMultipleFragment(name, interpolation, invoke); + } + } + + private void emitMultipleFragment(String name, Interpolation interpolation, PluginInvoke invoke) { + // Simplified algorithm for attribute output, which works when the interpolation is not of size 1. In this + // case we are certain that the attribute value cannot be the boolean value true, so we can skip this test + // altogether + Expression expression = expressionWrapper.transform(interpolation, getAttributeMarkupContext(name)); + String attrContent = symbolGenerator.next("attrContent"); + String shouldDisplayAttr = symbolGenerator.next("shouldDisplayAttr"); + stream.emit(new VariableBinding.Start(attrContent, expression.getRoot())); + stream.emit( + new VariableBinding.Start( + shouldDisplayAttr, + new BinaryOperation( + BinaryOperator.OR, + new Identifier(attrContent), + new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrContent)) + ) + ) + ); + stream.emit(new Conditional.Start(shouldDisplayAttr, true)); + emitAttributeStart(name); + invoke.beforeAttributeValue(stream, name, expression.getRoot()); + emitAttributeValueStart(); + stream.emit(new OutVariable(attrContent)); + emitAttributeEnd(); + invoke.afterAttributeValue(stream, name); + stream.emit(Conditional.END); + stream.emit(VariableBinding.END); + stream.emit(VariableBinding.END); + } + + private void emitSingleFragment(String name, Interpolation interpolation, PluginInvoke invoke) { + Expression valueExpression = expressionWrapper.transform(interpolation, null); //raw expression + String attrValue = symbolGenerator.next("attrValue"); //holds the raw attribute value + String attrContent = symbolGenerator.next("attrContent"); //holds the escaped attribute value + String isTrueVar = symbolGenerator.next("isTrueAttr"); // holds the comparison (attrValue == true) + String shouldDisplayAttr = symbolGenerator.next("shouldDisplayAttr"); + MarkupContext markupContext = getAttributeMarkupContext(name); + Expression contentExpression = valueExpression.withNode(new Identifier(attrValue)); + ExpressionNode node = valueExpression.getRoot(); + stream.emit(new VariableBinding.Start(attrValue, node)); //attrContent = + stream.emit(new VariableBinding.Start(attrContent, expressionWrapper.adjustToContext(contentExpression, markupContext).getRoot())); + stream.emit( + new VariableBinding.Start( + shouldDisplayAttr, + new BinaryOperation( + BinaryOperator.OR, + new Identifier(attrContent), + new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrValue)) + ) + ) + ); + stream.emit(new Conditional.Start(shouldDisplayAttr, true)); // if (attrContent) + emitAttributeStart(name); //write("attrName"); + invoke.beforeAttributeValue(stream, name, node); + stream.emit(new VariableBinding.Start(isTrueVar, //isTrueAttr = (attrValue == true) + new BinaryOperation(BinaryOperator.EQ, new Identifier(attrValue), BooleanConstant.TRUE))); + stream.emit(new Conditional.Start(isTrueVar, false)); //if (!isTrueAttr) + emitAttributeValueStart(); // write("='"); + stream.emit(new OutVariable(attrContent)); //write(attrContent) + emitAttributeEnd(); //write("'"); + stream.emit(Conditional.END); //end if isTrueAttr + stream.emit(VariableBinding.END); //end scope for isTrueAttr + invoke.afterAttributeValue(stream, name); + stream.emit(Conditional.END); //end if attrContent + stream.emit(VariableBinding.END); + stream.emit(VariableBinding.END); //end scope for attrContent + stream.emit(VariableBinding.END); //end scope for attrValue + } + + + private void emitAttributeStart(String name) { + out(" " + name); + } + + private void emitAttributeValueStart() { + out("=\""); + } + + private void emitAttributeEnd() { + out("\""); + } + + @Override + public void onCloseTag(String markup) { + ElementContext context = elementStack.pop(); + PluginInvoke invoke = context.pluginInvoke(); + invoke.afterChildren(stream); + boolean selfClosingTag = StringUtils.isEmpty(markup); + invoke.beforeTagClose(stream, selfClosingTag); + out(markup); + invoke.afterTagClose(stream, selfClosingTag); + invoke.afterElement(stream); + } + + @Override + public void onText(String text) { + String tag = currentElementTag(); + boolean explicitContextRequired = isExplicitContextRequired(tag); + MarkupContext markupContext = (explicitContextRequired) ? null : MarkupContext.TEXT; + outText(text, markupContext); + } + + @Override + public void onComment(String markup) { + if (!Syntax.isSightlyComment(markup)) { + outText(markup, MarkupContext.COMMENT); + } + } + + @Override + public void onDataNode(String markup) { + out(markup); + } + + @Override + public void onDocType(String markup) { + out(markup); + } + + @Override + public void onDocumentFinished() { + this.stream.signalDone(); + } + + private void outText(String content, MarkupContext context) { + Interpolation interpolation = expressionParser.parseInterpolation(content); + if (context == null) { + interpolation = requireContext(interpolation); + } + String text = tryAsSimpleText(interpolation); + if (text != null) { + out(text); + } else { + outExprNode(expressionWrapper.transform(interpolation, context).getRoot()); + } + } + + private Interpolation requireContext(Interpolation interpolation) { + Interpolation result = new Interpolation(); + for (Fragment fragment : interpolation.getFragments()) { + Fragment addedFragment; + if (fragment.isString()) { + addedFragment = fragment; + } else { + if (fragment.getExpression().containsOption(Syntax.CONTEXT_OPTION)) { + addedFragment = fragment; + } else { + String currentTag = currentElementTag(); + log.warn("Element {} requires that all expressions have an explicit context specified. Expression will be " + + "replaced by the empty string", currentTag); + addedFragment = new Fragment.Expr(new Expression(StringConstant.EMPTY)); + } + } + result.addFragment(addedFragment); + } + return result; + } + + private Interpolation attributeChecked(String attributeName, Interpolation interpolation) { + if (!MarkupUtils.isSensitiveAttribute(attributeName)) { + return interpolation; + } + Interpolation newInterpolation = new Interpolation(); + for (Fragment fragment : interpolation.getFragments()) { + Fragment addedFragment = fragment; + if (fragment.isExpression()) { + Expression expression = fragment.getExpression(); + if (!expression.containsOption(Syntax.CONTEXT_OPTION)) { + log.warn("All expressions within the value of attribute {} need to have an explicit context option. The expression will be erased.", + attributeName); + addedFragment = new Fragment.Text(""); + } + } + newInterpolation.addFragment(addedFragment); + } + return newInterpolation; + } + + + private void outExprNode(ExpressionNode node) { + String variable = symbolGenerator.next(); + stream.emit(new VariableBinding.Start(variable, node)); + stream.emit(new OutVariable(variable)); + stream.emit(VariableBinding.END); + } + + + private String tryAsSimpleText(Interpolation interpolation) { + if (interpolation.size() == 1) { + Fragment fragment = interpolation.getFragment(0); + if (fragment.isString()) { + return fragment.getText(); + } + } else if (interpolation.size() == 0) { + return ""; + } + return null; + } + + private void out(String text) { + stream.emit(new OutText(text)); + } + + private void handlePlugin(String name, String value, ElementContext context) { + PluginCallInfo callInfo = Syntax.parsePluginAttribute(name); + if (callInfo != null) { + Plugin plugin = obtainPlugin(callInfo.getName()); + Expression expr = expressionWrapper.transform( + expressionParser.parseInterpolation(value), null); + PluginInvoke invoke = plugin.invoke(expr, callInfo, compilerContext); + context.addPlugin(invoke, plugin.priority()); + context.addPluginCall(name, callInfo, expr); + } + } + + private Plugin obtainPlugin(String name) { + Plugin plugin = pluginRegistry.get(name); + if (plugin == null) { + throw new UnsupportedOperationException(String.format("Plugin %s does not exist", name)); + } + return plugin; + } + + private MarkupContext getAttributeMarkupContext(String attributeName) { + if ("src".equalsIgnoreCase(attributeName) || "href".equalsIgnoreCase(attributeName)) { + return MarkupContext.URI; + } + return MarkupContext.ATTRIBUTE; + } + + private String currentElementTag() { + if (elementStack.isEmpty()) { + return null; + } + ElementContext current = elementStack.peek(); + return current.getTagName(); + } + + private boolean isExplicitContextRequired(String parentElementName) { + return parentElementName != null && + ("script".equals(parentElementName) || "style".equals(parentElementName)); + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserException.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserException.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserException.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserException.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +/** + * Plugin runtime exception to be used for either html or expression parser exceptions. + */ +public class ParserException extends RuntimeException { + + public ParserException() { + super(); + } + + public ParserException(String message) { + super(message); + } + + public ParserException(String message, Throwable throwable) { + super(message, throwable); + } + + public ParserException(Throwable throwable) { + super(throwable); + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserHelper.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserHelper.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserHelper.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/ParserHelper.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ + +package org.apache.sling.scripting.sightly.compiler.frontend; + +import org.apache.commons.lang.StringEscapeUtils; + +import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant; +import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant; + +/** + * Helper utilities for the ANTLR parser + */ +public class ParserHelper { + + public static String unEscape(String original) { + return original.replaceAll("\\\\\"", "\"").replaceAll("\\\\'", "'"); + } + + public static StringConstant createStringConstant(String original) { + String escaped = StringEscapeUtils.unescapeJava(original); + String trimmed = escaped.substring(1, escaped.length() - 1); + return new StringConstant(trimmed); + } + +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SightlyParserErrorListener.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SightlyParserErrorListener.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SightlyParserErrorListener.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SightlyParserErrorListener.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ + +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.Collections; +import java.util.List; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.sling.scripting.sightly.api.SightlyParsingException; + +/** + * The {@code SightlyParserErrorListener} handles parsing error reporting by sending offending input to a logger. + */ +public class SightlyParserErrorListener extends BaseErrorListener { + + private static final Logger LOG = LoggerFactory.getLogger(SightlyParserErrorListener.class); + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + List stack = ((Parser) recognizer).getRuleInvocationStack(); + Collections.reverse(stack); + StringBuilder errorMessage = new StringBuilder(); + errorMessage.append("Sightly syntax error detected.\n"); + errorMessage.append("rule stack: ").append(stack).append("\n"); + errorMessage.append("error starts at column: ").append(charPositionInLine).append("\n"); + errorMessage.append(msg); + throw new SightlyParsingException("Sightly syntax error detected", ((CommonTokenStream) recognizer.getInputStream()).getTokenSource().getInputStream().toString(), e); + } +} Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SimpleFrontend.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SimpleFrontend.java?rev=1639641&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SimpleFrontend.java (added) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiler/frontend/SimpleFrontend.java Fri Nov 14 14:04:56 2014 @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.compiler.frontend; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.sling.scripting.sightly.compiler.CompilerFrontend; +import org.apache.sling.scripting.sightly.compiler.api.Filter; +import org.apache.sling.scripting.sightly.compiler.api.MarkupHandler; +import org.apache.sling.scripting.sightly.compiler.api.MarkupParser; +import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin; +import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream; +import org.apache.sling.scripting.sightly.compiler.api.MarkupHandler; + +/** + * DOM-based compiler implementation + */ +public class SimpleFrontend implements CompilerFrontend { + + private final MarkupParser parser; + private final Map plugins; + private final List filters; + + public SimpleFrontend(MarkupParser markupParser, Collection plugins, Collection filters) { + this.plugins = new HashMap(); + for (Plugin plugin : plugins) { + this.plugins.put(plugin.name(), plugin); + } + this.filters = new ArrayList(filters); + this.parser = markupParser; + } + + @Override + public void compile(PushStream stream, String source) { + MarkupHandler markupHandler = new MarkupHandlerImpl(stream, plugins, filters); + parser.parse(source, markupHandler); + } +}