All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.blazebit.persistence.impl.BaseUpdateCriteriaBuilderImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015 Blazebit.
 *
 * Licensed 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 com.blazebit.persistence.impl;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.blazebit.persistence.BaseUpdateCriteriaBuilder;
import com.blazebit.persistence.MultipleSubqueryInitiator;
import com.blazebit.persistence.SubqueryInitiator;
import com.blazebit.persistence.impl.builder.expression.ExpressionBuilder;
import com.blazebit.persistence.impl.builder.expression.ExpressionBuilderEndedListener;
import com.blazebit.persistence.impl.expression.Expression;
import com.blazebit.persistence.impl.expression.SubqueryExpression;
import com.blazebit.persistence.impl.expression.VisitorAdapter;
import com.blazebit.persistence.spi.DbmsStatementType;

/**
 *
 * @param  The query result type
 * @author Christian Beikov
 * @since 1.1.0
 */
public class BaseUpdateCriteriaBuilderImpl, Y> extends AbstractModificationCriteriaBuilder implements BaseUpdateCriteriaBuilder, SubqueryBuilderListener, ExpressionBuilderEndedListener {

    private final VisitorAdapter parameterRegistrationVisitor;
	private final Map setAttributes = new LinkedHashMap();
	private SubqueryInternalBuilder currentSubqueryBuilder;
	private String currentAttribute;

	public BaseUpdateCriteriaBuilderImpl(MainQuery mainQuery, boolean isMainQuery, Class clazz, String alias, String cteName, Class cteClass, Y result, CTEBuilderListener listener) {
		super(mainQuery, isMainQuery, DbmsStatementType.UPDATE, clazz, alias, cteName, cteClass, result, listener);
        this.parameterRegistrationVisitor = parameterManager.getParameterRegistrationVisitor();
	}

    @Override
    @SuppressWarnings("unchecked")
	public X set(String attributeName, Object value) {
        verifyBuilderEnded();
        checkAttribute(attributeName);
        Expression attributeExpression = parameterManager.addParameterExpression(value);
		setAttributes.put(attributeName, attributeExpression);
		return (X) this;
	}

	@Override
    @SuppressWarnings("unchecked")
    public X setExpression(String attributeName, String expression) {
        verifyBuilderEnded();
        checkAttribute(attributeName);
        Expression attributeExpression = expressionFactory.createScalarExpression(expression);
        attributeExpression.accept(parameterRegistrationVisitor);
        setAttributes.put(attributeName, attributeExpression);
        return (X) this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public SubqueryInitiator set(String attribute) {
        verifySubqueryBuilderEnded();
        checkAttribute(attribute);
        this.currentAttribute = attribute;
        return subqueryInitFactory.createSubqueryInitiator((X) this, this);
    }

    @SuppressWarnings("unchecked")
    @Override
    public MultipleSubqueryInitiator setSubqueries(String attribute, String expression) {
        verifySubqueryBuilderEnded();
        checkAttribute(attribute);
        this.currentAttribute = attribute;
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        MultipleSubqueryInitiator initiator = new MultipleSubqueryInitiatorImpl((X) this, expr, this, subqueryInitFactory);
        return initiator;
    }
    
    private void verifySubqueryBuilderEnded() {
        if (currentAttribute != null) {
            throw new BuilderChainingException("An initiator was not ended properly.");
        }
        if (currentSubqueryBuilder != null) {
            throw new BuilderChainingException("An subquery builder was not ended properly.");
        }
    }

    @Override
    public void onBuilderEnded(ExpressionBuilder builder) {
        if (currentAttribute == null) {
            throw new BuilderChainingException("There was an attempt to end a builder that was not started or already closed.");
        }

        Expression attributeExpression = builder.getExpression();
        attributeExpression.accept(parameterRegistrationVisitor);
        setAttributes.put(currentAttribute, attributeExpression);
    }

    @Override
    public void onBuilderEnded(SubqueryInternalBuilder builder) {
        if (currentAttribute == null) {
            throw new BuilderChainingException("There was an attempt to end a builder that was not started or already closed.");
        }
        if (currentSubqueryBuilder == null) {
            throw new BuilderChainingException("There was an attempt to end a builder that was not started or already closed.");
        }
        Expression attributeExpression = new SubqueryExpression(builder);
        attributeExpression.accept(parameterRegistrationVisitor);
        setAttributes.put(currentAttribute, attributeExpression);
        currentAttribute = null;
        currentSubqueryBuilder = null;
    }

    @Override
    public void onBuilderStarted(SubqueryInternalBuilder builder) {
        if (currentAttribute == null) {
            throw new BuilderChainingException("There was an attempt to start a builder without an originating initiator.");
        }
        if (currentSubqueryBuilder != null) {
            throw new BuilderChainingException("There was an attempt to start a builder but a previous builder was not ended.");
        }
        currentSubqueryBuilder = builder;
    }

    @Override
    public void onReplaceBuilder(SubqueryInternalBuilder oldBuilder, SubqueryInternalBuilder newBuilder) {
        throw new IllegalArgumentException("Replace not valid!");
    }

    @Override
    public void onInitiatorStarted(SubqueryInitiator initiator) {
        throw new IllegalArgumentException("Initiator started not valid!");
    }

    private void checkAttribute(String attributeName) {
        // Just do that to assert the attribute exists
        JpaUtils.getBasicAttributePath(getMetamodel(), entityType, attributeName);
        Expression attributeExpression = setAttributes.get(attributeName);
        
        if (attributeExpression != null) {
            throw new IllegalArgumentException("The attribute [" + attributeName + "] has already been bound!");
        }
    }

    @Override
	protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean externalRepresentation) {
		sbSelectFrom.append("UPDATE ");
		sbSelectFrom.append(entityType.getName()).append(' ');
	    sbSelectFrom.append(entityAlias);
		sbSelectFrom.append(" SET ");

        queryGenerator.setQueryBuffer(sbSelectFrom);
        SimpleQueryGenerator.BooleanLiteralRenderingContext oldBooleanLiteralRenderingContext = queryGenerator.setBooleanLiteralRenderingContext(SimpleQueryGenerator.BooleanLiteralRenderingContext.CASE_WHEN);
        
        Iterator> setAttributeIter = setAttributes.entrySet().iterator();
        if (setAttributeIter.hasNext()) {
        	Map.Entry attributeEntry = setAttributeIter.next();
        	sbSelectFrom.append(attributeEntry.getKey());
			sbSelectFrom.append(" = ");
			attributeEntry.getValue().accept(queryGenerator);
			while (setAttributeIter.hasNext()) {
				attributeEntry = setAttributeIter.next();
				sbSelectFrom.append(',');
	        	sbSelectFrom.append(attributeEntry.getKey());
				sbSelectFrom.append(" = ");
				attributeEntry.getValue().accept(queryGenerator);
			}
        }

        queryGenerator.setBooleanLiteralRenderingContext(oldBooleanLiteralRenderingContext);
    	appendWhereClause(sbSelectFrom);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy