001package org.vishia.xml;
002
003import java.io.*;
004
005import org.vishia.mainCmd.*;
006import org.vishia.util.FileSystem;
007
008/** Class for conversion of any plain text files, source codes etc. into a browser visible HTML-format.</br>
009    The problem is: Some browsers shows files with xml content and with the extension txt
010    yet in form of xml files with hardheaded interpretation. If the content of the file
011    will be shown only in text format, all things of xml like scripting should be hided,
012    especially the tag structur. The <-char is converted to &lt; A HTML frame is generated.
013*/
014
015public class Textfile2Html extends MainCmd
016{
017  
018  /**Version, history and license.
019   * <ul>
020   * <li>2014-05-03 Hartmut bugfix: if a line cannot wrapped on space, a character was missed.
021   * <li>2009-12-31: Hartmut corr: Creation of a directory of output path. 
022   * <li>2005-06-00 Hartmut Created.                  
023   * </ul>
024   * <br><br>
025   * <b>Copyright/Copyleft</b>:
026   * For this source the LGPL Lesser General Public License,
027   * published by the Free Software Foundation is valid.
028   * It means:
029   * <ol>
030   * <li> You can use this source without any restriction for any desired purpose.
031   * <li> You can redistribute copies of this source to everybody.
032   * <li> Every user of this source, also the user of redistribute copies
033   *    with or without payment, must accept this license for further using.
034   * <li> But the LPGL is not appropriate for a whole software product,
035   *    if this source is only a part of them. It means, the user
036   *    must publish this part of source,
037   *    but don't need to publish the whole source of the own product.
038   * <li> You can study and modify (improve) this source
039   *    for own using or for redistribution, but you have to license the
040   *    modified sources likewise under this LGPL Lesser General Public License.
041   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
042   * </ol>
043   * If you are intent to use this sources without publishing its usage, you can get
044   * a second license subscribing a special contract with the author. 
045   * 
046   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
047   * 
048   */
049  public static final String sVersion = "2014-05-03";
050
051
052  /**Cmdline-argument, set on -i option. Inputpath.*/
053  String sPathIn = null;
054
055  /**Cmdline-argument, set on -o option. Outputpath.*/
056  String sPathOut = null;
057
058  /**Cmdline-argument, set on -f option. Filename.*/
059  String sFile = "";
060
061  /**Cmdline-argument, set on -linesize: option.*/
062  int maxLineSize = 120;
063  
064  /** String of spaces to provide some spaces for indent*/
065  static String sIndent = "                              ";
066
067  /**Writer of the output used internally.*/
068  private BufferedWriter writer;
069    
070  
071  
072  /*---------------------------------------------------------------------------------------------*/
073  /** main started from java
074   * The command line arguments follow this help text: <pre>
075    super.addHelpInfo("param: -iINPUT -oOUTPUT -fFILE -linesize:size");
076    super.addStandardHelpInfo();
077    super.addHelpInfo("-iINPUT    inputfilepath, a xml like file.");
078    super.addHelpInfo("-oOUTPUT   outputfilepath, this file is written.");
079    super.addHelpInfo("-fFILE     if this argument is given, read from INPUT/FILE, write to OUTPUT/FILE.html.");
080    super.addHelpInfo("-linesize: length of a line, a wrapping is generated after it.");
081    </pre>
082   * */
083  public static void main(String [] args)
084  { Textfile2Html main = new Textfile2Html(args);
085    main.execute();
086    main.exit();
087  }
088
089
090  /** Executes the cmd-line-application. The functionality application class is created inside this method
091      independent of the command line invoke.
092  */
093  void execute()
094  { boolean bOk = true;
095    try{ super.parseArguments(); }
096    catch(Exception exception)
097    { setExitErrorLevel(MainCmdLogging_ifc.exitWithArgumentError);
098      bOk = false;
099    }
100
101    if(bOk)
102    { /** The execution class knows the Textfile2Html Main class in form of the MainCmd super class
103          to hold the contact to the command line execution.
104      */
105
106      try
107      { convert(); 
108      }
109      catch(Exception exception)
110      { //catch the last level of error. No error is reported direct on command line!
111        report("Abort the routine:", exception);
112        setExitErrorLevel(MainCmdLogging_ifc.exitWithErrors);
113      }
114    }
115    //note: exit the command line application in static main()
116  }
117
118
119
120
121
122  /*---------------------------------------------------------------------------------------------*/
123  /** Constructor of the main class.
124      The command line arguments are parsed here. After them the execute class is created as composition of Textfile2Html.
125  */
126  Textfile2Html(String[] args)
127  { super(args);
128    //super.addHelpInfo(getAboutInfo());
129    super.addAboutInfo("Translator text files to a html readable represantiation");
130    super.addAboutInfo("made by JcHartmut, 2006-02-25");
131    super.addHelpInfo("param: -iINPUT -oOUTPUT -fFILE -linesize:size");
132    super.addStandardHelpInfo();
133    super.addHelpInfo("-iINPUT    inputfilepath, a xml like file.");
134    super.addHelpInfo("-oOUTPUT   outputfilepath, this file is written.");
135    super.addHelpInfo("-fFILE     if this argument is given, read from INPUT/FILE, write to OUTPUT/FILE.html.");
136    super.addHelpInfo("-linesize: length of a line, a wrapping is generated after it.");
137
138  }
139
140
141
142
143
144
145  /*---------------------------------------------------------------------------------------------*/
146  /** Tests one argument. This method is invoked from parseArgument. It is abstract in the superclass MainCmd
147      and must be overwritten from the user.
148      @param argc String of the actual parsed argument from cmd line
149      @param nArg number of the argument in order of the command line, the first argument is number 1.
150      @return true is okay,
151              false if the argument doesn't match. The parseArgument method in MainCmd throws an exception,
152              the application should be aborted.
153  */
154  @Override
155  public boolean testArgument(String arg, int nArg)
156  { boolean bOk = true;  //set to false if the argc is not passed
157
158    if(arg.startsWith("-i"))             { sPathIn    = getArgument(2);}
159    else if(arg.startsWith("-o"))        { sPathOut   = getArgument(2);}
160    else if(arg.startsWith("-f"))        { sFile      = getArgument(2);}
161    else if(arg.startsWith("-linesize:")){ maxLineSize= Integer.parseInt(getArgument(10)); }
162    else bOk=false;
163
164    return bOk;
165  }
166
167
168
169
170
171  /*---------------------------------------------------------------------------------------------*/
172  /**Checks the cmdline arguments relation together.
173     If there is an inconsistents, a message should be written. It may be also a warning.
174     @return true if successfull, false if failed.
175  */
176  @Override
177  protected boolean checkArguments()
178  { boolean bOk = true;
179
180    if(sPathIn == null)            { bOk = false; writeError("ERROR argument -i is obligat."); }
181    else if(sPathIn.length()==0)   { bOk = false; writeError("ERROR argument -i without content.");}
182
183    if(sPathOut == null)           { writeWarning("argument -o no outputfile is given, use default"); sPathOut = "out.txt";}
184    else if(sPathOut.length()==0)  { bOk = false; writeError("argument -o without content"); }
185
186    if(!bOk) setExitErrorLevel(exitWithArgumentError);
187
188    return bOk;
189
190 }
191
192  
193  void convert()
194  throws Exception
195  { 
196    BufferedReader reader = null;
197    if(sFile.length()>0 ){ sPathIn = sPathIn + "/" + sFile; }
198    try
199    { reader = new BufferedReader(new FileReader(sPathIn));
200    }
201    catch(FileNotFoundException exception)
202    { writeError("input file not found", exception);
203      setExitErrorLevel(exitWithFileProblems);
204      throw exception;
205    }
206    
207    if(sFile.length()>0 ){ sPathOut = sPathOut + "/" + sFile + ".html"; }
208    try
209    { FileSystem.mkDirPath(sPathOut);  //if the dst directory doesn't exists.
210      writer = new BufferedWriter(new FileWriter(sPathOut));
211    }
212    catch(FileNotFoundException exception)
213    { writeError("output file not found", exception);
214      setExitErrorLevel(exitWithFileProblems);
215      throw exception;
216    }
217
218    report(info, "translate " + sPathIn + " to " + sPathOut);
219    
220    writer.write("<html><head><title>" + sPathIn + "</title></head>\n<body><pre>\n");
221    
222    String sLine;
223    while( (sLine = reader.readLine()) != null)
224    { /**ascertain the indentitation of the block of this line*/
225      int indent = 0;
226      while(sLine.length() > indent && sLine.charAt(indent) == ' '){ indent +=1; }
227      sLine = sLine.substring(indent);  //without indentitation.
228      //don't exaggerate it. We haven't enaugh room.
229      //note, that 2 addtional spaces are needed for wrapping a line
230      if(indent > sIndent.length()-2){ indent = sIndent.length()-2; }
231      
232      /** Cut the line if it is to long*/
233      int indentWrapped = indent;  //first line with same indent.
234      int maxLength = maxLineSize - indentWrapped;
235      while(sLine.length() > maxLength)
236      { int posLast=sLine.lastIndexOf(' ', maxLength);
237        int posNext = posLast +1; //continue AFTER space, otherwise an infinite loop may occure!!!
238        if(posLast < 0){ posNext = posLast = maxLength; } //cutting it at max Length, continue direct.
239        printLine( sIndent.substring(0, indentWrapped) + sLine.substring(0, posLast));
240        sLine = sLine.substring(posNext);
241        indentWrapped = indent +2;  //next wrapped lines with higher indent.
242        maxLength = maxLineSize - indentWrapped;
243      }
244      printLine( sIndent.substring(0, indentWrapped) + sLine);  //print the rest.
245      
246    }
247    writer.write("\n</pre>\n</body></html>\n");
248    writer.close();
249    writer = null;  //no longer used.
250    reportln(info,"....successfull.");
251  }
252  
253  void printLine(String sLine) 
254  throws IOException
255  { { //the main task: replace all < with the named periphrases.
256      String sLine1 = sLine.replaceAll("&", "&amp;");
257      sLine1 = sLine1.replaceAll("<", "&lt;");
258      sLine1 = sLine1.replaceAll(">", "&gt;");
259      writer.write(sLine);
260      writer.write("\n");
261    }
262    
263  }
264  
265  
266  
267  
268  
269  
270  
271}
272
273
274
275