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

org.onetwo.common.db.filequery.BaseNamedSqlFileManager Maven / Gradle / Ivy

package org.onetwo.common.db.filequery;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Stream;

import org.onetwo.common.db.dquery.DbmSqlFileResource;
import org.onetwo.common.db.spi.NamedQueryFile;
import org.onetwo.common.db.spi.NamedQueryFileListener;
import org.onetwo.common.db.spi.NamedQueryInfo;
import org.onetwo.common.db.spi.NamedQueryInfoParser;
import org.onetwo.common.db.spi.NamedSqlFileManager;
import org.onetwo.common.exception.BaseException;
import org.onetwo.common.log.JFishLoggerFactory;
import org.onetwo.common.propconf.ResourceAdapter;
import org.onetwo.common.utils.Assert;
import org.onetwo.common.utils.LangUtils;
import org.onetwo.common.watch.FileChangeListener;
import org.onetwo.common.watch.FileWatcher;
import org.onetwo.dbm.exception.DbmException;
import org.onetwo.dbm.exception.FileNamedQueryException;
import org.slf4j.Logger;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;


abstract public class BaseNamedSqlFileManager implements NamedSqlFileManager {

	
	/*public static final String COMMENT = "--";
	public static final String MULTIP_COMMENT_START = "/*";
	public static final String MULTIP_COMMENT_END = "* /";
	public static final String CONFIG_PREFIX = "--@@";
	public static final String NAME_PREFIX = "--@";
	public static final String EQUALS_MARK = "=";*/
//	public static final String IGNORE_NULL_KEY = "ignore.null";

	protected final Logger logger = JFishLoggerFactory.getLogger(getClass());
	
	private FileWatcher fileMonitor;
	private long period = 1;
	
	private Map namespaceProperties = Maps.newHashMap();
//	private List sqlfiles;
//	private PropertiesWraper wrapper;
	private Map namedQueryCache = Maps.newConcurrentMap();
//	private DbmNamedQueryInfoParser sqlFileParser = new DefaultSqlFileParser();
	private List queryInfoParsers = Lists.newArrayList(new DefaultSqlFileParser());
	final private NamedQueryFileListener listener;
	
	private boolean watchSqlFile;
	
	public BaseNamedSqlFileManager(boolean watchSqlFile, NamedQueryFileListener listener) {
		this.watchSqlFile = watchSqlFile;
		this.listener = listener;
	}
	
	public NamedQueryFileListener getListener() {
		return listener;
	}

	final public void setQueryInfoParsers(List queryInfoParsers) {
		this.queryInfoParsers = queryInfoParsers;
	}

	/****
	 * 解释sql文件
	 */
	@Override
	public NamedQueryFile buildSqlFile(DbmSqlFileResource sqlFile){
		Assert.notNull(sqlFile);
		NamedQueryFile info = this.parseSqlFile(sqlFile, true);
		this.buildSqlFileMonitor(sqlFile);

		if(this.listener!=null){
			this.listener.afterBuild(sqlFile, info);
		}
		/*logger.info("all named query : ");
		for(T prop : this.namedQueryCache.values()){
			logger.info(prop.toString());
		}*/
		return info;
	}
	
	/****
	 * 根据配置扫描文件
	 * @param conf
	 * @return
	 */
	/*protected ResourceAdapter[] scanMatchSqlFiles(JFishPropertyConf conf){
		String sqldirPath = FileUtils.getResourcePath(conf.getClassLoader(), conf.getDir());

		File[] sqlfileArray = FileUtils.listFiles(sqldirPath, conf.getPostfix());
		if(logger.isInfoEnabled())
			logger.info("find {} sql named file in dir {}", sqlfileArray.length, sqldirPath);
		
		if(StringUtils.isNotBlank(conf.getOverrideDir())){
			String overridePath = sqldirPath+"/"+conf.getOverrideDir();
			logger.info("scan database dialect dir : " + overridePath);
			File[] dbsqlfiles = FileUtils.listFiles(overridePath, conf.getPostfix());

			if(logger.isInfoEnabled())
				logger.info("find {} sql named file in dir {}", dbsqlfiles.length, overridePath);
			
			if(!LangUtils.isEmpty(dbsqlfiles)){
				sqlfileArray = (File[]) ArrayUtils.addAll(sqlfileArray, dbsqlfiles);
			}
		}
		return FileUtils.adapterResources(sqlfileArray);
	}*/
	
	/***
	 * 监测sql文件变化
	 * @param sqlfileArray
	 */
	protected void buildSqlFileMonitor(DbmSqlFileResource... sqlfileArray){
		if(watchSqlFile){
			if(fileMonitor==null)
				fileMonitor = FileWatcher.newWatcher(1);
			this.watchFiles(sqlfileArray);
		}
	}
	protected void watchFiles(DbmSqlFileResource[] sqlResourceArray){
		if(LangUtils.isEmpty(sqlResourceArray))
			return ;
		this.fileMonitor.watchFile(period, new FileChangeListener() {
			
			@Override
			public void fileChanged(ResourceAdapter file) {
				try {
					reloadFile((DbmSqlFileResource)file);
				} catch (Exception e) {
					logger.error("watch sql file error: " + e.getMessage(), e);
				}
			}
		}, sqlResourceArray);
	}
	
	public void reloadFile(DbmSqlFileResource file){
		/*JFishProperties pf = loadSqlFile(file);
		if(pf==null){
			logger.warn("no file relaoded : " + file);
			return ;
		}*/
		NamedQueryFile namepsaceInfo = this.parseSqlFile(file, false);
		logger.warn("file relaoded : " + file);
		if(listener!=null){
			listener.afterReload(file, namepsaceInfo);
		}
	}
	
	private boolean isGlobalNamespace(String namespace){
		return GLOBAL_NS_KEY.equals(namespace) || !namespace.contains(".");
	}
	
	protected Map parseSqlFiles(DbmSqlFileResource[] sqlfileArray){
		if(LangUtils.isEmpty(sqlfileArray)){
			logger.info("no named sql file found.");
			return Collections.emptyMap();
		}
		
//		Map> nsproperties = LangUtils.newHashMap(sqlfileArray.length);
		Stream.of(sqlfileArray).parallel().forEach( f-> {
//			logger.info("parse named sql file: {}", f);
			this.parseSqlFile(f, true);
		});
		return namespaceProperties;
	}


	protected NamedQueryFile parseSqlFile(DbmSqlFileResource f, boolean throwIfExist){
		logger.info("parse named sql file: {}", f.getName());
		
		String namespace = getFileNameNoJfishSqlPostfix(f);
		boolean globalNamespace = isGlobalNamespace(namespace);
		if(globalNamespace){
			namespace = GLOBAL_NS_KEY;
		}
		

		NamedQueryFile namespaceInfo = null;
		if(globalNamespace){
			namespaceInfo = namespaceProperties.get(namespace);
			if(namespaceInfo==null){
				namespaceInfo = new GlobalNamespaceProperties();
				namespaceProperties.put(namespaceInfo.getKey(), namespaceInfo);
			}
//			np.addAll(namedinfos, throwIfExist);
		}else{
			if(namespaceProperties.containsKey(namespace) && throwIfExist){
				namespaceInfo = namespaceProperties.get(namespace);
				throw new DbmException("sql namespace has already exist : " + namespace+", file: " + f+", exists file: "+ namespaceInfo.getSource());
//				if (throwIfExist) {
//					throw new DbmException("sql namespace has already exist : " + namespace+", file: " + f+", exists file: "+ namespaceInfo.getSource());
//				}
			} else {
				namespaceInfo = new CommonNamespaceProperties(namespace, f);
				namespaceProperties.put(namespaceInfo.getKey(), namespaceInfo);
			}
		}
		
		buildNamedInfosToNamespaceFromResource(namespaceInfo, f);
		/*if(namedinfos.isEmpty())
			return null;*/

//		namespacesMap.put(namespace, np);
		for(FileBaseNamedQueryInfo nsp : namespaceInfo.getNamedProperties()){
			if(namedQueryCache.containsKey(nsp.getFullName()) && throwIfExist){
				throw new FileNamedQueryException("cache file named query error, key is exists : " + nsp.getFullName());
			}
			putIntoCaches(nsp.getFullName(), nsp);
		}
		
		return namespaceInfo;
	}
	
	protected void putIntoCaches(String key, FileBaseNamedQueryInfo nsp){
		logger.info("cache query : {}", key);
		this.namedQueryCache.put(key, nsp);
	}
	
	protected String getFileNameNoJfishSqlPostfix(ResourceAdapter f){
		String fname = f.getName();
		String postfix = f.getPostfix();
		if(!fname.endsWith(postfix)){
			return fname;
		}else{
			return fname.substring(0, fname.length()-postfix.length());
		}
	}

	/****
	 * 解释sql文件,构建为对象
	 * @param np
	 * @param file
	 */
	protected void buildNamedInfosToNamespaceFromResource(NamedQueryFile np, DbmSqlFileResource file){
//		sqlFileParser.parseToNamedQueryFile(np, file);
		
		this.queryInfoParsers.forEach(parser->{
			parser.parseToNamedQueryFile(np, file);
		});
		
		//post process 
	}
	
	/*private static final Pattern DIPATCHER_PATTER = Pattern.compile("\\((\\w+)(?:\\|{2}(\\w+))*\\)");
	private void postProccessNamedInnfo(PropertiesNamespaceInfo np){
		//JFishNamedFileQueryInfo
		np.getNamedProperties().forEach(prop->{
			Matcher matcher = DIPATCHER_PATTER.matcher(prop.getName());
			if(matcher.find()){
				
			}
		});
	}*/
	@Override
	public NamedQueryInfo getNamedQueryInfo(String fullname) {
		FileBaseNamedQueryInfo info = namedQueryCache.get(fullname);
		return info;
	}

	@Override
	public boolean contains(String fullname){
		return namedQueryCache.containsKey(fullname);
	}

	@Override
	public boolean containsNamespace(String namespace){
		return namespaceProperties.containsKey(namespace);
	}

	public String toString(){
		StringBuilder sb = new StringBuilder("named query : \n");
		for(NamedQueryInfo info : this.namedQueryCache.values()){
			sb.append(info).append(",\n");
		}
		return sb.toString();
	}

	@Override
	public NamedQueryFile getNamespaceProperties(String namespace) {
		return namespaceProperties.get(namespace);
	}

	public Collection getAllNamespaceProperties() {
		return namespaceProperties.values();
	}
	
	/*final public void setSqlFileParser(DbmNamedQueryInfoParser sqlFileParser) {
		this.sqlFileParser = sqlFileParser;
	}*/



	public static class CommonNamespaceProperties implements NamedQueryFile {
		private final String namespace;
		private ResourceAdapter source;
		private Map dbmNamedQueryInfoMap;
		
		public CommonNamespaceProperties(String namespace){
			this.namespace = namespace;
			this.dbmNamedQueryInfoMap = LangUtils.newHashMap();
		}
		public CommonNamespaceProperties(String namespace, ResourceAdapter source) {
			super();
			this.namespace = namespace;
			this.source = source;
			this.dbmNamedQueryInfoMap = LangUtils.newHashMap();
//			this.namedProperties = namedProperties;
		}

		@Override
		public String getNamespace() {
			return namespace;
		}

		/****
		 * cache key
		 */
		@Override
		public String getKey() {
			return namespace;
		}

		@Override
		public Collection getNamedProperties() {
			return ImmutableList.copyOf(dbmNamedQueryInfoMap.values());
		}

		public ResourceAdapter getSource() {
			return source;
		}
		@Override
		public FileBaseNamedQueryInfo getNamedProperty(String name) {
			return dbmNamedQueryInfoMap.get(name);
		}
		@Override
		public void addAll(Map namedInfos, boolean throwIfExist) {
			for(Entry entry : namedInfos.entrySet()){
				put(entry.getKey(), entry.getValue(), throwIfExist);
			}
		}
		@Override
		public void put(String name, FileBaseNamedQueryInfo info, boolean throwIfExist) {
			Assert.hasText(name);
			Assert.notNull(info);
			if(throwIfExist && this.dbmNamedQueryInfoMap.containsKey(name)){
				FileBaseNamedQueryInfo exitProp = this.dbmNamedQueryInfoMap.get(name);
				throw new BaseException("int file["+info.getSrcfile()+"], sql key["+name+"] has already exist in namespace: " + namespace+", in file: "+ exitProp.getSrcfile());
			}
			this.dbmNamedQueryInfoMap.put(name, info);
			/*DbmNamedQueryInfo newE = this.dbmNamedQueryInfoMap.get(name);
			logger.info("newE:"+newE);*/
		}
		@Override
		public boolean isGlobal() {
			return false;
		}
		
	}

	public class GlobalNamespaceProperties extends CommonNamespaceProperties {
		private final List sources;
		
		private GlobalNamespaceProperties() {
			super("");
			this.sources = LangUtils.newArrayList();
		}

		@Override
		public String getKey() {
			return GLOBAL_NS_KEY;
		}

		public List getSources() {
			return sources;
		}
		@Override
		public boolean isGlobal() {
			return true;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy