RefactorInsight-master/plugin/src/main/java/org/jetbrains/research/refactorinsight/services/RefactoringsMapConverter.java
package org.jetbrains.research.refactorinsight.services;

import com.intellij.util.xmlb.Converter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.research.refactorinsight.data.RefactoringEntry;

import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import static org.jetbrains.research.refactorinsight.utils.StringUtils.*;

/**
 * RefactoringsMap converter that serializes and deserializes data.
 * Converts the data in the .xml to a RefactoringMap object.
 * Converts a RefactoringMap object into a string that can be stored in refactorings.xml.
 */
public class RefactoringsMapConverter extends Converter<RefactoringsMap> {

    /**
     * Deserializes the data in the .idea/refactorings.xml into a refactorings
     * map an object.
     *
     * @param value to be converted
     * @return a refactoring map
     */
    public RefactoringsMap fromString(@NotNull String value) {
        try {
            String regex1 = delimiter(MAP, true);
            String regex2 = delimiter(MAP_ENTRY, true);
            String[] tokens = value.split(regex1, 3);
            String version = tokens[0];
            String projectPath = tokens[1];
            if (!projectPath.contains(delimiter(MAP_ENTRY, false))) { // ignore the serialized map generated by earlier version
                ConcurrentMap<String, RefactoringEntry> map = Arrays.stream(tokens[2].split(regex1))
                        .map(entry -> entry.split(regex2))
                        .collect(Collectors.toConcurrentMap(entry -> entry[0],
                                entry -> RefactoringEntry.fromString(entry[1], entry[0])));
                map.values().forEach(entry -> entry.getRefactorings().forEach(ref -> ref.setProjectPath(projectPath)));
                return new RefactoringsMap(map, version);
            }
        } catch (Exception e) {
            // pass
        }

        return new RefactoringsMap(new ConcurrentHashMap<>(), "-1");
    }

    /**
     * Converts a RefactoringMap object into a string that can be stored
     * in the .idea/refactorings.xml file.
     *
     * @param value map to be converted
     * @return a string representation of the refactorings map
     */
    public String toString(RefactoringsMap value) {
        String projectPath = "";
        for (RefactoringEntry entry : value.map.values()) {
            if (!entry.getRefactorings().isEmpty()) {
                projectPath = entry.getRefactorings().get(0).getProjectPath();
                break;
            }
        }
        return value.version + delimiter(MAP)
                + projectPath + delimiter(MAP)
                + value.map.entrySet().stream()
                .map(entry -> entry.getKey() + delimiter(MAP_ENTRY) + entry.getValue().toString())
                .collect(Collectors.joining(delimiter(MAP)));
    }

}