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

com.abubusoft.kripton.processor.sqlite.SqlAnalyzer Maven / Gradle / Ivy

There is a newer version: 8.2.0-rc.4
Show newest version
/*******************************************************************************
 * Copyright 2015, 2017 Francesco Benincasa ([email protected]).
 *
 * 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.abubusoft.kripton.processor.sqlite;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.lang.model.util.Elements;

import com.abubusoft.kripton.common.CaseFormat;
import com.abubusoft.kripton.common.Converter;
import com.abubusoft.kripton.common.StringUtils;
import com.abubusoft.kripton.processor.core.ModelProperty;
import com.abubusoft.kripton.processor.core.reflect.TypeUtility;
import com.abubusoft.kripton.processor.exceptions.MethodParameterNotFoundException;
import com.abubusoft.kripton.processor.exceptions.PropertyInAnnotationNotFoundException;
import com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker.JQLParameterName;
import com.abubusoft.kripton.processor.sqlite.model.SQLProperty;
import com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity;
import com.abubusoft.kripton.processor.sqlite.model.SQLiteModelMethod;
import com.squareup.javapoet.TypeName;


/**
 * Analyze an SQL statement, extract parameter and replace with ?.
 *
 * @author Francesco Benincasa ([email protected])
 */
public class SqlAnalyzer {
	
	public static String PARAM_PREFIX=":";
	public static String PARAM_SUFFIX="";
	
	public static String PARAM_PATTERN="(\\$\\{\\s*([\\w._]*)\\s*\\})|(\\:\\{\\s*([\\w._]*)\\s*\\})|(\\:\\s*([\\w._]*))";
	
	/**
	 * @param matcher
	 * @return
	 */
	public static String extractParamName(Matcher matcher) {
		int index;
		if (StringUtils.hasText(matcher.group(2))) {
			index=2;
		} else if (StringUtils.hasText(matcher.group(4))) {
			index=4;
		} else {
			index=6;
		}
		return matcher.group(index);
	}

	/** The parameter. */
	private final Pattern PARAMETER = Pattern.compile(PARAM_PATTERN);

	/** The word. */
	private final Pattern WORD = Pattern.compile("([_a-zA-Z]\\w*)");

	/** The property converter. */
	Converter propertyConverter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_CAMEL);

	/** The param names. */
	private List paramNames;
	
	/** The param type names. */
	private List paramTypeNames;
	
	/**
	 * Gets the param type names.
	 *
	 * @return the paramTypes
	 */
	public List getParamTypeNames() {
		return paramTypeNames;
	}

	/**
	 * bean properties typeName used into statement.
	 */
	private List usedBeanPropertyNames;

	/**
	 * Gets the param names.
	 *
	 * @return the paramNames
	 */
	public List getParamNames() {
		return paramNames;
	}

	/**
	 * Gets the param getters.
	 *
	 * @return the paramGetters
	 */
	public List getParamGetters() {
		return paramGetters;
	}

	/** The param getters. */
	private List paramGetters;

	/** The sql statement. */
	private String sqlStatement;
	
	/**
	 * used method parameter.
	 */
	private Set usedMethodParameters;

	/**
	 * Gets the used method parameters.
	 *
	 * @return the usedMethodParameters
	 */
	public Set getUsedMethodParameters() {
		return usedMethodParameters;
	}

	/**
	 * Extract from value string every placeholder :{}, replace it with ? and then convert every field typeName with column typeName. The result is a pair: the first value is the elaborated string. The second is the list of parameters associated to
	 * ?. This second parameter is the list of parameters and replaced with ?.
	 *
	 * @param elementUtils the element utils
	 * @param method the method
	 * @param sqlStatement the sql statement
	 */
	public void execute(Elements elementUtils, SQLiteModelMethod method, String sqlStatement) {
		SQLiteEntity entity=method.getEntity();
		
		usedMethodParameters=new HashSet();		
		
		paramNames = new ArrayList();
		paramGetters = new ArrayList();
		usedBeanPropertyNames=new ArrayList();
		paramTypeNames=new ArrayList();

		// replace placeholder :{ } with ?
		{
			Matcher matcher = PARAMETER.matcher(sqlStatement);

			StringBuffer buffer = new StringBuffer();
			while (matcher.find()) {
				matcher.appendReplacement(buffer, "?");
								
				
				paramNames.add(extractParamName(matcher));
			}
			matcher.appendTail(buffer);

			sqlStatement = buffer.toString();
		}

		// replace property typeName to column typeName
		{
			Matcher matcher = WORD.matcher(sqlStatement);

			StringBuffer buffer = new StringBuffer();
			while (matcher.find()) {
				SQLProperty property = entity.findPropertyByName(matcher.group(1));
				if (property != null) {
					matcher.appendReplacement(buffer, property.columnName);
				}

			}
			matcher.appendTail(buffer);
			sqlStatement = buffer.toString();
		}
		
		TypeName rawNameType;
		// analyze parametersName
		String effectiveName;
		for (String rawName: paramNames)
		{
			JQLParameterName pName=JQLParameterName.parse(rawName);			
			
			if (!pName.isNested())
			{
				effectiveName=method.findParameterNameByAlias(pName.getValue());
				rawNameType = method.findParameterTypeByAliasOrName(effectiveName);
				if (rawNameType==null)
				{
					throw new MethodParameterNotFoundException(method, effectiveName);
				}
				paramGetters.add(effectiveName);
				paramTypeNames.add(rawNameType);				
				usedMethodParameters.add(effectiveName);
				usedBeanPropertyNames.add(null);
			} else {
				if (method.findParameterTypeByAliasOrName(pName.getBeanName())==null)
				{
					throw new MethodParameterNotFoundException(method, pName.getBeanName());
				}
				 
				if (TypeUtility.isEquals(method.findParameterTypeByAliasOrName(pName.getBeanName()), entity) && entity.contains(pName.getValue()))
				{				
					// there are nested property invocation
					paramGetters.add(method.findParameterNameByAlias(pName.getBeanName())+"."+getter(entity.findPropertyByName(pName.getValue())));
					usedBeanPropertyNames.add(pName.getValue());
					paramTypeNames.add(TypeUtility.typeName(entity.findPropertyByName(pName.getValue()).getElement().asType()));				
					usedMethodParameters.add(method.findParameterNameByAlias(pName.getBeanName()));
				} else {
					throw (new PropertyInAnnotationNotFoundException(method, pName.getValue()));
				}
			}
//			} else {
//				throw (new PropertyInAnnotationNotFoundException(method, rawName));
//			}
			
		}
				
		this.sqlStatement=sqlStatement;
	}

	/**
	 * Gets the used bean property names.
	 *
	 * @return the usedBeanProperties
	 */
	public List getUsedBeanPropertyNames() {
		return usedBeanPropertyNames;
	}

	/**
	 * Gets the ter.
	 *
	 * @param property the property
	 * @return the ter
	 */
	public String getter(ModelProperty property) {		
		if (property.isPublicField())
			return property.getName();

		if (property.isFieldWithGetter()) {
			return "get" + propertyConverter.convert(property.getName()) + "()";
		}

		if (property.isFieldWithIs()) {
			return "is" + propertyConverter.convert(property.getName()) + "()";
		}

		return null;
	}

	/**
	 * Setter.
	 *
	 * @param property the property
	 * @return the string
	 */
	public String setter(ModelProperty property) {
		if (property.isPublicField())
			return property.getName();

		if (property.isFieldWithGetter() || property.isFieldWithIs()) {
			return "set" + propertyConverter.convert(property.getName());
		}

		return null;
	}

	/**
	 * Gets the SQL statement.
	 *
	 * @return the SQL statement
	 */
	public String getSQLStatement() {
		return sqlStatement;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy