package com.constellio.data.dao.services.transactionLog.writer1; import static com.constellio.data.dao.services.solr.DateUtils.correctDate; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.solr.common.SolrDocumentBase; import org.apache.solr.common.SolrInputDocument; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import com.constellio.data.dao.services.bigVault.solr.BigVaultServerTransaction; import com.constellio.data.extensions.DataLayerSystemExtensions; public class TransactionWriterV1 { boolean writeZZRecords; DataLayerSystemExtensions extensions; public TransactionWriterV1(boolean writeZZRecords, DataLayerSystemExtensions extensions) { this.extensions = extensions; this.writeZZRecords = writeZZRecords; } public String toSetSequenceLogEntry(String sequenceId, long value) { StringBuilder stringBuilder = new StringBuilder("--transaction--\n"); stringBuilder.append("sequence set " + sequenceId + "=" + value + "\n"); return stringBuilder.toString(); } public String toNextSequenceLogEntry(String sequenceId) { StringBuilder stringBuilder = new StringBuilder("--transaction--\n"); stringBuilder.append("sequence next " + sequenceId + "\n"); return stringBuilder.toString(); } public String toLogEntry(BigVaultServerTransaction transaction) { StringBuilder stringBuilder = new StringBuilder("--transaction--\n"); for (SolrInputDocument solrDocument : transaction.getNewDocuments()) { String id = (String) solrDocument.getFieldValue("id"); if (isLogged(id)) { appendAddUpdateSolrDocument(stringBuilder, solrDocument); } } for (SolrInputDocument solrDocument : transaction.getUpdatedDocuments()) { String id = (String) solrDocument.getFieldValue("id"); if (isLogged(id)) { appendAddUpdateSolrDocument(stringBuilder, solrDocument); } } List<String> deletedIds = new ArrayList<>(); for (String id : transaction.getDeletedRecords()) { if (isLogged(id)) { deletedIds.add(id); } } appendDeletedRecords(stringBuilder, deletedIds); for (String deletedByQuery : transaction.getDeletedQueries()) { appendDeletedByQuery(stringBuilder, deletedByQuery); } return stringBuilder.toString(); } private void appendDeletedRecords(StringBuilder stringBuilder, List<String> deletedDocumentIds) { if (!deletedDocumentIds.isEmpty()) { stringBuilder.append("delete"); for (String deletedDocumentId : deletedDocumentIds) { stringBuilder.append(" "); stringBuilder.append(deletedDocumentId); } stringBuilder.append("\n"); } } protected void appendAddUpdateSolrDocument(StringBuilder stringBuilder, SolrDocumentBase document) { String id = (String) document.getFieldValue("id"); Object version = document.getFieldValue("_version_"); String schema_s; Object schema = document.getFieldValue("schema_s"); if (schema instanceof String) { schema_s = (String) schema; } else if (schema instanceof Map) { schema_s = (String) ((Map) schema).values().iterator().next(); } else { schema_s = null; //throw new ImpossibleRuntimeException("Invalid schema of type"); } String collection_s = (String) document.getFieldValue("collection_s"); stringBuilder.append("addUpdate "); stringBuilder.append(id); stringBuilder.append(" "); stringBuilder.append(version == null ? "-1" : version); stringBuilder.append("\n"); Collection<String> fieldNames = document.getFieldNames(); for (String name : fieldNames) { if (!name.equals("id") && !name.equals("_version_") && isLogged(name, schema_s, collection_s)) { Collection<Object> value = removeEmptyStrings(document.getFieldValues(name)); if (value.isEmpty()) { appendValue(stringBuilder, name, ""); } else { for (Object item : value) { String fieldLogName = name; if (item instanceof Map) { Map<String, Object> mapItemValue = ((Map<String, Object>) item); String firstKey = mapItemValue.keySet().iterator().next(); Object mapValue = mapItemValue.get(firstKey); fieldLogName = firstKey + " " + name; if (mapValue instanceof Collection) { Collection<Object> mapValueList = removeEmptyStrings((Collection) mapValue); if (mapValueList.isEmpty()) { appendValue(stringBuilder, fieldLogName, ""); } else { for (Object mapValueListItem : mapValueList) { appendValue(stringBuilder, fieldLogName, mapValueListItem); } } } else { appendValue(stringBuilder, fieldLogName, mapValue); } } else { appendValue(stringBuilder, fieldLogName, item); } } } } } } private boolean isLogged(String name, String schema, String collection) { boolean defaultValue = !name.endsWith("content_txt_fr") && !name.endsWith("content_txt_en") && !name.endsWith("contents_txt_fr") && !name .endsWith("contents_txt_en"); return extensions.isDocumentFieldLoggedInTransactionLog(name, schema, collection, defaultValue); } private Collection<Object> removeEmptyStrings(Collection collection) { if (collection.contains("")) { List<Object> values = new ArrayList<>(); for (Object item : collection) { if (!"".equals(item)) { values.add(item); } } return values; } else { return collection; } } private void appendValue(StringBuilder stringBuilder, String fieldLogName, Object item) { //if (!"".equals(item)) { String correctedValue = correct(item); if (correctedValue != null) { stringBuilder.append(fieldLogName); stringBuilder.append("="); stringBuilder.append(correctedValue); stringBuilder.append("\n"); } //} } private boolean isLogged(String id) { return writeZZRecords || !id.endsWith("ZZ"); } protected void appendDeletedByQuery(StringBuilder stringBuilder, String deletedByQuery) { stringBuilder.append("deletequery " + deletedByQuery + "\n"); } private Pattern lineFeedPattern = Pattern.compile("\n", Pattern.LITERAL); private Pattern zPattern = Pattern.compile("Z", Pattern.LITERAL); private String correct(Object value) { if (value == null || "null".equals(value)) { return ""; } else if (value instanceof Date) { LocalDateTime dateTime = new LocalDateTime(value); return zPattern.matcher(correctDate(dateTime).toString()).replaceAll(Matcher.quoteReplacement("")) + "Z"; } else if (value instanceof LocalDateTime || value instanceof LocalDate) { return zPattern.matcher(value.toString()).replaceAll(Matcher.quoteReplacement("")) + "Z"; } else { return lineFeedPattern.matcher(value.toString()).replaceAll(Matcher.quoteReplacement("__LINEBREAK__")); } } }