001    package com.softwarementors.extjs.djn.jscodegen;
002    
003    import java.io.File;
004    import java.io.IOException;
005    import java.util.HashMap;
006    import java.util.Map;
007    
008    import org.apache.commons.io.FileUtils;
009    import org.apache.log4j.Logger;
010    
011    import com.softwarementors.extjs.djn.StringUtils;
012    import com.softwarementors.extjs.djn.api.RegisteredApi;
013    import com.softwarementors.extjs.djn.api.Registry;
014    import com.softwarementors.extjs.djn.config.GlobalConfiguration;
015    
016    public class CodeFileGenerator {
017      private Registry registry;
018      Map<String, StringBuilder> debugFileOutputs = new HashMap<String,StringBuilder>();
019      Map<String, StringBuilder> noCommentsFileOutputs = new HashMap<String,StringBuilder>();
020      
021      private GlobalConfiguration getGlobalConfiguration() {
022        return this.registry.getGlobalConfiguration();
023      }
024      
025      private CodeFileGenerator( Registry registry) {
026        assert registry != null;
027        
028        this.registry = registry;
029      }
030      
031      private static final Logger logger = Logger.getLogger( CodeFileGenerator.class);
032      
033      public static void updateApiFiles( Registry registry ) throws IOException {
034        assert registry != null;
035        
036        CodeFileGenerator generator = new CodeFileGenerator(registry);
037        
038        generator.generateCode();
039        generator.saveCode();
040      }
041    
042      private void generateCode() {
043        for( RegisteredApi api : this.registry.getApis() ) {
044          String fileName = api.getFullApiFileName();
045          StringBuilder debugOutput = this.debugFileOutputs.get(fileName);
046          StringBuilder noCommentsOutput = this.noCommentsFileOutputs.get(fileName);
047          assert (debugOutput == null) == (noCommentsOutput == null);
048          
049          if( debugOutput == null) {
050            debugOutput = new StringBuilder();
051            this.debugFileOutputs.put( fileName, debugOutput);
052            
053            noCommentsOutput = new StringBuilder();
054            this.noCommentsFileOutputs.put( fileName, noCommentsOutput);
055          }
056          
057          ApiCodeGenerator generator = new ApiCodeGenerator( getGlobalConfiguration(), api );
058          generator.appendCode(debugOutput, false);
059          generator.appendCode(noCommentsOutput, true);
060        }
061      }
062    
063      private void saveCode() throws IOException 
064      {
065        for( String defaultFileName : this.debugFileOutputs.keySet() ) {
066          String debugFileName = getDebugFileName(defaultFileName);
067          String minifiedFileName = Minifier.getMinifiedFileName(defaultFileName);
068    
069          boolean minify = getGlobalConfiguration().getMinify();
070          boolean debug = getGlobalConfiguration().getDebug();
071          
072          String debugCode = this.debugFileOutputs.get(defaultFileName).toString();
073          String defaultCode = debugCode;
074          String minifiedCode = debugCode;
075          
076          boolean haveMinifiedCode = false;
077          if( minify ) {
078            String noCommentsCode = this.noCommentsFileOutputs.get(defaultFileName).toString();
079            minifiedCode = Minifier.minify(noCommentsCode, defaultFileName, debugCode.length());
080            if( minifiedCode == null ) {
081              logger.warn( "Unable to minify code: using Debug code for '" + minifiedFileName + "'.");
082              minifiedCode = debugCode;
083            }
084            else {
085              haveMinifiedCode = true;
086            }
087          }
088          
089          if( !debug && haveMinifiedCode) {
090            defaultCode = minifiedCode;
091            if( logger.isDebugEnabled()) {
092              logger.debug( "Production mode: using minified code for '" + defaultFileName + "'");
093            }
094          }
095          else {
096            if( logger.isDebugEnabled()) {
097              logger.debug( "Using Debug code for '" + defaultFileName + "'");
098            }
099          }
100    
101          updateFile( debugFileName, debugCode );
102          updateFile( defaultFileName, defaultCode );
103          if( minify ) {
104            updateFile( minifiedFileName, minifiedCode );
105          }
106          else {
107            deleteFile( minifiedFileName );
108          }
109          
110        }
111      }
112    
113      private void deleteFile( String fullFileName ) {
114        assert !StringUtils.isEmpty(fullFileName);
115    
116        File file = new File( fullFileName );
117        if( file.exists()) {
118          file.delete();
119          if( logger.isDebugEnabled() ) {
120            logger.debug( "Api file deleted: '" + file.getAbsolutePath() + "'");
121          }
122        }
123      }
124      
125      private void updateFile( String  fullFileName, String code ) throws IOException {
126        assert !StringUtils.isEmpty(fullFileName);
127        assert code != null;
128        
129        File file = new File( fullFileName );    
130        if( !fileContentEquals(file, code) ) {
131          FileUtils.writeStringToFile(file, code);
132          if( logger.isDebugEnabled() ) {
133            logger.debug( "Api file updated: '" + file.getAbsolutePath() + "'");
134          }
135        }
136        else {
137          if( logger.isDebugEnabled() ) {
138            logger.debug( "Api file '" + file.getAbsolutePath() + '\'' + " is up to date: it was not rewritten.");
139          }
140        }
141      }
142    
143      private boolean fileContentEquals(File file, String code) throws IOException {
144        assert file != null;
145        assert code != null;
146        
147        if( file.exists()) {
148          String contents = FileUtils.readFileToString(file);
149          boolean result = contents.equals( code );
150          return result;
151        }
152        return false;
153      }
154      
155      private String getDebugFileName( String file ) {
156        String result = file.replace( ".js", "-debug.js");
157        return result;
158      }
159    }