001 /** 002 * The contents of this file are subject to the Mozilla Public License Version 1.1 003 * (the "License"); you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005 * Software distributed under the License is distributed on an "AS IS" basis, 006 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007 * specific language governing rights and limitations under the License. 008 * 009 * The Original Code is "TreePanel.java". Description: 010 * "This is a Swing panel that displays the contents of a Message object in a JTree" 011 * 012 * The Initial Developer of the Original Code is University Health Network. Copyright (C) 013 * 2001. All Rights Reserved. 014 * 015 * Contributor(s): ______________________________________. 016 * 017 * Alternatively, the contents of this file may be used under the terms of the 018 * GNU General Public License (the ?GPL?), in which case the provisions of the GPL are 019 * applicable instead of those above. If you wish to allow use of your version of this 020 * file only under the terms of the GPL and not to allow others to use your version 021 * of this file under the MPL, indicate your decision by deleting the provisions above 022 * and replace them with the notice and other provisions required by the GPL License. 023 * If you do not delete the provisions above, a recipient may use your version of 024 * this file under either the MPL or the GPL. 025 * 026 */ 027 028 /* 029 * Created on October 17, 2001, 11:44 AM 030 */ 031 package ca.uhn.hl7v2.view; 032 033 import java.awt.BorderLayout; 034 import java.awt.event.WindowAdapter; 035 import java.awt.event.WindowEvent; 036 import java.io.File; 037 import java.io.FileReader; 038 039 import javax.swing.JFrame; 040 import javax.swing.JScrollPane; 041 import javax.swing.JTree; 042 import javax.swing.tree.DefaultMutableTreeNode; 043 import javax.swing.tree.MutableTreeNode; 044 045 import ca.uhn.hl7v2.HL7Exception; 046 import ca.uhn.hl7v2.model.*; 047 import ca.uhn.hl7v2.parser.EncodingCharacters; 048 import ca.uhn.hl7v2.parser.PipeParser; 049 import ca.uhn.log.HapiLog; 050 import ca.uhn.log.HapiLogFactory; 051 import ca.uhn.hl7v2.util.Terser; 052 053 /** 054 * This is a Swing panel that displays the contents of a Message object in a JTree. 055 * The tree currently only expands to the field level (components shown as one node). 056 * @author Bryan Tripp (bryan_tripp@sourceforge.net) 057 */ 058 public class TreePanel extends javax.swing.JPanel { 059 060 private static final HapiLog log = HapiLogFactory.getHapiLog(TreePanel.class); 061 062 private PipeParser parser; 063 private EncodingCharacters encChars; 064 private Message message; 065 066 /** Creates new TreePanel */ 067 public TreePanel(PipeParser parser) { 068 this.parser = parser; 069 this.encChars = new EncodingCharacters('|', null); 070 } 071 072 /** 073 * Updates the panel with a new Message. 074 */ 075 public void setMessage(Message message) { 076 this.message = message; 077 DefaultMutableTreeNode top = new DefaultMutableTreeNode(message.getClass().getName()); 078 addChildren(message, top); 079 080 JTree tree = new JTree(top); 081 //JScrollPane treeView = new JScrollPane(tree); 082 this.removeAll(); 083 this.add(tree); 084 this.revalidate(); 085 } 086 087 /** 088 * Returns the message that is currently displayed in the tree panel. 089 */ 090 public Message getMessage() { 091 return this.message; 092 } 093 094 /** 095 * Adds the children of the given group under the given tree node. 096 */ 097 private void addChildren(Group messParent, MutableTreeNode treeParent) { 098 String[] childNames = messParent.getNames(); 099 int currChild = 0; 100 for (int i = 0; i < childNames.length; i++) { 101 try { 102 Structure[] childReps = messParent.getAll(childNames[i]); 103 for (int j = 0; j < childReps.length; j++) { 104 DefaultMutableTreeNode newNode = null; 105 if (childReps[j] instanceof Group) { 106 String groupName = childReps[j].getClass().getName(); 107 groupName = groupName.substring(groupName.lastIndexOf('.') + 1, groupName.length()); 108 newNode = new DefaultMutableTreeNode(groupName + " (rep " + j + ")"); 109 addChildren((Group)childReps[j], newNode); 110 } else if (childReps[j] instanceof Segment) { 111 newNode = new DefaultMutableTreeNode(parser.encode((Segment)childReps[j], encChars)); 112 addChildren((Segment)childReps[j], newNode); 113 } 114 treeParent.insert(newNode, currChild++); 115 } 116 } catch (HL7Exception e) { 117 e.printStackTrace(); 118 } 119 } 120 } 121 122 /** 123 * Add fields of a segment to the tree ... 124 */ 125 private void addChildren(Segment messParent, MutableTreeNode treeParent) { 126 int n = messParent.numFields(); 127 int currChild = 0; 128 for (int i = 1; i <= n; i++) { 129 try { 130 Type[] reps = messParent.getField(i); 131 for (int j = 0; j < reps.length; j++) { 132 String field = parser.encode(reps[j], encChars); 133 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("Field " + i + " rep " + j + " (" + getLabel(reps[j]) + "): " + field); 134 addChildren(reps[j], newNode); 135 treeParent.insert(newNode, currChild++); 136 } 137 } catch (HL7Exception e) { 138 e.printStackTrace(); 139 } 140 } 141 } 142 143 /** 144 * Adds children to the tree. If the Type is a Varies, the Varies data are 145 * added under a new node called "Varies". If there are extra components, 146 * these are added under a new node called "ExtraComponents" 147 */ 148 private void addChildren(Type messParent, MutableTreeNode treeParent) { 149 if (Varies.class.isAssignableFrom(messParent.getClass())) { 150 //DefaultMutableTreeNode variesNode = new DefaultMutableTreeNode("Varies"); 151 //treeParent.insert(variesNode, treeParent.getChildCount()); 152 Type data = ((Varies) messParent).getData(); 153 DefaultMutableTreeNode dataNode = new DefaultMutableTreeNode(getLabel(data)); 154 treeParent.insert(dataNode, 0); 155 addChildren(data, dataNode); 156 } else { 157 if (Composite.class.isAssignableFrom(messParent.getClass())) { 158 addChildren((Composite)messParent, treeParent); 159 } else if (Primitive.class.isAssignableFrom(messParent.getClass())) { 160 addChildren((Primitive)messParent, treeParent); 161 } 162 163 if (messParent.getExtraComponents().numComponents() > 0) { 164 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("ExtraComponents"); 165 treeParent.insert(newNode, treeParent.getChildCount()); 166 for (int i = 0; i < messParent.getExtraComponents().numComponents(); i++) { 167 DefaultMutableTreeNode variesNode = new DefaultMutableTreeNode("Varies"); 168 newNode.insert(variesNode, i); 169 addChildren(messParent.getExtraComponents().getComponent(i), variesNode); 170 } 171 } 172 } 173 } 174 175 /** 176 * Adds components of a composite to the tree ... 177 */ 178 private void addChildren(Composite messParent, MutableTreeNode treeParent) { 179 Type[] components = messParent.getComponents(); 180 for (int i = 0; i < components.length; i++) { 181 DefaultMutableTreeNode newNode; 182 newNode = new DefaultMutableTreeNode(getLabel(components[i])); 183 addChildren(components[i], newNode); 184 treeParent.insert(newNode, i); 185 } 186 } 187 188 /** 189 * Adds single text value to tree as a leaf 190 */ 191 private void addChildren(Primitive messParent, MutableTreeNode treeParent) { 192 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(messParent.getValue()); 193 treeParent.insert(newNode, 0); 194 } 195 196 /** 197 * Returns the unqualified class name as a label for tree nodes. 198 */ 199 private static String getLabel(Object o) { 200 String name = o.getClass().getName(); 201 return name.substring(name.lastIndexOf('.')+1, name.length()); 202 } 203 204 /** 205 * A convenience method for displaying a message by creating a new 206 * TreePanel and displaying the given message in a new window. 207 * Currently only works with v2.4 messages. 208 */ 209 public static void showInNewWindow(Message message) { 210 //Create the top-level container and add contents to it. 211 JFrame frame = new JFrame(message.getClass().getName()); 212 213 try { 214 TreePanel panel = new TreePanel(new PipeParser()); 215 panel.setMessage(message); 216 JScrollPane scroll = new JScrollPane(panel); 217 frame.getContentPane().add(scroll, BorderLayout.CENTER); 218 219 //Finish setting up the frame 220 frame.addWindowListener(new WindowAdapter() { 221 public void windowClosing(WindowEvent e) { 222 System.exit(0); 223 } 224 }); 225 226 frame.pack(); 227 frame.setVisible(true); 228 } catch (Exception e) { 229 System.err.println("Can't display message in new window: "); 230 e.printStackTrace(); 231 } 232 } 233 234 /** 235 * Opens window and displays a message in a file (file named in command line arg). 236 */ 237 public static void main(String args[]) { 238 if (args.length != 1) { 239 System.out.println("Usage: TreePanel msg_file_name"); 240 System.exit(1); 241 } 242 243 try { 244 PipeParser parser = new PipeParser(); 245 File messageFile = new File(args[0]); 246 long fileLength = messageFile.length(); 247 FileReader r = new FileReader(messageFile); 248 char[] cbuf = new char[(int)fileLength]; 249 System.out.println("Reading message file ... " + r.read(cbuf) + " of " + fileLength + " chars"); 250 r.close(); 251 String messString = String.valueOf(cbuf); 252 Message mess = parser.parse(messString); 253 System.out.println("Got message of type " + mess.getClass().getName()); 254 showInNewWindow(mess); 255 256 //write message to console ... 257 System.out.println(parser.encode(mess, "VB")); 258 } catch (Exception e) { 259 e.printStackTrace(); 260 log.error( e ); 261 } 262 } 263 264 }