You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2014/11/28 11:18:09 UTC

svn commit: r1642281 [5/14] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/main/antlr4/org/apache/sling/parser/expr/generated/ engine/src/main/antlr4/org/apache/sling/scripting/ engine/src/main/antlr4/org/apache/sling/scripting/sigh...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * 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.impl.compiler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
+import org.apache.sling.commons.compiler.CompilationResult;
+import org.apache.sling.commons.compiler.CompilationUnit;
+import org.apache.sling.commons.compiler.CompilerMessage;
+import org.apache.sling.commons.compiler.Options;
+import org.apache.sling.jcr.compiler.JcrJavaCompiler;
+import org.apache.sling.scripting.sightly.ResourceResolution;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The {@code SightlyJavaCompiler} allows for simple instantiation of arbitrary classes that are either stored in the repository
+ * or in regular OSGi bundles. It also compiles Java sources on-the-fly and can discover class' source files based on
+ * {@link Resource}s (typically Sling components). It supports Sling Resource type inheritance.
+ */
+@Component
+@Service(SightlyJavaCompilerService.class)
+public class SightlyJavaCompilerService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SightlyJavaCompilerService.class);
+
+    @Reference
+    private ClassLoaderWriter classLoaderWriter = null;
+
+    @Reference
+    private JcrJavaCompiler jcrJavaCompiler = null;
+
+    @Reference
+    private ResourceResolverFactory rrf = null;
+
+    private Options options;
+
+    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+    private Lock readLock = lock.readLock();
+    private Lock writeLock = lock.writeLock();
+
+    /**
+     * This method returns an Object instance based on a class that is either found through regular classloading mechanisms or on-the-fly
+     * compilation. In case the requested class does not denote a fully qualified classname, this service will try to find the class through
+     * Sling's servlet resolution mechanism and compile the class on-the-fly if required.
+     *
+     * @param resource  the lookup will be performed based on this resource
+     * @param className name of class to use for object instantiation
+     * @return object instance of the requested class
+     * @throws CompilerException in case of any runtime exception
+     */
+    public Object getInstance(Resource resource, String className) {
+
+        LOG.debug("Attempting to obtain bean instance of resource '{}' and class '{}'", resource.getPath(), className);
+
+        // assume fully qualified class name
+        if (className.contains(".")) {
+            Resource pojoResource = checkIfPojoIsInRepo(className);
+            if (pojoResource != null) {
+                return compileSource(pojoResource, className);
+            } else {
+                LOG.debug("fully qualified classname provided, loading object directly");
+                return loadObject(className);
+            }
+        }
+
+        LOG.debug("trying to find Java source based on resource: {}", resource.getPath());
+
+        // try to find Java source in JCR
+        // use the servlet resolver to do all the magic lookup (resource type hierarchy and search path) for us
+
+        Resource scriptResource = ResourceResolution
+                .resolveComponentRelative(resource.getResourceResolver(), resource, className + ".java");
+        if (scriptResource != null) {
+            LOG.debug("found Java bean script resource: " + scriptResource.getPath());
+            try {
+                return compileJavaResource(new SlingResourceCompilationUnit(scriptResource), scriptResource.getPath());
+            } catch (Exception e) {
+                throw new CompilerException(e);
+            }
+        } else {
+            // not found in JCR, try to load from bundle using current resource type package
+            // /apps/project/components/foo => apps.project.components.foo.<scriptName>
+            Resource resourceType = resource.getResourceResolver().getResource(resource.getResourceType());
+
+            if (resourceType == null) {
+                resourceType = resource;
+            }
+
+            String resourceTypeDir = resourceType.getPath();
+            className = getJavaNameFromPath(resourceTypeDir) + "." + className;
+
+            LOG.debug("Java bean source not found, trying to locate using" + " component directory as packagename: {}", resourceTypeDir);
+
+            LOG.debug("loading Java class: " + className);
+            return loadObject(className);
+        }
+    }
+
+    /**
+     * Compiles a class using the passed fully qualified classname and based on the resource that represents the class' source.
+     *
+     * @param javaResource resource that constitutes the class' source
+     * @param fqcn         fully qualified name of the class to compile
+     * @return object instance of the class to compile
+     * @throws CompilerException in case of any runtime exception
+     */
+    public Object compileSource(Resource javaResource, String fqcn) {
+        LOG.debug("Compiling Sightly based Java class from resource: " + javaResource.getPath());
+        try {
+            CompilationUnit compilationUnit = new SightlyCompilationUnit(javaResource, fqcn);
+            return compileJavaResource(compilationUnit, javaResource.getPath());
+        } catch (Exception e) {
+            throw new CompilerException(e);
+        }
+    }
+
+    /**
+     * Instantiate and return an instance of a class.
+     *
+     * @param className class to instantiate
+     * @return instance of class
+     */
+    private Object loadObject(String className) {
+        try {
+            return loadClass(className).newInstance();
+        } catch (Exception e) {
+            throw new CompilerException(e);
+        }
+    }
+
+    /**
+     * Retrieve a class from the ClassLoaderWriter service.
+     *
+     * @param name name of class to load
+     * @return Class
+     * @throws ClassNotFoundException
+     */
+    private Class loadClass(String name) throws ClassNotFoundException {
+        readLock.lock();
+        try {
+            if (classLoaderWriter != null) {
+                return classLoaderWriter.getClassLoader().loadClass(name);
+            }
+        } finally {
+            readLock.unlock();
+        }
+        return Class.forName(name);
+    }
+
+    /**
+     * Compiles a class stored in the repository and returns an instance of the compiled class.
+     *
+     * @param compilationUnit a compilation unit
+     * @param scriptPath      the path of the script to compile
+     * @return instance of compiled class
+     * @throws Exception
+     */
+    private Object compileJavaResource(CompilationUnit compilationUnit, String scriptPath) throws Exception {
+        writeLock.lock();
+        try {
+            long start = System.currentTimeMillis();
+            CompilationResult compilationResult = jcrJavaCompiler.compile(new String[]{scriptPath}, options);
+            long end = System.currentTimeMillis();
+            List<CompilerMessage> errors = compilationResult.getErrors();
+            if (errors != null && errors.size() > 0) {
+                throw new CompilerException(createErrorMsg(errors));
+            }
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("script compiled: {}", compilationResult.didCompile());
+                LOG.debug("compilation took {}ms", end - start);
+            }
+            return compilationResult.loadCompiledClass(compilationUnit.getMainClassName()).newInstance();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Activate
+    @SuppressWarnings("unused")
+    protected void activate() {
+        LOG.info("Activating {}", getClass().getName());
+
+        String version = System.getProperty("java.specification.version");
+        options = new Options();
+        options.put(Options.KEY_GENERATE_DEBUG_INFO, true);
+        options.put(Options.KEY_SOURCE_VERSION, version);
+        options.put(Options.KEY_TARGET_VERSION, version);
+        options.put(Options.KEY_CLASS_LOADER_WRITER, classLoaderWriter);
+    }
+
+    //---------------------------------- private -----------------------------------
+
+    /**
+     * Checks is a POJO class name is represented by a resource from the repository.
+     *
+     * @param className the class name
+     * @return the Resource in which the class is defined, {@code null} if the POJO was not found in the repository
+     */
+    private Resource checkIfPojoIsInRepo(String className) {
+        // POJOs will always be loaded through the compiler (prevents stale class loader issues)
+        String pojoPath = "/" + className.replaceAll("\\.", "/") + ".java";
+        ResourceResolver rr = null;
+        try {
+            rr = rrf.getAdministrativeResourceResolver(null);
+            Resource pojoResource = rr.getResource(pojoPath);
+            if (pojoResource != null) {
+                for (String s : rr.getSearchPath()) {
+                    if (pojoPath.startsWith(s)) {
+                        return pojoResource;
+                    }
+                }
+            }
+        } catch (LoginException le) {
+            LOG.error("Cannot search repository for POJO.", le);
+        } finally {
+            if (rr != null) {
+                rr.close();
+            }
+        }
+        return null;
+    }
+
+    private String getJavaNameFromPath(String path) {
+        if (path.endsWith(".java")) {
+            path = path.substring(0, path.length() - 5);
+        }
+        return path.substring(1).replace("/", ".").replace("-", "_");
+    }
+
+    private String createErrorMsg(List<CompilerMessage> errors) {
+        final StringBuilder buffer = new StringBuilder();
+        buffer.append("Compilation errors in ");
+        buffer.append(errors.get(0).getFile());
+        buffer.append(":");
+        StringBuilder errorsBuffer = new StringBuilder();
+        boolean duplicateVariable = false;
+        for (final CompilerMessage e : errors) {
+            if (!duplicateVariable) {
+                if (e.getMessage().contains("Duplicate local variable")) {
+                    duplicateVariable = true;
+                    buffer.append(" Maybe you defined more than one identical block elements without defining a different variable for "
+                            + "each one?");
+                }
+            }
+            errorsBuffer.append("\nLine ");
+            errorsBuffer.append(e.getLine());
+            errorsBuffer.append(", column ");
+            errorsBuffer.append(e.getColumn());
+            errorsBuffer.append(" : ");
+            errorsBuffer.append(e.getMessage());
+        }
+        buffer.append(errorsBuffer);
+        return buffer.toString();
+    }
+
+    class SlingResourceCompilationUnit implements CompilationUnit {
+        private final Resource resource;
+
+        public SlingResourceCompilationUnit(Resource resource) {
+            this.resource = resource;
+        }
+
+        public Reader getSource() throws IOException {
+            return new InputStreamReader(resource.adaptTo(InputStream.class), "UTF-8");
+        }
+
+        public String getMainClassName() {
+            return getJavaNameFromPath(resource.getPath());
+        }
+
+        public long getLastModified() {
+            return resource.getResourceMetadata().getModificationTime();
+        }
+    }
+
+    class SightlyCompilationUnit extends SlingResourceCompilationUnit {
+        private String fqcn;
+
+        public SightlyCompilationUnit(Resource resource, String fqcn) {
+            super(resource);
+            this.fqcn = fqcn;
+        }
+
+        public String getMainClassName() {
+            return fqcn;
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyParsingException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyParsingException.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyParsingException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyParsingException.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.impl.compiler;
+
+import org.apache.sling.scripting.sightly.SightlyException;
+
+/**
+ * The runtime {@code SightlyParsingException} is thrown during the parsing stage for any grammar offending input.
+ */
+public class SightlyParsingException extends SightlyException {
+
+    private String offendingInput;
+
+    public SightlyParsingException() {
+    }
+
+    public SightlyParsingException(String message) {
+        super(message);
+    }
+
+    public SightlyParsingException(String message, String offendingInput) {
+        super(message);
+        this.offendingInput = offendingInput;
+    }
+
+    public SightlyParsingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SightlyParsingException(String message, String offendingInput, Throwable cause) {
+        super(message, cause);
+        this.offendingInput = offendingInput;
+    }
+
+    public SightlyParsingException(Throwable cause) {
+        super(cause);
+    }
+
+    public String getOffendingInput() {
+        return offendingInput;
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyParsingException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Syntax.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Syntax.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Syntax.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Syntax.java Fri Nov 28 10:18:01 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.impl.compiler;
+
+import java.util.Arrays;
+
+import org.apache.sling.scripting.sightly.impl.plugin.PluginCallInfo;
+
+/**
+ * Sightly Syntax specific elements
+ */
+public class Syntax {
+
+    public static final String SLY_COMMENT_PREFIX = "<!--/*";
+
+    public static final String SLY_COMMENT_SUFFIX = "*/-->";
+
+    public static final String PLUGIN_ATTRIBUTE_PREFIX = "data-sly-";
+
+    public static final String DEFAULT_LIST_ITEM_VAR_NAME = "item";
+
+    public static final String ITEM_LOOP_STATUS_SUFFIX = "List";
+
+    public static final String CONTEXT_OPTION = "context";
+
+    public static final String MAP_ITEM_KEY_PROPERTY = "key";
+
+    public static final String MAP_ITEM_VALUE_PROPERTY = "value";
+
+    public static final String LENGTH_PROPERTY = "size";
+
+    /**
+     * Checks whether a piece of text represents a Sightly comment
+     * @param text - the text
+     * @return - true if it is a Sightly comment, false otherwise
+     */
+    public static boolean isSightlyComment(String text) {
+        //todo: performance concern
+        String trimmed = text.trim();
+        return trimmed.startsWith(SLY_COMMENT_PREFIX) && trimmed.endsWith(SLY_COMMENT_SUFFIX);
+    }
+
+    public static boolean isPluginAttribute(String attributeName) {
+        return attributeName.startsWith(PLUGIN_ATTRIBUTE_PREFIX);
+    }
+
+    public static PluginCallInfo parsePluginAttribute(String attributeName) {
+        if (!isPluginAttribute(attributeName)) {
+            return null;
+        }
+        String fragment = attributeName.substring(PLUGIN_ATTRIBUTE_PREFIX.length());
+        String[] parts = fragment.split("\\.");
+        if (parts.length == 0) {
+            return null;
+        }
+        return new PluginCallInfo(parts[0], Arrays.copyOfRange(parts, 1, parts.length));
+    }
+
+    public static String itemLoopStatusVariable(String itemVariable) {
+        return itemVariable + ITEM_LOOP_STATUS_SUFFIX;
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Syntax.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/common/DefaultPluginInvoke.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/common/DefaultPluginInvoke.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/common/DefaultPluginInvoke.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/common/DefaultPluginInvoke.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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.impl.compiler.common;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+
+/**
+ * Empty implementation for plugin invocation. Use this to implement
+ * methods selectively.
+ * @see org.apache.sling.scripting.sightly.impl.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) {
+
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/common/DefaultPluginInvoke.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/LoggingHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/LoggingHandler.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/LoggingHandler.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/LoggingHandler.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.impl.compiler.debug;
+
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 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");
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/LoggingHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/SanityChecker.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/SanityChecker.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/SanityChecker.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/SanityChecker.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * 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.impl.compiler.debug;
+
+import java.util.Stack;
+
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandHandler;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandVisitor;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Loop;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.OutText;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Procedure;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.VariableBinding;
+
+/**
+ * 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<NestedType> stack = new Stack<NestedType>();
+    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(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);
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/debug/SanityChecker.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/Expression.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/Expression.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/Expression.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/Expression.java Fri Nov 28 10:18:01 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.impl.compiler.expression;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class represent a Sightly Expression.
+ */
+public class Expression {
+
+    private final Map<String, ExpressionNode> options;
+    private final ExpressionNode root;
+
+    public Expression(ExpressionNode root, Map<String, ExpressionNode> options) {
+        this.root = root;
+        this.options = new HashMap<String, ExpressionNode>(options);
+    }
+
+    public Expression(ExpressionNode root) {
+        this(root, Collections.<String, ExpressionNode>emptyMap());
+    }
+
+    /**
+     * Get the options for this expression
+     * @return - the expression options
+     */
+    public Map<String, ExpressionNode> getOptions() {
+        return Collections.unmodifiableMap(options);
+    }
+
+    /**
+     * Get the root node of this expression
+     * @return - the root expression node
+     */
+    public ExpressionNode getRoot() {
+        return root;
+    }
+
+    /**
+     * Get the option with the specified name
+     * @param name the name of the option
+     * @return the expression node for the option value, or null if the
+     * option is not in the expression
+     */
+    public ExpressionNode getOption(String name) {
+        return options.get(name);
+    }
+
+    /**
+     * Return an expression where the given options are no longer present
+     * @param removedOptions the options to be removed
+     * @return a copy where the mention options are no longer present
+     */
+    public Expression removeOptions(String ... removedOptions) {
+        HashMap<String, ExpressionNode> newOptions = new HashMap<String, ExpressionNode>(options);
+        for (String option : removedOptions) {
+            newOptions.remove(option);
+        }
+        return new Expression(root, newOptions);
+    }
+
+    /**
+     * Return a copy, but with the specified node as root
+     * @param node the new root
+     * @return a copy with a new root
+     */
+    public Expression withNode(ExpressionNode node) {
+        return new Expression(node, options);
+    }
+
+    /**
+     * Checks whether the expression has the specified option
+     * @param name the name of the option
+     * @return true if the option is present, false otherwise
+     */
+    public boolean containsOption(String name) {
+        return options.containsKey(name);
+    }
+
+    @Override
+    public String toString() {
+        return "Expression{" +
+                "options=" + getOptions() +
+                ", root=" + root +
+                '}';
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/Expression.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/ExpressionNode.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/ExpressionNode.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/ExpressionNode.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/ExpressionNode.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression;
+
+/**
+ * ExpressionNode in a Sightly expression tree
+ */
+public interface ExpressionNode {
+
+    /**
+     * Accept a visitor to process this node.
+     * @param visitor The visitor
+     */
+    <T> T accept(NodeVisitor<T> visitor);
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/ExpressionNode.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/NodeVisitor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/NodeVisitor.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/NodeVisitor.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/NodeVisitor.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.ArrayLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.NullLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.NumericConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.PropertyAccess;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.TernaryOperator;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.UnaryOperation;
+
+/**
+ * Visitor for all expression nodes
+ */
+public interface NodeVisitor<T> {
+
+    T evaluate(PropertyAccess propertyAccess);
+
+    T evaluate(Identifier identifier);
+
+    T evaluate(StringConstant text);
+
+    T evaluate(BinaryOperation binaryOperation);
+
+    T evaluate(BooleanConstant booleanConstant);
+
+    T evaluate(NumericConstant numericConstant);
+
+    T evaluate(UnaryOperation unaryOperation);
+
+    T evaluate(TernaryOperator ternaryOperator);
+
+    T evaluate(RuntimeCall runtimeCall);
+
+    T evaluate(MapLiteral mapLiteral);
+
+    T evaluate(ArrayLiteral arrayLiteral);
+
+    T evaluate(NullLiteral nullLiteral);
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/NodeVisitor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/ArrayLiteral.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/ArrayLiteral.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/ArrayLiteral.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/ArrayLiteral.java Fri Nov 28 10:18:01 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.impl.compiler.expression.node;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Syntactical structure for an array of items
+ */
+public class ArrayLiteral implements ExpressionNode {
+
+    private final List<ExpressionNode> items;
+
+    public ArrayLiteral(List<ExpressionNode> items) {
+        this.items = new ArrayList<ExpressionNode>(items);
+    }
+
+    public List<ExpressionNode> getItems() {
+        return Collections.unmodifiableList(items);
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/ArrayLiteral.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Atom.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Atom.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Atom.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Atom.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+
+/**
+ * Nodes that can be translated to simple text, like identifiers
+ * or string constants.
+ */
+public interface Atom extends ExpressionNode {
+
+    /**
+     * Get the text content for this node
+     * @return The text content
+     */
+    String getText();
+
+}
+

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Atom.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperation.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperation.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperation.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * An expression where a binary operator is applied.
+ * Ex.: "a AND b"
+ */
+public class BinaryOperation implements ExpressionNode {
+
+    private BinaryOperator operator;
+    private ExpressionNode leftOperand;
+    private ExpressionNode rightOperand;
+
+    public BinaryOperation(BinaryOperator operator, ExpressionNode leftOperand, ExpressionNode rightOperand) {
+        this.operator = operator;
+        this.leftOperand = leftOperand;
+        this.rightOperand = rightOperand;
+    }
+
+    public BinaryOperator getOperator() {
+        return operator;
+    }
+
+    public ExpressionNode getLeftOperand() {
+        return leftOperand;
+    }
+
+    public ExpressionNode getRightOperand() {
+        return rightOperand;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    @Override
+    public String toString() {
+        return "BinaryOperation{" +
+                "operator=" + operator +
+                ", leftOperand=" + leftOperand +
+                ", rightOperand=" + rightOperand +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperation.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperator.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperator.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperator.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.render.RenderContext;
+
+/**
+ * Binary operators used in expressions
+ */
+public enum BinaryOperator {
+    // logical conjunction
+    AND {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return (renderContext.toBoolean(left)) ? right : left;
+        }
+    },
+    // logical disjunction
+    OR {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return (renderContext.toBoolean(left)) ? left : right;
+        }
+    },
+    // string concatenation
+    CONCATENATE
+    {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return renderContext.toString(left).concat(renderContext.toString(right));
+        }
+    },
+    // less-than
+    LT {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return lt(left, right);
+        }
+    },
+    // less or equal
+    LEQ {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return leq(left, right);
+        }
+    },
+    // greater than
+    GT {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return !leq(left, right);
+        }
+    },
+    // greater or equal
+    GEQ {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return !lt(left, right);
+        }
+    },
+    // equal
+    EQ {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return eq(left, right);
+        }
+    },
+    // not equal
+    NEQ {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return !eq(left, right);
+        }
+
+    },
+    // strict version of equality, restricted to just some types
+    STRICT_EQ {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return strictEq(left, right);
+        }
+    },
+    // strict version of the not-equal operator
+    STRICT_NEQ
+    {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return !strictEq(left, right);
+        }
+    },
+    // addition
+    ADD {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).doubleValue()
+                + renderContext.toNumber(right).doubleValue());
+        }
+    },
+
+    // difference
+    SUB {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).doubleValue()
+                - renderContext.toNumber(right).doubleValue());
+        }
+    },
+    // multiplication
+    MUL {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).doubleValue()
+                * renderContext.toNumber(right).doubleValue());
+        }
+    },
+    // floating point division
+    DIV {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).doubleValue()
+                / renderContext.toNumber(right).doubleValue());
+        }
+    },
+
+    // integer division
+    I_DIV {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).intValue()
+                / renderContext.toNumber(right).intValue());
+        }
+    },
+
+    // reminder
+    REM
+    {
+        @Override
+        public Object eval(RenderContext renderContext, Object left, Object right) {
+            return adjust(renderContext.toNumber(left).intValue()
+                % renderContext.toNumber(right).intValue());
+        }
+
+    };
+
+    public static String OBJECT_NAME = BinaryOperator.class.getName();
+    public static String METHOD_STRICT_EQ = "strictEq";
+    public static String METHOD_LEQ = "leq";
+    public static String METHOD_LT = "lt";
+
+    private static boolean eq(Object left, Object right) {
+        if (left == null) {
+            return right == null;
+        }
+        return left.equals(right);
+    }
+
+    public static boolean lt(final Object left, final Object right) {
+        if (left instanceof Number && right instanceof Number) {
+            return ((Number) left).doubleValue() < ((Number) right).doubleValue();
+        }
+        throw new UnsupportedOperationException("Invalid types in comparison. Comparison is supported for Number types only");
+    }
+
+    public static boolean leq(final Object left, final Object right) {
+        if (left instanceof Number && right instanceof Number) {
+            return ((Number) left).doubleValue() <= ((Number) right).doubleValue();
+        }
+        throw new UnsupportedOperationException("Invalid types in comparison. Comparison is supported for Number types only");
+    }
+
+
+   public static boolean strictEq(Object left, Object right) {
+       if (left instanceof Number && right instanceof Number) {
+           return ((Number) left).doubleValue() == ((Number) right).doubleValue();
+       }
+       if (left instanceof String && right instanceof String) {
+           return left.equals(right);
+       }
+       if (left instanceof Boolean && right instanceof Boolean) {
+           return left.equals(right);
+       }
+       if (left == null && right == null) {
+           return true;
+       }
+       if (left == null || right == null) {
+           Object notNull = (left != null) ? left : right;
+           if (notNull instanceof String || notNull instanceof Boolean || notNull instanceof Number) {
+               return false;
+           }
+       }
+       throw new UnsupportedOperationException("Invalid types in comparison. Equality is supported for String, Number & Boolean types");
+   }
+
+   private static Number adjust(double x) {
+       if (Math.floor(x) == x) {
+           return (int)x;
+       }
+       return x;
+   }
+
+     public abstract Object eval(RenderContext renderContext, Object left, Object right);
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BinaryOperator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BooleanConstant.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BooleanConstant.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BooleanConstant.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BooleanConstant.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Boolean constant.
+ * Ex: "true" or "false"
+ */
+public class BooleanConstant implements Atom {
+
+    private String rawText;
+
+    public static final BooleanConstant FALSE = new BooleanConstant(Boolean.toString(false));
+    public static final BooleanConstant TRUE = new BooleanConstant(Boolean.toString(true));
+
+    public BooleanConstant(String text) {
+        this.rawText = text;
+    }
+
+    public BooleanConstant(boolean value) {
+        this(Boolean.toString(value));
+    }
+
+    public boolean getValue() {
+        return Boolean.parseBoolean(rawText);
+    }
+
+
+    @Override
+    public String getText() {
+        return rawText;
+    }
+
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    @Override
+    public String toString() {
+        return "BooleanConstant{" +
+                "rawText='" + rawText + '\'' +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/BooleanConstant.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Identifier.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Identifier.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Identifier.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Identifier.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * A single variable. Ex: "myVar"
+ */
+public class Identifier implements Atom {
+
+    private final String name;
+
+    /**
+     * Create an identifier
+     * @param name the name of the identifier
+     */
+    public Identifier(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    /**
+     * Retrieve the name of the identifier
+     * @return the name string
+     */
+    public String getName() {
+        return name;
+    }
+
+
+    @Override
+    public String getText() {
+        return getName();
+    }
+
+    @Override
+    public String toString() {
+        return "Identifier{" +
+                "name='" + name + '\'' +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/Identifier.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/MapLiteral.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/MapLiteral.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/MapLiteral.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/MapLiteral.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * A syntactical construction representing a map
+ */
+public class MapLiteral implements ExpressionNode {
+
+    private Map<String, ExpressionNode> map;
+
+    public static final MapLiteral EMPTY = new MapLiteral(new HashMap<String, ExpressionNode>());
+
+    public MapLiteral(Map<String, ExpressionNode> map) {
+        this.map = new HashMap<String, ExpressionNode>();
+        this.map.putAll(map);
+    }
+
+    public Map<String, ExpressionNode> getMap() {
+        return Collections.unmodifiableMap(map);
+    }
+
+    public ExpressionNode getValue(String property) {
+        return map.get(property);
+    }
+
+    public boolean containsKey(String name) {
+        return map.containsKey(name);
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    @Override
+    public String toString() {
+        return "MapLiteral{" +
+                "map=" + map +
+                '}';
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/MapLiteral.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NullLiteral.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NullLiteral.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NullLiteral.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NullLiteral.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * The null literal
+ */
+public final class NullLiteral implements ExpressionNode {
+
+    public static final NullLiteral INSTANCE = new NullLiteral();
+
+    private NullLiteral() {
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NullLiteral.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NumericConstant.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NumericConstant.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NumericConstant.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NumericConstant.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Numeric constant expression.
+ * Ex: "42.1"
+ */
+public class NumericConstant implements Atom {
+
+    public static final NumericConstant ZERO = new NumericConstant(0);
+    public static final NumericConstant ONE = new NumericConstant(1);
+    public static final NumericConstant TWO = new NumericConstant(2);
+
+    private final String text;
+    private final Number value;
+
+    /**
+     * Create a numeric constant
+     * @param text - the text representation
+     * @throws java.lang.NumberFormatException - if the text is not in a numeric format
+     */
+    public NumericConstant(String text) {
+        this.text = text;
+        this.value = parseNumber(text);
+    }
+
+    public NumericConstant(Number value) {
+        this.value = value.longValue();
+        this.text = value.toString();
+    }
+
+    public Number getValue() {
+        return value;
+    }
+
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    @Override
+    public String toString() {
+        return "NumericConstant{" +
+                "text='" + text + '\'' +
+                '}';
+    }
+
+    private Number parseNumber(String s) {
+        try {
+            return Long.parseLong(s);
+        } catch (NumberFormatException e) {
+            return Double.parseDouble(s);
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/NumericConstant.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/PropertyAccess.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/PropertyAccess.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/PropertyAccess.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/PropertyAccess.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Expressions in which a property is queried for an object.
+ * Ex.: "E.prop"
+ */
+public class PropertyAccess implements ExpressionNode {
+
+    private final ExpressionNode target;
+    private final ExpressionNode property;
+
+    /**
+     * Create a property access node
+     * @param target The expression for the object being accessed
+     * @param property The name of the property
+     */
+    public PropertyAccess(ExpressionNode target, ExpressionNode property) {
+        this.target = target;
+        this.property = property;
+    }
+
+    public PropertyAccess(ExpressionNode target, String property) {
+        this.target = target;
+        this.property = new StringConstant(property);
+    }
+
+    /**
+     * Build a chained property access node with the given target and the specified properties
+     * @param target The target node
+     * @param properties A non-empty list of property names
+     * @throws IllegalArgumentException if the list of properties is empty
+     */
+    public PropertyAccess(ExpressionNode target, Iterable<String> properties) {
+        String lastProp = null;
+        ExpressionNode result = target;
+        for (String property : properties) {
+            if (lastProp != null) {
+                result = new PropertyAccess(result, new StringConstant(lastProp));
+            }
+            lastProp = property;
+        }
+        if (lastProp == null) {
+            throw new IllegalArgumentException("The list of properties must be non-empty");
+        }
+        this.target = result;
+        this.property = new StringConstant(lastProp);
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    /**
+     * The object being accessed
+     * @return a node representing the object being accessed
+     */
+    public ExpressionNode getTarget() {
+        return target;
+    }
+
+    /**
+     * Return the property name
+     * @return the property name
+     */
+    public ExpressionNode getProperty() {
+        return property;
+    }
+
+    @Override
+    public String toString() {
+        return "PropertyAccess{" +
+                "target=" + target +
+                ", property='" + property + '\'' +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/PropertyAccess.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/RuntimeCall.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/RuntimeCall.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/RuntimeCall.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/RuntimeCall.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Special expression which provides access to utility functions from
+ * the runtime. This mechanism should not be abused!
+ */
+public class RuntimeCall implements ExpressionNode {
+
+    private final String functionName;
+    private final List<ExpressionNode> arguments;
+
+    public RuntimeCall(String functionName, ExpressionNode... arguments) {
+        this(functionName, Arrays.asList(arguments));
+    }
+
+    public RuntimeCall(String functionName, List<ExpressionNode> arguments) {
+        this.functionName = functionName;
+        this.arguments = new ArrayList<ExpressionNode>(arguments);
+    }
+
+    /**
+     * Get the name of the function
+     * @return - the name of the function
+     */
+    public String getFunctionName() {
+        return functionName;
+    }
+
+    /**
+     * Get the nodes of the argument calls
+     * @return - an array of nodes
+     */
+    public List<ExpressionNode> getArguments() {
+        return Collections.unmodifiableList(arguments);
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/RuntimeCall.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/StringConstant.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/StringConstant.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/StringConstant.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/StringConstant.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Simple string constant. Ex: "'hello'"
+ */
+public class StringConstant implements Atom {
+
+    private String text;
+
+    public static final StringConstant EMPTY = new StringConstant("");
+
+    /**
+     * Create a string constant node
+     * @param text the string content (without it's original quotes).
+     */
+    public StringConstant(String text) {
+        this.text = text;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    /**
+     * Get the string content - it strips the quotes from the string
+     * @return a string inner content
+     */
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public String toString() {
+        return "StringConstant{" +
+                "text='" + text + '\'' +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/StringConstant.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain