/**
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* 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.
*
* The Original Code is OpenELIS code.
*
* Copyright (C) ITECH, University of Washington, Seattle WA. All Rights Reserved.
*
*/
package us.mn.state.health.lims.common.services.historyservices;
import org.apache.commons.validator.GenericValidator;
import us.mn.state.health.lims.audittrail.action.workers.AuditTrailItem;
import us.mn.state.health.lims.audittrail.dao.AuditTrailDAO;
import us.mn.state.health.lims.audittrail.daoimpl.AuditTrailDAOImpl;
import us.mn.state.health.lims.audittrail.valueholder.History;
import us.mn.state.health.lims.common.services.StatusService;
import us.mn.state.health.lims.common.services.TypeOfTestResultService;
import us.mn.state.health.lims.common.util.DateUtil;
import us.mn.state.health.lims.common.util.StringUtil;
import us.mn.state.health.lims.dictionary.dao.DictionaryDAO;
import us.mn.state.health.lims.dictionary.daoimpl.DictionaryDAOImpl;
import us.mn.state.health.lims.dictionary.valueholder.Dictionary;
import us.mn.state.health.lims.result.valueholder.Result;
import us.mn.state.health.lims.systemuser.dao.SystemUserDAO;
import us.mn.state.health.lims.systemuser.daoimpl.SystemUserDAOImpl;
import us.mn.state.health.lims.systemuser.valueholder.SystemUser;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
public abstract class HistoryService {
protected static final String STATUS_ATTRIBUTE = "status";
protected static final String VALUE_ATTRIBUTE = "value";
protected static AuditTrailDAO auditTrailDAO = new AuditTrailDAOImpl();
private static SystemUserDAO userDAO = new SystemUserDAOImpl();
protected static DictionaryDAO dictDAO = new DictionaryDAOImpl();
protected Map<String, String> attributeToIdentifierMap;
protected List<History> historyList;
protected String identifier = "";
protected Map<String, String> newValueMap;
protected HistoryService() {
}
protected abstract void addInsertion(History history, List<AuditTrailItem> items);
protected abstract String getObjectName();
protected abstract void getObservableChanges(History history, Map<String, String> changeMap, String changes);
// should be overridden if needed
protected boolean showAttribute() {
return false;
}
private void reverseSortByTime(List<History> list) {
Collections.sort(list, new Comparator<History>() {
@Override
public int compare(History o1, History o2) {
return o2.getTimestamp().compareTo(o1.getTimestamp());
}
});
}
public List<AuditTrailItem> getAuditTrailItems() {
reverseSortByTime(historyList);
List<AuditTrailItem> items = new ArrayList<AuditTrailItem>();
for (History history : historyList) {
try {
if ("U".equals(history.getActivity()) || "D".equals(history.getActivity())) {
Map<String, String> changeMaps = getChangeMap(history);
if (!changeMaps.isEmpty()) {
addItemsForKeys(items, history, changeMaps);
}
} else {
addInsertion(history, items);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return items;
}
protected void addItemsForKeys(List<AuditTrailItem> items, History history, Map<String, String> changeMaps) {
for (String key : changeMaps.keySet()) {
setIdentifierForKey(key);
AuditTrailItem item = getCoreTrail(history);
item.setAttribute(showAttribute() && !GenericValidator.isBlankOrNull( key ) ? key : StringUtil.getMessageForKey( "auditTrail.action.update" ));
item.setOldValue(changeMaps.get(key));
item.setNewValue(newValueMap.get(key));
newValueMap.put(key, item.getOldValue());
if (item.newOldDiffer()) {
items.add(item);
}
}
}
protected void setAndAddIfValueNotNull(List<AuditTrailItem> items, History history, String attribute) {
String value = newValueMap.get(attribute);
if (!GenericValidator.isBlankOrNull(value)) {
setIdentifierForKey(attribute);
AuditTrailItem item;
item = getCoreTrail(history);
item.setNewValue(value);
items.add(item);
newValueMap.remove(attribute);
}
}
protected void setIdentifierForKey(String key) {
if (attributeToIdentifierMap != null && attributeToIdentifierMap.get(key) != null) {
identifier = attributeToIdentifierMap.get(key);
}
}
protected AuditTrailItem getCoreTrail(History history) {
AuditTrailItem ati = new AuditTrailItem();
ati.setTimeStamp(history.getTimestamp());
ati.setDate(DateUtil.convertTimestampToStringDate(history.getTimestamp()));
ati.setTime(DateUtil.convertTimestampToStringTime(history.getTimestamp()));
ati.setAction(history.getActivity());
ati.setUser(getUserName(history));
ati.setItem(getObjectName());
ati.setIdentifier(identifier);
return ati;
}
private Map<String, String> getChangeMap(History history) throws SQLException, IOException {
Map<String, String> changeMap = new HashMap<String, String>();
//System.out.println( history.getId() + " : " + history.getActivity() );
if ("U".equals(history.getActivity()) || "D".equals(history.getActivity())) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
byte[] bindata = new byte[1024];
int bytesread;
BufferedInputStream bis = new BufferedInputStream(history.getChanges().getBinaryStream());
if ((bytesread = bis.read(bindata, 0, bindata.length)) != -1) {
baos.write(bindata, 0, bytesread);
}
String changes = baos.toString();
// System.out.println(history.getActivity() + " : "+ changes);
getObservableChanges(history, changeMap, changes);
}
return changeMap;
}
protected void simpleChange(Map<String, String> changeMap, String changesString, String attribute) {
String value = extractSimple(changesString, attribute);
if (value != null) {
changeMap.put(attribute, value);
}
}
protected String extractSimple(String changes, String attribute) {
String startTag = "<" + attribute + ">";
int begin = changes.indexOf(startTag);
if (begin > -1) {
begin += startTag.length();
int end = changes.indexOf("</" + attribute + ">");
return changes.substring(begin, end);
}
return null;
}
protected String extractStatus(String changes) {
String statusId = extractSimple(changes, "statusId");
return statusId == null ? null : StatusService.getInstance().getStatusNameFromId(statusId);
}
protected String getViewableValue(String value, Result result) {
if ( TypeOfTestResultService.ResultType.isDictionaryVariant(result.getResultType()) && !GenericValidator.isBlankOrNull(value) && org.apache.commons.lang.StringUtils.isNumeric(value)) {
Dictionary dictionaryValue = dictDAO.getDictionaryById(value);
value = dictionaryValue != null ? dictionaryValue.getDictEntry() : StringUtil.getMessageForKey("result.undefined");
}
return value;
}
private String getUserName(History history) {
SystemUser user = userDAO.getUserById(history.getSysUserId());
return user.getDisplayName();
}
}