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

com.viiyue.plugins.mybatis.template.TemplateEngine Maven / Gradle / Ivy

Go to download

Mybatis generic mapper plugin for solving most basic operations, simplifying sql syntax and improving dynamic execution efficiency

There is a newer version: 1.3.7
Show newest version
/**
 * Copyright (C) 2017 the original author or authors.
 *
 * 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.viiyue.plugins.mybatis.template;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import com.viiyue.plugins.mybatis.Constants;
import com.viiyue.plugins.mybatis.template.builder.base.TemplateBuilder;
import com.viiyue.plugins.mybatis.template.function.BlankFunction;
import com.viiyue.plugins.mybatis.template.function.EqualFunction;
import com.viiyue.plugins.mybatis.template.function.NotBlankFunction;
import com.viiyue.plugins.mybatis.template.function.NotNullFunction;
import com.viiyue.plugins.mybatis.template.function.NullFunction;
import com.viiyue.plugins.mybatis.utils.CaseUtil;
import com.viiyue.plugins.mybatis.utils.MapUtil;

/**
 * The SQL script template engine parsing tool class, all the parts about the
 * template used in the plugin are parsed by this tool class.
 *
 * @author tangxbai
 * @since 1.0.0
 * 
 * @see NotBlankFunction
 * @see EqualFunction
 * @see NotBlankFunction
 * @see NotNullFunction
 * @see NullFunction
 * @see Constants#ENV_PROP_NAMES
 */
public final class TemplateEngine {

	/**
	 * Template engine singleton object
	 */
	private static final FelEngine engine;
	
	/**
	 * Template engine context environments
	 */
	private static final Map environments;
	
//	private static final String paramsNameKey = "params";
//	private static final String translatedTemplateKey = "template";
//	private static final Pattern pramemterPattern = Pattern.compile( "(['\"]([^'\"].*?)['\"])" );
//	private static final Map expressions = new ConcurrentHashMap();
	
	private TemplateEngine() {}
	
	// Register the default available environment variables
	static {
		Properties properties = System.getProperties();
		List propNames = Constants.ENV_PROP_NAMES;
		environments = new HashMap( propNames.size() );
		for ( String propName : propNames ) {
			environments.put( CaseUtil.toCamelCase( propName, '.' ), properties.getProperty( propName ) );
		}
	}
	
	// Registration template helper function
	static {
		engine = new FelEngineImpl( context() );
		engine.addFun( new NullFunction() ); 	// isNull( ? )
		engine.addFun( new NotNullFunction() ); // isNotNull( ? )
		engine.addFun( new BlankFunction() );	// isBlank( ? )
		engine.addFun( new NotBlankFunction() );// isNotBlank( ? ) - default function
		engine.addFun( new EqualFunction() ); 	// equals( ?, ? )
	}
	
	/**
	 * Provide access to some system data
	 * 
	 * 

Currently supported

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
DescriptionExampleValue typeResult style
Generate UUIDeval("system.uuid")String30803fc4-c22a-11e9-9cb5-2a2ae2dbcce4
Get a random numbereval("system.random.nextInt(100)")Integer0 - 100
Get system timeeval("system.now")Datenew Date()
Get system millisecond timeeval("system.systime")Long4564646132487
* * @return partial system data */ private static Map systemContext() { Map systemContext = new HashMap( 4 ); systemContext.put( "now", new Date() ); // now -> Date systemContext.put( "uuid", UUID.randomUUID().toString() ); // uuid -> 30803fc4-c22a-11e9-9cb5-2a2ae2dbcce4 systemContext.put( "random", ThreadLocalRandom.current() ); // rundom.nexInt(maxValue) systemContext.put( "systime", System.currentTimeMillis() ); // systime -> 4564646132487 return systemContext; } /** * Generates a template context object that has environment variables and * system help properties, and can automatically box array objects of * similar key-value pairs in the parameters into a Map object and set them * into the context object. * *

Note: The key must be a string, the value can be any type or even null. * *

Call sample: *

	 * 1. No parameters
	 * context() -> { 
	 *     "env" : {}, 
	 *     "system" : {} 
	 * }
	 * 
	 * 2. Two parameters
	 * content("name" : "mybatis-mapper") -> { 
	 *     "env" : {}, 
	 *     "system" : {}, 
	 *     "name" : "mybatis-mapper"
	 * }
	 * 
	 * 3. Infinite parameter
	 * content("key", Object, "name" : "mybatis-mapper", "description", "A powerful myabtis generic mapper plugin" ) -> { 
	 *     "env" : {}, 
	 *     "system" : {}, 
	 *     "key" : Object,
	 *     "name" : "mybatis-mapper",
	 *     "description" : "A powerful myabtis generic mapper plugin"
	 * }
* * @param properties an array similar to a Map key-value pair * @return full template context object */ public static FelContext context( Object ... properties ) { return context( MapUtil.newMap( properties ) ); } /** * Generates a template context object that has environment variables and * system help properties, and set the Map parameter to the context. * * @param metadata your own metadata * @return full template context object */ public static FelContext context( Map metadata ) { MapContext context = new MapContext(); context.set( "env", environments ); context.set( "system", systemContext() ); context.putItems( metadata ); return context; } /** * Parse the target expression using the template engine * * @param expression template expression * @param properties an array similar to a Map key-value pair * @return the value solved by the template engine * @see #context(Object...) * @see #eval(String, FelContext) */ public static Object eval( String expression, Object ... properties ) { return eval( expression, context( properties ) ); } /** * Parse the target expression using the template engine, and you must * explicitly pass in the context object of the template engine * * @param expression template expression * @param properties an array similar to a Map key-value pair * @return the value solved by the template engine * @see #context(Map) * @see #eval(String, FelContext) */ public static Object eval( String expression, Map metadata ) { return eval( expression, context( metadata ) ); } /** * Parse the target expression using the template engine, and you must * explicitly pass in the context object of the template engine * * @param expression template expression * @param properties an array similar to a Map key-value pair * @return the value solved by the template engine */ public static Object eval( String expression, FelContext context ) { return getResolvedValue( context == null ? engine.eval( expression ) : engine.eval( expression, context ) ); } // public static Object resolve( String content, Object ... properties ) { // return resolve( content, context( properties ) ); // } // public static Object resolve( String content, Map context ) { // return resolve( content, context( context ) ); // } // public static Object resolve( String content, FelContext context ) { // Map paramBindings = getParamBindings( paramsNameKey, content ); // String template = paramBindings.remove( translatedTemplateKey ); // FelContext finalContext = prepareContext( content, context, paramBindings ); // Expression expression = getExpression( content, template, finalContext ); // return getResolvedValue( expression == null ? engine.eval( content, context ) : expression.eval( context ) ); // } /** * Get the resolved value, if the return is the internal Builder object, * then call the builder's getContent method to get the real content. * * @param resolved resolved object value, it can be any object or a template Builder object. * @return the resolved value, usually most of the time is String. */ private static Object getResolvedValue( Object resolved ) { if ( resolved == null ) return Constants.EMPTY; if ( resolved instanceof TemplateBuilder ) { return ( ( TemplateBuilder ) resolved ).build(); } return resolved; } // /** // * Prepare the context object and put the template parameter name into the // * context object for the template engine to handle properly // * // * @param content template content // * @param context template context object // * @param paramBindings parameter binding mapping // * @return the final template context object // */ // private static FelContext prepareContext( String content, FelContext context, Map paramBindings ) { // if ( context == null ) { // context = context( paramsNameKey, paramBindings ); // } else if ( context.get( paramsNameKey ) == null ) { // context.set( paramsNameKey, paramBindings ); // } // return context; // } // /** // * In fact, through testing, I found that the compilation will consume a lot // * of time, and the efficiency of the post-compilation execution is almost // * the same as the efficiency of the direct eval execution, so I temporarily // * gave up the compilation. // * // * @param content template content // * @param template translated template string content // * @param context template context object // * @return compiled expression object // */ // private static Expression getExpression( String content, String template, FelContext context ) { // Expression expression = expressions.get( template ); // if ( expression == null ) { // synchronized ( expressions ) { // expression = engine.compile( template, context ); // Assert.notNull( expression, "Template compilation failed, the template is '{}', original input is '{}'", template, content ); // expressions.put( template, expression ); // } // } // return expression; // } // /** // * The input text is parsed to get the fixed template content so that we can // * cache the same kind of expression object // * // * @param parameterName defined parameter name // * @param input original input content // * @return parameter template and parameter mapping object // */ // private static Map getParamBindings( String parameterName, String input ) { // String paramName = null; // int index = 0; // String clipping start subscript // int paramIndex = 0; // Parameter number suffix // int initialCapacity = input.split( "\\)" ).length; // Just guessing // input = input.replaceAll( "\\s+", Constants.EMPTY ); // Remove extra white space // String newInput = input; // StringBuffer replacement = new StringBuffer(); // Map params = new HashMap( initialCapacity + 1 ); // Matcher matcher = pramemterPattern.matcher( input ); // while ( matcher.find() ) { // paramName = "param" + ( paramIndex ++ ); // params.put( paramName, matcher.group( 2 ) ); // replacement.append( input.substring( index, matcher.start() ) ); // replacement.append( parameterName ).append( "." ).append( paramName ); // index = matcher.end(); // } // if ( index > 0 && index <= input.length() - 1 ) { // replacement.append( input.substring( index ) ); // Last part // newInput = replacement.toString(); // } // params.put( translatedTemplateKey, newInput ); // return params; // } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy