/******************************************************************************* * Copyright (c) 2007-2010, G. Weirich, SGAM.Informatics and Elexis * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * G. Weirich - initial implementation * *******************************************************************************/ package ch.elexis.core.ui.exchange; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map.Entry; import java.util.Properties; import org.eclipse.core.runtime.IConfigurationElement; import org.jdom.Document; import org.jdom.Element; import org.jdom.Namespace; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import ch.elexis.core.data.activator.CoreHub; import ch.elexis.core.data.util.Extensions; import ch.elexis.core.ui.Hub; import ch.elexis.core.ui.constants.ExtensionPointConstantsUi; import ch.elexis.core.ui.exchange.elements.ContactElement; import ch.elexis.core.ui.exchange.elements.ContactsElement; import ch.elexis.core.ui.exchange.elements.DocumentElement; import ch.elexis.core.ui.exchange.elements.EpisodeElement; import ch.elexis.core.ui.exchange.elements.FindingElement; import ch.elexis.core.ui.exchange.elements.MedicationElement; import ch.elexis.core.ui.exchange.elements.RecordElement; import ch.elexis.core.ui.exchange.elements.RiskElement; import ch.elexis.core.ui.exchange.elements.XChangeElement; import ch.elexis.core.ui.util.Log; import ch.elexis.data.PersistentObject; import ch.rgw.tools.StringTool; import ch.rgw.tools.TimeTool; import ch.rgw.tools.XMLTool; public class XChangeContainer { public static final String Version = "2.0.0"; //$NON-NLS-1$ public static final String ATTR_LANGUAGE = "language"; private static final String ATTR_PROTOCOL_VERSION = "protocolVersion"; private static final String ATTR_CREATOR_VERSION = "creatorVersion"; private static final String ATTR_CREATOR_ID = "creatorID"; public static final String ATTR_CREATOR_NAME = "creatorName"; public static final String ATTR_RESPONSIBLE = "responsible"; public static final String ATTR_DESTINATION = "destination"; public static final String ATTR_ORIGIN = "origin"; private static final String XCHANGE_MAGIC = "xChange"; private static final String ATTR_ID = "id"; public static final String ATTR_TIMESTAMP = "timestamp"; private static final String PLURAL = "s"; //$NON-NLS-1$ public static final Namespace ns = Namespace.getNamespace(XCHANGE_MAGIC, "http://informatics.sgam.ch/xChange"); //$NON-NLS-1$ public static final Namespace nsxsi = Namespace.getNamespace( "xsi", "http://www.w3.org/2001/XML Schema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ public static final Namespace nsschema = Namespace.getNamespace( "schemaLocation", "http://informatics.sgam.ch/xChange xchange.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ public static final String ROOT_ELEMENT = XCHANGE_MAGIC; public static final String ROOTPATH = StringTool.slash + ROOT_ELEMENT + StringTool.slash; public static final String ENCLOSE_CONTACTS = ContactElement.XMLNAME + PLURAL; //public static final String PATIENT_ELEMENT = "patient"; //$NON-NLS-1$ public static final String ENCLOSE_DOCUMENTS = DocumentElement.XMLNAME + PLURAL; public static final String ENCLOSE_RECORDS = RecordElement.XMLNAME + PLURAL; public static final String ENCLOSE_FINDINGS = FindingElement.XMLNAME + PLURAL; public static final String ENCLOSE_MEDICATIONS = MedicationElement.XMLNAME + PLURAL; public static final String ENCLOSE_RISKS = RiskElement.XMLNAME + PLURAL; public static final String ENCLOSE_EPISODES = EpisodeElement.XMLNAME + PLURAL; private Document doc; private final Element eHeader = new Element("header", ns); private Element eRoot; private boolean bValid = false; protected static Log log = Log.get("XChange"); //$NON-NLS-1$ protected HashMap<String, byte[]> binFiles = new HashMap<String, byte[]>(); /** * Collection of all UserChoices to display to tzhe user for selection */ protected HashMap<Element, UserChoice> choices = new HashMap<Element, UserChoice>(); /** * Mapping between element in the xChange Container to the corresponding internal data object */ private final HashMap<XChangeElement, PersistentObject> mapElementToObject = new HashMap<XChangeElement, PersistentObject>(); /** * Mapping from an internal data object to an element in the xChange Container */ private final HashMap<PersistentObject, XChangeElement> mapObjectToElement = new HashMap<PersistentObject, XChangeElement>(); private final List<IConfigurationElement> lex = Extensions .getExtensions(ExtensionPointConstantsUi.XCHANGE_CONTRIBUTION); // public abstract Kontakt findContact(String id); public XChangeContainer(){ doc = new Document(); eRoot = new Element(XChangeContainer.ROOT_ELEMENT, XChangeContainer.ns); eRoot.addNamespaceDeclaration(XChangeContainer.nsxsi); eRoot.addNamespaceDeclaration(XChangeContainer.nsschema); eRoot.setAttribute(ATTR_TIMESTAMP, new TimeTool().toString(TimeTool.DATETIME_XML)); eRoot.setAttribute(ATTR_ID, XMLTool.idToXMLID(StringTool.unique(XCHANGE_MAGIC))); eRoot.setAttribute(ATTR_ORIGIN, XMLTool.idToXMLID(CoreHub.actMandant.getId())); eRoot.setAttribute(ATTR_DESTINATION, "undefined"); eRoot.setAttribute(ATTR_RESPONSIBLE, XMLTool.idToXMLID(CoreHub.actMandant.getId())); doc.setRootElement(eRoot); eHeader.setAttribute(ATTR_CREATOR_NAME, Hub.APPLICATION_NAME); eHeader.setAttribute(ATTR_CREATOR_ID, "ch.elexis"); eHeader.setAttribute(ATTR_CREATOR_VERSION, CoreHub.Version); eHeader.setAttribute(ATTR_PROTOCOL_VERSION, XChangeContainer.Version); eHeader.setAttribute(ATTR_LANGUAGE, Locale.getDefault().toString()); eRoot.addContent(eHeader); } public void setDocument(Document doc){ this.doc = doc; eRoot = doc.getRootElement(); } public String toString(){ Format format = Format.getPrettyFormat(); format.setEncoding("utf-8"); XMLOutputter xmlo = new XMLOutputter(format); String xmlAspect = xmlo.outputString(doc); return xmlAspect; } public Document getDocument(){ return doc; } public boolean isValid(){ return bValid; } public void setValid(boolean bValid){ this.bValid = bValid; } public List<IConfigurationElement> getXChangeContributors(){ return lex; } /** * Map a database object to an xChange container element and vice versa * * @param element * the Element * @param obj * the Object */ public void addMapping(XChangeElement element, PersistentObject obj){ mapElementToObject.put(element, obj); mapObjectToElement.put(obj, element); } /** * Return the database Object that maps to a specified Element * * @param element * the Element * @return the object or null if no such mapping exists */ public PersistentObject getMapping(XChangeElement element){ return mapElementToObject.get(element); } /** * return the Container Element that is mapped to a specified database object * * @param obj * the object * @return the element or null if no such mapping exists */ public XChangeElement getMapping(PersistentObject obj){ return mapObjectToElement.get(obj); } /** * Retrieve the UserChoice attributed to a given Element * * @param key * teh element * @return the UserChoice or null if no such UserChoice exists */ public UserChoice getChoice(XChangeElement key){ return choices.get(key.getElement()); } public UserChoice getChoice(Element key){ return choices.get(key); } public void addChoice(Element key, String name){ choices.put(key, new UserChoice(true, name, key)); } public void addChoice(XChangeElement key, String name){ choices.put(key.getElement(), new UserChoice(true, name, key)); } public ContactsElement getContactsElement(){ Element ec = eRoot.getChild(ENCLOSE_CONTACTS, ns); ContactsElement eContacts = new ContactsElement(); if (ec == null) { eRoot.addContent(eContacts.getElement()); choices.put(eContacts.getElement(), new UserChoice(true, Messages.XChangeContainer_kontakte, eContacts)); } else { eContacts.setElement(ec); } return eContacts; } public List<Element> getContactElements(){ return getElements(ROOTPATH + ENCLOSE_CONTACTS + StringTool.slash + ContactElement.XMLNAME); } /** * get a binary content from the Container * * @param id * id of the content * @return the content or null if no such content exists */ public byte[] getBinary(String id){ return binFiles.get(id); } public void addChoice(XChangeElement e, String name, Object o){ choices.put(e.getElement(), new UserChoice(true, name, o)); } public void addChoice(Element e, String name, Object o){ choices.put(e, new UserChoice(true, name, o)); } /** * Get the root element. * * @return the root element */ public Element getRoot(){ return eRoot; } /** * Retrieve a List of all Elements with a given Name at a given path * * @param path * a string of the form /element1/element2/name will get all Elements with "name" in * the body of element2. If name is *, will retrieve all Children of element2. Path * must begin at root level. * @return a possibly empty list af all matching elements at the given position */ @SuppressWarnings("unchecked") public List<Element> getElements(String path){ LinkedList<Element> ret = new LinkedList<Element>(); String[] trace = path.split(StringTool.slash); Element runner = eRoot; for (int i = 2; i < trace.length - 1; i++) { runner = runner.getChild(trace[i], ns); if (runner == null) { return ret; } } String name = trace[trace.length - 1]; if (trace.equals("*")) { //$NON-NLS-1$ return runner.getChildren(); } return runner.getChildren(name, ns); } public Namespace getNamespace(){ return ns; } /** * get an Iterator over all binary contents of this Container */ public Iterator<Entry<String, byte[]>> getBinaries(){ return binFiles.entrySet().iterator(); } /* * public List<Object> getSelectedChildren(Tree<UserChoice> tSelection){ List<Object> ret=new * LinkedList<Object>(); for(Tree<UserChoice> runner:tSelection.getChildren()){ UserChoice * choice=runner.contents; if(choice.isSelected()){ ret.add(choice.object); } } return ret; } */ /** * Set any implementation-spezific configuration * * @param props */ public void setConfiguration(Properties props){ this.props = props; } /** * Set a named property for this container * * @param name * the name of the property * @param value * the value for the property */ public void setProperty(String name, String value){ if (props == null) { props = new Properties(); } props.setProperty(name, value); } public String getProperty(String name){ if (props == null) { props = new Properties(); } return props.getProperty(name); } protected Properties getProperties(){ return props; } protected Properties props; /** * A UserChoice contains the information, whether the user selected the associated object for * transfer * * @author gerry * */ public static class UserChoice { boolean bSelected; String title; Object object; /** * Include the object in the transfer * * @param bSelection */ public void select(boolean bSelection){ bSelected = bSelection; } /** * tell wether the object is selected for transfer * * @return */ public boolean isSelected(){ return bSelected; } /** * get the Title to display to the user when asked for selection * * @return */ public String getTitle(){ return title; } /** * Get the associated object * * @return */ public Object getObject(){ return object; } /** * Create a new UserChoice * * @param bSelected * true if initially selected * @param title * title to display to the user in selection form * @param object * the object to select for transfer */ public UserChoice(boolean bSelected, String title, Object object){ this.bSelected = bSelected; this.title = title; this.object = object; } } }