All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ajaxjs.util.map.MapTool Maven / Gradle / Ivy

/**
 * Copyright sp42 [email protected]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ajaxjs.util.map;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.ajaxjs.util.CommonUtil;
import com.ajaxjs.util.MappingValue;
import com.ajaxjs.util.ReflectUtil;
import com.ajaxjs.util.XMLHelper;
import com.ajaxjs.util.logger.LogHelper;

/**
 * Map 转换工具
 * 
 * @author sp42 [email protected]
 *
 */
public class MapTool {
	private static final LogHelper LOGGER = LogHelper.getLog(MapTool.class);

	// --------------------------------------------------------------------------------------------------
	// -----------------------------------------------Map转换---------------------------------------------
	// --------------------------------------------------------------------------------------------------

	/**
	 * Map 转换为 String
	 * 
	 * @param map Map 结构,Key 必须为 String 类型
	 * @param div 分隔符
	 * @param fn  对 Value 的处理函数,返回类型 T
	 * @return Map 序列化字符串
	 */
	public static  String join(Map map, String div, Function fn) {
		String[] pairs = new String[map.size()];

		int i = 0;

		for (String key : map.keySet())
			pairs[i++] = key + "=" + fn.apply(map.get(key));

		return String.join(div, pairs);
	}

	public static  String join(Map map, Function fn) {
		return join(map, "&", fn);
	}

	public static  String join(Map map, String div) {
		return join(map, div, v -> v == null ? null : v.toString());
	}

	public static  String join(Map map) {
		return join(map, "&");
	}

	/**
	 * String[] 转换为 Map
	 * 
	 * @param pairs 结对的字符串数组,包含 = 字符分隔 key 和 value
	 * @param fn    对 Value 的处理函数,返回类型 Object
	 * @return Map 对象
	 */
	public static Map toMap(String[] pairs, Function fn) {
		if (CommonUtil.isNull(pairs))
			return null;

		Map map = new HashMap<>();

		for (String pair : pairs) {
			if (!pair.contains("="))
				throw new IllegalArgumentException("没有 = 不能转化为 map");

			String[] column = pair.split("=");

			if (column.length >= 2)
				map.put(column[0], fn == null ? column[1] : fn.apply(column[1]));
			else
				map.put(column[0], "");// 没有 等号后面的,那设为空字符串
		}

		return map;
	}

	/**
	 * String[] 转换为 Map,key 与 value 分别一个数组
	 * 
	 * @param columns 结对的键数组
	 * @param values  结对的值数组
	 * @param fn      对 Value 的处理函数,返回类型 Object
	 * @return Map 对象
	 */
	public static Map toMap(String[] columns, String[] values, Function fn) {
		if (CommonUtil.isNull(columns))
			return null;

		if (columns.length != values.length)
			throw new UnsupportedOperationException("两个数组 size 不一样");

		Map map = new HashMap<>();

		int i = 0;
		for (String column : columns)
			map.put(column, fn.apply(values[i++]));

		return map;
	}

	/**
	 * 判断 map 非空,然后根据 key 获取 value,若 value 非空则作为参数传入函数接口 s
	 * 
	 * @param map 输入的map
	 * @param key map的键
	 * @param s   如果过非空,那么接着要做什么?在这个回调函数中处理。传入的参数就是map.get(key)的值
	 */
	public static  void getValue(Map map, String key, Consumer s) {
		if (map != null) {
			T value = map.get(key);
			if (value != null)
				s.accept(value);
		}
	}

	/**
	 * 万能 Map 转换器,为了泛型的转换而设的一个方法,怎么转换在 fn 中处理
	 * 
	 * @param map 原始 Map,key 必须为 String 类型
	 * @param fn  转换函数
	 * @return 转换后的 map
	 */
	public static  Map as(Map map, Function fn) {
		Map _map = new HashMap<>();
		map.forEach((k, v) -> _map.put(k, v == null ? null : fn.apply(v)));

		return _map;
	}

	// --------------------------------------------------------------------------------------------------
	// -----------------------------------------------Bean-----------------------------------------------
	// --------------------------------------------------------------------------------------------------

	@FunctionalInterface
	public static interface EachFieldArg {
		public void item(String key, Object value, PropertyDescriptor property);
	}

	/**
	 * 遍历一个 Java Bean
	 * 
	 * @param bean Java Bean
	 * @param fn   执行的任务,参数有 key, value, property
	 */
	public static void eachField(Object bean, EachFieldArg fn) {
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());

			for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
				String key = property.getName();

				// 得到 property 对应的 getter 方法
				Method getter = property.getReadMethod();
				Object value = getter.invoke(bean);

				fn.item(key, value, property);
			}
		} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			LOGGER.warning(e);
		}
	}

	/**
	 * Map 转为 Bean
	 * 
	 * @param map         原始数据
	 * @param clz         实体 bean 的类
	 * @param isTransform 是否尝试转换值
	 * @return 实体 bean 对象
	 */
	public static  T map2Bean(Map map, Class clz, boolean isTransform) {
		T bean = ReflectUtil.newInstance(clz);

		eachField(bean, (key, v, property) -> {

			try {
				if (map.containsKey(key)) {
					Object value = map.get(key);

					// null 是不会传入 bean 的
					if (value != null) {
						Class t = property.getPropertyType(); // Bean 值的类型,这是期望传入的类型,也就 setter 参数的类型

						if (isTransform && t != value.getClass()) { // 类型相同,直接传入;类型不相同,开始转换
							value = MappingValue.objectCast(value, t);
						}
//						LOGGER.info("v:" + value + " type: " + value.getClass());
						property.getWriteMethod().invoke(bean, value);
					}
				}

				// 子对象
				for (String mKey : map.keySet()) {
					if (mKey.contains(key + '_')) {
						Method getter = property.getReadMethod(), setter = property.getWriteMethod();// 得到对应的 setter 方法

						Object subBean = getter.invoke(bean);
						String subBeanKey = mKey.replaceAll(key + '_', "");

						if (subBean != null) {// 已有子 bean
							if (map.get(mKey) != null) // null 值不用处理
								ReflectUtil.setProperty(subBean, subBeanKey, map.get(mKey));
						} else { // map2bean
							Map subMap = new HashMap<>();
							subMap.put(subBeanKey, map.get(mKey));
							subBean = map2Bean(subMap, setter.getParameterTypes()[0], isTransform);
							setter.invoke(bean, subBean); // 保存新建的 bean
						}
					}
				}
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				LOGGER.warning(e);
			}
		});

		return bean;
	}

	/**
	 * map 转实体
	 * 
	 * @param map 原始数据
	 * @param clz 实体 bean 的类
	 * @return 实体 bean 对象
	 */
	public static  T map2Bean(Map map, Class clz) {
		return map2Bean(map, clz, false);
	}

	/**
	 * Bean 转为 Map
	 * 
	 * @param bean 实体 bean 对象
	 * @return Map 对象
	 */
	public static  Map bean2Map(T bean) {
		Map map = new HashMap<>();

		eachField(bean, (k, v, property) -> {
			if (!k.equals("class")) // 过滤 class 属性
				map.put(k, v);
		});

		return map;
	}
	
	/**
	 * 遍历注解的配置,需要什么类,收集起来,放到一个 hash 之中, Servlet 或 Filter 通用
	 * 
	 * @param getInitParameterNames
	 * @param getValue
	 * @return Map
	 */
	public static Map emu2map(Enumeration emu, Function getValue) {
		Map map = new HashMap<>();

		while (emu.hasMoreElements()) {
			String key = emu.nextElement();
			String value = getValue.apply(key);

			map.put(key, value);
		}

		return map;
	}

	// --------------------------------------------------------------------------------------------------
	// -----------------------------------------------XML------------------------------------------------
	// --------------------------------------------------------------------------------------------------

	/**
	 *
	 * 将 Map 转换为 XML 格式的字符串
	 *
	 * @param data Map 类型数据
	 * @return XML 格式的字符串
	 */
	public static String mapToXml(Map data) {
		Document doc = XMLHelper.initBuilder().newDocument();
		Element root = doc.createElement("xml");
		doc.appendChild(root);

		data.forEach((k, v) -> {
			String value = data.get(k).toString();
			if (value == null)
				value = "";

			Element filed = doc.createElement(k);
			filed.appendChild(doc.createTextNode(value.trim()));
			root.appendChild(filed);
		});

		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");

			try (StringWriter writer = new StringWriter();) {
				transformer.transform(new DOMSource(doc), new StreamResult(writer));
				String output = writer.getBuffer().toString(); // .replaceAll("\n|\r", "");
				return output;
			}
		} catch (IOException | TransformerException | TransformerFactoryConfigurationError e) {
			LOGGER.warning(e);
		}

		return null;
	}

	/**
	 * XML 格式字符串转换为 Map
	 *
	 * @param strXML XML 字符串
	 * @return XML 数据转换后的 Map
	 */
	public static Map xmlToMap(String strXML) {
		if (strXML == null)
			return null;

		Map data = new HashMap<>();

		try (InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));) {
			Document doc = XMLHelper.initBuilder().parse(stream);
			doc.getDocumentElement().normalize();
			NodeList nodeList = doc.getDocumentElement().getChildNodes();

			for (int idx = 0; idx < nodeList.getLength(); ++idx) {
				Node node = nodeList.item(idx);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					Element element = (Element) node;
					data.put(element.getNodeName(), element.getTextContent());
				}
			}

			return data;
		} catch (IOException | SAXException e) {
			LOGGER.warning(e);
			return null;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy