package se.cambio.cds.controller.guide;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import se.cambio.cds.gdl.model.Guide;
import se.cambio.cds.model.facade.execution.vo.ExecutionMode;
import se.cambio.cds.model.instance.ArchetypeReference;
import se.cambio.cds.model.instance.ElementInstance;
import se.cambio.cds.util.Domains;
import se.cambio.cds.util.ElementInstanceCollection;
import se.cambio.cds.util.GeneratedElementInstanceCollection;
import se.cambio.cm.model.guide.dto.GuideDTO;
import se.cambio.openehr.util.ExceptionHandler;
import se.cambio.openehr.util.exceptions.InternalErrorException;
import java.util.*;
public class SimpleGuideManager {
private Map<String, Guide> _allGuidesMap = null;
private Map<String, ElementInstanceCollection> _elementInstanceCollectionByIdGuideMap = null;
private GeneratedElementInstanceCollection _completeElementInstanceCollection = null;
private Map<String, Set<String>> _guideIdsByElementIdsMap = null;
public SimpleGuideManager(Collection<Guide> guides){
init();
try{
loadGuides(guides);
}catch(InternalErrorException e){
ExceptionHandler.handle(e);
}
}
public String getId(){
return generateId(_allGuidesMap.keySet());
}
public static String generateId(Collection<String> guideIds) {
List<String> guideIdsAux = new ArrayList<String>(guideIds);
Collections.sort(guideIdsAux);
return StringUtils.join(guideIdsAux, ",");
}
private void init(){
_allGuidesMap = new HashMap<String, Guide>();
_elementInstanceCollectionByIdGuideMap = new HashMap<String, ElementInstanceCollection>();
_completeElementInstanceCollection = new GeneratedElementInstanceCollection();
_guideIdsByElementIdsMap = new HashMap<String, Set<String>>();
}
public void loadGuides(Collection<Guide> guides) throws InternalErrorException{
for (Guide guide : guides) {
GeneratedElementInstanceCollection gei = proccessGuide(guide);
_completeElementInstanceCollection.merge(gei);
}
}
private GeneratedElementInstanceCollection proccessGuide(Guide guide) throws InternalErrorException{
GeneratedElementInstanceCollection elementInstanceCollection = new GeneratedElementInstanceCollection();
GuideUtil.fillElementInstanceCollection(guide, elementInstanceCollection);
_allGuidesMap.put(guide.getId(), guide);
_elementInstanceCollectionByIdGuideMap.put(guide.getId(), elementInstanceCollection);
return elementInstanceCollection;
}
public Collection<String> getGuideIds(ExecutionMode executionMode, ElementInstanceCollection elementInstancesCollection)
throws InternalErrorException {
Collection<String> guideIds = null;
if (executionMode.equals(ExecutionMode.STRICT_BY_CONTEXT)){
guideIds = getGuideIdsStrict(elementInstancesCollection);
}else if (executionMode.equals(ExecutionMode.CHAINED_BY_CONTEXT)){
guideIds = getGuideIdsNormal(elementInstancesCollection);
}else{
guideIds = getAllGuideIds();
}
return guideIds;
}
public Collection<ElementInstance> getElementInstances(String idGuide){
ElementInstanceCollection eic = _elementInstanceCollectionByIdGuideMap.get(idGuide);
if (eic==null){
Logger.getLogger(SimpleGuideManager.class).warn("Guide id '"+idGuide+"' not found!");
return new ArrayList<ElementInstance>();
}else{
return eic.getAllElementInstances();
}
}
public Collection<String> getGuideIdsStrict(ElementInstanceCollection elementInstancesCollection){
Set<String> guideIds = new HashSet<String>();
//Get all idElements
Set<String> idElementsEHR = elementInstancesCollection.getElementIdsByIdDomain(Domains.EHR_ID);
for (String idGuide : _elementInstanceCollectionByIdGuideMap.keySet()) {
ElementInstanceCollection eic = _elementInstanceCollectionByIdGuideMap.get(idGuide);
Set<String> idElementsEHRAux = new HashSet<String>();
idElementsEHRAux.addAll(eic.getElementIdsByIdDomain(Domains.EHR_ID));
idElementsEHRAux.addAll(eic.getElementIdsByIdDomain(ElementInstanceCollection.EMPTY_CODE));
if (idElementsEHR.containsAll(idElementsEHRAux)){
guideIds.add(idGuide);
}
}
return guideIds;
}
public GeneratedElementInstanceCollection getCompleteElementInstanceCollection(){
return _completeElementInstanceCollection;
}
public GeneratedElementInstanceCollection getElementInstanceCollection(Collection<String> guideIds){
if (guideIds==null){
return getCompleteElementInstanceCollection();
}else{
GeneratedElementInstanceCollection guideEIC = new GeneratedElementInstanceCollection();
for (String guideId : guideIds) {
ElementInstanceCollection eic = _elementInstanceCollectionByIdGuideMap.get(guideId);
if (eic!=null){
guideEIC.merge(eic);
}
}
return guideEIC;
}
}
public Collection<String> getGuideIdsNormal(ElementInstanceCollection elementInstancesCollection) throws InternalErrorException {
//Get all idElements
Set<String> elementIds = elementInstancesCollection.getElementIdsByIdDomain(Domains.EHR_ID);
return getGuideIdsNormal(elementIds);
}
public Set<String> getGuideIdsNormal(Collection<String> elementIds)
throws InternalErrorException {
String elementIdsKey = getELementIdsKey(elementIds);
Set<String> guideIds = _guideIdsByElementIdsMap.get(elementIdsKey);
if (guideIds==null){
guideIds = generateGuideIdsNormal(elementIds);
}
return guideIds;
}
private Set<String> generateGuideIdsNormal(Collection<String> elementIds) throws InternalErrorException {
return getGuideIdsNormal(null, elementIds, Domains.EHR_ID);
}
private String getELementIdsKey(Collection<String> elementIds){
StringBuffer sb = new StringBuffer();
ArrayList<String> elementIdsList = new ArrayList<String>(elementIds);
Collections.sort(elementIdsList);
for(String elementId: elementIdsList){
sb.append(elementId);
}
return sb.toString();
}
private Set<String> getGuideIdsNormal(Set<String> skipElementIds, Collection<String> elementIds, String domainId) throws InternalErrorException {
Set<String> guideIds = new HashSet<String>();
for (String guideId : getAllGuideIds()) {
Set<String> idElementsRead = getElementIdsByReads(Collections.singleton(guideId), domainId);
Iterator<String> i = idElementsRead.iterator();
boolean contains = false;
while (i.hasNext() && !contains){
if (elementIds.contains(i.next())){
guideIds.add(guideId);
contains = true;
}
}
}
//Look for linked guides
Set<String> elementIdsByCDSWrites = getElementIdsByCDSWrites(guideIds);
if (skipElementIds==null){
skipElementIds = new HashSet<String>();
}
//First call are EHR element ids, we dont want to include those
if (Domains.CDS_ID.equals(domainId)){
skipElementIds.addAll(elementIds);
}
elementIdsByCDSWrites.removeAll(skipElementIds);
if (!elementIdsByCDSWrites.isEmpty()){
guideIds.addAll(getGuideIdsNormal(skipElementIds, elementIdsByCDSWrites, Domains.CDS_ID));
}
return guideIds;
}
private Set<String> getElementIdsByReads(Collection<String> guideIds, String domainId) throws InternalErrorException {
Set<String> elementIds = new HashSet<String>();
for (String guideId: guideIds){
Guide guide = getGuide(guideId);
if (guide==null){
throw new InternalErrorException(new Exception("Guide '"+guideId+"' not found on GuideManager."));
}
Set<String> gtCodes = GuideUtil.getGTCodesInReads(guide);
Map<String, String> elementIdsByGtCodesMap = GuideUtil.getGtCodeElementIdMap(guide, domainId);
for (String gtCode: gtCodes){
String elementId = elementIdsByGtCodesMap.get(gtCode);
if (elementId!=null){
elementIds.add(elementId);
}
}
}
return elementIds;
}
private Set<String> getElementIdsByCDSWrites(Collection<String> guideIds) throws InternalErrorException {
Set<String> elementIds = new HashSet<String>();
for (String guideId: guideIds){
Guide guide = getGuide(guideId);
if (guide==null){
throw new InternalErrorException(new Exception("Guide '"+guideId+"' not found on GuideManager."));
}
Set<String> gtCodes = GuideUtil.getGTCodesInWrites(guide);
Map<String, String> elementIdsByGtCodesMap = GuideUtil.getGtCodeElementIdMap(guide);
for (String gtCode: gtCodes){
String elementId = elementIdsByGtCodesMap.get(gtCode);
if (elementId==null){
throw new InternalErrorException(new Exception("GT code '"+gtCode+"' not found for guide '"+guideId+"' on GuideManager."));
}
elementIds.add(elementId);
}
}
return elementIds;
}
public ArrayList<String> getAllGuideIds(){
return new ArrayList<String>(_allGuidesMap.keySet());
}
public Guide getGuide(String idGuide){
return _allGuidesMap.get(idGuide);
}
public Collection<Guide> getAllGuides(){
return new ArrayList<Guide>(_allGuidesMap.values());
}
public final Map<String,Guide> getAllGuidesMap(){
return _allGuidesMap;
}
public Collection<String> getGuidesKey(Collection<GuideDTO> guides){
ArrayList<String> idGuides = new ArrayList<String>();
for (GuideDTO guideDTO : guides) {
idGuides.add(guideDTO.getId());
}
Collections.sort(idGuides);
return idGuides;
}
public Set<ElementInstance> getElementIdsCDSDomain(String idGuide){
ElementInstanceCollection eic = _elementInstanceCollectionByIdGuideMap.get(idGuide);
if (eic==null){
Logger.getLogger(SimpleGuideManager.class).warn("Guide id '"+idGuide+"' not found!");
return new HashSet<ElementInstance>();
}else{
return eic.getAllElementInstancesByDomain(Domains.CDS_ID);
}
}
public Set<ElementInstance> getElementIdsEHRDomain(String idGuide){
ElementInstanceCollection eic = _elementInstanceCollectionByIdGuideMap.get(idGuide);
if (eic==null){
Logger.getLogger(SimpleGuideManager.class).warn("Guide id '"+idGuide+"' not found!");
return new HashSet<ElementInstance>();
}else{
return eic.getAllElementInstancesByDomain(Domains.EHR_ID);
}
}
public Set<ElementInstance> getAllElementIdsCDSDomain(){
Set<ElementInstance> elementInstances = new HashSet<ElementInstance>();
for (String idGuide : _elementInstanceCollectionByIdGuideMap.keySet()) {
elementInstances.addAll(getElementIdsCDSDomain(idGuide));
}
return elementInstances;
}
public Set<String> getAllGuideIdsWithCDSDomain(ElementInstance elementInstance){
Set<String> idGuides = new HashSet<String>();
for (String idGuide : _elementInstanceCollectionByIdGuideMap.keySet()) {
Set<ArchetypeReference> archetypeReferences =
_elementInstanceCollectionByIdGuideMap.get(idGuide).getArchetypeReferences(elementInstance.getArchetypeReference());
Iterator<ArchetypeReference> i = archetypeReferences.iterator();
boolean inCDS = false;
while(i.hasNext() && !inCDS){
ArchetypeReference ar = i.next();
if (Domains.CDS_ID.equals(ar.getIdDomain()) && ar.getElementInstancesMap().containsKey(elementInstance.getId())){
inCDS = true;
}
}
if (inCDS){
idGuides.add(idGuide);
}
}
return idGuides;
}
}
/*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 2.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 2.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://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 Initial Developers of the Original Code are Iago Corbal and Rong Chen.
* Portions created by the Initial Developer are Copyright (C) 2012-2013
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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.
*
* ***** END LICENSE BLOCK *****
*/