1 package org.openphacts.nextprot;
2
3
4
5
6
7
8
9
10 import java.io.File;
11 import java.io.FileWriter;
12 import java.io.InputStream;
13 import java.io.IOException;
14 import java.io.Writer;
15
16 import java.net.URL;
17
18 import java.sql.SQLException;
19
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Properties;
24
25 import org.apache.commons.cli.Option;
26 import org.apache.commons.cli.Options;
27 import org.apache.commons.cli.OptionBuilder;
28 import org.apache.commons.cli.ParseException;
29 import org.apache.commons.cli.PosixParser;
30 import org.apache.commons.cli.CommandLine;
31 import org.apache.commons.cli.CommandLineParser;
32 import org.apache.commons.cli.HelpFormatter;
33
34 import org.apache.commons.io.FileUtils;
35
36
37 import org.apache.commons.lang.StringUtils;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 import org.apache.velocity.VelocityContext;
43 import org.apache.velocity.context.Context;
44 import org.apache.velocity.app.VelocityEngine;
45 import org.apache.velocity.runtime.RuntimeConstants;
46
47 import org.apache.velocity.tools.ToolManager;
48 import org.apache.velocity.tools.ToolContext;
49 import org.apache.velocity.tools.config.XmlFactoryConfiguration;
50
51 import velosurf.Velosurf;
52
53 public class TemplateAssembler {
54 private ToolManager toolManager;
55 private VelocityEngine vEngine;
56
57 private static Log log = LogFactory.getLog(TemplateAssembler.class);
58
59 private static final String LOGGER_NAME = "CONSOLE";
60 private static final String MAIN_TEMPLATE = "main.vm";
61 private static final String TOOLS_CONFIG = "tools.xml";
62 private static final String DATABASE_CONFIG = "database.xml";
63 private static final String VELOSURF_KEY = "db";
64
65 private static final String OPT_OUTPUT = "output";
66 private static final String OPT_VELOSURF = "velosurf";
67 private static final String OPT_USER = "user";
68 private static final String OPT_PASSWORD = "password";
69 private static final String OPT_MODEL = "dbmodel";
70
71 private static final String USAGE = "nextor [<template-directory>|<template-file>] [<options>]";
72
73 public TemplateAssembler() {
74 }
75
76 private ToolManager getToolManager() {
77 if( toolManager == null ) {
78 toolManager = new ToolManager( false, true );
79 try {
80 InputStream is = this.getClass().getClassLoader().getResourceAsStream( TOOLS_CONFIG );
81 if( is != null ) {
82 XmlFactoryConfiguration cfg = new XmlFactoryConfiguration();
83 cfg.read( is );
84 is.close();
85 toolManager.configure( cfg );
86 log.debug( "Configured context tools from "+TOOLS_CONFIG );
87 }
88 else
89 log.warn( "Cannot configure tools" );
90 }
91 catch( IOException ioe ) {
92 log.warn( "Cannot configure tools: "+((ioe.getMessage()!=null)?ioe.getMessage():"") );
93 }
94 }
95 return toolManager;
96 }
97
98 private void insertVelosurf( File templDir, String mPath, Context ctxt ) {
99 File tDir = templDir.getAbsoluteFile();
100 if( templDir.isFile() )
101 tDir = templDir.getParentFile();
102 if( tDir == null ) {
103 log.warn( "Cannot inject Velosurf tool into velocity context" );
104 return;
105 }
106
107 File modelFile = null;
108 if( mPath != null )
109 modelFile = new File( mPath );
110 else
111 modelFile = new File( tDir, DATABASE_CONFIG );
112 if( !modelFile.exists() ) {
113 log.warn( "Cannot find database model configuration at "+modelFile );
114 return;
115 }
116 log.debug( "Reading database model from "+modelFile );
117 try {
118 Velosurf velo = new Velosurf( modelFile );
119 String kName = (String)ctxt.get( OPT_VELOSURF );
120 if( kName == null )
121 kName = VELOSURF_KEY;
122 ctxt.put( kName, velo );
123 log.debug( "Velosurf injected into context, access name is \""+kName+"\"" );
124 }
125 catch( IOException ioe ) {
126 log.warn( ioe );
127 }
128 catch( SQLException sqe ) {
129 log.warn( sqe );
130 }
131 }
132
133 private void insertTemplateContent( File templDir, Context ctxt ) {
134 File tDir = templDir;
135 if( templDir.isFile() )
136 tDir = templDir.getParentFile();
137
138 Iterator<File> it = FileUtils.iterateFiles( tDir, new String[] { "xml", "vm", "vtl" }, false );
139 while( it.hasNext() ) {
140 File theF = it.next();
141 try {
142 String cont = FileUtils.readFileToString( theF );
143 String fKey = theF.getName().replace( '.', '_' );
144 ctxt.put( fKey, cont );
145 log.debug( "Load content of \""+fKey+"\" from "+theF );
146 }
147 catch( IOException ioe ) {
148 log.warn( ioe );
149 }
150 }
151 }
152
153 private Context createVelocityContext( File templDir, Map context ) {
154 ToolManager manager = getToolManager();
155 if( manager == null )
156 return new VelocityContext( context );
157 ToolContext tc = manager.createContext();
158
159
160 insertVelosurf( templDir, (String)context.get( OPT_MODEL ), tc );
161
162
163 insertTemplateContent( templDir, tc );
164
165
166 tc.put( "files", FileUtils.class );
167 tc.put( "strings", StringUtils.class );
168
169
170 tc.putAll( context );
171
172 return tc;
173 }
174
175 private Properties extractVelocityProperties( Map context ) {
176 Properties props = new Properties();
177 String rLoader = null;
178 if( (rLoader = (String)context.get( "resource.loader" )) == null )
179 rLoader = "file";
180 props.put( "resource.loader", rLoader );
181 rLoader = rLoader + ".";
182 Iterator<Map.Entry> it = context.entrySet().iterator();
183 while( it.hasNext() ) {
184 Map.Entry me = it.next();
185 if( (me.getKey() != null) &&
186 (me.getKey().toString().startsWith( rLoader )) )
187 props.put( me.getKey().toString(), me.getValue() );
188 }
189 return props;
190 }
191
192 private VelocityEngine getVelocityEngine( Properties props )
193 throws TemplateException {
194
195 if( vEngine == null ) {
196 Properties vProps = extractVelocityProperties( props );
197
198 log.debug( "Creating velocity engine using properties: "+vProps );
199
200 vEngine = new VelocityEngine();
201 vEngine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
202 "org.apache.velocity.runtime.log.Log4JLogChute" );
203 vEngine.setProperty("runtime.log.logsystem.log4j.logger",
204 LOGGER_NAME);
205 log.debug( "Velocity engine logging setup done." );
206 try {
207 vEngine.init( vProps );
208 log.debug( "Velocity engine initialized." );
209 }
210 catch( Exception ex ) {
211 log.error( ex );
212 throw new TemplateException( ex.getMessage() );
213 }
214 }
215 return vEngine;
216 }
217
218 private Properties createVelocityProperties( File templDir, Map context ) {
219 Properties props = new Properties();
220
221 StringBuilder stb = new StringBuilder( System.getProperty( "user.dir" ) );
222 if( templDir.isFile() ) {
223 File parent = templDir.getParentFile();
224 if( parent != null ) {
225 stb.append( ", " );
226 stb.append( parent );
227 }
228 }
229 else {
230 stb.append( ", " );
231 stb.append( templDir.getAbsoluteFile() );
232 }
233
234 props.put("file.resource.loader.path", stb.toString() );
235 props.put("file.resource.loader.modificationCheckInterval", "120" );
236 props.put("file.resource.loader.cache", "true" );
237
238 if( context != null ) {
239 String rLoader = null;
240 if( (rLoader = (String)context.get( "resource.loader" )) == null )
241 rLoader = "file";
242 props.put( "resource.loader", rLoader );
243 props.putAll( context );
244 }
245 else
246 props.put( "resource.loader", "file" );
247
248 return props;
249 }
250
251 private Writer createWriter( File templDir, File outDir )
252 throws IOException {
253
254 File outD = null;
255 Writer outW = null;
256 if( outDir == null ) {
257 if( templDir.isDirectory() )
258 outD = templDir;
259 else
260 outD = templDir.getParentFile();
261 }
262 else {
263 if( outDir.exists() && outDir.isDirectory() )
264 outD = outDir;
265 else
266 outW = new FileWriter( outDir );
267 }
268
269 if( outW == null )
270 outW = new FileWriter( File.createTempFile( "nextprot", ".rdf", outD ) );
271
272 return outW;
273 }
274
275
276
277
278
279
280
281
282
283
284 public void processTemplates( File templDir, File outDir, Map context )
285 throws TemplateException {
286
287 if( !templDir.exists() ) {
288 log.error( "Template path does not exist: "+templDir );
289 throw new TemplateException( "Template path does not exist: "+templDir );
290 }
291
292 Properties props = createVelocityProperties( templDir, context );
293 String tName = MAIN_TEMPLATE;
294 if( templDir.isFile() )
295 tName = templDir.getName();
296
297 log.debug( "Using template "+tName );
298
299 VelocityEngine ve = getVelocityEngine( props );
300 Context vc = createVelocityContext( templDir, context );
301
302 try {
303 Writer outW = createWriter( templDir, outDir );
304 if( !ve.mergeTemplate( tName, vc, outW ) )
305 log.error( "Cannot transform template "+tName );
306 }
307 catch( Exception ex ) {
308 log.error( ex );
309 throw new TemplateException( ex.getMessage() );
310 }
311 }
312
313
314
315
316
317
318
319 public void processTemplates( File templDir )
320 throws TemplateException {
321
322 processTemplates( templDir, null, null );
323 }
324
325 private static Properties parse( String[] argv ) {
326 Options options = new Options();
327
328 options.addOption( OptionBuilder.withLongOpt( OPT_OUTPUT )
329 .withDescription( "output directory, defaults to the current directory" )
330 .hasArgs()
331 .withArgName("DIRECTORY")
332 .create( "o" ) );
333
334 options.addOption( OptionBuilder.withLongOpt( OPT_VELOSURF )
335 .withDescription( "attribute key for accessing the velosurf functionality, defaults to \""+
336 VELOSURF_KEY+"\"" )
337 .hasArgs()
338 .withArgName("KEY")
339 .create( "k" ) );
340
341 options.addOption( OptionBuilder.withLongOpt( OPT_MODEL )
342 .withDescription( "database model mapping file, defaults to \""+DATABASE_CONFIG+"\"" )
343 .hasArgs()
344 .withArgName("MODELFILE")
345 .create( "m" ) );
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360 options.addOption( "v", "verbose", false, "switch verbose mode on" );
361 options.addOption( "h", "help", false, "print help screen" );
362
363 CommandLineParser parser = new PosixParser();
364 CommandLine line = null;
365 HelpFormatter help = new HelpFormatter();
366
367 Properties props = new Properties();
368 props.put( OPT_VELOSURF, VELOSURF_KEY );
369 props.put( OPT_MODEL, DATABASE_CONFIG );
370
371
372
373
374 try {
375 line = parser.parse( options, argv );
376 }
377 catch( ParseException pex ) {
378 log.error( pex );
379 error( "parsing command line: "+
380 ((pex.getMessage()!=null)?pex.getMessage():"" ),
381 1 );
382 }
383 if( line.hasOption( "h" ) ) {
384 help.printHelp( USAGE, options );
385 System.exit( 1 );
386 }
387
388 Option[] opts = line.getOptions();
389 for( int i = 0; i < opts.length; i++ ) {
390 if( opts[i].getValue() != null )
391 props.put( opts[i].getLongOpt(), opts[i].getValue() );
392 }
393
394 String[] al = line.getArgs();
395 if( (al.length <= 0) && (opts.length <= 0) ) {
396 help.printHelp( USAGE, options );
397 error( "missing arguments", 2 );
398 }
399
400 for( int i = 0; i < al.length; i++ )
401 props.put( "_arg"+i, al[i] );
402
403 File testF = new File( props.getProperty( "_arg0", System.getProperty( "user.dir", "." ) ) );
404 if( !testF.exists() )
405 error( testF+" does not exist", 3 );
406 props.put( "templatePath", testF );
407
408 return props;
409 }
410
411 private static void error( String msg, int rc ) {
412 System.out.println();
413 System.out.println( "Error ["+Math.abs(rc)+"]: "+msg );
414 System.out.println();
415 if( rc > 0 )
416 System.exit( rc );
417 }
418
419 private static void logo() {
420 System.out.println();
421 System.out.println( "nextor - a template based tool to transform relational database models into rdf");
422 System.out.println( "mailto:Oliver.Karch@merckgroup.com");
423 System.out.println( "(c) 2012 merckgroup.com");
424 System.out.println();
425 }
426
427 public static void main( String[] args ) {
428 logo();
429 Properties props = parse( args );
430 log.debug( "Command line properties: "+props );
431 TemplateAssembler ass = new TemplateAssembler();
432 try {
433 File templDir = (File)props.get( "templatePath" );
434 File outDir = new File( props.getProperty( OPT_OUTPUT, System.getProperty( "user.dir", "" ) ) );
435 ass.processTemplates( templDir, outDir, props );
436 }
437 catch( TemplateException ex ) {
438 ex.printStackTrace();
439 error( ex.getMessage(), 4 );
440 }
441 }
442 }