<commit_before>package org.csstudio.opibuilder.converter.writer;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.csstudio.java.string.StringSplitter;

public class PVNameConversion {

	private static Logger log = Logger.getLogger("org.csstudio.opibuilder.converter.writer.PVNameConversion");

	private static Collection<String> functions = new ArrayList<String>();
	static {
		functions.add("sum");
	}

	private static Collection<String> operators = new ArrayList<String>();
	static {
		// Escaped for the purposes of regexing.
		operators.add("\\+");
		operators.add("-");
		operators.add("/");
		operators.add("\\*");
		operators.add("&&");
		operators.add("\\|\\|");
		operators.add("<");
		operators.add(">");
		operators.add("=");
	}


	private PVNameConversion() {
		// No instantiation.
	}


	/**
	 * If pvName is a LOC or CALC EDM PV, attempt to convert it to a syntax
	 * understood by CSS.
	 * 
	 * If conversion fails or it is a regular PV, return the unchanged PV name.
	 * @param pvName PV name to convert
	 * @return converted PV name
	 */
	public static String convertPVName(String pvName) {
		if (pvName.startsWith("LOC")) {
			log.debug("EDM local PV: " + pvName);
			pvName = parseLocPV(pvName);
			log.debug("Converted local PV: " + pvName);
		} else if (pvName.startsWith("CALC")) {
			log.debug("EDM calc PV: " + pvName);
			pvName = parseCalcPV(pvName);
			log.debug("Converted calc PV: " + pvName);
		}
		return pvName;
	}

	/**
	 * Convert an EDM local PV into a CSS local PV.
	 * @param pvName local EDM PV name
	 * @return local CSS PV name
	 */
	private static String parseLocPV(String pvName) {
		if(pvName.startsWith("LOC\\")){
			try {
				String newName = pvName.replace("$(!W)", "$(DID)");
				newName = newName.replaceAll("\\x24\\x28\\x21[A-Z]{1}\\x29", "\\$(DID)");
				String[] parts = StringSplitter.splitIgnoreInQuotes(newName, '=', true);
				StringBuilder sb = new StringBuilder("loc://");
				sb.append(parts[0].substring(5));
				if (parts.length > 1) {
					String type = "";
					String initValue = parts[1];
					if (parts[1].startsWith("d:")) {
						type = "<VDouble>";
						initValue = parts[1].substring(2);
					} else if (parts[1].startsWith("i:")) {
//						type = "<VDouble>";
						initValue = parts[1].substring(2);
					} else if (parts[1].startsWith("s:")) {
//						  type = "<VString>";
						initValue = "\""+parts[1].substring(2)+"\"";
					} else if (parts[1].startsWith("e:")) { // Enumerated pv
															// cannot be
															// converted.
						return pvName;
					}
					//doesn't append type yet to support utility pv.
					sb.append("(").append(initValue).append(")");
					}
				return sb.toString();
			} catch (Exception e) {
					return pvName;
				}
			}
			return pvName;
	}


	/**
	 * Parse the expression component of an EDM CALC PV; that is, the
	 * part before the parentheses:
	 * {A/B}(...)
	 * {A*B}(...)
	 * {1000 > x}(...)
	 * The string must be tokens separated by the items in the static variable
	 * operators.
	 * 
	 * @param op the substring to parse
	 * @return a List<String> of the operators
	 */
	private static List<String> parseExpression(String expr) {
		// expression contained within {}
		assert (StringUtils.startsWith(expr, "\\{") &&
				StringUtils.endsWith(expr, "\\}")):
					"Failed to parse CALC expression";
		expr = expr.substring(2, expr.length() - 2);
		List<String> parts = splitString(expr, operators, true);
		// The = in EDM expressions is == in CSS ones
		Collections.replaceAll(parts, "=", "==");
		return parts;
	}

	/**
	 * Return variables provided in arguments to CALC pv as a List of Strings.
	 * If an argument is a PV name, convert that PV name.
	 * 
	 * @param argString
	 *			- the arguments to a CALC PV, inside parentheses
	 * @return List<String> of variables
	 */
	private static List<String> parseArguments(String argString) {
		assert (StringUtils.startsWith(argString, "(") &&
				StringUtils.endsWith(argString, ")")):
					"Failed to parse CALC arguments";
		List<String> arguments = new ArrayList<String>();
		argString = argString.substring(1, argString.length() -1);
		List<String> pieces = splitString(argString, ",", false);
		for (String piece : pieces) {
			if (isPVString(piece)) {
				// recurse
				piece = convertPVName(piece);
				arguments.add("pv(\"" + piece + "\")");
			} else {
				arguments.add(piece);
			}
		}
		return arguments;
	}

	/**
	 * Convert EDM CALC PV into an equivalent CSS formula
	 * @param pvName EDM CALC PV name
	 * @return CSS formula string
	 */
	private static String parseCalcPV(String pvName) {
		try {
			// Remove CALC\\ from the start of the string.
			String calcString = pvName.substring(6);
			int firstParen = calcString.indexOf('(');
			String ops = calcString.substring(0, firstParen);
			String args = calcString.substring(firstParen, calcString.length());
			System.out.println("args is " + args);
			Deque<String> arguments = new ArrayDeque<String>(parseArguments(args));
			StringBuilder sb = new StringBuilder("=(");
			if (functions.contains(ops)) {<commit_msg>Converter: remove rogue print statement<commit_after>package org.csstudio.opibuilder.converter.writer;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.csstudio.java.string.StringSplitter;

public class PVNameConversion {

	private static Logger log = Logger.getLogger("org.csstudio.opibuilder.converter.writer.PVNameConversion");

	private static Collection<String> functions = new ArrayList<String>();
	static {
		functions.add("sum");
	}

	private static Collection<String> operators = new ArrayList<String>();
	static {
		// Escaped for the purposes of regexing.
		operators.add("\\+");
		operators.add("-");
		operators.add("/");
		operators.add("\\*");
		operators.add("&&");
		operators.add("\\|\\|");
		operators.add("<");
		operators.add(">");
		operators.add("=");
	}


	private PVNameConversion() {
		// No instantiation.
	}


	/**
	 * If pvName is a LOC or CALC EDM PV, attempt to convert it to a syntax
	 * understood by CSS.
	 * 
	 * If conversion fails or it is a regular PV, return the unchanged PV name.
	 * @param pvName PV name to convert
	 * @return converted PV name
	 */
	public static String convertPVName(String pvName) {
		if (pvName.startsWith("LOC")) {
			log.debug("EDM local PV: " + pvName);
			pvName = parseLocPV(pvName);
			log.debug("Converted local PV: " + pvName);
		} else if (pvName.startsWith("CALC")) {
			log.debug("EDM calc PV: " + pvName);
			pvName = parseCalcPV(pvName);
			log.debug("Converted calc PV: " + pvName);
		}
		return pvName;
	}

	/**
	 * Convert an EDM local PV into a CSS local PV.
	 * @param pvName local EDM PV name
	 * @return local CSS PV name
	 */
	private static String parseLocPV(String pvName) {
		if(pvName.startsWith("LOC\\")){
			try {
				String newName = pvName.replace("$(!W)", "$(DID)");
				newName = newName.replaceAll("\\x24\\x28\\x21[A-Z]{1}\\x29", "\\$(DID)");
				String[] parts = StringSplitter.splitIgnoreInQuotes(newName, '=', true);
				StringBuilder sb = new StringBuilder("loc://");
				sb.append(parts[0].substring(5));
				if (parts.length > 1) {
					String type = "";
					String initValue = parts[1];
					if (parts[1].startsWith("d:")) {
						type = "<VDouble>";
						initValue = parts[1].substring(2);
					} else if (parts[1].startsWith("i:")) {
//						type = "<VDouble>";
						initValue = parts[1].substring(2);
					} else if (parts[1].startsWith("s:")) {
//						  type = "<VString>";
						initValue = "\""+parts[1].substring(2)+"\"";
					} else if (parts[1].startsWith("e:")) { // Enumerated pv
															// cannot be
															// converted.
						return pvName;
					}
					//doesn't append type yet to support utility pv.
					sb.append("(").append(initValue).append(")");
					}
				return sb.toString();
			} catch (Exception e) {
					return pvName;
				}
			}
			return pvName;
	}


	/**
	 * Parse the expression component of an EDM CALC PV; that is, the
	 * part before the parentheses:
	 * {A/B}(...)
	 * {A*B}(...)
	 * {1000 > x}(...)
	 * The string must be tokens separated by the items in the static variable
	 * operators.
	 * 
	 * @param op the substring to parse
	 * @return a List<String> of the operators
	 */
	private static List<String> parseExpression(String expr) {
		// expression contained within {}
		assert (StringUtils.startsWith(expr, "\\{") &&
				StringUtils.endsWith(expr, "\\}")):
					"Failed to parse CALC expression";
		expr = expr.substring(2, expr.length() - 2);
		List<String> parts = splitString(expr, operators, true);
		// The = in EDM expressions is == in CSS ones
		Collections.replaceAll(parts, "=", "==");
		return parts;
	}

	/**
	 * Return variables provided in arguments to CALC pv as a List of Strings.
	 * If an argument is a PV name, convert that PV name.
	 * 
	 * @param argString
	 *			- the arguments to a CALC PV, inside parentheses
	 * @return List<String> of variables
	 */
	private static List<String> parseArguments(String argString) {
		assert (StringUtils.startsWith(argString, "(") &&
				StringUtils.endsWith(argString, ")")):
					"Failed to parse CALC arguments";
		List<String> arguments = new ArrayList<String>();
		argString = argString.substring(1, argString.length() -1);
		List<String> pieces = splitString(argString, ",", false);
		for (String piece : pieces) {
			if (isPVString(piece)) {
				// recurse
				piece = convertPVName(piece);
				arguments.add("pv(\"" + piece + "\")");
			} else {
				arguments.add(piece);
			}
		}
		return arguments;
	}

	/**
	 * Convert EDM CALC PV into an equivalent CSS formula
	 * @param pvName EDM CALC PV name
	 * @return CSS formula string
	 */
	private static String parseCalcPV(String pvName) {
		try {
			// Remove CALC\\ from the start of the string.
			String calcString = pvName.substring(6);
			int firstParen = calcString.indexOf('(');
			String ops = calcString.substring(0, firstParen);
			String args = calcString.substring(firstParen, calcString.length());
			Deque<String> arguments = new ArrayDeque<String>(parseArguments(args));
			StringBuilder sb = new StringBuilder("=(");
			if (functions.contains(ops)) {
{'fraction_non_alphanumeric': 0.15353817504655493, 'fraction_numerical': 0.00633147113594041, 'mean_word_length': 3.346823148522865, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5666124', 'n_tokens_mistral': 4089, 'n_tokens_neox': 3435, 'n_words': 933}