/******************************************************************************* * Copyright (c) 2017 Rogue Wave Software Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rogue Wave Software Inc. - initial implementation *******************************************************************************/ package org.eclipse.php.internal.ui.wizards.types; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.php.internal.core.util.FileUtils; import org.eclipse.wst.sse.core.utils.StringUtils; /** * Simple template engine similar to PHPLib's */ public class TextTemplate { static class StructPatternHandler { protected Matcher matcher; protected Pattern pattern; protected String placeHolder; protected String regexp; protected String structName; public StructPatternHandler(final String regexp, final String placeHolder) { this.regexp = regexp; this.placeHolder = placeHolder; } public StructPatternHandler(final String regexp, final String placeHolder, final String structName) { this(regexp, placeHolder); setStructName(structName); } @Override public boolean equals(final Object o) { if (o instanceof StructPatternHandler) { final StructPatternHandler handler = (StructPatternHandler) o; return regexp.equals(handler.getRegexp()) && placeHolder.equals(handler.getPlaceHolder()) && (structName != null && structName.equals(handler.getStructName()) || structName == null && handler.getStructName() == null); } return false; } public Matcher getMatcher() { return matcher; } public String getPlaceHolder() { return placeHolder; } public String getRegexp() { return regexp; } /** * @return the structName */ public String getStructName() { return structName; } public void setStructName(final String structName) { if (!structName.equals(this.structName)) { this.structName = structName; pattern = Pattern.compile(StringUtils.replace(REGEXP_STRUCT, REGEXP_ELEMENT_PLACEHOLDER, structName), flags); matcher = pattern.matcher(""); //$NON-NLS-1$ matcher.reset(); } } } final static private int flags = Pattern.MULTILINE | Pattern.DOTALL; final static public String NULL_VAR = ""; //$NON-NLS-1$ protected static StructPatternHandler patternHandler; /** * Placeholder for the following regular expressions which is replaced by an * element name */ protected static String REGEXP_ELEMENT_PLACEHOLDER = "@"; //$NON-NLS-1$ /** * Valid element name */ protected static String REGEXP_ELEMENT_VALID = "(\\w+)"; //$NON-NLS-1$ /** * Struct definition pattern */ protected static String REGEXP_STRUCT = "/\\*\\s*" + REGEXP_ELEMENT_PLACEHOLDER + ":\\s*\\*/(.*?)/\\*\\s*:" //$NON-NLS-1$ //$NON-NLS-2$ + REGEXP_ELEMENT_PLACEHOLDER + "\\s*\\*/"; // e.g. /* //$NON-NLS-1$ // Struct: */ Some Text // /* :Struct */ /** * Variable definition pattern */ protected static String REGEXP_VAR = "#" + REGEXP_ELEMENT_PLACEHOLDER + "#"; // e.g. //$NON-NLS-1$ //$NON-NLS-2$ // _VarName_ static { patternHandler = new StructPatternHandler(REGEXP_STRUCT, REGEXP_ELEMENT_PLACEHOLDER); } /** * @param text * Source text which should contain struct definition. * @param structName * Name of a struct defined by {@link #REGEXP_STRUCT} * @return Content of a found struct */ public static String extract(final String text, final String structName) { if ("".equals(text)) //$NON-NLS-1$ return null; if (!structName.matches(REGEXP_ELEMENT_VALID)) return null; patternHandler.setStructName(structName); final Matcher matcher = patternHandler.getMatcher().reset(text); if (matcher.find()) return matcher.group(); return null; } Map<String, String> vars; /** * @param text * {@link #compile(String)} * @return {@link #compile(String)} */ public String compile(String text) { Object val; String valCompiled; String var; if ("".equals(text)) //$NON-NLS-1$ return ""; //$NON-NLS-1$ final Matcher matcher = Pattern .compile(StringUtils.replace(REGEXP_VAR, REGEXP_ELEMENT_PLACEHOLDER, REGEXP_ELEMENT_VALID)) .matcher(text); while (matcher.find()) { var = matcher.group(1); val = vars.get(var); if (val == null) continue; valCompiled = compile(val.toString()); // WARNING: recursion text = StringUtils.replace(text, matcher.group(0), valCompiled); } return text; } /** * @param sourceVar * See {@link #get(String)} * @param targetVar * See {@link #set(String, String)} * @param append * Wheter to append or rewrite the compiled text to the source. * @return targetVar new value */ public String compile(final String sourceVar, final String targetVar, final boolean append) { set(targetVar, (append ? get(targetVar) : "") + compile(get(sourceVar))); //$NON-NLS-1$ return get(targetVar); } Pattern createStructPattern(final String structName) { return Pattern.compile(StringUtils.replace(REGEXP_STRUCT, REGEXP_ELEMENT_PLACEHOLDER, structName), flags); } /** * @param sourceVar * See {@link #get(String)} * @param structName * See {@link #extract(String, String)} * @param targetVar * Variable which replaces the extracted structure */ public void extract(final String sourceVar, final String structName, String targetVar) { String text = get(sourceVar); if (text == null) return; if (targetVar == null) targetVar = structName; final String struct = extract(text, structName); if (struct != null) { text = StringUtils.replace(text, struct, StringUtils.replace(REGEXP_VAR, REGEXP_ELEMENT_PLACEHOLDER, structName)); vars.put(targetVar, patternHandler.getMatcher().group(1)); vars.put(sourceVar, text); } } /** * @param var * Variable to get * @return Variable's value */ public String get(final String var) { if (vars == null) return ""; //$NON-NLS-1$ final Object val = vars.get(var); if (val == null) return ""; //$NON-NLS-1$ return val.toString(); } /** * @param var * variable to set * @param val * New variable's value * @return previous {@link #get(String)} */ public String set(final String var, final String val) { if (vars == null) vars = new HashMap<>(); return vars.put(var, val); } /** * @param var * See {@link #set(String, String)} * @param file * File to read * @throws IOException */ public void setFile(final String var, final File file) throws IOException { set(var, FileUtils.getContents(file)); } }