/*
* Name: GenericMerger
* Authors: Richard Rodger
*
* Copyright (c) 2004 Richard Rodger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// package
package org.jostraca.process;
// import
import org.jostraca.Property;
import org.jostraca.Template;
import org.jostraca.WriterFormat;
import org.jostraca.BasicWriterFormat;
import org.jostraca.WriterFormatLexer;
import org.jostraca.WriterFormatParser;
import org.jostraca.ParseMessage;
import org.jostraca.transform.TextualTransformManager;
import org.jostraca.section.SectionSet;
import org.jostraca.section.ModifierManager;
import org.jostraca.util.Standard;
import org.jostraca.util.PropertySet;
import org.jostraca.util.ValueSet;
import org.jostraca.util.ValueCode;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.StringReader;
/** Processing class for merging template text and script into <code>CodeWriter</code> formats.
*/
public class GenericMerger extends TemplateHandlerSupport {
private ModifierManager iSectionModifierManager = new ModifierManager();
private TextualTransformManager iCodeWriterTextualTransformManager = new TextualTransformManager( "CodeWriter" );
public GenericMerger() {
// do nothing
}
protected void processImpl( Template pTemplate ) {
Template template = pTemplate;
PropertySet tmps = pTemplate.getMergedPropertySet();
SectionSet sectionSet = template.getSectionSet();
WriterFormat wf = makeWriterFormat( tmps );
modifySections( wf.getSource(), sectionSet, tmps );
String codeWriterSource = insertText( wf.getPath(), wf.getSource(), sectionSet, tmps );
// perform some text transformations after code writer has been generated
codeWriterSource = postProcess( codeWriterSource, tmps );
String codeWriterPath = createCodeWriterPath( tmps );
template.setCodeWriterPath( new File( codeWriterPath ) );
template.setCodeWriterSource( codeWriterSource );
}
protected void completeImpl( List pTemplateList ) {
// do nothing
}
protected WriterFormat makeWriterFormat( PropertySet pPropertySet ) {
BasicWriterFormat bwf = new BasicWriterFormat( pPropertySet );
return bwf;
}
/** Modify sections just prior to build.
* @param pWriterFormatSource Source of writer format
* @param pSectionSet Set of Sections to modify
* @param pPropertySet PropertySet used
*/
protected void modifySections( String pWriterFormatSource,
SectionSet pSectionSet,
PropertySet pPropertySet
)
{
// create section modifier property set
PropertySet sectionModPropertySet = new PropertySet();
sectionModPropertySet.overrideWith( pPropertySet );
sectionModPropertySet.set( Property.jostraca_writerformat_source, pWriterFormatSource );
// apply global modifications
iSectionModifierManager.loadModifierClasses( sectionModPropertySet.get( Property.lang_section_all_Modifiers ));
iSectionModifierManager.modify( pSectionSet, sectionModPropertySet );
}
/** Insert sections and properties into writer code.
* @param pSectionSet Set of Sections to insert, if found.
* @param pPropertySet Set of Properties to insert, if found.
*/
private String insertText( String pWriterFormatPath, String pWriterFormatSource, SectionSet pSectionSet, PropertySet pPropertySet ) {
try {
// init lexer/parser
StringReader writerFormatReader = new StringReader( pWriterFormatSource );
WriterFormatLexer writerFormatLexer = new WriterFormatLexer( writerFormatReader );
writerFormatLexer.setSectionSet( pSectionSet );
writerFormatLexer.setPropertySet( pPropertySet );
WriterFormatParser writerFormatParser = new WriterFormatParser( writerFormatLexer );
// parse
writerFormatParser.start();
// check for user errors
if( writerFormatLexer.hasParseMessages() ) {
throw ProcessException.CODE_writer_format_parse( makeParseErrorContext( pWriterFormatPath,
writerFormatLexer.getParseMessages() ) );
}
return writerFormatLexer.getCodeWriter();
}
catch( ProcessException pe ) {
throw pe;
}
catch( Exception e ) {
throw new ProcessException( e );
}
}
/** Post process code writer code using textual transforms.
* @param pCodeWriter Code Writer text
* @param pPropertySet PropertySet used for build.
*/
private String postProcess( String pCodeWriter, PropertySet pPropertySet ) {
loadPostProcessTextualTransforms( pPropertySet );
return iCodeWriterTextualTransformManager.transform( pCodeWriter );
}
/** Create code writer path.
* @param pPropertySet Determines code writer path.
*/
private String createCodeWriterPath( PropertySet pPropertySet ) {
String prefix = pPropertySet.get( Property.main_CodeWriterPrefix );
String writer = pPropertySet.get( Property.main_CodeWriter );
String suffix = pPropertySet.get( Property.main_CodeWriterSuffix );
String output = pPropertySet.get( Property.main_WorkFolder, Standard.DOT );
if( ! output.endsWith( File.separator ) ) {
output = output + File.separator;
}
String cwp = output + prefix + writer + suffix;
return cwp;
}
private PropertySet makeParseErrorContext( String pWriterFormatPath, ArrayList pParseMessages ) {
PropertySet context = new PropertySet();
// REVIEW; hard code Strings!
context.set( "file", pWriterFormatPath );
StringBuffer parse_error = new StringBuffer();
int numPM = pParseMessages.size();
for( int pmI = 0; pmI < numPM; pmI++ ) {
ParseMessage pm = (ParseMessage) pParseMessages.get(pmI);
parse_error.append( pm.getType() + Standard.COLON +
(Standard.EMPTY.equals(pm.getFileName()) ? Standard.EMPTY : pm.getFileName() + Standard.COLON ) +
( (ParseMessage.INVALID == pm.getLine()) ? Standard.EMPTY : "line:"+pm.getLine() + Standard.COLON ) +
( (ParseMessage.INVALID == pm.getColumn()) ? Standard.EMPTY : "column:"+pm.getColumn() + Standard.COLON ) +
pm.getMessage() +
( pmI < numPM - 1 ? Standard.COMMA_SPACE : Standard.EMPTY )
);
}
if( 0 < numPM ) {
context.set("parse-error", parse_error.toString() );
}
return context;
}
/** Get post processing text transforms
* @param PropertySet PropertySet determines text transforms to load
*/
private void loadPostProcessTextualTransforms( PropertySet pPropertySet ) {
String classList = null;
try {
classList = pPropertySet.get( Property.lang_CodeWriterTransforms );
iCodeWriterTextualTransformManager.loadClasses( classList );
}
catch( Exception e ) {
throw ProcessException.CODE_post_proc_tran( new ValueSet( ValueCode.CLASSLIST, classList ), e );
}
}
}