Coverage Report - ca.uhn.hl7v2.parser.CustomModelClassFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
CustomModelClassFactory
48%
32/66
34%
11/32
2.214
 
 1  
 /**
 2  
 The contents of this file are subject to the Mozilla Public License Version 1.1
 3  
 (the "License"); you may not use this file except in compliance with the License.
 4  
 You may obtain a copy of the License at http://www.mozilla.org/MPL/
 5  
 Software distributed under the License is distributed on an "AS IS" basis,
 6  
 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
 7  
 specific language governing rights and limitations under the License.
 8  
 
 9  
 The Initial Developer of the Original Code is University Health Network. Copyright (C)
 10  
 2001.  All Rights Reserved.
 11  
 
 12  
 Contributor(s): ______________________________________.
 13  
 
 14  
 Alternatively, the contents of this file may be used under the terms of the
 15  
 GNU General Public License (the  �GPL�), in which case the provisions of the GPL are
 16  
 applicable instead of those above.  If you wish to allow use of your version of this
 17  
 file only under the terms of the GPL and not to allow others to use your version
 18  
 of this file under the MPL, indicate your decision by deleting  the provisions above
 19  
 and replace  them with the notice and other provisions required by the GPL License.
 20  
 If you do not delete the provisions above, a recipient may use your version of
 21  
 this file under either the MPL or the GPL.
 22  
 
 23  
 */
 24  
 package ca.uhn.hl7v2.parser;
 25  
 
 26  
 import java.util.HashMap;
 27  
 import java.util.Map;
 28  
 import java.util.Map.Entry;
 29  
 
 30  
 import org.slf4j.Logger;
 31  
 import org.slf4j.LoggerFactory;
 32  
 
 33  
 import ca.uhn.hl7v2.HL7Exception;
 34  
 import ca.uhn.hl7v2.Version;
 35  
 import ca.uhn.hl7v2.model.Group;
 36  
 import ca.uhn.hl7v2.model.Message;
 37  
 import ca.uhn.hl7v2.model.Segment;
 38  
 import ca.uhn.hl7v2.model.Type;
 39  
 import ca.uhn.hl7v2.util.StringUtil;
 40  
 
 41  
 /**
 42  
  * ModelClassFactory which allows custom packages to search to be specified.
 43  
  * These packages will be searched first, and if nothing is found for a particular
 44  
  * structure, a delegate ModelClassFactory (by default DefaultModelClassFactory) is used. 
 45  
  * <p>
 46  
  * Also, a custom event map location is supported (by setting {@link #setEventMapDirectory(String)}
 47  
  * in a way that only new or modified structures needs to be defined there. If no structure was
 48  
  * found, the event map of the delegate ModelClassFactory serves as fallback.
 49  
  *
 50  
  * @author Christian Ohr
 51  
  * @author James Agnew
 52  
  * @since 1.0
 53  
  */
 54  
 public class CustomModelClassFactory extends AbstractModelClassFactory {
 55  
 
 56  
     private static final long serialVersionUID = 1;
 57  1
     private static Logger LOG = LoggerFactory.getLogger(CustomModelClassFactory.class);
 58  
 
 59  
     private final ModelClassFactory delegate;
 60  
     private Map<String, String[]> customModelClasses;
 61  
 
 62  
     /**
 63  
      * Constructor which just delegated to {@link DefaultModelClassFactory}
 64  
      */
 65  
     public CustomModelClassFactory() {
 66  0
         this((Map<String, String[]>)null);
 67  0
     }
 68  
 
 69  
 
 70  
     /**
 71  
      * Constructor
 72  
      *
 73  
      * @param packageName The base package name to use.
 74  
      * <p>
 75  
      * When searching, package specified here will be appended with .[version].[structure type].
 76  
      * </p>
 77  
      * <p>
 78  
      * So, for instance, when looking for a v2.5 segment object, if "<code>com.foo</code>" is passed in, HAPI will look in "<code>com.foo.v25.segment.*</code>"
 79  
      * </p>
 80  
      */
 81  
     public CustomModelClassFactory(String packageName) {
 82  2
         this(new HashMap<String, String[]>());
 83  
 
 84  2
         if (!packageName.endsWith(".")) {
 85  2
             packageName += ".";
 86  
         }
 87  18
         for (Version v : Version.values()) {
 88  16
                 addModel(v.getVersion(), new String[] {packageName + v.getPackageVersion()});
 89  
         }
 90  2
     }
 91  
 
 92  
     
 93  
     /**
 94  
      * Constructor
 95  
      * @param map Map of packages to include.
 96  
      * <p>
 97  
      * Keys are versions of HL7, e.g. "2.5".
 98  
      * </p>
 99  
      * <p>
 100  
      * Values are an array of packages to search in for custom model classes.
 101  
      * When searching, the package name here will be appended with "<b>.[structure type]</b>".
 102  
      * So, for example, to specify a custom message type, you could create the class
 103  
      * <code>foo.example.v23.message.ZRM_Z01</code>, and pass in the string "<code>foo.example.v23</code>".
 104  
      * </p>
 105  
      */
 106  
     public CustomModelClassFactory(Map<String, String[]> map) {
 107  2
         this(new DefaultModelClassFactory(), map);
 108  2
     }
 109  
     
 110  
     /**
 111  
      * Set an explicit {@link ModelClassFactory} is underlying delegate
 112  
      * @param defaultFactory default factory to be delegated to
 113  
      * @param map custom model map
 114  
      */
 115  2
     public CustomModelClassFactory(ModelClassFactory defaultFactory, Map<String, String[]> map) {
 116  2
         this.delegate = defaultFactory;
 117  2
         customModelClasses = map;
 118  2
     }    
 119  
 
 120  
     /**
 121  
      * {@inheritDoc }
 122  
      */
 123  
         public Class<? extends Message> getMessageClass(String name, String version, boolean isExplicit) throws HL7Exception {
 124  2
         if (!isExplicit) {
 125  0
             name = getMessageStructureForEvent(name, Version.versionOf(version));
 126  
         }
 127  2
         Class<? extends Message> retVal = findClass("message", name, version);
 128  2
         if (retVal == null) {
 129  0
             retVal = delegate.getMessageClass(name, version, isExplicit);
 130  
         }
 131  2
         return retVal;
 132  
     }
 133  
 
 134  
     /**
 135  
      * {@inheritDoc }
 136  
      */
 137  
         public Class<? extends Group> getGroupClass(String name, String version) throws HL7Exception {
 138  0
         Class<? extends Group> retVal = findClass("group", name, version);
 139  0
         if (retVal == null) {
 140  0
             retVal = delegate.getGroupClass(name, version);
 141  
         }
 142  0
         return retVal;
 143  
     }
 144  
 
 145  
     /**
 146  
      * {@inheritDoc }
 147  
      */
 148  
         public Class<? extends Segment> getSegmentClass(String name, String version) throws HL7Exception {
 149  0
         Class<? extends Segment> retVal = findClass("segment", name, version);
 150  0
         if (retVal == null) {
 151  0
             retVal = delegate.getSegmentClass(name, version);
 152  
         }
 153  0
         return retVal;
 154  
     }
 155  
 
 156  
     /**
 157  
      * {@inheritDoc }
 158  
      */
 159  
         public Class<? extends Type> getTypeClass(String name, String version) throws HL7Exception {
 160  0
         Class<? extends Type> retVal = findClass("datatype", name, version);
 161  0
         if (retVal == null) {
 162  0
             retVal = delegate.getTypeClass(name, version);
 163  
         }
 164  0
         return retVal;
 165  
     }
 166  
 
 167  
     /**
 168  
      * Finds appropriate classes to be loaded for the given structure/type
 169  
      */
 170  
     @SuppressWarnings("unchecked")
 171  
         protected <T> Class<T> findClass(String subpackage, String name, String version) throws HL7Exception {
 172  2
         Parser.assertVersionExists(version);
 173  2
         Class<T> classLoaded = null;
 174  2
         if (customModelClasses != null) {
 175  2
             if (customModelClasses.containsKey(version)) {
 176  4
                 for (String next : customModelClasses.get(version)) {
 177  2
                     if (!next.endsWith(".")) {
 178  2
                         next += ".";
 179  
                     }
 180  2
                     String fullyQualifiedName = next + subpackage + '.' + name;
 181  
                     try {
 182  2
                         classLoaded = (Class<T>) Class.forName(fullyQualifiedName);
 183  2
                         LOG.debug("Found " + fullyQualifiedName + " in custom HL7 model");
 184  0
                     } catch (ClassNotFoundException e) {
 185  
                         // ignore
 186  2
                     }
 187  
                 }
 188  
             }
 189  
         }
 190  2
         return classLoaded;
 191  
     }
 192  
 
 193  
     /**
 194  
      * Delegates calls to {@link DefaultModelClassFactory#getMessageClassInASpecificPackage(String, String, boolean, String)}
 195  
      */
 196  
         public Class<? extends Message> getMessageClassInASpecificPackage(String theName, String theVersion, boolean theIsExplicit, String thePackageName) throws HL7Exception {
 197  0
                 return delegate.getMessageClassInASpecificPackage(theName, theVersion, theIsExplicit, thePackageName);
 198  
         }
 199  
 
 200  
     /**
 201  
      * Returns the configured custom model classes
 202  
      * @return a map of custom model classes
 203  
      */
 204  
     public Map<String, String[]> getCustomModelClasses() {
 205  0
                 return customModelClasses;
 206  
         }
 207  
 
 208  
         /**
 209  
          * Add model class packages after the object has been instantiated
 210  
          * 
 211  
          * @param addedModelClasses map with version number as key and package names has value
 212  
          */
 213  
         public void addModels(Map<String, String[]> addedModelClasses) {
 214  0
         if (customModelClasses == null) {
 215  0
                 customModelClasses = new HashMap<String, String[]>();
 216  
         }
 217  0
         for (Entry<String, String[]> entry : addedModelClasses.entrySet()) {
 218  0
                 addModel(entry.getKey(), entry.getValue());
 219  0
         }
 220  0
     }
 221  
         
 222  
         private void addModel(String version, String[] newPackageNames) {
 223  16
         if (customModelClasses.containsKey(version)) {
 224  
             // the new packages must be added after the existing ones.
 225  0
             String[] existingPackageNames = customModelClasses.get(version);
 226  0
             customModelClasses.put(version, StringUtil.concatenate(existingPackageNames, newPackageNames));
 227  0
         } else {
 228  16
                 customModelClasses.put(version, newPackageNames);
 229  
         }                
 230  16
         }
 231  
 
 232  
 
 233  
         /**
 234  
          * Looks up its own event map. If no structure was found, the call is delegated to
 235  
          * the default ModelClassFactory. If nothing can be found, the eventName is returned
 236  
          * as structure.
 237  
          * 
 238  
          * @see ca.uhn.hl7v2.parser.AbstractModelClassFactory#getMessageStructureForEvent(java.lang.String, ca.uhn.hl7v2.Version)
 239  
          */
 240  
         @Override
 241  
         public String getMessageStructureForEvent(String eventName, Version version) throws HL7Exception {
 242  0
                 String structure = super.getMessageStructureForEvent(eventName, version);
 243  0
                 if (structure == null) {
 244  0
                         structure = delegate.getMessageStructureForEvent(eventName, version);
 245  
                 }
 246  0
                 if (structure != null) {
 247  0
                         structure = eventName;
 248  
                 }
 249  0
                 return structure;
 250  
         }
 251  
         
 252  
         
 253  
         
 254  
 }