package cn.net.communion.core; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import cn.net.communion.helper.FileHelper; import cn.net.communion.helper.PropsReader; import cn.net.communion.helper.RandomData; public class Parser { private String value; private Map<String, String> map; private Pattern varPattern; private Pattern rulePattern; private Pattern poolPattern; private Pattern datePattern; private PropsReader props; private Map<String, String> poolFileMap = new HashMap<String, String>(); static private Parser instance = null; private Random rand = new Random(); private Parser() { varPattern = Pattern.compile("\\$var\\{(\\w+)\\}"); rulePattern = Pattern.compile("\\$rule\\{([0-9a-zA-Z,]+)\\}"); poolPattern = Pattern.compile("\\$pool\\{([0-9a-zA-Z.]+)\\}"); datePattern = Pattern.compile("\\$date\\{([^\\s,]+),([^\\s,]+),([^\\s,]+)\\}"); props = PropsReader.getInstance(); } static Parser getInstance(String value, Map<String, String> map) { if (instance == null) { instance = new Parser(); } instance.setValue(value); instance.setMap(map); return instance; } static public boolean checkGrammar(String value) { return value.contains("$var") || value.contains("$rule") || value.contains("$pool") || value.contains("$date"); } public String execute() { parseVar().parseRule().parsePool().parseDate(); return value; } private Parser parseVar() { Matcher m = varPattern.matcher(value); if (m.find()) { String name = m.group(1); String propValue = props.getProperty("var." + name); value = value.replace(m.group(0), propValue != null ? propValue : this.map.get(name)); } return this; } private Parser parseRule() { Matcher m = rulePattern.matcher(value); if (m.find()) { value = value.replace(m.group(0), getRuleData(m.group(1).split(","))); } return this; } private String getRuleData(String[] arr) { String content = props.getProperty("rule." + arr[0]); if (content != null) { return RandomData.getRuleData(content, arr.length < 2 ? 6 : Integer.parseInt(arr[1])); } return null; } private Parser parsePool() { Matcher m = poolPattern.matcher(value); if (m.find()) { value = value.replace(m.group(0), getPoolData(m.group(1))); } return this; } private String getPoolData(String name) { String content = props.getProperty("pool." + name); if (content != null) { return RandomData.getPoolData(content.split(",")); } else { String poolContent = poolFileMap.get(name); if (poolContent == null) { poolContent = FileHelper.read("pool/" + name); if (poolContent == null) { return null; } poolFileMap.put(name, poolContent); } return RandomData.getPoolData(poolContent.split(",")); } } private Parser parseDate() { Matcher m = datePattern.matcher(value); if (m.find()) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(m.group(3)); LocalDate startDate = m.group(1).trim().equals("now") ? LocalDate.now() : LocalDate.parse(m.group(1).trim()); LocalDate endDate = m.group(2).trim().equals("now") ? LocalDate.now() : LocalDate.parse(m.group(2).trim()); int length = (int) startDate.until(endDate, ChronoUnit.DAYS); LocalDate randDate = length > 0 ? startDate.plusDays(rand.nextInt(length + 1)) : startDate.minusDays(rand.nextInt(1 - length)); value = value.replace(m.group(), randDate.format(formatter)); } return this; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } // public static void main(String [] args){ // Pattern datePattern = Pattern.compile("\\$date\\{([^\\s,]+),([^\\s,]+),([^\\s,]+)\\}"); // Matcher m = datePattern.matcher("$date{2017-02-01,now,yyyy/MM/dd}"); // // if(m.find()){ // System.out.println(m.group(3)); // DateTimeFormatter formatter = DateTimeFormatter.ofPattern(m.group(3)); // String start = m.group(1).trim(); // String end = m.group(2).trim(); // LocalDate startDate = start.equals("now") ? LocalDate.now() : LocalDate.parse(start); // LocalDate endDate = end.equals("now") ? LocalDate.now() : LocalDate.parse(end); // int length = (int) startDate.until(endDate, ChronoUnit.DAYS); // System.out.println(startDate.plusDays(rand.nextInt(length)).format(formatter)); // } // } }