package net.rrm.ehour.backup.service.backup;
import com.google.common.collect.Maps;
import net.rrm.ehour.backup.common.BackupConfig;
import net.rrm.ehour.backup.common.BackupEntityType;
import net.rrm.ehour.backup.common.BackupJoinTable;
import net.rrm.ehour.backup.domain.ExportElements;
import net.rrm.ehour.config.EhourConfigStub;
import net.rrm.ehour.config.service.ConfigurationService;
import net.rrm.ehour.domain.Configuration;
import net.rrm.ehour.persistence.backup.dao.BackupDao;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author thies
*/
@Service("databaseBackupService")
public class DatabaseBackupServiceImpl implements DatabaseBackupService {
private static final Logger LOGGER = Logger.getLogger(DatabaseBackupServiceImpl.class);
private BackupDao backupDao;
private ConfigurationService configurationService;
private BackupConfig backupConfig;
@Autowired
public DatabaseBackupServiceImpl(BackupDao backupDao, ConfigurationService configurationService, BackupConfig backupConfig) {
this.backupDao = backupDao;
this.configurationService = configurationService;
this.backupConfig = backupConfig;
}
@Override
public synchronized byte[] exportDatabase() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
XMLStreamWriter writer = null;
try {
writer = createXmlWriter(outputStream);
exportDatabase(writer);
return outputStream.toByteArray();
} catch (XMLStreamException e) {
LOGGER.error(e);
return new byte[0];
} finally {
if (writer != null) {
try {
writer.close();
} catch (XMLStreamException e) {
}
}
}
}
protected XMLStreamWriter createXmlWriter(OutputStream stream) throws XMLStreamException {
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(stream, "UTF-8");
PrettyPrintHandler handler = new PrettyPrintHandler(writer);
return (XMLStreamWriter) Proxy.newProxyInstance(
XMLStreamWriter.class.getClassLoader(),
new Class[]{XMLStreamWriter.class},
handler);
}
private void exportDatabase(XMLStreamWriter writer) throws XMLStreamException {
writer.writeStartDocument("UTF-8", "1.0");
EhourConfigStub stub = configurationService.getConfiguration();
writer.writeStartElement(ExportElements.EHOUR.name());
writer.writeAttribute(ExportElements.DB_VERSION.name(), stub.getVersion());
backupConfiguration(writer);
writer.writeStartElement(ExportElements.JOIN_TABLES.name());
backupJoinTables(writer);
writer.writeEndElement();
writer.writeStartElement(ExportElements.ENTITY_TABLES.name());
backupEntities(writer);
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
}
private void backupConfiguration(XMLStreamWriter writer) throws XMLStreamException {
writer.writeStartElement(ExportElements.CONFIGURATION.name());
List<Configuration> configurationList = configurationService.findAllConfiguration();
for (Configuration configuration : configurationList) {
writer.writeStartElement(ExportElements.CONFIG.name());
writer.writeAttribute(ExportElements.KEY.name(), configuration.getConfigKey());
writer.writeCharacters(configuration.getConfigValue());
writer.writeEndElement();
}
writer.writeEndElement();
}
private void backupJoinTables(XMLStreamWriter writer) throws XMLStreamException {
List<BackupJoinTable> joinTables = backupConfig.joinTables();
for (BackupJoinTable joinTable : joinTables) {
String container = joinTable.getContainer();
writer.writeStartElement(container);
String tableName = joinTable.getTableName();
List<Map<String, Object>> rows = backupDao.findAll(tableName);
for (Map<String, Object> row : rows) {
Map<String, Object> uppercaseRowMap = Maps.newHashMap();
for (Entry<String, Object> s : row.entrySet()) {
uppercaseRowMap.put(s.getKey().toUpperCase(), s.getValue());
}
writer.writeStartElement(tableName);
Object source = uppercaseRowMap.get(joinTable.getAttributeSource().toUpperCase());
Object target = uppercaseRowMap.get(joinTable.getAttributeTarget().toUpperCase());
writer.writeAttribute(joinTable.getAttributeSource().toUpperCase(), source.toString());
writer.writeAttribute(joinTable.getAttributeTarget().toUpperCase(), target.toString());
writer.writeEndElement();
}
writer.writeEndElement();
}
}
private void backupEntities(XMLStreamWriter writer) throws XMLStreamException {
for (BackupEntityType type : backupConfig.backupEntities()) {
backupType(type, writer);
}
}
private void backupType(BackupEntityType entity, XMLStreamWriter writer) throws XMLStreamException {
writer.writeStartElement(entity.getParentName());
if (entity.getDomainObjectClass() != null) {
writer.writeAttribute("CLASS", entity.getDomainObjectClass().getName());
}
List<Map<String, Object>> rows = backupDao.findAll(entity.name());
if (entity.getProcessor() != null) {
rows = entity.getProcessor().processRows(rows);
}
for (Map<String, Object> rowMap : rows) {
writer.writeStartElement(entity.name());
for (Entry<String, Object> columns : rowMap.entrySet()) {
if (StringUtils.isNotBlank(columns.getKey()) && columns.getValue() != null) {
writer.writeStartElement(columns.getKey());
writer.writeCharacters(columns.getValue().toString());
writer.writeEndElement();
}
}
writer.writeEndElement();
}
writer.writeEndElement();
}
}