/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.hl7;

// Java classes
import java.util.ResourceBundle;

// Framework classes
import gov.va.med.fw.util.Reflector;

/**
 * @author DNS   LEV
 * @version 1.0
 */
public class SegmentFactory {

   private static final String SEGMENT_CLASS_PROPERTIES = "segments";
   
   /**
    * Comment for <code>instance</code>
    */
   private static SegmentFactory instance = null;

   /**
    * Comment for <code>sem</code>
    */
   private static ThreadLocal sem = new ThreadLocal();
   
   /**
    * A private constructor to prevent other classes from 
    * instantiating this class directly
    */
   protected SegmentFactory() {
      super();
   }

   /** Returns a single instance of a segment factory
    * @return A single instance of a segment factory
    */
   public static SegmentFactory getInstance() {

      if (sem.get() == null) {
         synchronized (SegmentFactory.class) {
            if (instance == null) {
               instance = new SegmentFactory();
               sem.set(Boolean.TRUE);
            }
         }
      }
      return instance;
   }
   
   public Segment createSegment( String[] encoders, String delimiter, String data ) 
   		throws InvalidSegmentException {
     
      Segment s = null;
      try {
         s = (Segment)Reflector.instantiate( getSegmentClassName( getSegmentName( data, delimiter ) ), 
               							     new Object[] {encoders,delimiter,data} );
      }
      catch( Exception e ) {
         throw new InvalidSegmentException( "Failed to create a segment", e);
      }
      return s;
   }
   
   protected String getSegmentName( String data, String delimiter ) throws InvalidSegmentException {
      
      if( data == null || delimiter == null) {
         throw new IllegalArgumentException( "Missing a segment data & delimiter" );
      }
      
      int pos = data.indexOf( delimiter );
      if( pos == -1 ) {
         throw new InvalidSegmentException( "Invalid segment delimiter in segment: " + data );
      }
      return data.substring( 0, pos );
   }
   
   protected String getSegmentClassName( String segmentName ) {
      // if a concrete segment class is not specified, use a generic segment
      String value = Segment.class.getName();
      
      try {
         ResourceBundle bundle = ResourceBundle.getBundle( SEGMENT_CLASS_PROPERTIES );
         value = bundle.getString( segmentName );
      }
      catch( Exception e ) {
         // Failed to find a concrete segment class so
         // use a generic segment class instead
      }
      return value;
   }
}
