package org.jabref.logic.exporter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.jabref.logic.util.OS; import org.jabref.model.bibtexkeypattern.AbstractBibtexKeyPattern; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.cleanup.FieldFormatterCleanups; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.metadata.ContentSelector; import org.jabref.model.metadata.MetaData; import org.jabref.model.strings.StringUtil; public class MetaDataSerializer { private MetaDataSerializer() { } /** * Writes all data in the format <key, serialized data>. */ public static Map<String, String> getSerializedStringMap(MetaData metaData, GlobalBibtexKeyPattern globalCiteKeyPattern) { // First write all meta data except groups Map<String, List<String>> stringyMetaData = new HashMap<>(); metaData.getSaveOrderConfig().ifPresent( saveOrderConfig -> stringyMetaData.put(MetaData.SAVE_ORDER_CONFIG, saveOrderConfig.getAsStringList())); metaData.getSaveActions().ifPresent( saveActions -> stringyMetaData.put(MetaData.SAVE_ACTIONS, saveActions.getAsStringList(OS.NEWLINE))); if (metaData.isProtected()) { stringyMetaData.put(MetaData.PROTECTED_FLAG_META, Collections.singletonList("true")); } stringyMetaData.putAll(serializeCiteKeyPattern(metaData, globalCiteKeyPattern)); metaData.getMode().ifPresent( mode -> stringyMetaData.put(MetaData.DATABASE_TYPE, Collections.singletonList(mode.getAsString()))); metaData.getDefaultFileDirectory().ifPresent( path -> stringyMetaData.put(MetaData.FILE_DIRECTORY, Collections.singletonList(path.trim()))); metaData.getUserFileDirectories().forEach((user, path) -> stringyMetaData .put(MetaData.FILE_DIRECTORY + '-' + user, Collections.singletonList(path.trim()))); for (ContentSelector selector: metaData.getContentSelectorList()) { stringyMetaData.put(MetaData.SELECTOR_META_PREFIX + selector.getFieldName(), selector.getValues()); } Map<String, String> serializedMetaData = serializeMetaData(stringyMetaData); // Write groups if present. // Skip this if only the root node exists (which is always the AllEntriesGroup). metaData.getGroups().filter(root -> root.getNumberOfChildren() > 0).ifPresent( root -> serializedMetaData.put(MetaData.GROUPSTREE, serializeGroups(root))); // finally add all unknown meta data items to the serialization map Map<String, List<String>> unknownMetaData = metaData.getUnknownMetaData(); for (Map.Entry<String, List<String>> entry : unknownMetaData.entrySet()) { StringBuilder value = new StringBuilder(); value.append(OS.NEWLINE); for (String line: entry.getValue()) { value.append(line.replaceAll(";", "\\\\;") + MetaData.SEPARATOR_STRING + OS.NEWLINE); } serializedMetaData.put(entry.getKey(), value.toString()); } return serializedMetaData; } private static Map<String, String> serializeMetaData(Map<String, List<String>> stringyMetaData) { Map<String, String> serializedMetaData = new TreeMap<>(); for (Map.Entry<String, List<String>> metaItem : stringyMetaData.entrySet()) { StringBuilder stringBuilder = new StringBuilder(); for (String dataItem : metaItem.getValue()) { stringBuilder.append(StringUtil.quote(dataItem, MetaData.SEPARATOR_STRING, MetaData.ESCAPE_CHARACTER)).append(MetaData.SEPARATOR_STRING); //in case of save actions, add an additional newline after the enabled flag if (metaItem.getKey().equals(MetaData.SAVE_ACTIONS) && (FieldFormatterCleanups.ENABLED.equals(dataItem) || FieldFormatterCleanups.DISABLED.equals(dataItem))) { stringBuilder.append(OS.NEWLINE); } } String serializedItem = stringBuilder.toString(); // Only add non-empty values if (!serializedItem.isEmpty() && !MetaData.SEPARATOR_STRING.equals(serializedItem)) { serializedMetaData.put(metaItem.getKey(), serializedItem); } } return serializedMetaData; } private static Map<String, List<String>> serializeCiteKeyPattern(MetaData metaData, GlobalBibtexKeyPattern globalCiteKeyPattern) { Map<String, List<String>> stringyPattern = new HashMap<>(); AbstractBibtexKeyPattern citeKeyPattern = metaData.getCiteKeyPattern(globalCiteKeyPattern); for (String key : citeKeyPattern.getAllKeys()) { if (!citeKeyPattern.isDefaultValue(key)) { List<String> data = new ArrayList<>(); data.add(citeKeyPattern.getValue(key).get(0)); String metaDataKey = MetaData.PREFIX_KEYPATTERN + key; stringyPattern.put(metaDataKey, data); } } if ((citeKeyPattern.getDefaultValue() != null) && !citeKeyPattern.getDefaultValue().isEmpty()) { List<String> data = new ArrayList<>(); data.add(citeKeyPattern.getDefaultValue().get(0)); stringyPattern.put(MetaData.KEYPATTERNDEFAULT, data); } return stringyPattern; } private static String serializeGroups(GroupTreeNode root) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(OS.NEWLINE); for (String groupNode : new GroupSerializer().serializeTree(root)) { stringBuilder.append(StringUtil.quote(groupNode, MetaData.SEPARATOR_STRING, MetaData.ESCAPE_CHARACTER)); stringBuilder.append(MetaData.SEPARATOR_STRING); stringBuilder.append(OS.NEWLINE); } return stringBuilder.toString(); } }