package com.constellio.app.services.importExport.records.writers;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Map;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import com.constellio.app.services.schemas.bulkImport.data.ImportDataOptions;
import com.constellio.data.utils.ImpossibleRuntimeException;
import com.constellio.data.utils.LangUtils;
import com.sun.xml.txw2.output.IndentingXMLStreamWriter;
import org.joda.time.LocalDateTime;
public class ImportRecordOfSameTypeWriter {
IndentingXMLStreamWriter writer;
OutputStream outputStream;
boolean tooLateToWriteOptions;
public ImportRecordOfSameTypeWriter(File outputFile) {
try {
outputFile.delete();
XMLOutputFactory factory = XMLOutputFactory.newInstance();
outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
XMLStreamWriter defaultWriter = factory.createXMLStreamWriter(outputStream, "UTF-8");
writer = new IndentingXMLStreamWriter(defaultWriter);
writer.setIndentStep(" ");
writer.writeStartDocument("UTF-8", "1.0");
writer.writeStartElement("records");
writer.writeAttribute("datePattern", "yyyy-MM-dd");
writer.writeAttribute("datetimePattern", "yyyy-MM-dd HH:mm:ss");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void write(ModifiableImportRecord importRecord) {
tooLateToWriteOptions = true;
try {
writer.writeStartElement("record");
writer.writeAttribute("id", importRecord.getPreviousSystemId());
if (StringUtils.isNotBlank(importRecord.getSchema())) {
writer.writeAttribute("schema", importRecord.getSchema());
}
for (Map.Entry<String, Object> importRecordMetadata : importRecord.getFields().entrySet()) {
Object value = importRecordMetadata.getValue();
if (value != null) {
if (value instanceof Collection) {
Collection collectionValue = LangUtils.withoutNulls((Collection) value);
if (!collectionValue.isEmpty()) {
writer.writeStartElement(importRecordMetadata.getKey());
writer.writeAttribute("multivalue", "true");
String type = null;
for (Object item : collectionValue) {
if (item instanceof Map) {
type = "structure";
} else if (item instanceof LocalDate) {
type = "date";
} else if (item instanceof LocalDateTime) {
type = "datetime";
}
}
if (type != null) {
writer.writeAttribute("type", type);
}
for (Object item : collectionValue) {
if (item != null) {
writer.writeStartElement("item");
if ("date".equals(type)) {
writeValue(((LocalDate) item).toString("yyyy-MM-dd"));
} else if ("datetime".equals(type)) {
writeValue(((LocalDateTime) item).toString("yyyy-MM-dd HH:mm:ss"));
} else {
writeValue(item);
}
writer.writeEndElement();
}
}
writer.writeEndElement();
}
} else if (value instanceof LocalDate) {
writer.writeStartElement(importRecordMetadata.getKey());
writer.writeAttribute("type", "date");
writer.writeCharacters(value.toString());
writer.writeEndElement();
} else if (value instanceof LocalDateTime) {
writer.writeStartElement(importRecordMetadata.getKey());
writer.writeAttribute("type", "datetime");
writer.writeCharacters(((LocalDateTime) value).toString("yyyy-MM-dd HH:mm:ss"));
writer.writeEndElement();
} else if (value instanceof ImportContent) {
writer.writeStartElement(importRecordMetadata.getKey());
writer.writeAttribute("type", "content");
writeValue(value);
writer.writeEndElement();
} else {
writer.writeStartElement(importRecordMetadata.getKey());
writeValue(value);
writer.writeEndElement();
}
}
}
writer.writeEndElement();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void writeValue(Object value)
throws XMLStreamException {
if (value instanceof String) {
writer.writeCharacters((String) value);
}
if (value instanceof Map) {
Map<String, Object> mapValue = (Map<String, Object>) value;
for (Map.Entry<String, Object> entry : mapValue.entrySet()) {
if (entry.getValue() != null && entry.getValue() instanceof String) {
writer.writeAttribute(entry.getKey(), (String) entry.getValue());
} else if (entry.getValue() != null && entry.getValue() instanceof Collection) {
String valueToWrite = "";
for (Object collectionElement : (Collection) entry.getValue()) {
valueToWrite += collectionElement + ",";
}
if (StringUtils.isNotBlank(valueToWrite)) {
writer.writeAttribute(entry.getKey(), valueToWrite.substring(0, valueToWrite.length() - 1));
}
}
}
}
if (value instanceof ImportContent) {
for (ImportContentVersion version : ((ImportContent) value).getVersions()) {
writer.writeStartElement("contentVersion");
writer.writeAttribute("url", version.getUrl());
writer.writeAttribute("filename", version.getFileName());
writer.writeAttribute("major", String.valueOf(version.isMajor()));
writer.writeEndElement();
}
}
}
public void close() {
try {
writer.writeEndElement();
writer.writeEndDocument();
writer.flush();
writer.close();
outputStream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void write(ImportDataOptions options) {
if (tooLateToWriteOptions) {
throw new ImpossibleRuntimeException("Too late to write options");
}
try {
if (!options.isImportAsLegacyId()) {
writer.writeAttribute("importAsLegacyId", "false");
}
if (options.isMergeExistingRecordWithSameUniqueMetadata()) {
writer.writeAttribute("mergeExistingRecordWithSameUniqueMetadata", "true");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}