View Javadoc

1   package ca.uhn.hl7v2.sourcegen;
2   
3   import java.io.BufferedWriter;
4   import java.io.File;
5   import java.io.FileOutputStream;
6   import java.io.FileWriter;
7   import java.io.IOException;
8   import java.io.OutputStreamWriter;
9   import java.io.Writer;
10  import java.sql.Connection;
11  import java.sql.ResultSet;
12  import java.sql.SQLException;
13  import java.sql.Statement;
14  import java.util.ArrayList;
15  import java.util.Collections;
16  import java.util.Comparator;
17  import java.util.List;
18  import java.util.Map;
19  import java.util.Set;
20  import java.util.TreeMap;
21  import java.util.TreeSet;
22  
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.velocity.Template;
25  import org.apache.velocity.VelocityContext;
26  import org.apache.velocity.context.Context;
27  
28  import ca.uhn.hl7v2.database.NormativeDatabase;
29  import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
30  import ca.uhn.hl7v2.sourcegen.util.VelocityFactory;
31  
32  public class EventMapGenerator {
33  	private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(EventMapGenerator.class);
34  
35  	private static ResultSet createStructureQuery(String theVersion) throws SQLException {
36  		String query = "SELECT " + "   HL7EventMessageTypes.event_code, HL7EventMessageTypes.message_typ_snd, " + "   HL7Versions.hl7_version, HL7EventMessageTypes.message_structure_snd " + "FROM " + "   HL7Versions "
37  				+ "INNER JOIN HL7EventMessageTypes ON HL7Versions.version_id = HL7EventMessageTypes.version_id " + "WHERE " + "   HL7Versions.hl7_version = '" + theVersion + "' " + "ORDER BY HL7EventMessageTypes.message_typ_snd, HL7EventMessageTypes.event_code;";
38  
39  		NormativeDatabase normativeDatabase = NormativeDatabase.getInstance();
40  		Connection conn = normativeDatabase.getConnection();
41  		Statement stmt = conn.createStatement();
42  		ResultSet rs = stmt.executeQuery(query);
43  
44  		normativeDatabase.returnConnection(conn);
45  		return rs;
46  	}
47  
48  	public static void generateEventDesc(String theTargetDirectory, String theVersion, String theTemplatePackage) throws Exception {
49  
50  		List<TriggerDesc> triggerDescs = getTriggers(theVersion);
51  		// Structures are not explicitly defined in 2.1 and 2.2
52  		if ("2.1".equals(theVersion) || "2.2".equals(theVersion)) {
53  			for (TriggerDesc next : triggerDescs) {
54  				next.setStructure(next.getType().replace("^", "_"));
55  			}
56  		}
57  		Collections.sort(triggerDescs);
58  
59  		List<String> segments = SegmentGenerator.getSegmentNames(theVersion);
60  		Collections.sort(segments);
61  
62  		List<String> dataTypes = DataTypeGenerator.getDataTypes(theVersion);
63  		Collections.sort(dataTypes);
64  
65  		if (!(theTargetDirectory.endsWith("\\") || theTargetDirectory.endsWith("/"))) {
66  			theTargetDirectory = theTargetDirectory + "/";
67  		}
68  		String fileName = theTargetDirectory + DefaultModelClassFactory.getVersionPackagePath(theVersion) + "available_structures.json";
69  		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName, false), SourceGenerator.ENCODING));
70  
71  		theTemplatePackage = theTemplatePackage.replace(".", "/");
72  		Template template = VelocityFactory.getClasspathTemplateInstance(theTemplatePackage + "/available_structures.vsm");
73  		Context ctx = new VelocityContext();
74  		ctx.put("triggers", triggerDescs);
75  		ctx.put("segments", segments);
76  		ctx.put("datatypes", dataTypes);
77  
78  		template.merge(ctx, out);
79  
80  		// String string = createSegmentString(version, segmentName, elements,
81  		// description, basePackage, datatypePackageString);
82  		// out.write(string);
83  
84  		out.flush();
85  		out.close();
86  
87  	}
88  
89  	public static void generateEventMap(String theOutputPath, String theVersion) throws SQLException, IOException {
90  
91  		ArrayList<String> messages = MessageGenerator.getMessages(theVersion).messages;
92  
93  		theOutputPath = theOutputPath + "/ca/uhn/hl7v2/parser/eventmap/";
94  
95  		new File(theOutputPath).mkdirs();
96  
97  		File file = new File(theOutputPath + theVersion + ".properties");
98  		file.delete();
99  		file.createNewFile();
100 		Writer writer = new FileWriter(file);
101 		writer = new BufferedWriter(writer);
102 
103 		writer.append("#event -> structure map for HL7 " + theVersion + "\r\n");
104 		if ("2.1".equals(theVersion) || "2.2".equals(theVersion)) {
105 			writer.append("#note: no mappings are defined for 2.1 and 2.2");
106 			writer.close();
107 			return;
108 		}
109 
110 		ResultSet rs = createStructureQuery(theVersion);
111 		Map<String, Set<String>> trigger2structure = new TreeMap<String, Set<String>>();
112 		while (rs.next()) {
113 			String messageType = rs.getString("message_typ_snd");
114 			String triggerCode = rs.getString("event_code");
115 			final String trigger = messageType + "_" + triggerCode;
116 			String structure = rs.getString("message_structure_snd");
117 
118 			if (messages.contains(trigger)) {
119 				ourLog.info("Skipping Eventmap for trigger {} because a structure exists!", trigger);
120 				continue;
121 			}
122 
123 			if ("ACK".equals(messageType)) {
124 				continue;
125 			}
126 			if ("NUL".equals(structure)) {
127 				continue;
128 			}
129 
130 			/*
131 			 * This logic keeps the structure value which matches exactly the
132 			 * trigger value at the end of the list. This is desirable as
133 			 * sometimes multiple structures mark themselves as being associated
134 			 * with the same trigger event, so we want to favour the one with
135 			 * the matching name.
136 			 * 
137 			 * Example: for an ORM^R01, favour creating an ORM_O01 structure and
138 			 * not an OMD_O01 even though the latter also declares itself as
139 			 * being the structure for ORM^R01 in the database.
140 			 */
141 
142 			if (!trigger2structure.containsKey(trigger)) {
143 				trigger2structure.put(trigger, new TreeSet<String>(new Comparator<String>() {
144 
145 					public int compare(String theO1, String theO2) {
146 						if (theO1.equals(theO2)) {
147 							return 0;
148 						} else if (theO1.equals(trigger)) {
149 							return 1;
150 						} else if (theO2.equals(trigger)) {
151 							return -1;
152 						} else {
153 							return theO1.compareTo(theO2);
154 						}
155 					}
156 				}));
157 			}
158 
159 			trigger2structure.get(trigger).add(structure);
160 
161 		}
162 
163 		for (Map.Entry<String, Set<String>> nextEntry : trigger2structure.entrySet()) {
164 			for (String nextStructure : nextEntry.getValue()) {
165 				writer.append(nextEntry.getKey()).append("\t").append(nextStructure).append("\r\n");
166 			}
167 		}
168 
169 		rs.close();
170 		writer.close();
171 	}
172 
173 	private static List<TriggerDesc> getTriggers(String theVersion) throws SQLException {
174 		String query = //
175 		"SELECT HL7Versions.hl7_version, HL7EventMessageTypes.message_typ_snd, HL7Events.event_code, " + "       HL7EventMessageTypes.message_structure_snd, HL7Events.description," + "        HL7EventMessageTypes.message_structure_return " + "FROM   HL7Versions "
176 				+ "INNER JOIN (HL7Events INNER JOIN HL7EventMessageTypes ON (HL7Events.version_id = HL7EventMessageTypes.version_id) AND (HL7Events.event_code = HL7EventMessageTypes.event_code)) ON HL7Versions.version_id = HL7Events.version_id"
177 				+ " WHERE HL7Versions.hl7_version = '" + theVersion + "';";
178 
179 		NormativeDatabase normativeDatabase = NormativeDatabase.getInstance();
180 		Connection conn = normativeDatabase.getConnection();
181 		List<TriggerDesc> triggerDescs = new ArrayList<TriggerDesc>();
182 		try {
183 			Statement stmt = conn.createStatement();
184 			ResultSet rs = stmt.executeQuery(query);
185 
186 			while (rs.next()) {
187 				String version = rs.getString("hl7_version");
188 				String type = rs.getString("message_typ_snd") + "^" + rs.getString("event_code");
189 				String structure = rs.getString("message_structure_snd");
190 				String description = StringUtils.defaultString(rs.getString("description"));
191 				String returnStructure = rs.getString("message_structure_return");
192 
193 				TriggerDesc td = new TriggerDesc();
194 				td.setVersion(version);
195 				td.setType(type);
196 				td.setStructure(structure);
197 				td.setDescription(description.replace("\"", "\\\""));
198 				td.setReturnStructure(returnStructure);
199 
200 				triggerDescs.add(td);
201 
202 			}
203 
204 		} finally {
205 			normativeDatabase.returnConnection(conn);
206 		}
207 		return triggerDescs;
208 	}
209 
210 }