package rocks.inspectit.shared.all.jpa; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.persistence.AttributeConverter; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; /** * {@link AttributeConverter} that can convert Map to a String value so it can be saved in a single * column in DB. * * @author Ivan Senic * */ public class MapStringConverter implements AttributeConverter<Map<?, ?>, String> { /** * Delimiter for key and value pairs. */ private static final char DELIMITER = '¦'; /** * {@inheritDoc} * <p> * Transforms map to a string. */ @Override public String convertToDatabaseColumn(Map<?, ?> map) { StringBuilder stringBuilder = new StringBuilder(); if (MapUtils.isNotEmpty(map)) { for (Map.Entry<?, ?> entry : map.entrySet()) { stringBuilder.append(entry.getKey().toString()); stringBuilder.append(DELIMITER); stringBuilder.append(entry.getValue()); stringBuilder.append(DELIMITER); } } return stringBuilder.toString(); } /** * {@inheritDoc} * <p> * Creates map out of the string. */ @Override public Map<?, ?> convertToEntityAttribute(String dbValue) { if (StringUtils.isNotEmpty(dbValue)) { Map<Object, Object> map = new HashMap<Object, Object>(); String[] split = StringUtils.splitPreserveAllTokens(dbValue, DELIMITER); // in order to support empty strings we add delimiter after each object (line 36/38) // as of splitPerserve will add additional object at the end that we don't want // thus iterate until i < length - 1 for (int i = 0; i < (split.length - 1); i += 2) { map.put(split[i], split[i + 1]); } return map; } else { return Collections.emptyMap(); } } }