/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.module.sync.ingest; import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.module.sync.SyncConstants; import org.openmrs.module.sync.SyncException; import org.openmrs.module.sync.SyncTransmission; import org.openmrs.module.sync.SyncTransmissionState; import org.openmrs.module.sync.serialization.FilePackage; import org.openmrs.module.sync.serialization.IItem; import org.openmrs.module.sync.serialization.Item; import org.openmrs.module.sync.serialization.Record; import org.openmrs.module.sync.serialization.TimestampNormalizer; import org.openmrs.module.sync.server.ConnectionResponse; import org.openmrs.module.sync.server.ServerConnectionState; import org.openmrs.util.OpenmrsUtil; /** * SyncTransmission a collection of sync records to be sent to the parent. */ public class SyncTransmissionResponse implements IItem { // consts // fields private final Log log = LogFactory.getLog(getClass()); private String fileName = null; private Date timestamp = null; private List<SyncImportRecord> syncImportRecords = null; private String uuid = null; private String fileOutput = ""; private SyncTransmissionState state; private String errorMessage; private String syncSourceUuid = null; //UUID of the node where the Tx came from private String syncTargetUuid = null; //UUID of the node where Tx is being applied to, and who is now sending a response private SyncTransmission syncTransmission = null; // constructor(s) public SyncTransmissionResponse() { } public SyncTransmission getSyncTransmission() { return syncTransmission; } public void setSyncTransmission(SyncTransmission syncTransmission) { this.syncTransmission = syncTransmission; } /* * Take passed in records and create a new sync_tx file */ public SyncTransmissionResponse(SyncTransmission transmission) { // needs to be null-safe if ( transmission != null ) { this.uuid = transmission.getUuid(); this.syncSourceUuid = transmission.getSyncSourceUuid(); this.syncTargetUuid = SyncConstants.UUID_UNKNOWN; fileName = transmission.getFileName(); int idx = fileName.lastIndexOf("."); if ( idx > -1 ) fileName = fileName.substring(0, idx) + SyncConstants.RESPONSE_SUFFIX + fileName.substring(idx); else fileName = fileName + SyncConstants.RESPONSE_SUFFIX; this.state = SyncTransmissionState.OK; // even though we really mean "OK so far" - it'll get overwritten later if there's a prob } else { this.uuid = SyncConstants.UUID_UNKNOWN; this.syncSourceUuid = SyncConstants.UUID_UNKNOWN; this.syncTargetUuid = SyncConstants.UUID_UNKNOWN; this.errorMessage = SyncConstants.ERROR_TX_NOT_UNDERSTOOD; this.fileName = SyncConstants.FILENAME_TX_NOT_UNDERSTOOD; this.state = SyncTransmissionState.TRANSMISSION_NOT_UNDERSTOOD; } } /** * @param connResponse */ public SyncTransmissionResponse(ConnectionResponse connResponse) { // this needs to be bulletproof if ( connResponse != null ) { if (log.isInfoEnabled()) log.info("RESPONSE PAYLOAD IS: " + connResponse.getResponsePayload()); if ( connResponse.getState().equals(ServerConnectionState.OK) ) { try { // this method is null safe SyncTransmissionResponse str = SyncDeserializer.xmlToSyncTransmissionResponse(connResponse.getResponsePayload()); this.errorMessage = str.getErrorMessage(); this.fileName = str.getFileName(); this.uuid = str.getUuid(); this.syncSourceUuid = str.getSyncSourceUuid(); this.syncTargetUuid = str.getSyncTargetUuid(); this.state = str.getState(); this.syncImportRecords = str.getSyncImportRecords(); this.syncTransmission = str.getSyncTransmission(); } catch (Exception e) { e.printStackTrace(); this.errorMessage = SyncConstants.ERROR_RESPONSE_NOT_UNDERSTOOD.toString(); this.fileName = SyncConstants.FILENAME_RESPONSE_NOT_UNDERSTOOD; this.uuid = SyncConstants.UUID_UNKNOWN; this.syncSourceUuid = SyncConstants.UUID_UNKNOWN; this.syncTargetUuid = SyncConstants.UUID_UNKNOWN; this.state = SyncTransmissionState.RESPONSE_NOT_UNDERSTOOD; } } else { this.errorMessage = SyncConstants.ERROR_SEND_FAILED.toString(); this.fileName = SyncConstants.FILENAME_SEND_FAILED; this.uuid = SyncConstants.UUID_UNKNOWN; this.syncSourceUuid = SyncConstants.UUID_UNKNOWN; this.syncTargetUuid = SyncConstants.UUID_UNKNOWN; this.state = SyncTransmissionState.FAILED; if ( connResponse.getState().equals(ServerConnectionState.MALFORMED_URL)) this.state = SyncTransmissionState.MALFORMED_URL; if ( connResponse.getState().equals(ServerConnectionState.CERTIFICATE_FAILED)) this.state = SyncTransmissionState.CERTIFICATE_FAILED; } } else { this.errorMessage = SyncConstants.ERROR_SEND_FAILED.toString(); this.fileName = SyncConstants.FILENAME_SEND_FAILED; this.uuid = SyncConstants.UUID_UNKNOWN; this.syncSourceUuid = SyncConstants.UUID_UNKNOWN; this.syncTargetUuid = SyncConstants.UUID_UNKNOWN; this.state = SyncTransmissionState.FAILED; } } public List<SyncImportRecord> getSyncImportRecords() { return syncImportRecords; } public void setSyncImportRecords(List<SyncImportRecord> syncImportRecords) { this.syncImportRecords = syncImportRecords; } public String getErrorMessage() { return errorMessage; } public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public String getSyncSourceUuid() { return syncSourceUuid; } public void setSyncSourceUuid(String value) { this.syncSourceUuid = value; } public String getSyncTargetUuid() { return syncTargetUuid; } public void setSyncTargetUuid(String value) { this.syncTargetUuid = value; } // methods public String getFileOutput() { return fileOutput; } public String getFileName() { return fileName; } public void setFileName(String value) { fileName = value; } public String getUuid() { return uuid; } public void setUuid(String value) { uuid = value; } public Date getTimestamp() { return timestamp; } public void setTimestamp(Date value) { timestamp = value; } /** Create a new transmission from records: use org.openmrs.serial to make a file * also, give option to write to a file or not */ public void createFile(boolean writeFile) { createFile(writeFile, SyncConstants.DIR_IMPORT); } /** Create a new transmission from records: use org.openmrs.serial to make a file * also, give option to write to a file or not */ public void createFile(boolean writeFile, String path) { if ( path == null ) path = SyncConstants.DIR_IMPORT; if ( path.length() == 0 ) path = SyncConstants.DIR_IMPORT; try { if (timestamp == null) this.timestamp = new Date(); //set timestamp of this export, if not already set FilePackage pkg = new FilePackage(); Record xml = pkg.createRecordForWrite(this.getClass().getName()); Item root = xml.getRootItem(); //serialize this.save(xml,root); //now dump to file //TODO: use path! File dir = OpenmrsUtil.getDirectoryInApplicationDataDirectory("sync"); File importdir = new File(dir, "import"); importdir.mkdir(); fileOutput = pkg.savePackage(new File(importdir, fileName), writeFile); } catch (Exception e) { log.error("Cannot create sync transmission.",e); throw new SyncException("Cannot create sync transmission", e); } return; } /** IItem.save() implementation * */ public Item save(Record xml, Item me) throws Exception { //Item me = xml.createItem(parent, this.getClass().getName()); //serialize primitives if (uuid != null) xml.setAttribute(me, "uuid", uuid); if (fileName != null) xml.setAttribute(me, "fileName", fileName); if (state != null) xml.setAttribute(me, "state", state.toString()); if (errorMessage != null ) xml.setAttribute(me, "errorMessage", errorMessage); if (syncSourceUuid != null) xml.setAttribute(me, "syncSourceUuid", syncSourceUuid); if (syncTargetUuid != null) xml.setAttribute(me, "syncTargetUuid", syncTargetUuid); if (timestamp != null) xml.setAttribute(me, "timestamp", new TimestampNormalizer().toString(timestamp)); //serialize Records list Item itemsCollection = xml.createItem(me, "records"); if (syncImportRecords != null) { me.setAttribute("itemCount", Integer.toString(syncImportRecords.size())); for ( SyncImportRecord importRecord : syncImportRecords ) { importRecord.save(xml, itemsCollection); } } Item syncTx = xml.createItem(me, "syncTransmission"); if (syncTransmission != null) { syncTransmission.save(xml, syncTx); } return me; } /** IItem.load() implementation * */ public void load(Record xml, Item me) throws Exception { this.uuid = me.getAttribute("uuid"); this.fileName = me.getAttribute("fileName"); this.syncSourceUuid = me.getAttribute("syncSourceUuid"); this.syncTargetUuid = me.getAttribute("syncTargetUuid"); if (me.getAttribute("timestamp") == null) this.timestamp = null; else this.timestamp = (Date)new TimestampNormalizer().fromString(Date.class,me.getAttribute("timestamp")); try { this.state = SyncTransmissionState.valueOf(me.getAttribute("state")); } catch ( Exception e ) { log.info("STATE IS [" + me.getAttribute("state") + "], defaulting to RESPONSE_NOT_UNDERSTOOD", e); this.state = SyncTransmissionState.RESPONSE_NOT_UNDERSTOOD; } this.errorMessage = me.getAttribute("errorMessage"); //now get items Item itemsCollection = xml.getItem(me, "records"); if (itemsCollection.isEmpty()) { this.syncImportRecords = null; } else { this.syncImportRecords = new ArrayList<SyncImportRecord>(); List<Item> serItems = xml.getItems(itemsCollection); for (int i = 0; i < serItems.size(); i++) { Item serItem = serItems.get(i); SyncImportRecord syncImportRecord = new SyncImportRecord(); syncImportRecord.load(xml, serItem); this.syncImportRecords.add(syncImportRecord); } } Item syncTx = xml.getItem(me, "syncTransmission"); if ( syncTx.isEmpty() ) { this.syncTransmission = null; } else { this.syncTransmission = new SyncTransmission(); this.syncTransmission.load(xml, syncTx); } } public SyncTransmissionState getState() { return state; } public void setState(SyncTransmissionState state) { this.state = state; } }