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 "SourceGenerator.java".  Description: 
010    "Tools for the generation of HL7 v3 source code." 
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    package ca.uhn.hl7v3.sourcegen;
029    
030    import java.io.*;
031    import java.sql.*;
032    
033    /**
034     * Tools for the generation of HL7 v3 source code.
035     * @author Bryan Tripp
036     */
037    public class SourceGenerator {
038        
039        /** Creates a new instance of SourceGenerator */
040        public SourceGenerator() {
041        }
042        
043        public static void writeEJBCode(File baseDirectory, Connection conn) throws Exception {
044            File rimDir = prepDirectories(baseDirectory);
045            
046            DefinitionLoader dl = new DefinitionLoader(conn);
047            String[] classes = dl.getRIMClassNames();
048            for (int i = 0; i < classes.length; i++) {
049                writeEJBCode(rimDir, classes[i], conn);
050            }
051            String[] datatypes = dl.getRIMDataTypeNames();
052            File dtDir = new File(rimDir, "datatype");
053            for (int i = 0; i < datatypes.length; i++) {
054                writeDataTypeCode(dtDir, datatypes[i], conn);
055            }        
056        }
057        
058        /** 
059         * Checks that the given baseDirectory is a directory (throws Exception otherwise) and 
060         * creates appropriate RIM class and datatype directories under it.  Returns the RIM class
061         * directory, under which the child "datatype" is the datatype directory.  
062         */
063        private static File prepDirectories(File baseDirectory) throws Exception {
064            if (!baseDirectory.isDirectory()) {
065                throw new Exception("The specified base directory " + baseDirectory.toString() + " is not a directory.");
066            }
067            
068            File rimDir = new File(baseDirectory, getRIMPackage().replace('.', File.separatorChar));
069            File dtDir = new File(rimDir, "datatype");
070            dtDir.mkdirs();
071    
072            return rimDir;
073        }
074        
075        /**
076         * Writes source code for an EJB representation of the given RIM class to
077         * the given directory.
078         */
079        public static void writeEJBCode(File rimDir, String RIMClass, Connection conn) throws Exception {
080            DefinitionLoader dl = new DefinitionLoader(conn);
081            ClassDefinition def = dl.getRIMClassDef(RIMClass);
082            CMPClassGenerator gen = new CMPClassGenerator();
083            
084            //write home interface ...
085            BufferedWriter home = new BufferedWriter(new FileWriter(new File(rimDir, def.getName() + "Home.java")));
086            home.write(gen.makeHomeCode(def));
087            home.flush();
088            home.close();
089            
090            //write remote interface ...
091            BufferedWriter remote = new BufferedWriter(new FileWriter(new File(rimDir, def.getName() + ".java")));
092            remote.write(gen.makeRemoteCode(def));
093            remote.flush();
094            remote.close();
095            
096            //write bean interface ...
097            BufferedWriter bean = new BufferedWriter(new FileWriter(new File(rimDir, def.getName() + "Bean.java")));
098            bean.write(gen.makeBeanCode(def));
099            bean.flush();
100            bean.close();
101        }
102        
103        public static void writeDataTypeCode(File dtDir, String dataType, Connection conn) throws Exception {
104            DefinitionLoader dl = new DefinitionLoader(conn);
105            DataTypeDefinition def = dl.getDataTypeDef(dataType);
106            DataTypeGenerator gen = new DataTypeGenerator();
107            
108            BufferedWriter out = new BufferedWriter(new FileWriter(new File(dtDir, def.getName() + ".java")));
109            out.write(gen.makeDataType(def));
110            out.flush();
111            out.close();
112        }
113        
114        /** Returns a public method signature for the setter of a given attribute (not incl. throws clause) */
115        public static String makeSetterSignature(AttributeDefinition att) {
116            StringBuffer code = new StringBuffer();
117            code.append("public void set");
118            code.append(att.getName().substring(0, 1).toUpperCase());
119            code.append(att.getName().substring(1, att.getName().length()));
120            code.append("(");
121            code.append(att.getDataType());
122            code.append(" ");
123            code.append(att.getName());
124            code.append(")");
125            return code.toString();
126        }
127        
128        /** Returns a public method signature for the getter of a given attribute (not incl. throws clause) */
129        public static String makeGetterSignature(AttributeDefinition att) {
130            StringBuffer code = new StringBuffer();
131            code.append("public ");
132            code.append(att.getDataType());
133            code.append(" get");
134            code.append(att.getName().substring(0, 1).toUpperCase());
135            code.append(att.getName().substring(1, att.getName().length()));
136            code.append("()");
137            return code.toString();
138        }
139        
140        public static String getRIMPackage() {
141            return "ca.uhn.hl7v3.rim";
142        }
143        
144        public static String getRIMDataTypePackage() {
145            return "ca.uhn.hl7v3.rim.datatype";
146        }
147        
148        public static String makeJavaDocComment(String description, int indent) {
149            if (description == null) {
150                return spaces(indent) + "/** */ \r\n";
151            }
152                
153            int width = 70 - indent;
154            StringBuffer comment = new StringBuffer();
155            comment.append(spaces(indent));
156            comment.append("/** \r\n");
157            
158            boolean done = false;
159            int start = 0;
160            while (!done) {
161                comment.append(spaces(indent));
162                comment.append(" * ");
163                int lineBreak = findLineBreak(description, start, width);
164                comment.append(description.substring(start, lineBreak).trim());
165                comment.append(" \r\n");
166                if (lineBreak == description.length()) {
167                    done = true;
168                } else {
169                    start = lineBreak;
170                }
171            }
172            comment.append(spaces(indent));
173            comment.append(" */ \r\n");
174            return comment.toString();
175        }
176        
177        /** Returns a String with the number of specified spaces. */
178        private static String spaces(int numSpaces) {
179            StringBuffer spaces = new StringBuffer();
180            for (int i = 0; i < numSpaces; i++) {
181                spaces.append(" ");
182            }
183            return spaces.toString();
184        }
185        
186        /**
187         * Returns a suitable location for a line break (e.g. beginning of a word) in the given
188         * String, starting at the given location, using the given maximum line length.
189         */
190        public static int findLineBreak(String s, int start, int maxLength) {
191            int lineBreak = start + maxLength;
192            int existingCarriageReturnLoc = s.indexOf('\r', start);
193            if (existingCarriageReturnLoc > -1 && existingCarriageReturnLoc < lineBreak) {
194                lineBreak = existingCarriageReturnLoc + 1;
195            } else if (lineBreak >= s.length()) {
196                lineBreak = s.length();
197            } else {
198                boolean found = false;
199                while (!found) {
200                    char c = s.charAt(lineBreak);
201                    if (Character.isWhitespace(c)) {
202                        found = true;
203                        lineBreak++;
204                    } else {
205                        lineBreak--;
206                    }
207                }
208            }
209            return lineBreak;
210        }
211        
212        public static void main(String args[]) {
213            if (args.length < 1 || args.length > 2) {
214                System.out.println("Usage: SourceGenerator base_directory [RIM_class]");
215                System.exit(1);
216            }
217            
218            try {
219                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
220                Connection conn = DriverManager.getConnection("jdbc:odbc:RIM");
221                File base = new File(args[0]);
222                base.mkdirs();
223                if (args.length == 1) {
224                    SourceGenerator.writeEJBCode(base, conn);
225                } else {
226                    SourceGenerator.writeEJBCode(base, args[1], conn);
227                }
228                conn.close();
229            } catch (Exception e) {
230                e.printStackTrace();
231            }
232        }
233    }