org.openspotlight.graph.query.XPathStatementBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.openspotlight.graph.query.XPathStatementBuilder.java

Source

/**
 * OpenSpotLight - Open Source IT Governance Platform
 *
 * Copyright (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA
 * or third-party contributors as indicated by the @author tags or express
 * copyright attribution statements applied by the authors.  All third-party
 * contributions are distributed under license by CARAVELATECH CONSULTORIA E
 * TECNOLOGIA EM INFORMATICA LTDA.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License  for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 *
 ***********************************************************************
 * OpenSpotLight - Plataforma de Governana de TI de Cdigo Aberto
 *
 * Direitos Autorais Reservados (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA
 * EM INFORMATICA LTDA ou como contribuidores terceiros indicados pela etiqueta
 * @author ou por expressa atribuio de direito autoral declarada e atribuda pelo autor.
 * Todas as contribuies de terceiros esto distribudas sob licena da
 * CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA.
 *
 * Este programa  software livre; voc pode redistribu-lo e/ou modific-lo sob os
 * termos da Licena Pblica Geral Menor do GNU conforme publicada pela Free Software
 * Foundation.
 *
 * Este programa  distribudo na expectativa de que seja til, porm, SEM NENHUMA
 * GARANTIA; nem mesmo a garantia implcita de COMERCIABILIDADE OU ADEQUAO A UMA
 * FINALIDADE ESPEC?FICA. Consulte a Licena Pblica Geral Menor do GNU para mais detalhes.
 *
 * Voc deve ter recebido uma cpia da Licena Pblica Geral Menor do GNU junto com este
 * programa; se no, escreva para:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.openspotlight.graph.query;

import static org.openspotlight.common.util.StringBuilderUtil.append;
import static org.openspotlight.common.util.StringBuilderUtil.appendIfNotNull;

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

import org.apache.commons.lang.StringUtils;
import org.openspotlight.common.exception.SLRuntimeException;
import org.openspotlight.graph.query.XPathStatementBuilder.Statement.Condition;

/**
 * The Class SLXPathStatementBuilder.
 * 
 * @author Vitor Hugo Chagas
 */
public class XPathStatementBuilder {

    /**
     * The Class Statement.
     * 
     * @author Vitor Hugo Chagas
     */
    public static class Statement {

        /**
         * The Class Condition.
         * 
         * @author Vitor Hugo Chagas
         */
        public static class Condition {

            /**
             * The Class LeftOperand.
             * 
             * @author Vitor Hugo Chagas
             */
            public static class LeftOperand {

                /**
                 * The Class RelationalOperator.
                 * 
                 * @author Vitor Hugo Chagas
                 */
                public static class RelationalOperator {

                    /** The condition. */
                    private final Condition condition;

                    /**
                     * Instantiates a new relational operator.
                     * 
                     * @param condition the condition
                     */
                    private RelationalOperator(final Condition condition) {
                        this.condition = condition;
                    }

                    /**
                     * Right operand.
                     * 
                     * @param value the value
                     * @return the statement
                     */
                    public Statement rightOperand(final Object value) {
                        condition.rightOperandValue = value;
                        condition.closed = true;
                        return condition.outerStatement;
                    }
                }

                /** The condition. */
                private final Condition condition;

                /**
                 * Instantiates a new left operand.
                 * 
                 * @param condition the condition
                 */
                private LeftOperand(final Condition condition) {
                    this.condition = condition;
                }

                /**
                 * Inexistent.
                 * 
                 * @return the statement
                 */
                public Statement inexistent() {
                    condition.closed = true;
                    condition.inexistent = true;
                    return condition.outerStatement;
                }

                /**
                 * Operator.
                 * 
                 * @param relationalOperator the relational operator
                 * @return the relational operator
                 */
                public RelationalOperator operator(final RelationalOperatorType relationalOperator) {
                    return operator(relationalOperator, false);
                }

                /**
                 * Operator.
                 * 
                 * @param relationalOperator the relational operator
                 * @param applyNot the apply not
                 * @return the relational operator
                 */
                public RelationalOperator operator(final RelationalOperatorType relationalOperator,
                        final boolean applyNot) {
                    condition.relationalOperator = relationalOperator;
                    condition.relationalOperatorApplyNot = applyNot;
                    return new RelationalOperator(condition);
                }
            }

            /** The closed. */
            private boolean closed = false;

            /** The conditional operator. */
            private ConditionalOperatorType conditionalOperator;

            /** The conditional operator apply not. */
            private boolean conditionalOperatorApplyNot;

            /** The inexistent. */
            private boolean inexistent = false;

            /** The inner statement. */
            private Statement innerStatement;

            /** The left operand value. */
            private Object leftOperandValue;

            /** The outer statement. */
            private Statement outerStatement;

            /** The relational operator. */
            private RelationalOperatorType relationalOperator;

            /** The relational operator apply not. */
            private boolean relationalOperatorApplyNot;

            /** The right operand value. */
            private Object rightOperandValue;

            /** The stack trace. */
            private final StackTraceElement[] stackTrace;

            /**
             * Instantiates a new condition.
             * 
             * @param outerStatement the outer statement
             */
            private Condition(final Statement outerStatement) {
                stackTrace = Thread.currentThread().getStackTrace();
                this.outerStatement = outerStatement;
            }

            /**
             * Left operand.
             * 
             * @param value the value
             * @return the left operand
             */
            public LeftOperand leftOperand(final Object value) {
                leftOperandValue = value;
                return new LeftOperand(this);
            }
        }

        /**
         * The Class ConditionalOperator.
         * 
         * @author Vitor Hugo Chagas
         */
        public static class ConditionalOperator {

            /** The apply not. */
            private final boolean applyNot;

            /** The conditional operator. */
            private final ConditionalOperatorType conditionalOperator;

            /** The statement. */
            private final Statement statement;

            /**
             * Instantiates a new conditional operator.
             * 
             * @param statement the statement
             * @param conditionalOperator the conditional operator
             * @param applyNot the apply not
             */
            private ConditionalOperator(final Statement statement,
                    final ConditionalOperatorType conditionalOperator, final boolean applyNot) {
                this.statement = statement;
                this.conditionalOperator = conditionalOperator;
                this.applyNot = applyNot;
            }

            /**
             * Condition.
             * 
             * @return the condition
             */
            public Condition condition() {
                final Condition condition = new Condition(statement);
                condition.conditionalOperator = conditionalOperator;
                condition.conditionalOperatorApplyNot = applyNot;
                condition.outerStatement = statement;
                statement.conditions.add(condition);
                return condition;
            }

            /**
             * Open bracket.
             * 
             * @return the statement
             */
            public Statement openBracket() {
                final Condition condition = new Condition(statement);
                condition.conditionalOperator = conditionalOperator;
                condition.conditionalOperatorApplyNot = applyNot;
                statement.conditions.add(condition);
                final Statement innerStatement = new Statement(condition);
                condition.innerStatement = innerStatement;
                return innerStatement;
            }
        }

        /** The conditions. */
        private final List<Condition> conditions = new ArrayList<Condition>();

        /** The parent. */
        private final Condition parent;

        /**
         * Instantiates a new statement.
         * 
         * @param parent the parent
         */
        private Statement(final Condition parent) {
            this.parent = parent;
        }

        /**
         * Close bracket.
         * 
         * @return the statement
         */
        public Statement closeBracket() {
            parent.closed = true;
            return parent.outerStatement;
        }

        /**
         * Condition.
         * 
         * @return the condition
         */
        public Condition condition() {
            final Condition condition = new Condition(this);
            conditions.add(condition);
            return condition;
        }

        /**
         * Gets the condition count.
         * 
         * @return the condition count
         */
        public int getConditionCount() {
            return conditions.size();
        }

        /**
         * Open bracket.
         * 
         * @return the statement
         */
        public Statement openBracket() {
            final Condition condition = new Condition(this);
            conditions.add(condition);
            final Statement innerStatement = new Statement(condition);
            condition.innerStatement = innerStatement;
            return innerStatement;
        }

        /**
         * Operator.
         * 
         * @param conditionalOperator the conditional operator
         * @return the conditional operator
         */
        public ConditionalOperator operator(final ConditionalOperatorType conditionalOperator) {
            return operator(conditionalOperator, false);
        }

        /**
         * Operator.
         * 
         * @param conditionalOperator the conditional operator
         * @param applyNot the apply not
         * @return the conditional operator
         */
        public ConditionalOperator operator(final ConditionalOperatorType conditionalOperator,
                final boolean applyNot) {
            return new ConditionalOperator(this, conditionalOperator, applyNot);
        }
    }

    /** The order by. */
    private String orderBy;

    /** The path. */
    private String path;

    /** The root statement. */
    private Statement rootStatement;

    /**
     * Instantiates a new sLX path statement builder.
     */
    public XPathStatementBuilder() {
    }

    /**
     * Instantiates a new sLX path statement builder.
     * 
     * @param path the path
     */
    public XPathStatementBuilder(final String path) {
        this.path = path;
    }

    /**
     * Prints the statement.
     * 
     * @param buffer the buffer
     * @param statement the statement
     * @param identLevel the ident level
     */
    private void printStatement(final StringBuilder buffer, final Statement statement, final int identLevel) {
        validate(rootStatement);
        final StringBuilder statementBuffer = new StringBuilder();
        final String tabs0 = StringUtils.repeat("\t", identLevel);
        final String tabs1 = StringUtils.repeat("\t", identLevel + 1);
        for (final Condition condition : statement.conditions) {
            append(statementBuffer, tabs0);
            if (condition.innerStatement == null) {
                if (condition.conditionalOperator != null) {
                    if (condition.conditionalOperator != null) {
                        append(statementBuffer, condition.conditionalOperator.symbol().toLowerCase(), ' ');
                    }
                    if (condition.conditionalOperatorApplyNot) {
                        append(statementBuffer, "not(\n", tabs1);
                    }
                }
                if (condition.inexistent) {
                    append(statementBuffer, "not(@", condition.leftOperandValue, ")\n");
                } else {
                    final String expression = condition.relationalOperator.xPathExpression(
                            condition.leftOperandValue, condition.rightOperandValue,
                            condition.relationalOperatorApplyNot);
                    append(statementBuffer, expression, '\n');
                    if (condition.conditionalOperator != null && condition.conditionalOperatorApplyNot) {
                        append(statementBuffer, tabs0, ")\n");
                    }
                }
            } else {
                if (condition.conditionalOperator != null) {
                    append(statementBuffer, condition.conditionalOperator.symbol().toLowerCase(), ' ');
                }
                if (condition.conditionalOperatorApplyNot) {
                    append(statementBuffer, "not(\n");
                } else {
                    append(statementBuffer, "(\n");
                }
                printStatement(statementBuffer, condition.innerStatement, identLevel + 1);
                append(statementBuffer, tabs0, ")\n");
            }
        }
        append(buffer, statementBuffer);
    }

    /**
     * Validate.
     * 
     * @param statement the statement
     */
    private void validate(final Statement statement) {
        if (statement != null) {
            for (final Condition condition : statement.conditions) {
                if (!condition.closed) {
                    final RuntimeException e = new SLRuntimeException("All conditions must be closed.");
                    e.setStackTrace(condition.stackTrace);
                    throw e;
                }
                validate(condition.innerStatement);
            }
        }
    }

    /**
     * Gets the root statement.
     * 
     * @return the root statement
     */
    public Statement getRootStatement() {
        if (rootStatement == null) {
            rootStatement = new Statement(null);
        }
        return rootStatement;
    }

    /**
     * Gets the x path.
     * 
     * @return the x path
     */
    public String getXPath() {
        final StringBuilder buffer = new StringBuilder();
        final StringBuilder statementBuffer = new StringBuilder();
        printStatement(statementBuffer, rootStatement, 0);
        append(buffer, path, "\n[\n", statementBuffer, "]");
        appendIfNotNull(buffer, orderBy, "\norder by @", orderBy);
        return buffer.toString();
    }

    /**
     * Gets the x path string.
     * 
     * @return the x path string
     */
    public String getXPathString() {
        String xpath = getXPath();
        xpath = StringUtils.replace(xpath, "\t", "");
        xpath = StringUtils.replace(xpath, "\n", " ");
        return xpath;
    }

    /**
     * Sets the order by.
     * 
     * @param orderBy the new order by
     */
    public void setOrderBy(final String orderBy) {
        this.orderBy = orderBy;
    }

    /**
     * Sets the path.
     * 
     * @param path the new path
     */
    public void setPath(final String path) {
        this.path = path;
    }
}