<commit_before>/*
 * jETeL/CloverETL - Java based ETL application framework.
 * Copyright (c) Javlin, a.s. (<EMAIL>)
 *  
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jetel.util.string;

/**
 * Utility to generate valid XML tag name from arbitrary string. Even that XML allows non-ASCII characters
 * as a tag name, this utility encodes them as well as any special ASCII characters. These characters are encoded as
 * "_xhhhh" where hhhh is the Unicode of the character as a hexa value. 
 * 
 * @author jan.michalica
 */
public class TagName {

	private static final char ENC_SEQ_CHAR = '_';
	private static final String ENC_SEQ_START = ENC_SEQ_CHAR + "x";
	
	/**
	 * Encodes given input string using unicodes.
	 * <pre>
	 * Example:
	 * input: "@Funny*Tag-Name()"
	 * output: "_x0040Funny_x002aTag-Name_x0028_x0029"
	 * </pre>
	 * @param s
	 * @return
	 */
	public static String encode(final String s) {
		
		if (s == null) {
			return null;
		}
		
		final StringBuilder sb = new StringBuilder(s.length());
		for (int i = 0; i < s.length(); ++i) {
			char c = s.charAt(i);
			if (!('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '-' || c == '.') ||
					c == ENC_SEQ_CHAR || (i == 0 && ('0' <= c && c <= '9' || c == '-' || c == '.'))) {
				sb.append(ENC_SEQ_START);
				String scode = Integer.toHexString(c);
				for (int j = 0; j < 4 - scode.length(); ++j) {
					sb.append('0');
				}
				sb.append(scode);
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}
	
	/**
	 * Decodes given input string previously encoded by this class.<commit_msg>MINOR: refactoring<commit_after>/*
 * jETeL/CloverETL - Java based ETL application framework.
 * Copyright (c) <NAME>. (<EMAIL>)
 *  
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jetel.util.string;

/**
 * Utility to generate valid XML tag name from arbitrary string. Even that XML allows non-ASCII characters
 * as a tag name, this utility encodes them as well as any special ASCII characters. These characters are encoded as
 * "_xhhhh" where hhhh is the Unicode of the character as a hexa value. 
 * 
 * @author jan.michalica
 */
public class TagName {

	private static final char ENC_SEQ_CHAR = '_';
	private static final String ENC_SEQ_START = ENC_SEQ_CHAR + "x";
	
	public static boolean isAllowedTagName(String name) {
		for (int i = 0; i < name.length(); ++i) {
			char c = name.charAt(i);
			if (!isAllowedTagCharacter(c,i)) {
				return false;
			}
		}
		return true;
	}
	
	private static boolean isAllowedTagCharacter(char c, int index) {
		return ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '-' || c == '.')
				|| c == ENC_SEQ_CHAR
				|| (index == 0 && ('0' <= c && c <= '9' || c == '-' || c == '.'));
	}
	
	/**
	 * Encodes given input string using unicodes.
	 * <pre>
	 * Example:
	 * input: "@Funny*Tag-Name()"
	 * output: "_x0040Funny_x002aTag-Name_x0028_x0029"
	 * </pre>
	 * @param s
	 * @return
	 */
	public static String encode(final String s) {
		
		if (s == null) {
			return null;
		}
		
		final StringBuilder sb = new StringBuilder(s.length());
		for (int i = 0; i < s.length(); ++i) {
			char c = s.charAt(i);
			if (!isAllowedTagCharacter(c,i)) {
				sb.append(ENC_SEQ_START);
				String scode = Integer.toHexString(c);
				for (int j = 0; j < 4 - scode.length(); ++j) {
					sb.append('0');
				}
				sb.append(scode);
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}
	
	/**
	 * Decodes given input string previously encoded by this class.
{'fraction_non_alphanumeric': 0.1305408702724685, 'fraction_numerical': 0.016470109800732005, 'mean_word_length': 3.137089991589571, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 10, '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': '4149796', 'n_tokens_mistral': 1762, 'n_tokens_neox': 1535, 'n_words': 609}