/*
 * semanticcms-core-view-content - SemanticCMS view of the content of the current page.
 * Copyright (C) 2016, 2017  AO Industries, Inc.
 *     support@aoindustries.com
 *     7262 Bull Pen Cir
 *     Mobile, AL 36695
 *
 * This file is part of semanticcms-core-view-content.
 *
 * semanticcms-core-view-content is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * semanticcms-core-view-content is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with semanticcms-core-view-content.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.semanticcms.core.view.content;

import com.aoindustries.servlet.http.Dispatcher;
import com.aoindustries.util.AoArrays;
import com.semanticcms.core.controller.PageUtils;
import com.semanticcms.core.controller.SemanticCMS;
import com.semanticcms.core.model.Link;
import com.semanticcms.core.model.Page;
import com.semanticcms.core.renderer.html.View;
import java.io.IOException;
import java.util.Collections;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.SkipPageException;
import org.joda.time.ReadableInstant;

/**
 * The default content view.
 */
public class ContentView extends View {

	static final String VIEW_NAME = Link.DEFAULT_VIEW_NAME;

	private static final String JSPX_TARGET = "/semanticcms-core-view-content/view.inc.jspx";

	@Override
	public Group getGroup() {
		return Group.FIRST;
	}

	@Override
	public String getDisplay() {
		return "Content";
	}

	@Override
	public String getName() {
		return VIEW_NAME;
	}

	@Override
	public boolean getAppliesGlobally() {
		return false;
	}

	/**
	 * The last modified time of a page is the most recent of:
	 *

	 *
{@link Page#getDateCreated()}

	 *
{@link Page#getDatePublished()}

	 *
{@link Page#getDateModified()}

	 *

	 * Note: {@link Page#getDateReviewed()} is left out because a change in its value alone does not indicate a change in content.
	 */
	@Override
	public ReadableInstant getLastModified(
		ServletContext servletContext,
		HttpServletRequest request,
		HttpServletResponse response,
		Page page
	) throws ServletException, IOException {
		return AoArrays.maxNonNull(
			page.getDateCreated(),
			page.getDatePublished(),
			page.getDateModified()
		);
	}

	@Override
	public String getTitle(
		ServletContext servletContext,
		HttpServletRequest request,
		HttpServletResponse response,
		Page page
	) {
		String bookTitle = SemanticCMS.getInstance(servletContext).getBook(page.getPageRef().getBookRef()).getTitle();
		if(bookTitle != null && !bookTitle.isEmpty()) {
			return page.getTitle() + TITLE_SEPARATOR + bookTitle;
		} else {
			return page.getTitle();
		}
	}

	@Override
	public String getDescription(Page page) {
		return page.getDescription();
	}

	@Override
	public String getKeywords(Page page) {
		return page.getKeywords();
	}

	/**
	 * Uses the page settings.
	 *
	 * @see  PageUtils#findAllowRobots(javax.servlet.ServletContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, com.semanticcms.core.model.Page)
	 */
	@Override
	public boolean getAllowRobots(ServletContext servletContext, HttpServletRequest request, HttpServletResponse response, Page page) throws ServletException, IOException {
		return PageUtils.findAllowRobots(servletContext, request, response, page);
	}

	@Override
	public void doView(ServletContext servletContext, HttpServletRequest request, HttpServletResponse response, Page page) throws ServletException, IOException, SkipPageException {
		Dispatcher.include(
			servletContext,
			JSPX_TARGET,
			request,
			response,
			Collections.singletonMap("page", page)
		);
	}
}


package samples.coffeemachine;

import cucumber.api.DataTable;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.assertj.core.api.Assertions;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;

/**
 * @author @aloyer
 */
public class TakeOrderSteps {

    private Context context;

    public TakeOrderSteps(Context context) {
        this.context = context;
    }

    /**
     * Provide an array based list of orders
     * @param arg1 orders in a table format
     * @throws Throwable
     */
    @Given("^the following orders:$")
    public void the_following_orders(DataTable arg1) throws Throwable {
        throw new PendingException();
    }

    @When("^I order an? \"([^\"]*)\"$")
    public void I_order_an(String drink) throws Throwable {
        context.getGateway().order(drink, 0, false);
    }

    @When("^I order an? \"([^\"]*)\" with (\\d+) sugar$")
    public void I_order_a_with_sugar(String drink, int nbSugar) throws Throwable {
        context.getGateway().order(drink, nbSugar, false);
    }

    /**
     * Order an extra hot drink with the specified number of sugar
     * @param drinkType type of the drink ordered
     * @param nbSugar number of sugar
     * @throws Throwable
     */
    @When("^I order an? extra hot \"([^\"]*)\" with (\\d+) sugar$")
    public void I_order_an_extra_hot_with_sugar(String drinkType, int nbSugar) throws Throwable {
        Assertions.fail("Extra hot is forbidden in summer!");
    }

    /**
     * Send the specified message.
     * @param message to send
     * @throws Throwable
     */
    @When("^the message \"([^\"]*)\" is sent$")
    public void the_message_is_sent(String message) throws Throwable {
        context.getGateway().publish(message);
    }

    /**
     * Assert that the generated command matches the specified command.
     * @param command expected command
     * @throws Throwable
     */
    @Then("^the instruction generated should be \"([^\"]*)\"$")
    public void the_instruction_generated_should_be(String command) throws Throwable {
        verify(context.getDrinkMaker()).executeCommand(eq(command));
    }

}


package tzatziki.analysis.java;

import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author @aloyer
 */
public class GrammarParser {
    public static Pattern STEP_KEYWORD_QUALIFIED_NAME = Pattern.compile("cucumber\\.api\\.java\\.[^.]+\\.(.+)");

    private Logger log = LoggerFactory.getLogger(GrammarParser.class);
    //
    private GrammarParserListener listener = new GrammarParserListenerAdapter();
    private JavaProjectBuilder builder = new JavaProjectBuilder();

    public GrammarParser usingSourceDirectory(File sourceTree) {
        builder.addSourceTree(sourceTree);
        return this;
    }

    public GrammarParser usingListener(GrammarParserListener listener) {
        this.listener = listener;
        return this;
    }

    public Grammar process() {
        Grammar grammar = new Grammar();

        Collection<JavaPackage> packages = builder.getPackages();
        listener.aboutToParsePackages(packages);
        for (JavaPackage pkg : packages) {
            PackageEntry pkgEntry = analyzePackage(pkg);
            if (pkgEntry.hasEntries())
                grammar.declarePackage(pkgEntry);
        }

        Collection<JavaClass> classes = builder.getClasses();
        listener.aboutToParseClasses(classes);
        for (JavaClass klazz : classes) {
            ClassEntry klazzEntry = analyzeClass(klazz);
            if (klazzEntry.hasEntries())
                grammar.declareClass(klazzEntry);
        }
        return grammar;
    }

    private PackageEntry analyzePackage(JavaPackage pkg) {
        listener.enteringPackage(pkg);

        PackageEntry pkgGroup = new PackageEntry(pkg.getName());
        describe(pkgGroup, pkg);

        for (JavaClass klazz : pkg.getClasses()) {
            ClassEntry classEntry = analyzeClass(klazz);
            if (classEntry.hasEntries())
                pkgGroup.declareClass(classEntry);
        }

//        for (JavaPackage subPkg : pkg.getSubPackages()) {
//            PackageEntry subPkgEntry = analyzePackage(subPkg);
//            if(subPkgEntry.hasEntries())
//                pkgGroup.declareSubPackage(subPkgEntry);
//        }
        listener.exitingPackage(pkg);
        return pkgGroup;
    }

    private ClassEntry analyzeClass(JavaClass klazz) {
        listener.enteringClass(klazz);

        ClassEntry group = new ClassEntry(klazz.getPackageName(), klazz.getName());
        describe(group, klazz);

        for (JavaMethod method : klazz.getMethods()) {
            MethodEntry methodEntry = analyzeMethod(method);
            if (methodEntry.hasPatterns()) {
                group.declareEntry(methodEntry);
            }
        }
        listener.exitingClass(klazz);
        return group;
    }

    private static void describe(Describable describable, JavaAnnotatedElement klazz) {
        describable.describeWith(klazz.getComment());
    }

    private MethodEntry analyzeMethod(JavaMethod method) {
        listener.enteringMethod(method);

        List<JavaType> parameterTypes = method.getParameterTypes();
        MethodEntry methodEntry = new MethodEntry(method.getName(), typesAsStrings(parameterTypes));
        describe(methodEntry, method);

        fillWithPatterns(method, methodEntry);

        if (methodEntry.hasPatterns()) {
            fillWithParameters(method, methodEntry);
        }

        listener.exitingMethod(method);
        return methodEntry;
    }

    private static List<String> typesAsStrings(List<JavaType> parameterTypes) {
        return FluentIterable.from(parameterTypes).transform(new Function<JavaType, String>() {
            @Override
            public String apply(JavaType javaType) {
                return javaType.getFullyQualifiedName();
            }
        }).toList();
    }

    private void fillWithParameters(JavaMethod method, MethodEntry methodEntry) {
        List<DocletTag> paramDocs = method.getTagsByName("param");
        List<JavaParameter> parameters = method.getParameters();
        for (int i = 0; i < parameters.size(); i++) {
            JavaParameter param = parameters.get(i);
            String paramName = param.getName();
            DocletTag paramDoc = findParamDocByNameOrIndex(paramName, i, paramDocs);
            String doc = (paramDoc != null) ? extractDoc(paramName, paramDoc) : null;

            methodEntry.defineParameter(i, paramName, doc);
        }
    }

    private String extractDoc(String value, DocletTag paramDoc) {
        String cleaned = paramDoc.getValue().trim();
        if (cleaned.startsWith(value))
            return cleaned.substring(value.length()).trim();
        return cleaned;
    }

    /**
     * Attempt to retrieve the parameter (@param doclet parameter)
     * using the parameter name, otherwise fallback to the parameter index.
     */
    private DocletTag findParamDocByNameOrIndex(String name, int paramIndex, List<DocletTag> tags) {
        for (DocletTag tag : tags) {
            if (name.equals(tag.getParameters().get(0))) {
                return tag;
            }
        }
        if (paramIndex < tags.size()) {
            return tags.get(paramIndex);
        }
        return null;
    }

    private void fillWithPatterns(JavaMethod method, MethodEntry methodEntry) {
        List<JavaAnnotation> annotations = method.getAnnotations();
        for (JavaAnnotation annotation : annotations) {
            String keyword = extractStepKeywordIfRelevant(annotation);
            if (keyword != null) {
                String pattern = String.valueOf(annotation.getNamedParameter("value"));
                methodEntry.declarePattern(keyword, unescape(unquote(pattern)));
            }
        }
    }

    private String extractStepKeywordIfRelevant(JavaAnnotation annotation) {
        JavaClass annotationType = annotation.getType();
        String name = qualifiedName(annotationType);

        // Note: it seems that a java annotation is itself annotated
        // with '@cucumber.runtime.java.StepDefAnnotation'
        // it may be a safer way to determine if an annotation corresponds
        // to a keyword...

        Matcher matcher = STEP_KEYWORD_QUALIFIED_NAME.matcher(name);
        if (matcher.matches()) {
            return matcher.group(1);
        }
        return null;
    }

    private static String qualifiedName(JavaClass klazz) {
        return klazz.getPackageName() + "." + klazz.getName();
    }

    private static String unescape(String value) {
        return value.replaceAll("\\\\(.)", "$1");
    }

    private static String unquote(String value) {
        int len = value.length();
        if (len >= 2 && value.charAt(0) == '"' && value.charAt(len - 1) == '"')
            return value.substring(1, len - 1);
        return value;
    }

}


package com.chenlb.mmseg4j.example;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;

import com.chenlb.mmseg4j.Dictionary;
import com.chenlb.mmseg4j.Dictionary.FileLoading;
import com.chenlb.mmseg4j.example.DicTransform.WriterRow;

public class MergeDic {

	/**
	 * 尝试合并 sogou（去除了没有词性的） 与 rmmseg 的词库。
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream(new File("dic/word-with-attr.dic"));
		final Set<String> words = new TreeSet<String>();
		final int[] num = {0};
		FileLoading fl = new FileLoading() {

			public void row(String line, int n) {
				words.add(line.trim());
				num[0]++;
			}

		};

		Dictionary.load(fis, fl);

		fis = new FileInputStream(new File("dic/words-rmmseg.dic"));

		Dictionary.load(fis, fl);

		WriterRow wr = new WriterRow(new File("dic/words-marge-sogou-no-attr-and-rmmseg.dic"));
		for(String word : words) {
			wr.writerRow(word);
		}
		wr.close();
		System.out.println("rows="+num[0]+", size="+words.size()+", same="+(num[0]-words.size()));
	}

}


package com.chenlb.mmseg4j.example;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.Properties;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;

import com.chenlb.mmseg4j.analysis.TokenUtils;

public class Effect {

	private File path;
	private Analyzer analyzer;

	public Effect(Analyzer analyzer) {
		super();
		path = new File("txt");
		this.analyzer = analyzer;
	}

	public Effect(File path, Analyzer analyzer) {
		this(analyzer);
		this.path = path;
	}

	public void run(String outputChipName, int n) throws IOException {
		File[] txts = path.listFiles(new FilenameFilter() {

			public boolean accept(File dir, String name) {

				return name.endsWith(".txt");
			}

		});
		long time = 0, size = 0;
		for(int i=0; i<n; i++) {
			for(File txt : txts) {
				FileInputStream ftxt = new FileInputStream(txt);
				int s = ftxt.available();
				size += s;
				BufferedReader reader = new BufferedReader(new InputStreamReader(ftxt));

				OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File(txt.getAbsoluteFile()+"."+outputChipName+".word")));
				BufferedWriter bw = new BufferedWriter(osw);

				String line = null;
				long start = System.currentTimeMillis();
				while((line = reader.readLine()) != null) {
					bw.append("--------------------------").append("\r\n");;
					bw.append(line).append("\r\n");
					TokenStream ts = analyzer.tokenStream("text", new StringReader(line));
					for(Token t= new Token(); (t=TokenUtils.nextToken(ts, t)) !=null;) {
						bw.append(new String(t.termBuffer(), 0, t.termLength())).append(" | ");
					}
					bw.append("\r\n");
				}

				long t = System.currentTimeMillis() - start;
				time += t;
				System.out.println("size="+(s/1024)+"kb, use "+t+"ms, speed="+speed(s, t)+"kb/s, file="+txt.getName());
				bw.close();
			}
		}
		System.out.println("size="+(size/1024)+"kb, use "+time+"ms, speed="+speed(size, time)+"kb/s");
	}

	/**
	 * -Dmode=simple, default is complex
	 * @param args args[0] txt path
	 * @author chenlb 2009-3-28 下午02:19:52
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		int n = 1;
		if(args.length < 1) {
			usage();
			return;
		}
		Properties analyzers = new Properties();
		analyzers.load(new FileInputStream(new File("analyzer.properties")));
		String mode = System.getProperty("mode", "complex");
		String a = System.getProperty("analyzer", "mmseg4j");
		Analyzer analyzer = null;
		String an = (String) analyzers.get(a);
		if(an != null) {
			analyzer = (Analyzer)Class.forName(an).newInstance();
			mode = a;
		} else {
			usage();
			return;
		}
		if(args.length > 1) {
			try {
				n = Integer.parseInt(args[1]);
			} catch (NumberFormatException e) {

			}
		}
		File path = new File(args[0]);
		System.out.println("analyzer="+analyzer.getClass().getName());
		Effect ef = new Effect(path, analyzer);
		ef.run(mode, n);
	}

	private static void usage() {
		System.out.println("Usage:");
		System.out.println("\t-Dmode=simple, defalut is complex");
		System.out.println("\t-Danalyzer=paoding, defalut is mmseg4j");
		System.out.println("\tEffect <txt path> - is a directory that contain *.txt");
	}

	private static double speed(long size, long time) {
		if(time == 0) {
			time = 1;
		}
		return (size*1000)/(time*1024);
	}

}


package com.chenlb.mmseg4j;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 词典类. 词库目录单例模式.

 * 保存单字与其频率,还有词库.

 * 有检测词典变更的接口，外部程序可以使用 {@link #wordsFileIsChange()} 和 {@link #reload()} 来完成检测与加载的工作.
 *
 * @author chenlb 2009-2-20 下午11:34:29
 */
public class Dictionary {

	private static final Logger log = Logger.getLogger(Dictionary.class.getName());

	private File dicPath;	//词库目录
	private volatile Map<Character, CharNode> dict;
	private volatile Map<Character, Object> unit;	//单个字的单位

	/** 记录 word 文件的最后修改时间 */
	private Map<File, Long> wordsLastTime = null;
	private long lastLoadTime = 0;

	/** 不要直接使用, 通过 {@link #getDefalutPath()} 使用*/
	private static File defalutPath = null;
	private static final ConcurrentHashMap<File, Dictionary> dics = new ConcurrentHashMap<File, Dictionary>();

	protected void finalize() throws Throwable {
		/*
		 * 使 class reload 的时也可以释放词库
		 */
		destroy();
	}

	/**
	 * 从默认目录加载词库文件.

	 * 查找默认目录顺序:
	 *

	 *
从系统属性mmseg.dic.path指定的目录中加载

	 *
从classpath/data目录

	 *
从user.dir/data目录

	 *

	 * @see #getDefalutPath()
	 */
	public static Dictionary getInstance() {
		File path = getDefalutPath();
		return getInstance(path);
	}

	/**
	 * @param path 词典的目录
	 */
	public static Dictionary getInstance(String path) {
		return getInstance(new File(path));
	}

	/**
	 * @param path 词典的目录
	 */
	public static Dictionary getInstance(File path) {
		Dictionary dic = dics.get(path);
		if(dic == null) {
			dic = new Dictionary(path);
			dics.put(path, dic);
		}
		return dic;
	}

	/**
	 * 销毁, 释放资源. 此后此对像不再可用.
	 */
	void destroy() {
		clear(dicPath);

		dicPath = null;
		dict = null;
		unit = null;
	}

	/**
	 * @see Dictionary#clear(File)
	 */
	public static Dictionary clear(String path) {
		return clear(new File(path));
	}

	/**
	 * 从单例缓存中去除
	 * @param path
	 * @return 没有返回 null
	 */
	public static Dictionary clear(File path) {
		return dics.remove(path);
	}

	/**
	 * 词典的目录
	 */
	private Dictionary(File path) {
		init(path);
	}

	private void init(File path) {
		dicPath = path;
		wordsLastTime = new HashMap<File, Long>();

		reload();	//加载词典
	}

	private static long now() {
		return System.currentTimeMillis();
	}

	/**
	 * 只要 wordsXXX.dic的文件
	 * @return
	 */
	protected File[] listWordsFiles() {
		return dicPath.listFiles(new FilenameFilter() {

			public boolean accept(File dir, String name) {

				return name.startsWith("words") && name.endsWith(".dic");
			}

		});
	}

	private Map<Character, CharNode> loadDic(File wordsPath) throws IOException {
		InputStream charsIn = null;
		File charsFile = new File(wordsPath, "chars.dic");
		if(charsFile.exists()) {
			charsIn = new FileInputStream(charsFile);
			addLastTime(charsFile);	//chars.dic 也检测是否变更
		} else {	//从 jar 里加载
			charsIn = this.getClass().getResourceAsStream("/data/chars.dic");
			charsFile = new File(this.getClass().getResource("/data/chars.dic").getFile());	//only for log
		}
		final Map<Character, CharNode> dic = new HashMap<Character, CharNode>();
		int lineNum = 0;
		long s = now();
		long ss = s;
		lineNum = load(charsIn, new FileLoading() {	//单个字的

			public void row(String line, int n) {
				if(line.length() < 1) {
					return;
				}
				String[] w = line.split(" ");
				CharNode cn = new CharNode();
				switch(w.length) {
				case 2:
					try {
						cn.setFreq((int)(Math.log(Integer.parseInt(w[1]))*100));//字频计算出自由度
					} catch(NumberFormatException e) {
						//eat...
					}
				case 1:

					dic.put(w[0].charAt(0), cn);
				}
			}
		});
		log.info("chars loaded time="+(now()-s)+"ms, line="+lineNum+", on file="+charsFile);

		//try load words.dic in jar
		InputStream wordsDicIn = this.getClass().getResourceAsStream("/data/words.dic");
		if(wordsDicIn != null) {
			File wordsDic = new File(this.getClass().getResource("/data/words.dic").getFile());
			loadWord(wordsDicIn, dic, wordsDic);
		}

		File[] words = listWordsFiles();	//只要 wordsXXX.dic的文件
		if(words != null) {	//扩展词库目录
			for(File wordsFile : words) {
				loadWord(new FileInputStream(wordsFile), dic, wordsFile);

				addLastTime(wordsFile);	//用于检测是否修改
			}
		}

		log.info("load all dic use time="+(now()-ss)+"ms");
		return dic;
	}

	/**
	 * @param is 词库文件流
	 * @param dic 加载的词保存在结构中
	 * @param wordsFile	日志用
	 * @throws IOException from {@link #load(InputStream, FileLoading)}
	 */
	private void loadWord(InputStream is, Map<Character, CharNode> dic, File wordsFile) throws IOException {
		long s = now();
		int lineNum = load(is, new WordsFileLoading(dic)); //正常的词库
		log.info("words loaded time="+(now()-s)+"ms, line="+lineNum+", on file="+wordsFile);
	}

	private Map<Character, Object> loadUnit(File path) throws IOException {
		InputStream fin = null;
		File unitFile = new File(path, "units.dic");
		if(unitFile.exists()) {
			fin = new FileInputStream(unitFile);
			addLastTime(unitFile);
		} else {	//在jar包里的/data/unit.dic
			fin = Dictionary.class.getResourceAsStream("/data/units.dic");
			unitFile = new File(Dictionary.class.getResource("/data/units.dic").getFile());
		}

		final Map<Character, Object> unit = new HashMap<Character, Object>();

		long s = now();
		int lineNum = load(fin, new FileLoading() {

			public void row(String line, int n) {
				if(line.length() != 1) {
					return;
				}
				unit.put(line.charAt(0), Dictionary.class);
			}
		});
		log.info("unit loaded time="+(now()-s)+"ms, line="+lineNum+", on file="+unitFile);

		return unit;
	}

	/**
	 * 加载 wordsXXX.dic 文件类。
	 *
	 * @author chenlb 2009-10-15 下午02:12:55
	 */
	private static class WordsFileLoading implements FileLoading {
		final Map<Character, CharNode> dic;

		/**
		 * @param dic 加载的词，保存在此结构中。
		 */
		public WordsFileLoading(Map<Character, CharNode> dic) {
			this.dic = dic;
		}

		public void row(String line, int n) {
			if(line.length() < 2) {
				return;
			}
			CharNode cn = dic.get(line.charAt(0));
			if(cn == null) {
				cn = new CharNode();
				dic.put(line.charAt(0), cn);
			}
			cn.addWordTail(tail(line));
		}
	}

	/**
	 * 加载词文件的模板
	 * @return 文件总行数
	 */
	public static int load(InputStream fin, FileLoading loading) throws IOException {
		BufferedReader br = new BufferedReader(
				new InputStreamReader(new BufferedInputStream(fin), "UTF-8"));
		String line = null;
		int n = 0;
		while((line = br.readLine()) != null) {
			if(line == null || line.startsWith("#")) {
				continue;
			}
			n++;
			loading.row(line, n);
		}
		return n;
	}

	/**
	 * 取得 str 除去第一个char的部分
	 * @author chenlb 2009-3-3 下午10:05:26
	 */
	private static char[] tail(String str) {
		char[] cs = new char[str.length()-1];
		str.getChars(1, str.length(), cs, 0);
		return cs;
	}

	public static interface FileLoading {
		/**
		 * @param line 读出的一行
		 * @param n 当前第几行
		 * @author chenlb 2009-3-3 下午09:55:54
		 */
		void row(String line, int n);
	}

	/**
	 * 把 wordsFile 文件的最后更新时间加记录下来.
	 * @param wordsFile 非 null
	 */
	private synchronized void addLastTime(File wordsFile) {
		if(wordsFile != null) {
			wordsLastTime.put(wordsFile, wordsFile.lastModified());
		}
	}

	/**
	 * 词典文件是否有修改过
	 * @return
	 */
	public synchronized boolean wordsFileIsChange() {
		//检查是否有修改文件,包括删除的
		for(Entry<File, Long> flt : wordsLastTime.entrySet()) {
			File words = flt.getKey();
			if(!words.canRead()) {	//可能是删除了
				return true;
			}
			if(words.lastModified() > flt.getValue()) {	//更新了文件
				return true;
			}
		}
		//检查是否有新文件
		File[] words = listWordsFiles();
		if(words != null) {
			for(File wordsFile : words) {
				if(!wordsLastTime.containsKey(wordsFile)) {	//有新词典文件
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 全新加载词库，没有成功加载会回滚。

	 * 注意：重新加载时，务必有两倍的词库树结构的内存，默认词库是 50M/个 左右。否则抛出 OOM。
	 * @return 是否成功加载
	 */
	public synchronized boolean reload() {
		Map<File, Long> oldWordsLastTime = new HashMap<File, Long>(wordsLastTime);
		Map<Character, CharNode> oldDict = dict;
		Map<Character, Object> oldUnit = unit;

		try {
			wordsLastTime.clear();
			dict = loadDic(dicPath);
			unit = loadUnit(dicPath);
			lastLoadTime = System.currentTimeMillis();
		} catch (IOException e) {
			//rollback
			wordsLastTime.putAll(oldWordsLastTime);
			dict = oldDict;
			unit = oldUnit;

			if(log.isLoggable(Level.WARNING)) {
				log.log(Level.WARNING, "reload dic error! dic="+dicPath+", and rollbacked.", e);
			}

			return false;
		}
		return true;
	}

	/**
	 * word 能否在词库里找到
	 * @author chenlb 2009-3-3 下午11:10:45
	 */
	public boolean match(String word) {
		if(word == null || word.length() < 2) {
			return false;
		}
		CharNode cn = dict.get(word.charAt(0));
		return search(cn, word.toCharArray(), 0, word.length()-1) >= 0;
	}

	public CharNode head(char ch) {
		return dict.get(ch);
	}

	/**
	 * sen[offset] 后 tailLen 长的词是否存在.
	 * @see CharNode#indexOf(char[], int, int)
	 * @author chenlb 2009-4-8 下午11:13:49
	 */
	public int search(CharNode node, char[] sen, int offset, int tailLen) {
		if(node != null) {
			return node.indexOf(sen, offset, tailLen);
		}
		return -1;
	}

	public int maxMatch(char[] sen, int offset) {
		CharNode node = dict.get(sen[offset]);
		return maxMatch(node, sen, offset);
	}

	public int maxMatch(CharNode node, char[] sen, int offset) {
		if(node != null) {
			return node.maxMatch(sen, offset+1);
		}
		return 0;
	}

	public ArrayList<Integer> maxMatch(CharNode node, ArrayList<Integer> tailLens, char[] sen, int offset) {
		tailLens.clear();
		tailLens.add(0);
		if(node != null) {
			return node.maxMatch(tailLens, sen, offset+1);
		}
		return tailLens;
	}

	public boolean isUnit(Character ch) {
		return unit.containsKey(ch);
	}

	/**
	 * 当 words.dic 是从 jar 里加载时, 可能 defalut 不存在
	 */
	public static File getDefalutPath() {
		if(defalutPath == null) {
			String defPath = System.getProperty("mmseg.dic.path");
			log.info("look up in mmseg.dic.path="+defPath);
			if(defPath == null) {
				URL url = Dictionary.class.getClassLoader().getResource("data");
				if(url != null) {
					defPath = url.getFile();
					log.info("look up in classpath="+defPath);
				} else {
					defPath = System.getProperty("user.dir")+"/data";
					log.info("look up in user.dir="+defPath);
				}

			}

			defalutPath = new File(defPath);
			if(!defalutPath.exists()) {
				log.warning("defalut dic path="+defalutPath+" not exist");
			}
		}
		return defalutPath;
	}

	/**
	 * 仅仅用来观察词库.
	 */
	public Map<Character, CharNode> getDict() {
		return dict;
	}

	/**
	 * 注意：当 words.dic 是从 jar 里加载时，此时 File 可能是不存在的。
	 */
	public File getDicPath() {
		return dicPath;
	}

	/** 最后加载词库的时间 */
	public long getLastLoadTime() {
		return lastLoadTime;
	}
}


package com.chenlb.mmseg4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.util.LinkedList;
import java.util.Queue;

/**
 * Reader 流的分词(有字母,数字等), 析出中文(其实是 CJK)成句子 {@link Sentence} 再对 mmseg 算法分词.<br/>
 *
 * 非线程安全
 * @author chenlb 2009-9-20下午10:41:41
 */
public class MMSeg {

	private PushbackReader reader;
	private Seg seg;

	private StringBuilder bufSentence = new StringBuilder(256);
	private Sentence currentSentence;
	private Queue<Word> bufWord;	// word 缓存, 因为有 chunk 分析三个以上.

	public MMSeg(Reader input, Seg seg) {
		this.seg = seg;

		reset(input);
	}

	private int readedIdx = 0;

	public void reset(Reader input) {
		this.reader = new PushbackReader(new BufferedReader(input), 20);
		currentSentence = null;
		bufWord = new LinkedList<Word>();
		bufSentence.setLength(0);
		readedIdx = -1;
	}

	private int readNext() throws IOException {
		int d = reader.read();
		if(d > -1) {
			readedIdx++;
			d = Character.toLowerCase(d);
		}
		return d;
	}

	private void pushBack(int data) throws IOException {
		readedIdx--;
		reader.unread(data);
	}

	public Word next() throws IOException {
		//先从缓存中取
		Word word = bufWord.poll();;
		if(word == null) {
			bufSentence.setLength(0);

			int data = -1;
			boolean read = true;
			while(read && (data=readNext()) != -1) {
				read = false;	//默认一次可以读出同一类字符,就可以分词内容
				int type = Character.getType(data);
				String wordType = Word.TYPE_WORD;
				switch(type) {
				case Character.UPPERCASE_LETTER:
				case Character.LOWERCASE_LETTER:
				case Character.TITLECASE_LETTER:
				case Character.MODIFIER_LETTER:
					/*
					 * 1. 0x410-0x44f -> А-я	//俄文
					 * 2. 0x391-0x3a9 -> Α-Ω	//希腊大写
					 * 3. 0x3b1-0x3c9 -> α-ω	//希腊小写
					 */
					data = toAscii(data);
					NationLetter nl = getNation(data);
					if(nl == NationLetter.UNKNOW) {
						read = true;
						break;
					}
					wordType = Word.TYPE_LETTER;
					bufSentence.appendCodePoint(data);
					switch(nl) {
					case EN:
						//字母后面的数字,如: VH049PA
						ReadCharByAsciiOrDigit rcad = new ReadCharByAsciiOrDigit();
						readChars(bufSentence, rcad);
						if(rcad.hasDigit()) {
							wordType = Word.TYPE_LETTER_OR_DIGIT;
						}
						//only english
						//readChars(bufSentence, new ReadCharByAscii());
						break;
					case RA:
						readChars(bufSentence, new ReadCharByRussia());
						break;
					case GE:
						readChars(bufSentence, new ReadCharByGreece());
						break;
					}
					bufWord.add(createWord(bufSentence, wordType));

					bufSentence.setLength(0);

					break;
				case Character.OTHER_LETTER:
					/*
					 * 1. 0x3041-0x30f6 -> ぁ-ヶ	//日文(平|片)假名
					 * 2. 0x3105-0x3129 -> ㄅ-ㄩ	//注意符号
					 */
					bufSentence.appendCodePoint(data);
					readChars(bufSentence, new ReadCharByType(Character.OTHER_LETTER));

					currentSentence = createSentence(bufSentence);

					bufSentence.setLength(0);

					break;
				case Character.DECIMAL_DIGIT_NUMBER:
					bufSentence.appendCodePoint(toAscii(data));
					readChars(bufSentence, new ReadCharDigit());	//读后面的数字, AsciiLetterOr
					wordType = Word.TYPE_DIGIT;
					int d = readNext();
					if(d > -1) {
						if(seg.isUnit(d)) {	//单位,如时间
							bufWord.add(createWord(bufSentence, startIdx(bufSentence)-1, Word.TYPE_DIGIT));	//先把数字添加(独立)

							bufSentence.setLength(0);

							bufSentence.appendCodePoint(d);
							wordType = Word.TYPE_WORD;	//单位是 word
						} else {	//后面可能是字母和数字
							pushBack(d);
							if(readChars(bufSentence, new ReadCharByAsciiOrDigit()) > 0) {	//如果有字母或数字都会连在一起.
								wordType = Word.TYPE_DIGIT_OR_LETTER;
							}
						}
					}

					bufWord.add(createWord(bufSentence, wordType));

					bufSentence.setLength(0);	//缓存的字符清除

					break;
				case Character.LETTER_NUMBER:
					// ⅠⅡⅢ 单分
					bufSentence.appendCodePoint(data);
					readChars(bufSentence, new ReadCharByType(Character.LETTER_NUMBER));

					int startIdx = startIdx(bufSentence);
					for(int i=0; i<bufSentence.length(); i++) {
						bufWord.add(new Word(new char[] {bufSentence.charAt(i)}, startIdx++, Word.TYPE_LETTER_NUMBER));
					}

					bufSentence.setLength(0);	//缓存的字符清除

					break;
				case Character.OTHER_NUMBER:
					//①⑩㈠㈩⒈⒑⒒⒛⑴⑽⑾⒇ 连着用
					bufSentence.appendCodePoint(data);
					readChars(bufSentence, new ReadCharByType(Character.OTHER_NUMBER));

					bufWord.add(createWord(bufSentence, Word.TYPE_OTHER_NUMBER));
					bufSentence.setLength(0);
					break;
				default :
					//其它认为无效字符
					read = true;
				}//switch
			}

			// 中文分词
			if(currentSentence != null) {
				do {
					Chunk chunk = seg.seg(currentSentence);
					for(int i=0; i<chunk.getCount(); i++) {
						bufWord.add(chunk.getWords()[i]);
					}
				} while (!currentSentence.isFinish());

				currentSentence = null;
			}

			word = bufWord.poll();
		}

		return word;
	}

	/**
	 * 读取下一串指定类型字符.
	 *
	 * @author chenlb 2009-8-15下午09:09:50
	 */
	private static abstract class ReadChar {
		/**
		 * 这个字符是否读取, 不读取也不会读下一个字符.
		 */
		abstract boolean isRead(int codePoint);
		int transform(int codePoint) {
			return codePoint;
		}
	}

	/**
	 * 读取下一串指定类型的字符放到 bufSentence 中.
	 * @param bufSentence
	 * @param readChar 判断字符的细节.
	 * @return 返回读取的个数
	 * @throws IOException {@link #readNext()} 或 {@link #pushBack()} 抛出的.
	 */
	private int readChars(StringBuilder bufSentence, ReadChar readChar) throws IOException {
		int num = 0;
		int data = -1;
		while((data = readNext()) != -1) {
			int d = readChar.transform(data);
			if(readChar.isRead(d)) {
				bufSentence.appendCodePoint(d);
				num++;
			} else {	//不是数字回压,要下一步操作
				pushBack(data);
				break;
			}
		}
		return num;
	}

	/**读取数字*/
	private static class ReadCharDigit extends ReadChar {

		boolean isRead(int codePoint) {
			int type = Character.getType(codePoint);
			return isDigit(type);
		}

		int transform(int codePoint) {
			return toAscii(codePoint);
		}

	}

	/**读取字母或数字*/
	private static class ReadCharByAsciiOrDigit extends ReadCharDigit {

		private boolean hasDigit = false;
		boolean isRead(int codePoint) {
			boolean isRead = super.isRead(codePoint);
			hasDigit |= isRead;
			return isAsciiLetter(codePoint) || isRead;
		}
		boolean hasDigit() {
			return hasDigit;
		}
	}

	/**读取字母*/
	@SuppressWarnings("unused")
	private static class ReadCharByAscii extends ReadCharDigit {
		boolean isRead(int codePoint) {
			return isAsciiLetter(codePoint);
		}
	}

	/**读取俄语*/
	private static class ReadCharByRussia extends ReadCharDigit {

		boolean isRead(int codePoint) {
			return isRussiaLetter(codePoint);
		}

	}

	/**读取希腊 */
	private static class ReadCharByGreece extends ReadCharDigit {

		boolean isRead(int codePoint) {
			return isGreeceLetter(codePoint);
		}

	}

	/**读取指定类型的字符*/
	private static class ReadCharByType extends ReadChar {
		int charType;
		public ReadCharByType(int charType) {
			this.charType = charType;
		}

		boolean isRead(int codePoint) {
			int type = Character.getType(codePoint);
			return type == charType;
		}

	}

	private Word createWord(StringBuilder bufSentence, String type) {
		return new Word(toChars(bufSentence), startIdx(bufSentence), type);
	}

	private Word createWord(StringBuilder bufSentence, int startIdx, String type) {
		return new Word(toChars(bufSentence), startIdx, type);
	}

	private Sentence createSentence(StringBuilder bufSentence) {
		return new Sentence(toChars(bufSentence), startIdx(bufSentence));
	}

	/**取得 bufSentence 的第一个字符在整个文本中的位置*/
	private int startIdx(StringBuilder bufSentence) {
		return readedIdx - bufSentence.length() + 1;
	}

	/**从 StringBuilder 里复制出 char[] */
	private static char[] toChars(StringBuilder bufSentence) {
		char[] chs = new char[bufSentence.length()];
		bufSentence.getChars(0, bufSentence.length(), chs, 0);
		return chs;
	}

	/**
	 * 双角转单角
	 */
	private static int toAscii(int codePoint) {
		if((codePoint>=65296 && codePoint<=65305)	//０-９
				|| (codePoint>=65313 && codePoint<=65338)	//Ａ-Ｚ
				|| (codePoint>=65345 && codePoint<=65370)	//ａ-ｚ
				) {
			codePoint -= 65248;
		}
		return codePoint;
	}

	private static boolean isAsciiLetter(int codePoint) {
		return (codePoint >= 'A' && codePoint <= 'Z') || (codePoint >= 'a' && codePoint <= 'z');
	}

	private static boolean isRussiaLetter(int codePoint) {
		return (codePoint >= 'А' && codePoint <= 'я') || codePoint=='Ё' || codePoint=='ё';
	}

	private static boolean isGreeceLetter(int codePoint) {
		return (codePoint >= 'Α' && codePoint <= 'Ω') || (codePoint >= 'α' && codePoint <= 'ω');
	}
	/**
	 * EN -> 英语
	 * RA -> 俄语
	 * GE -> 希腊
	 *
	 */
	private static enum NationLetter {EN, RA, GE, UNKNOW};

	private NationLetter getNation(int codePoint) {
		if(isAsciiLetter(codePoint)) {
			return NationLetter.EN;
		}
		if(isRussiaLetter(codePoint)) {
			return NationLetter.RA;
		}
		if(isGreeceLetter(codePoint)) {
			return NationLetter.GE;
		}
		return NationLetter.UNKNOW;
	}

	@SuppressWarnings("unused")
	private static boolean isCJK(int type) {
		return type == Character.OTHER_LETTER;
	}
	private static boolean isDigit(int type) {
		return type == Character.DECIMAL_DIGIT_NUMBER;
	}
	@SuppressWarnings("unused")
	private static boolean isLetter(int type) {
		return type <= Character.MODIFIER_LETTER && type >= Character.UPPERCASE_LETTER;
	}
}


package com.chenlb.mmseg4j.example;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import com.chenlb.mmseg4j.ComplexSeg;
import com.chenlb.mmseg4j.Dictionary;
import com.chenlb.mmseg4j.MMSeg;
import com.chenlb.mmseg4j.Seg;
import com.chenlb.mmseg4j.SimpleSeg;
import com.chenlb.mmseg4j.Word;

public class Performance {

	/**
	 * -Dmode=simple, default is complex
	 * -Dfile.encode=utf-8 or other
	 * @param args args[0] txt path
	 * @author chenlb 2009-3-28 下午02:19:52
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		if(args.length < 1) {
			System.out.println("Usage:");
			System.out.println("\t-Dmode=simple, defalut is complex");
			System.out.println("\tPerformance <txt path> - is a directory that contain *.txt");
			return;
		}
		String mode = System.getProperty("mode", "complex");
		Seg seg = null;
		Dictionary dic = Dictionary.getInstance();
		if("simple".equals(mode)) {
			seg = new SimpleSeg(dic);
		} else {
			seg = new ComplexSeg(dic);
		}
		File path = new File(args[0]);
		File[] txts = path.listFiles(new FilenameFilter() {

			public boolean accept(File dir, String name) {

				return name.endsWith(".txt");
			}

		});
		long time = 0;
		for(File txt : txts) {
			MMSeg mmSeg = new MMSeg(new InputStreamReader(new FileInputStream(txt)), seg);
			Word word = null;
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File(txt.getAbsoluteFile()+"."+mode+".word")));
			BufferedWriter bw = new BufferedWriter(osw);
			long start = System.currentTimeMillis();
			while((word=mmSeg.next())!=null) {

				bw.append(new String(word.getString())).append("\r\n");
			}
			time += System.currentTimeMillis() - start;
			bw.close();
		}
		System.out.println("use "+time+"ms");
	}

}


package com.chenlb.mmseg4j;

/**
 * 它是MMSeg分词算法中一个关键的概念。Chunk中包含依据上下文分出的一组词和相关的属性，包括长度(Length)、平均长度(Average Length)、标准差的平方(Variance)和自由语素度(Degree Of Morphemic Freedom)。
 *
 * @author chenlb 2009-3-16 上午11:39:42
 */
public class Chunk {

	Word[] words = new Word[3];

	int count = -1;

	/** Word Length */
	private int len = -1;
	/** Largest Average Word Length */
	private double avgLen = -1;
	/** Variance of Word Lengths 就是 标准差的平方 */
	private double variance = -1;
	/** Sum of Degree of Morphemic Freedom of One-Character */
	private int sumDegree = -1;

	/** Word Length */
	public int getLen() {
		if(len < 0) {
			len = 0;
			count = 0;
			for(Word word : words) {
				if(word != null) {
					len += word.getLength();
					count++;
				}
			}
		}
		return len;
	}

	/** 有多少个词，最多3个。*/
	public int getCount() {
		if(count < 0) {
			count = 0;
			for(Word word : words) {
				if(word != null) {
					count++;
				}
			}
		}
		return count;
	}

	/** Largest Average Word Length */
	public double getAvgLen() {
		if(avgLen < 0) {
			avgLen = (double)getLen()/getCount();
		}
		return avgLen;
	}

	/** Variance of Word Lengths 就是 标准差的平方 */
	public double getVariance() {
		if(variance < 0) {
			double sum = 0;
			for(Word word : words) {
				if(word != null) {
					sum += Math.pow(word.getLength()-getAvgLen(), 2);
				}
			}
			variance = sum/getCount();
		}
		return variance;
	}

	/** Sum of Degree of Morphemic Freedom of One-Character */
	public int getSumDegree() {
		if(sumDegree < 0) {
			int sum = 0;
			for(Word word : words) {
				if(word != null && word.getDegree() > -1) {
					sum += word.getDegree();
				}
			}
			sumDegree = sum;
		}
		return sumDegree;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(Word word : words) {
			if(word != null) {
				sb.append(word.getString()).append('_');
			}
		}
		return sb.toString();
	}

	public String toFactorString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		sb.append("len=").append(getLen()).append(", ");
		sb.append("avgLen=").append(getAvgLen()).append(", ");
		sb.append("variance=").append(getVariance()).append(", ");
		sb.append("sum100log=").append(getSumDegree()).append("]");
		return sb.toString();
	}

	public Word[] getWords() {
		return words;
	}

	public void setWords(Word[] words) {
		this.words = words;
		count = words.length;
	}
}


package com.chenlb.mmseg4j;

import java.util.ArrayList;
import java.util.List;

/**
 * 分词抽象类.
 *
 * @author chenlb 2009-3-16 下午09:15:30
 */
public abstract class Seg {

	protected Dictionary dic;

	public Seg(Dictionary dic) {
		super();
		this.dic = dic;
	}

	/**
	 * 输出 chunks, 调试用.
	 */
	protected void printChunk(List<Chunk> chunks) {
		for(Chunk ck : chunks) {
			System.out.println(ck+" -> "+ck.toFactorString());
		}
	}

	/**
	 * @see Dictionary#isUnit(Character)
	 */
	protected boolean isUnit(int codePoint) {
		return dic.isUnit((char) codePoint);
	}

	/**
	 * 查找chs[offset]后面的 tailLen个char是否为词.
	 * @return 返回chs[offset]字符结点下的词尾索引号,没找到返回 -1.
	 */
	protected int search(char[] chs, int offset, int tailLen) {
		if(tailLen == 0) {
			return -1;
		}
		CharNode cn = dic.head(chs[offset]);

		return search(cn, chs, offset, tailLen);
	}

	/**
	 * 没有数组的复制.
	 * @author chenlb 2009-4-8 下午11:39:15
	 */
	protected int search(CharNode cn, char[] chs, int offset, int tailLen) {
		if(tailLen == 0 || cn == null) {
			return -1;
		}
		return dic.search(cn, chs, offset, tailLen);
	}

	/**
	 * 最大匹配

	 * 从 chs[offset] 开始匹配, 同时把 chs[offset] 的字符结点保存在 cns[cnIdx]
	 * @return 最大匹配到的词尾长, > 0 找到
	 */
	protected int maxMatch(CharNode[] cns, int cnIdx, char[] chs, int offset) {
		CharNode cn = null;
		if(offset < chs.length) {
			cn = dic.head(chs[offset]);
		}
		cns[cnIdx] = cn;
		return dic.maxMatch(cn, chs, offset);
	}

	/**
	 * 匹配,同时找出长度.

	 * 从 chs[offset] 开始找所有匹配的词, 找到的放到 tailLens[tailLensIdx] 中.

	 * 同时把 chs[offset] 的字符结点保存在 cns[cnIdx].
	 * @author chenlb 2009-4-12 上午10:37:58
	 */
	protected void maxMatch(CharNode[] cns, int cnIdx, char[] chs, int offset, ArrayList<Integer>[] tailLens, int tailLensIdx) {
		CharNode cn = null;
		if(offset < chs.length) {
			cn = dic.head(chs[offset]);
		}
		cns[cnIdx] = cn;
		dic.maxMatch(cn, tailLens[tailLensIdx], chs, offset);
	}

	/**
	 * 对句子 sen 进行分词.
	 * @return 不返回 null.
	 */
	public abstract Chunk seg(Sentence sen);
}


package com.chenlb.mmseg4j.example;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class DicTransform {

	public static interface Transform {
		String transform(String line);
	}

	/** 去频率*/
	public static class DeFreq implements Transform {

		public String transform(String line) {
			String[] w = line.split("\\s+");
			if(w.length > 0 && !"".equals(w[0])) {

				return w[0];
			}
			return null;
		}

	}

	public static class NoAttr implements Transform {
		WriterRow wr = new WriterRow(new File("dic/no-word-attr.dic"));
		public String transform(String line) {
			String[] w = line.split("\\s+");
			if(w.length > 0 && !"".equals(w[0])) {
				if(w.length < 3) {
					wr.writerRow(w[0]);	//没有词性的写到哪一文件
				} else {
					return w[0];
				}
			}
			return null;
		}
	}

	public static class TwoOrThreeChar extends DeFreq {

		public String transform(String line) {
			String word = super.transform(line);
			if(word != null && word.length() < 4) {

				return word;
			}
			return null;
		}

	}

	public int transform(File src, String srcCharset, File dist, Transform tf) throws IOException {
		WriterRow wr = new WriterRow(dist);
		BufferedReader br = new BufferedReader(
				new InputStreamReader(new BufferedInputStream(new FileInputStream(src)), srcCharset));
		String line = null;
		int n = 0, ava = 0;
		long start = System.currentTimeMillis();
		while((line = br.readLine()) != null) {
			n++;
			if(line == null || "".equals(line) || line.startsWith("#")) {
				continue;
			}
			String li = tf.transform(line);
			if(li != null) {
				ava++;
				wr.writerRow(li);
			}
		}
		wr.close();
		System.out.println("----line="+n+", available="+ava+", time="+(System.currentTimeMillis()-start)+"ms");
		return ava;
	}

	public static class WriterRow {
		Writer writer;

		public WriterRow(File dist) {
			try {
				writer = new BufferedWriter(
						new OutputStreamWriter(new FileOutputStream(dist), "UTF-8"));
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		public void writerRow(String line) {
			try {
				writer.append(line).append("\r\n");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		public void writerRow(char[] chs) {
			try {
				for(char ch : chs) {
					writer.append(ch);
				}
				if(chs.length > 0) {
					writer.append("\r\n");
				}
			} catch (IOException e) {

				e.printStackTrace();
			}
		}
		public void close() {
			try {
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 词库转换
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		String words = "sogou/SogouLabDic.dic";
		String charset = "GBK";
		if(args.length > 0) {
			words = args[0];
		}
		File file = new File(words);
		//File path = file.getParentFile();
		//File dist = new File("dic/words.dic");
		File dist = new File("dic/word-with-attr.dic");
		DicTransform dt = new DicTransform();
		//只要词,不频率
		//dt.transform(file, charset, dist, new DeFreq());
		//只要两或三个字的词.
		//dt.transform(file, charset, dist, new TwoOrThreeChar());
		dt.transform(file, charset, dist, new NoAttr());
	}

}


package org.nameapi.client.lib;

import com.optimaize.anythingworks.client.common.Keys;
import com.optimaize.anythingworks.client.rest.RestKeys;
import com.optimaize.anythingworks.client.rest.RestPortUrlFactory;
import com.optimaize.anythingworks.common.host.Host;
import com.optimaize.command4j.Mode;
import org.jetbrains.annotations.NotNull;
import org.nameapi.ontology5.input.context.Context;

/**
 * Provides Mode instances that contain the minimum.
 *
 * @author Fabian Kessler
 */
public class NameApiModeFactory {

    private static final Host DEFAULT_HOST = new Host("api.nameapi.org", 80);
    private static final NameApiPortUrlFactory DEFAULT_PORT_FACTORY = NameApiPortUrlFactory.versionLatestStable();

    /**
     * You can take this and extend for your setup if you need more.
     *
     *
Example: .with(StdoutLoggingExtension.enabled())

     *
     * @param apiKey Your personal api key from registering with us.
     * @param host for example {@code new Host("api.nameapi.org", 80)}
     * @param portUrlFactory for example {@code NameApiPortUrlFactory.versionLatestStable()}
     */
    @NotNull
    public static Mode minimal(@NotNull String apiKey, @NotNull Host host, @NotNull RestPortUrlFactory portUrlFactory) {
        return Mode.create()
                .with(RestKeys.REST_PORT_URL_FACTORY, portUrlFactory)
//                .with(ExceptionTranslationExtension.TRANSLATOR, new CombinedExceptionTranslator(new DefaultClientExceptionTranslator(), new SoapFaultExceptionTranslator()))
                .with(Keys.HOST, host)
                .with(NameApiKeys.API_KEY, apiKey);
    }

    /**
     * Overloaded method that uses
     * for host: {@code new Host("api.nameapi.org", 80)}
     * for port url: {@code NameApiPortUrlFactory.versionLatestStable()}
     */
    @NotNull
    public static Mode minimal(@NotNull String apiKey) {
        return minimal(apiKey, DEFAULT_HOST, DEFAULT_PORT_FACTORY);
    }

    /**
     * You can take this and extend for your setup if you need more.
     *
     *
Example: .with(StdoutLoggingExtension.enabled())

     *
     * @param apiKey Your personal api key from registering with us.
     * @param context for example {@code new ContextBuilder().priority(Priority.REALTIME).build()}
     * @param host for example {@code new Host("api.nameapi.org", 80)}
     * @param portUrlFactory for example {@code NameApiPortUrlFactory.versionLatestStable()}
     */
    @NotNull
    public static Mode withContext(@NotNull String apiKey, @NotNull Context context, @NotNull Host host, @NotNull RestPortUrlFactory portUrlFactory) {
        return minimal(apiKey, host, portUrlFactory)
                .with(NameApiKeys.CONTEXT, context);
    }

    /**
     * Overloaded method that uses
     * for host: {@code new Host("api.nameapi.org", 80)}
     * for port url: {@code NameApiPortUrlFactory.versionLatestStable()}
     */
    @NotNull
    public static Mode withContext(@NotNull String apiKey, @NotNull Context context) {
        return withContext(apiKey, context, DEFAULT_HOST, DEFAULT_PORT_FACTORY);
    }

}


package autofixture.publicinterface;

import autofixture.implementationdetails.ErrorMessages;
import autofixture.interfaces.InlineConstrainedGenerator;
import autofixture.interfaces.InlineInstanceGenerator;
import com.google.common.reflect.TypeToken;
import lombok.NonNull;

import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;

import static autofixture.generators.objects.implementationdetails.TypeAssertions.assertIsNotParameterized;
import static autofixture.implementationdetails.Boxing.boxed;
import static autofixture.publicinterface.InlineGenerators.identifierString;
import static autofixture.publicinterface.InlineGenerators.portNumber;
import static autofixture.publicinterface.InlineGenerators.without;

public class Any {

  @NonNull
  public static <T> T anonymous(final InstanceOf<T> instanceType) {
    return PrivateGenerate.FIXTURE.create(instanceType);
  }

  @NonNull
  public static <T> T anonymous(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("anonymous"));
    return PrivateGenerate.FIXTURE.create(clazz);
  }

  @NonNull
  public static <T> T instanceOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("instanceOf"));
    return PrivateGenerate.FIXTURE.create(clazz);
  }

  @NonNull
  public static <T> T instanceOf(final InlineInstanceGenerator<T> generator) {
    return PrivateGenerate.FIXTURE.create(generator);
  }

  @NonNull
  public static <T> T instanceOf(final Class<T> instanceType, final InlineConstrainedGenerator<T> generator) {
    assertIsNotParameterized(instanceType, ErrorMessages.msgInline("anonymous"));
    return PrivateGenerate.any(TypeToken.of(instanceType), generator);
  }

  @NonNull
  public static <T> T anonymous(final InlineInstanceGenerator<T> generator) {
    return PrivateGenerate.FIXTURE.create(generator);
  }

  @NonNull
  public static <T> T anonymous(final InstanceOf<T> type, final InlineConstrainedGenerator<T> generator) {
    return PrivateGenerate.FIXTURE.create(type, generator);
  }

  @NonNull
  public static <T> T anonymous(final Class<T> instanceType, final InlineConstrainedGenerator<T> generator) {
    assertIsNotParameterized(instanceType, ErrorMessages.msgInline("anonymous"));
    return PrivateGenerate.any(TypeToken.of(instanceType), generator);
  }

  @NonNull
  public static <T> T dummy(final InstanceOf<T> instanceType) {
    return PrivateGenerate.FIXTURE.createDummy(instanceType);
  }

  @NonNull
  public static <T> T dummy(final Class<T> clazz) {
    return PrivateGenerate.FIXTURE.createDummy(clazz);
  }

  public static String string() {
    return anonymous(String.class);
  }

  @NonNull
  public static String string(String seed) {
    return anonymous(InlineGenerators.seededString(seed));
  }

  public static String string(final int charactersCount) {
    return stringOfLength(charactersCount);
  }

  public static String stringOfLength(final int charactersCount) {
    return anonymous(InlineGenerators.stringOfLength(charactersCount));
  }

  @NonNull
  public static String stringNotContaining(final String... excludedSubstrings) {
    return anonymous(InlineGenerators.stringNotContaining(excludedSubstrings));
  }

  @NonNull
  public static String stringContaining(final String str) {
    return anonymous(InlineGenerators.stringContaining(str));
  }

  public static Character alphaChar() {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.alphaChar());
  }

  public static Character digitChar() {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.digitChar());
  }

  public static String alphaString() {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.alphaString());
  }

  public static String alphaString(final int length) {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.alphaString(length));
  }

  public static String lowercaseString() {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.lowercaseString());
  }

  public static String lowercaseString(final int length) {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.lowercaseString(length));
  }

  public static String uppercaseString() {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.uppercaseString());
  }

  public static String uppercaseString(final int length) {
    return PrivateGenerate.FIXTURE.create(InlineGenerators.uppercaseString(length));
  }

  public static String identifier() {
    return PrivateGenerate.FIXTURE.create(identifierString());
  }

  public static String legalXmlTagName() {
    return PrivateGenerate.FIXTURE.create(identifierString());
  }

  public static Integer intValue() {
    return PrivateGenerate.FIXTURE.create(int.class);
  }

  public static Short shortValue() {
    return PrivateGenerate.FIXTURE.create(short.class);
  }

  public static Double doubleValue() {
    return PrivateGenerate.FIXTURE.create(double.class);
  }

  public static Float floatValue() {
    return PrivateGenerate.FIXTURE.create(float.class);
  }

  public static Character charValue() {
    return PrivateGenerate.FIXTURE.create(char.class);
  }

  public static Long longValue() {
    return PrivateGenerate.FIXTURE.create(long.class);
  }

  @NonNull
  public static <T> T otherThan(final T... others) {
    assertHasElements(others);
    Class<?> requestedType = others[0].getClass();
    assertIsNotParameterized(requestedType, "otherThan() does not work for generics. Try Any.anonymous(new InstanceOf<MyType<GenericType>>() {}, otherThan(x,y,z))");
    return Any.anonymous((Class<T>) requestedType, InlineGenerators.otherThan(others));
  }

  @NonNull
  public static <T> T[] arrayWithout(final T... others) {
    assertHasElements(others);
    Class<T> elementClass = (Class<T>) (others[0].getClass());
    assertIsNotParameterized(elementClass, "arrayWithout() does not work for generics. Try Any.arrayOf(new InstanceOf<MyType<GenericType>>() {}, without(x))");

    return Any.arrayOf(elementClass, without(others));
  }

  @NonNull
  public static <T> T[] arrayOtherThan(final T[] otherArray) {
    assertHasElements(otherArray);
    Class<T> elementClass = (Class<T>) (otherArray[0].getClass());
    assertIsNotParameterized(elementClass, "arrayWithout() does not work for generics. Try Any.arrayOf(new InstanceOf<MyType<GenericType>>() {}, without(x))");

    return Any.arrayOf(elementClass, without(otherArray));
  }

  @NonNull
  public static Long longOtherThan(final long... others) {
    assertHasElements(boxed(others));
    return PrivateGenerate.FIXTURE.create(new InstanceOf<Long>() {
    }, InlineGenerators.otherThan(boxed(others)));
  }

  @NonNull
  public static String stringOtherThan(final String... others) {
    assertHasElements(others);
    return PrivateGenerate.FIXTURE.create(new InstanceOf<String>() {
    }, InlineGenerators.otherThan(others));
  }

  @NonNull
  public static Integer intOtherThan(final int... others) {
    assertHasElements(boxed(others));
    return PrivateGenerate.FIXTURE.create(new InstanceOf<Integer>() {
    }, InlineGenerators.otherThan(boxed(others)));
  }

  @NonNull
  public static Short shortOtherThan(final short... others) {
    assertHasElements(boxed(others));
    return PrivateGenerate.FIXTURE.create(new InstanceOf<Short>() {
    }, InlineGenerators.otherThan(boxed(others)));
  }

  @NonNull
  public static Double doubleOtherThan(final double... others) {
    assertHasElements(boxed(others));
    return PrivateGenerate.FIXTURE.create(new InstanceOf<Double>() {
    }, InlineGenerators.otherThan(boxed(others)));
  }

  @NonNull
  public static Float floatOtherThan(final float... others) {
    assertHasElements(boxed(others));
    return PrivateGenerate.FIXTURE.create(new InstanceOf<Float>() {
    }, InlineGenerators.otherThan(boxed(others)));
  }

  @NonNull
  public static <T> T of(final Class<T> enumClass) {
    return anonymous(enumClass);
  }

  public static Date date() {
    return anonymous(Date.class);
  }

  @NonNull
  public static <T> T exploding(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("exploding"));
    return PrivateGenerate.anyExploding(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> T exploding(final InstanceOf<T> typeToken) {
    return PrivateGenerate.anyExploding(typeToken);
  }

  @NonNull
  public static <T> T exploding(final TypeToken<T> typeToken) {
    return PrivateGenerate.anyExploding(typeToken);
  }

  public static Exception exception() {
    return anonymous(RuntimeException.class);
  }

  public static RuntimeException runtimeException() {
    return anonymous(RuntimeException.class);
  }

  public static Exception checkedException() {
    return PrivateGenerate.FIXTURE.create(Exception.class);
  }

  public static Throwable throwable() {
    return PrivateGenerate.FIXTURE.create(Throwable.class);
  }

  public static Throwable uncheckedThrowable() {
    return runtimeException();
  }

  public static Error error() {
    return PrivateGenerate.FIXTURE.create(Error.class);
  }

  public static Boolean booleanValue() {
    return PrivateGenerate.FIXTURE.create(Boolean.class);
  }

  public static Object object() {
    return anonymous(Object.class);
  }

  public static URI uri() {
    return PrivateGenerate.FIXTURE.create(URI.class);
  }

  public static URL url() {
    return PrivateGenerate.FIXTURE.create(URL.class);
  }

  public static Path path() {
    return PrivateGenerate.FIXTURE.create(Path.class);
  }

  public static Path absolutePath() {
    return PrivateGenerate.FIXTURE.create(Path.class);
  }

  public static Path relativePath() {
    return anonymous(InlineGenerators.relativePath());
  }

  public static int port() {
    return PrivateGenerate.FIXTURE.create(portNumber());
  }

  public static InetAddress ip() {
    return PrivateGenerate.FIXTURE.create(InetAddress.class);
  }

  public static ChronoLocalDate chronoLocalDate() {
    return PrivateGenerate.FIXTURE.create(ChronoLocalDate.class);
  }

  public static ChronoLocalDateTime chronoLocalDateTime() {
    return PrivateGenerate.FIXTURE.create(ChronoLocalDateTime.class);
  }

  public static LocalDateTime localDateTime() {
    return PrivateGenerate.FIXTURE.create(LocalDateTime.class);
  }

  public static LocalDate localDate() {
    return PrivateGenerate.FIXTURE.create(LocalDate.class);
  }

  public static ZonedDateTime zonedDateTime() {
    return PrivateGenerate.FIXTURE.create(ZonedDateTime.class);
  }

  public static ZoneId zoneId() {
    return PrivateGenerate.FIXTURE.create(ZoneId.class);
  }

  public static OffsetTime offsetTime() {
    return PrivateGenerate.FIXTURE.create(OffsetTime.class);
  }

  public static Period period() {
    return PrivateGenerate.FIXTURE.create(Period.class);
  }

  public static Duration duration() {
    return PrivateGenerate.FIXTURE.create(Duration.class);
  }

  public static ZoneOffset zoneOffset() {
    return PrivateGenerate.FIXTURE.create(ZoneOffset.class);
  }

  public static Clock clock() {
    return PrivateGenerate.FIXTURE.create(Clock.class);
  }

  public static Instant instant() {
    return PrivateGenerate.FIXTURE.create(Instant.class);
  }

  @NonNull
  public static <T> T from(final T... possibleValues) {
    return InlineGenerators.from(possibleValues).next(PrivateGenerate.FIXTURE);
  }

  // ITERABLES - complete
  @NonNull
  public static <T> Iterable<T> iterableOf(final InstanceOf<T> type) {
    return PrivateGenerate.FIXTURE.createMany(type);
  }

  @NonNull
  public static <T> Iterable<T> iterableOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("iterableOf"));
    return PrivateGenerate.FIXTURE.createMany(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> Iterable<T> iterableOf(
      final InstanceOf<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsIterableOf(typeToken, omittedValues);
  }

  @NonNull
  public static <T> Iterable<T> iterableOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("iterableOf"));
    return PrivateGenerate.manyAsIterableOf(TypeToken.of(type), omittedValues);
  }

  //ARRAYS - complete
  @NonNull
  public static <T> T[] arrayOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("arrayOf"));
    return PrivateGenerate.manyAsArrayOf(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> T[] arrayOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsArrayOf(type);
  }

  @NonNull
  public static <T> T[] arrayOf(final InstanceOf<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsArrayOf(typeToken, omittedValues);
  }

  @NonNull
  public static <T> T[] arrayOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("arrayOf"));
    return PrivateGenerate.manyAsArrayOf(TypeToken.of(type), omittedValues);
  }

  //LISTS - complete

  @NonNull
  public static <T> List<T> listOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("listOf"));
    return PrivateGenerate.manyAsListOf(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> List<T> listOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsListOf(type);
  }

  @NonNull
  public static <T> List<T> listOf(final InstanceOf<T> typeToken, final InlineConstrainedGenerator<T> generator) {
    return PrivateGenerate.manyAsListOf(typeToken, generator);
  }

  @NonNull
  public static <T> List<T> listOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("listOf"));
    return PrivateGenerate.manyAsListOf(TypeToken.of(type), omittedValues);
  }

  // COLLECTIONS - complete

  @NonNull
  public static <T> Collection<T> collectionOf(final InstanceOf<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsListOf(typeToken, omittedValues);
  }

  @NonNull
  public static <T> Collection<T> collectionOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("collectionOf"));
    return PrivateGenerate.FIXTURE.createMany(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> Collection<T> collectionOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("collectionOf"));
    return PrivateGenerate.manyAsListOf(TypeToken.of(type), omittedValues);
  }

  @NonNull
  public static <T> Collection<T> collectionOf(final InstanceOf<T> instanceType) {
    return PrivateGenerate.FIXTURE.createMany(instanceType);
  }

  //SETS: incomplete

  //TODO variations
  @NonNull
  public static <T> Set<T> setOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("setOf"));
    return PrivateGenerate.manyAsSetOf(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> Set<T> setOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsSetOf(type);
  }

  //TODO UT
  @NonNull
  public static <T> Set<T> setOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("setOf"));
    return PrivateGenerate.manyAsSetOf(TypeToken.of(type), omittedValues);
  }

  //TODO UT
  @NonNull
  public static <T> Set<T> setOf(final InstanceOf<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsSetOf(type, omittedValues);
  }

  //queues: incomplete
  @NonNull
  public static <T> Queue<T> queueOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("queueOf"));
    return PrivateGenerate.manyAsQueueOf(TypeToken.of(clazz));
  }

  @NonNull
  public static <T> Queue<T> queueOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsQueueOf(type);
  }

  //TODO UT

  @NonNull
  public static <T> Queue<T> queueOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("queueOf"));
    return PrivateGenerate.manyAsQueueOf(TypeToken.of(type), omittedValues);
  }
  //TODO UT

  @NonNull
  public static <T> Queue<T> queueOf(final InstanceOf<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsQueueOf(type, omittedValues);
  }
  //Deques: incomplete

  @NonNull
  public static <T> Deque<T> dequeOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("dequeOf"));
    return PrivateGenerate.manyAsDequeOf(TypeToken.of(clazz));
  }
  @NonNull
  public static <T> Deque<T> dequeOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsDequeOf(type);
  }

  //TODO UT
  @NonNull
  public static <T> Deque<T> dequeOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("dequeOf"));
    return PrivateGenerate.manyAsDequeOf(TypeToken.of(type), omittedValues);
  }

  //TODO UT

  @NonNull
  public static <T> Deque<T> dequeOf(final InstanceOf<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsDequeOf(type, omittedValues);
  }
  //sorted sets: incomplete

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final Class<T> clazz) {
    assertIsNotParameterized(clazz, ErrorMessages.msg("sortedSetOf"));
    return PrivateGenerate.manyAsSortedSetOf(TypeToken.of(clazz));
  }
  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final InstanceOf<T> type) {
    return PrivateGenerate.manyAsSortedSetOf(type);
  }

  //TODO UT

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, ErrorMessages.msgInline("sortedSetOf"));
    return PrivateGenerate.manyAsSortedSetOf(TypeToken.of(type), omittedValues);
  }
  //TODO UT

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final InstanceOf<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    return PrivateGenerate.manyAsSortedSetOf(type, omittedValues);
  }

  //sorted maps
  //TODO variations and UT

  @NonNull
  public static <T, V> SortedMap<T, V> sortedMapBetween(final Class<T> keyClass, final Class<V> valueClass) {
    assertIsNotParameterized(keyClass, "generic key types are not allowed for this method.");
    assertIsNotParameterized(valueClass, "generic value types are not allowed for this method.");
    return PrivateGenerate.manyAsSortedMapBetween(TypeToken.of(keyClass), TypeToken.of(valueClass));
  }

  @NonNull
  public static <T, V> SortedMap<T, V> sortedMapBetween(final InstanceOf<T> key, final InstanceOf<V> value) {
    return PrivateGenerate.manyAsSortedMapBetween(key, value);
  }

  //maps

  //TODO variations
  @NonNull
  public static <T, V> Map<T, V> mapBetween(final Class<T> keyClass, final Class<V> valueClass) {
    assertIsNotParameterized(keyClass, "generic key types are not allowed for this method.");
    assertIsNotParameterized(valueClass, "generic value types are not allowed for this method.");
    return PrivateGenerate.manyAsMapBetween(TypeToken.of(keyClass), TypeToken.of(valueClass));
  }

  @NonNull
  public static <T, V> Map<T, V> mapBetween(final InstanceOf<T> keyType, final InstanceOf<V> valueType) {
    return PrivateGenerate.manyAsMapBetween(keyType, valueType);
  }

  /// optionals

  @NonNull
  public static <T> Optional<T> optional(Class<T> type) {
    return Optional.of(Any.anonymous(type));
  }

  @NonNull
  public static <T> Optional<T> optional(InstanceOf<T> type) {
    return Optional.of(Any.anonymous(type));
  }

  @NonNull
  public static <T> Optional<T> optionalOtherThan(Optional<T>... others) {
    T[] others1 = (T[])Arrays.stream(others)
        .map(Optional::get)
        .toArray(Object[]::new);
    T o = Any.otherThan(others1);
    return Optional.of(o);
  }

  private static <T> void assertHasElements(T[] otherArray) {
    if(otherArray.length == 0) {
      throw new RuntimeException(
          "expected the input array to contain at least one element, but is empty");
    }
  }

}


package autofixture.publicinterface;

import autofixture.implementationdetails.CollectionFactory;
import autofixture.interfaces.InlineConstrainedGenerator;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;

import java.util.*;

import static autofixture.publicinterface.InlineGenerators.exploding;

/**
 * Created by grzes on 01.07.2017.
 */
class PrivateGenerate {
  public static final Fixture FIXTURE = new Fixture();

  static <T> T any(final TypeToken<T> type, final InlineConstrainedGenerator<T> generator) {
    return FIXTURE.create(type, generator);
  }

  static <T> T anyExploding(final TypeToken<T> typeToken) {
    return Any.anonymous(exploding(typeToken));
  }

  static <T> Iterable<T> manyAsIterableOf(
      final TypeToken<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    return manyAsListOf(typeToken, omittedValues);
  }

  static <T> T[] manyAsArrayOf(final TypeToken<T> type) {
    return FIXTURE.createArray(type);
  }

  static <T> T[] manyAsArrayOf(final TypeToken<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    final List<T> list = manyAsListOf(typeToken, omittedValues);
    T[] templateArray = CollectionFactory.createArray(typeToken, list.size());
    return list.toArray(templateArray);
  }

  static <T> List<T> manyAsListOf(final TypeToken<T> type) {
    return Lists.newArrayList(FIXTURE.createMany(type));
  }

  //TODO rethink putting this into the Fixture class
  static <T> List<T> manyAsListOf(final TypeToken<T> typeToken, final InlineConstrainedGenerator<T> generator) {
    final List<T> result = CollectionFactory.createList();
    result.add(any(typeToken, generator));
    result.add(any(typeToken, generator));
    result.add(any(typeToken, generator));

    return result;
  }

  private static <T> Collection<T> manyAsCollectionOf(final TypeToken<T> typeToken, final InlineConstrainedGenerator<T> omittedValues) {
    return manyAsListOf(typeToken, omittedValues);
  }

  private static <T> Collection<T> manyAsCollectionOf(final TypeToken<T> instanceType) {
    return PrivateGenerate.FIXTURE.createMany(instanceType);
  }

  static <T> Set<T> manyAsSetOf(final TypeToken<T> type) {
    final Collection<T> many = FIXTURE.createMany(type);
    final Set<T> collection = CollectionFactory.createSetFrom(many);
    return collection;
  }

  static <T> Set<T> manyAsSetOf(final TypeToken<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    final Collection<T> collection = manyAsCollectionOf(type, omittedValues);
    return CollectionFactory.createSetFrom(collection);
  }

  static <T> Queue<T> manyAsQueueOf(final TypeToken<T> type) {
    final Collection<T> many = FIXTURE.createMany(type);
    final Queue<T> queue = CollectionFactory.createQueueFrom(many);
    return queue;
  }

  static <T> Queue<T> manyAsQueueOf(final TypeToken<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    final Collection<T> collection = manyAsCollectionOf(type, omittedValues);
    return CollectionFactory.createQueueFrom(collection);
  }

  static <T> Deque<T> manyAsDequeOf(final TypeToken<T> type) {
    final Collection<T> many = FIXTURE.createMany(type);
    final Deque<T> collection = CollectionFactory.createDequeFrom(many);
    return collection;
  }

  static <T> Deque<T> manyAsDequeOf(final TypeToken<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    final Collection<T> collection = manyAsCollectionOf(type, omittedValues);
    return CollectionFactory.createDequeFrom(collection);
  }

  static <T> SortedSet<T> manyAsSortedSetOf(final TypeToken<T> type) {
    final Collection<T> many = FIXTURE.createMany(type);
    final SortedSet<T> collection = CollectionFactory.createSortedSetFrom(many);
    return collection;
  }

  static <T> SortedSet<T> manyAsSortedSetOf(final TypeToken<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    final Collection<T> collection = manyAsCollectionOf(type, omittedValues);
    return CollectionFactory.createSortedSetFrom(collection);
  }

  static <T, V> SortedMap<T, V> manyAsSortedMapBetween(final TypeToken<T> key, final TypeToken<V> value) {
    return CollectionFactory.createSortedMapFrom(manyAsMapBetween(key, value));
  }

  static <T, V> Map<T, V> manyAsMapBetween(final TypeToken<T> keyType, final TypeToken<V> valueType) {
    final T[] keys = (T[]) manyAsCollectionOf(keyType).toArray();
    final V[] values = (V[]) manyAsCollectionOf(valueType).toArray();

    final Map<T, V> map = CollectionFactory.createMapFrom(keys, values);

    return map;
  }
}


package autofixture.generators.objects.implementationdetails;

import autofixture.interfaces.FixtureContract;
import autofixture.interfaces.InstanceType;
import com.google.common.base.Optional;
import com.google.common.reflect.TypeToken;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InterfaceHandler<T> implements InvocationHandler {

  private final FixtureContract fixture;
  private final InstanceType<T> instanceType;
  private final MethodsInvocationResultCache methodsInvocationResultCache = new MethodsInvocationResultCache();

  public InterfaceHandler(final FixtureContract fixture, final InstanceType<T> instanceType) {
    this.fixture = fixture;
    this.instanceType = instanceType;
  }

  @Override
  public Object invoke(final Object proxy, final Method method, final Object[] arguments) throws Exception {

    final TypeToken<?> returnType = instanceType.resolveActualTypeOf(method);

    if (isHashCodeMethod(method)) {
      return System.identityHashCode(proxy);
    }

    if (isEqualsMethod(method, arguments)) {
      return proxy == arguments[0];
    }

    if (wasCalledAtLeastOnceOn(proxy, method)) {
      return methodsInvocationResultCache.getResultFor(proxy, method);
    }

    return generateFreshValueFor(proxy, method, returnType);
  }

  private boolean isHashCodeMethod(final Method method) {
    return "hashCode".equals(method.getName());
  }

  private boolean wasCalledAtLeastOnceOn(final Object proxy, final Method method) {
    return methodsInvocationResultCache.containAResultFor(proxy, method);
  }

  private boolean isEqualsMethod(final Method mtd, final Object[] arguments) {
    return "equals".equals(mtd.getName()) && arguments.length == 1;
  }

  //TODO check case when new X<Integer>().GetValue() and new X<String>().GetValue() afterwards - does this work?
  private Object generateFreshValueFor(final Object proxy, final Method method, final TypeToken<?> returnType) {
    final Optional<Object> freshReturnValue = createReturnValue(fixture, returnType);
    if (freshReturnValue.isPresent()) {
      methodsInvocationResultCache.setFor(proxy, method, freshReturnValue.get());
    }
    return freshReturnValue.orNull();
  }

  private Optional<Object> createReturnValue(final FixtureContract fixture, final TypeToken<?> returnType) {
    if (returnType.getRawType() != void.class) {
      final Object o = fixture.create(returnType);
      return Optional.of(o);
    } else {
      return Optional.absent();
    }
  }

}


package autofixture.publicinterface.thirdpartysupport;

import autofixture.interfaces.InlineConstrainedGenerator;
import autofixture.publicinterface.Any;
import autofixture.publicinterface.InstanceOf;
import io.vavr.collection.*;
import io.vavr.control.Either;
import io.vavr.control.Option;
import io.vavr.control.Try;
import io.vavr.control.Validation;
import lombok.NonNull;

import static autofixture.generators.objects.implementationdetails.TypeAssertions.assertIsNotParameterized;
import static autofixture.implementationdetails.ErrorMessages.msg;
import static autofixture.implementationdetails.ErrorMessages.msgInline;

public class AnyVavr {
  //todo add generics checks
  @NonNull
  public static <T> List<T> listOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("listOf"));
    return io.vavr.collection.List.ofAll(Any.listOf(clazz));
  }

  @NonNull
  public static <T> List<T> listOf(final InstanceOf<T> clazz) {
    return io.vavr.collection.List.ofAll(Any.listOf(clazz));

  }

  @NonNull
  public static <T> List<T> listOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return io.vavr.collection.List.ofAll(Any.listOf(clazz, generator));
  }

  @NonNull
  public static <T> List<T> listOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("listOf"));
    return List.ofAll(Any.listOf(type, omittedValues));
  }

/////////////// arrays

  @NonNull
  public static <T> Array<T> arrayOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("arrayOf"));
    return Array.ofAll(Any.listOf(clazz));
  }

  @NonNull
  public static <T> Array<T> arrayOf(final InstanceOf<T> clazz) {
    return Array.ofAll(Any.listOf(clazz));
  }

  @NonNull
  public static <T> Array<T> arrayOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return Array.ofAll(Any.listOf(clazz, generator));
  }

  @NonNull
  public static <T> Array<T> arrayOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("arrayOf"));
    return Array.ofAll(Any.listOf(type, omittedValues));
  }

  /////////////// hashsets

  @NonNull
  public static <T> HashSet<T> hashSetOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("hashSetOf"));
    return HashSet.ofAll(Any.listOf(clazz));
  }

  @NonNull
  public static <T> HashSet<T> hashSetOf(final InstanceOf<T> clazz) {
    return HashSet.ofAll(Any.listOf(clazz));
  }

  @NonNull
  public static <T> HashSet<T> hashSetOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return HashSet.ofAll(Any.listOf(clazz, generator));
  }

  @NonNull
  public static <T> HashSet<T> hashSetOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("hashSetOf"));
    return HashSet.ofAll(Any.listOf(type, omittedValues));
  }

  //////// tree sets

  @NonNull
  public static <T> TreeSet<T> treeSetOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("treeSetOf"));
    return TreeSet.ofAll((Iterable)Any.iterableOf(clazz));
  }

  @NonNull
  public static <T> TreeSet<T> treeSetOf(final InstanceOf<T> clazz) {
    return TreeSet.ofAll((Iterable)Any.listOf(clazz));
  }

  @NonNull
  public static <T> TreeSet<T> treeSetOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return TreeSet.ofAll((Iterable)Any.listOf(clazz, generator));
  }

  @NonNull
  public static <T> TreeSet<T> treeSetOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("treeSetOf"));
    return TreeSet.ofAll((Iterable)Any.listOf(type, omittedValues));
  }

//////// sets

  @NonNull
  public static <T> Set<T> setOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("setOf"));
    return hashSetOf(clazz);
  }

  @NonNull
  public static <T> Set<T> setOf(final InstanceOf<T> clazz) {
    return hashSetOf(clazz);
  }

  @NonNull
  public static <T> Set<T> setOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return hashSetOf(clazz, generator);
  }

  @NonNull
  public static <T> Set<T> setOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("setOf"));
    return hashSetOf(type, omittedValues);
  }

/////// sorted sets

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("sortedSetOf"));
    return treeSetOf(clazz);
  }

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final InstanceOf<T> clazz) {
    return treeSetOf(clazz);
  }

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return treeSetOf(clazz, generator);
  }

  @NonNull
  public static <T> SortedSet<T> sortedSetOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("sortedSetOf"));
    return treeSetOf(type, omittedValues);
  }

  /////////////////////////////// hash maps

  @NonNull
  public static <T, V> HashMap<T, V> hashMapBetween(final Class<T> keyClass, final Class<V> valueClass) {
    assertIsNotParameterized(keyClass, "generic key types are not allowed for this method.");
    assertIsNotParameterized(valueClass, "generic value types are not allowed for this method.");
    return HashMap.ofAll(Any.mapBetween(keyClass, valueClass));
  }

  @NonNull
  public static <T, V> HashMap<T, V> hashMapBetween(final InstanceOf<T> keyType, final InstanceOf<V> valueType) {
    return HashMap.ofAll(Any.mapBetween(keyType, valueType));
  }

  /////////////////////////////// maps

  @NonNull
  public static <T, V> Map<T, V> mapBetween(final Class<T> keyClass, final Class<V> valueClass) {
    assertIsNotParameterized(keyClass, "generic key types are not allowed for this method.");
    assertIsNotParameterized(valueClass, "generic value types are not allowed for this method.");
    return hashMapBetween(keyClass, valueClass);
  }

  @NonNull
  public static <T, V> Map<T, V> mapBetween(final InstanceOf<T> keyType, final InstanceOf<V> valueType) {
    return hashMapBetween(keyType, valueType);
  }

  @NonNull
  public static <T, V> LinkedHashMap<T, V> linkedHashMapBetween(final Class<T> keyClass, final Class<V> valueClass) {
    assertIsNotParameterized(keyClass, "generic key types are not allowed for this method.");
    assertIsNotParameterized(valueClass, "generic value types are not allowed for this method.");
    return LinkedHashMap.ofAll(Any.mapBetween(keyClass, valueClass));
  }

  @NonNull
  public static <T, V> LinkedHashMap<T, V> linkedHashMapBetween(final InstanceOf<T> keyType, final InstanceOf<V> valueType) {
    return LinkedHashMap.ofAll(Any.mapBetween(keyType, valueType));
  }

//////////////////// queues

  @NonNull
  public static <T> Queue<T> queueOf(Class<T> clazz) {
    assertIsNotParameterized(clazz, msg("queueOf"));
    return Queue.ofAll(Any.queueOf(clazz));
  }

  @NonNull
  public static <T> Queue<T> queueOf(final InstanceOf<T> clazz) {
    return Queue.ofAll(Any.queueOf(clazz));
  }

  @NonNull
  public static <T> Queue<T> queueOf(final InstanceOf<T> clazz, final InlineConstrainedGenerator<T> generator) {
    return Queue.ofAll(Any.queueOf(clazz, generator));
  }

  @NonNull
  public static <T> Queue<T> queueOf(final Class<T> type, final InlineConstrainedGenerator<T> omittedValues) {
    assertIsNotParameterized(type, msgInline("queueOf"));
    return Queue.ofAll(Any.queueOf(type, omittedValues));
  }

  // options

  @NonNull
  public static <T> Option<T> option(final Class<T> type) {
    assertIsNotParameterized(type, msgInline("option"));
    return Option.of(Any.instanceOf(type));
  }

  @NonNull
  public static <T> Option<T> option(final InstanceOf<T> type) {
    return Option.of(Any.anonymous(type));
  }

  // eithers - left

  @NonNull
  public static <T,U> Either<T, U> left(final Class<T> leftType) {
    assertIsNotParameterized(leftType, msgInline("left"));
    return Either.left(Any.instanceOf(leftType));
  }

  @NonNull
  public static <T,U> Either<T, U> left(final InstanceOf<T> leftType) {
    return Either.left(Any.anonymous(leftType));
  }

  // eithers - right

  @NonNull
  public static <T,U> Either<T, U> right(final Class<U> rightType) {
    assertIsNotParameterized(rightType, msgInline("right"));
    return Either.right(Any.instanceOf(rightType));
  }

  @NonNull
  public static <T,U> Either<T, U> right(final InstanceOf<U> rightType) {
    return Either.right(Any.anonymous(rightType));
  }

  // validations - failures

  @NonNull
  public static <T,U> Validation<T, U> validationFailed(final Class<T> type) {
    assertIsNotParameterized(type, msgInline("validationFailed"));
    return Validation.invalid(Any.instanceOf(type));
  }

  @NonNull
  public static <T,U> Validation<T, U> validationFailed(final InstanceOf<T> type) {
    return Validation.invalid(Any.anonymous(type));
  }

  // validations - successful

  @NonNull
  public static <T,U> Validation<T, U> validationSuccess(final Class<U> type) {
    assertIsNotParameterized(type, msgInline("validationSuccess"));
    return Validation.valid(Any.instanceOf(type));
  }

  @NonNull
  public static <T,U> Validation<T, U> validationSuccess(final InstanceOf<U> type) {
    return Validation.valid(Any.anonymous(type));
  }

  // try - failures

  @NonNull
  public static Try tryFailed() {
    return Try.failure(Any.throwable());
  }

  // try - successful

  @NonNull
  public static <T> Try<T> trySuccess(final Class<T> type) {
    assertIsNotParameterized(type, msgInline("trySuccess"));
    return Try.success(Any.instanceOf(type));
  }

  @NonNull
  public static <T> Try<T> trySuccess(final InstanceOf<T> type) {
    return Try.success(Any.anonymous(type));
  }

  //multimap, hashmultimap, linkedhashmultimap
  //priorityqueue,
  //charseq, indexedseq, seq

}


package com.github.andreptb.fitnesse;

import java.sql.Driver;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

/**
 * Slim fixture to execute jdbc commands, see README.md for more information.
 */
public class JdbcFixture {

	private static final String SELECT_COMMAND_PREFIX = "SELECT";
	/**
	 * Registered databases, the key being database name and value an instance of JdbcTemplate
	 */
	private Map<String, JdbcTemplate> templateMap = new TreeMap<>();

	/**
	 * Registers a database to further execute SQL commands
	 *
	 *

	 * | connect jdbc on | database | with url | url | and driver | driver | and username | username | and | password |
	 *

	 * @param url
	 */
	@SuppressWarnings("unchecked")
	public boolean connectJdbcOnWithUrlAndDriverAndUsernameAndPassword(String dataBaseId, String url, String driverClassName, String username, String password) throws ReflectiveOperationException {
		SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
		dataSource.setUrl(url);
		dataSource.setDriverClass((Class<Driver>) Class.forName(driverClassName));
		dataSource.setUsername(username);
		dataSource.setPassword(password);
		this.templateMap.put(dataBaseId, new JdbcTemplate(dataSource));
		return true;
	}

	/**
	 * Simply runs a SQL command, used for udpates, inserts which the result doesn't matter.
	 *
	 *

	 * | run in | database | the sql | sql |
	 *

	 * @param database registered database to run the SQL
	 * @param sql to run
	 */
	public boolean runInTheSql(String database, final String sql) {
		getDatabaseJdbcTemplate(database).update(sql);
		return true;
	}

	/**
	 * Used generally when the result is assigned to a variable
	 *
	 *

	 * | $variable= | query in | database | with sql | sql |
	 *

	 * @param database registered database to run the SQL
	 * @param sql to run
	 */
	public String queryInWithSql(String database, String sql) {
		JdbcTemplate template = getDatabaseJdbcTemplate(database);
		if (sql != null && !sql.trim().toUpperCase().startsWith(JdbcFixture.SELECT_COMMAND_PREFIX)) {
			return Objects.toString(template.update(sql));
		}
		List<String> results = template.queryForList(sql, String.class);
		if(results == null || results.isEmpty()) {
			return null;
		}
		return results.get(0);
	}

	private JdbcTemplate getDatabaseJdbcTemplate(String database) {
		JdbcTemplate template = this.templateMap.get(database);
		if(template == null) {
			throw new IllegalArgumentException(String.format("No database registered for name '%s'. Registered databases: %s", database, this.templateMap.keySet()));
		}
		return template;
	}

}