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

com.blazebit.persistence.impl.datanucleus.function.DataNucleusJpqlFunctionAdapter Maven / Gradle / Ivy

The newest version!
package com.blazebit.persistence.impl.datanucleus.function;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping;
import org.datanucleus.store.rdbms.mapping.java.TemporalMapping;
import org.datanucleus.store.rdbms.sql.SQLText;
import org.datanucleus.store.rdbms.sql.expression.AggregateNumericExpression;
import org.datanucleus.store.rdbms.sql.expression.AggregateTemporalExpression;
import org.datanucleus.store.rdbms.sql.expression.BooleanExpression;
import org.datanucleus.store.rdbms.sql.expression.ByteExpression;
import org.datanucleus.store.rdbms.sql.expression.CharacterExpression;
import org.datanucleus.store.rdbms.sql.expression.NumericExpression;
import org.datanucleus.store.rdbms.sql.expression.SQLExpression;
import org.datanucleus.store.rdbms.sql.expression.StringExpression;
import org.datanucleus.store.rdbms.sql.expression.TemporalExpression;
import org.datanucleus.store.rdbms.sql.method.AbstractSQLMethod;

import com.blazebit.persistence.spi.JpqlFunction;

public class DataNucleusJpqlFunctionAdapter extends AbstractSQLMethod {
	
	private static final Logger LOG = Logger.getLogger(DataNucleusJpqlFunctionAdapter.class.getName());
	private final JpqlFunction function;
	private final boolean aggregate;

	public DataNucleusJpqlFunctionAdapter(JpqlFunction function, boolean aggregate) {
		this.function = function;
		this.aggregate = aggregate;
	}

	@Override
	public SQLExpression getExpression(SQLExpression expr, List args) {
	    // NOTE: expr will be the first argument for class methods like getMonth!
		int argsSize = args.size();
        List newArgs = new ArrayList(argsSize + (expr == null ? 0 : 1));
        Class firstArgumentType = null;
        JavaTypeMapping firstArgumentTypeMapping = null;
        
        if (expr != null) {
            firstArgumentTypeMapping = expr.getJavaTypeMapping();
            firstArgumentType = firstArgumentTypeMapping.getJavaType();
            newArgs.add(expr.toSQLText().toSQL());
            for (int i = 0; i < argsSize; i++) {
                newArgs.add(args.get(i).toSQLText().toSQL());
            }
        } else if (argsSize > 0) {
        	firstArgumentTypeMapping = args.get(0).getJavaTypeMapping();
        	firstArgumentType = firstArgumentTypeMapping.getJavaType();
            newArgs.add(args.get(0).toSQLText().toSQL());
	        for (int i = 1; i < argsSize; i++) {
	            newArgs.add(args.get(i).toSQLText().toSQL());
	        }
        }
        
        Class returnType = function.getReturnType(firstArgumentType);
        JavaTypeMapping returnTypeMapping;
        
        if (returnType == firstArgumentType) {
        	returnTypeMapping = firstArgumentTypeMapping;
        } else {
        	returnTypeMapping = getMappingForClass(returnType);
        }
        
        if (returnTypeMapping == null) {
        	throw new IllegalArgumentException("Invalid return type null returned from function: " + function);
        }
        
        final DataNucleusFunctionRenderContext context = new DataNucleusFunctionRenderContext(newArgs);
        function.render(context);
        
        final SQLText sqlText = new CustomSQLText(context.renderToString(), expr, args);
        
        if (aggregate) {
        	if (returnTypeMapping instanceof TemporalMapping) {
        		return new AggregateTemporalExpression(stmt, returnTypeMapping, "", null) {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
        		};
        	} else if (Number.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
        		return new AggregateNumericExpression(stmt, returnTypeMapping, "") {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
        	} else {
        		LOG.warning("Aggregate type [" + returnType + "] could not be represented as aggregate. Please report this so we can support the type! Falling back to normal expression.");
        	}
        } else {
	        if (returnTypeMapping instanceof TemporalMapping) {
	    		return new TemporalExpression(stmt, returnTypeMapping, "", null) {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else if (Byte.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
	    		return new ByteExpression(stmt, null, returnTypeMapping) {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else if (Number.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
	    		return new NumericExpression(stmt, returnTypeMapping, "") {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else if (String.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
	    		return new StringExpression(stmt, null, returnTypeMapping) {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else if (Character.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
	    		return new CharacterExpression(stmt, null, returnTypeMapping) {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else if (Boolean.class.isAssignableFrom(returnTypeMapping.getJavaType())) {
	    		return new BooleanExpression(stmt, returnTypeMapping, "") {
					@Override
					public SQLText toSQLText() {
						return sqlText;
					}
	    		};
	    	} else {
	    		LOG.warning("Type [" + returnType + "] could not be represented as aggregate. Please report this so we can support the type! Falling back to normal expression.");
	    	}
        }
        
        return new SQLExpression(stmt, null, returnTypeMapping) {
			@Override
			public SQLText toSQLText() {
				return sqlText;
			}
		};
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy