001/****************************************************************************
002 * Copyright/Copyleft:
003 *
004 * For this source the LGPL Lesser General Public License,
005 * published by the Free Software Foundation is valid.
006 * It means:
007 * 1) You can use this source without any restriction for any desired purpose.
008 * 2) You can redistribute copies of this source to everybody.
009 * 3) Every user of this source, also the user of redistribute copies
010 *    with or without payment, must accept this license for further using.
011 * 4) But the LPGL is not appropriate for a whole software product,
012 *    if this source is only a part of them. It means, the user
013 *    must publish this part of source,
014 *    but don't need to publish the whole source of the own product.
015 * 5) You can study and modify (improve) this source
016 *    for own using or for redistribution, but you have to license the
017 *    modified sources likewise under this LGPL Lesser General Public License.
018 *    You mustn't delete this Copyright/Copyleft inscription in this source file.
019 *
020 * @author Hartmut Schorrig: hartmut.schorrig@vishia.de, www.vishia.org
021 * @version 0.93 2011-01-05  (year-month-day)
022 *******************************************************************************/ 
023package org.vishia.java2C;
024
025import java.io.File;
026import java.io.FileNotFoundException;
027import java.io.IOException;
028import java.text.ParseException;
029import java.util.LinkedList;
030import java.util.List;
031
032import org.vishia.java2C.ConfigSrcPathPkg_ifc.Set;
033
034/**Representation of an existing Java file.
035 */
036public class JavaSrcTreeFile implements JavaSources.ClassDataOrJavaSrcFile
037{
038  
039  private final String sFileName;
040  
041  /**The name of the public class of this file. In Java only one class can be public in a file.
042   */
043  private final String sPublicClassName;
044  
045  private final String sJavaSrcPath;
046
047  /**Pre- and Suffixes to build the class name in C additional to the java-name of classes. */
048  private final String sPrefixClassNameC, sSuffixClassNameC;
049  
050  private final String sStcPath;
051  
052  private final String sFilePathC;
053
054  private final JavaSrcTreePkg itsPkg;
055  
056  private File fileJava;
057  
058  /**True if this file is to be translate. */
059  private boolean bToTranslateToC;
060  
061  /**informations to find out where the C-file is found and which pre/suffix are valid. */
062  private final ConfigSrcPathPkg_ifc.Set replaceCinfo;
063  
064  /**If set, the file is translated, the classData presents its content for foreign use.
065   */
066  ClassData classData = null;
067  
068  /**Initializes the instance.
069   * @param itsPkg The package where the file is member of.
070   * @param javaSrcPath The source path where the file is found first time.
071   * @param fileJava The File instance ready to open source file.
072   * @param sFileNameJava The file name without path but with extension <code>.java</code> without directories.
073   * @param prefixCFile The prefix to build the C class name and the C file name. 
074   *        The part after the last slash <code>/</code> is the prefix for class names.
075   *        The prefix should ended with slash if the file name has no prefix, 
076   *        but a path to store the to create *.c and *.h files are given.
077   *        The prefix may contain <code>""</code>.
078   *        <br>
079   *        If the prefix is null, the param suffixCFile contains the complete C-File-name. 
080   *        This is only possible for Files, which are not translated from Java2C, 
081   *        but it is parsed their stc-File. In this case the stc-File contains the valid 
082   *        <code>struct</code> names for C. No {@link#sPrefixClassNameC} or suffix is necessary than.
083   * @param suffixCFile The suffix to build the C class name and the C file name.
084   * @param prefixNames
085   * @param suffixNames
086   * @param info information to find out where the C-file is found and which pre/suffix are valid.
087   * @param stcPath null or a special path where the stc-file is located.
088   * @param translateToC false than the file should not be translate to C,
089   *        instead the stc-file should be used any time. This is if it is a standard class 
090   *        or a users class, which is located in a library.
091   */
092  public JavaSrcTreeFile(JavaSrcTreePkg itsPkg
093  , String javaSrcPath, File fileJava, String sFileNameJava
094  , ConfigSrcPathPkg_ifc.Set info
095  , String stcPath
096  , boolean translateToC
097  )
098  {
099    super();
100    this.replaceCinfo = info;
101    if(sFileNameJava.endsWith(".java")){
102            this.sPublicClassName = sFileNameJava.substring(0, sFileNameJava.length()-5); // without ".java"
103    } else {
104        this.sPublicClassName = sFileNameJava;  //may be a package, for package replacement.
105    }
106          this.sJavaSrcPath = javaSrcPath;
107    this.fileJava = fileJava;
108    this.sFileName = sFileNameJava;
109    if(info !=null){
110            String prefixCFile = info.getFilePrefix();
111        int posFolderPrefix1 = prefixCFile.lastIndexOf('/');
112            int posFolderPrefix2 = prefixCFile.lastIndexOf('\\');
113            int posFolderPrefix = posFolderPrefix1 >=0 && posFolderPrefix1 > posFolderPrefix2 ? posFolderPrefix1 : posFolderPrefix2;
114            //sPrefixClassNameC = posFolderPrefix >=0 ? prefixCFile.substring(posFolderPrefix+1): prefixCFile; //may be empty, but not null.
115            sPrefixClassNameC = info.getNamePrefix(); //may be empty, but not null.
116            sSuffixClassNameC = info.getNameSuffix();
117            String suffixCFile = info.getFileSuffix();
118            sFilePathC = prefixCFile + (suffixCFile == null ? "" : sPublicClassName + suffixCFile);
119    } else {
120            sPrefixClassNameC = null; //may be empty, but not null.
121            sSuffixClassNameC = null;
122            sFilePathC = null;
123    }
124          sStcPath = stcPath;
125    this.bToTranslateToC = translateToC;
126    this.itsPkg = itsPkg;
127    itsPkg.getPkgLevelIdents().putClassType(sPublicClassName, this);
128  }
129  
130  /**returns <code>null</code>if the file is not translated, returns the ClassData if it is translated.
131   * @see org.vishia.java2C.JavaSources.ClassDataOrJavaSrcFile#getClassData()
132   */
133  public ClassData getClassData()
134  {
135    return classData;  //null if not translated
136  }
137
138
139  /**returns the instance because it is.
140   * @see org.vishia.java2C.JavaSources.ClassDataOrJavaSrcFile#getJavaSrc()
141   */
142  public JavaSrcTreeFile getJavaSrc()
143  {
144    return this;
145  }
146  
147  
148  
149  /**
150   * @param fileJava
151   */
152  void infoSecondFile(File fileJava, boolean shouldTranslated)
153  { if(shouldTranslated){
154      if(this.fileJava == null){
155        //if it is created while package replacement, the file isn't associated. do it now.
156        this.fileJava = fileJava; 
157      }
158          bToTranslateToC = true;
159    }
160  
161  }
162  
163  public String getStcPath(){
164        if(sStcPath != null) return sStcPath;  //special convention
165        else return sFilePathC + ".stc";                //standard convention
166  }
167  
168  public String getPublicClassName(){ return sPublicClassName; }
169  
170  public LocalIdents getPkgLevelTypes(){ return itsPkg.getPkgLevelIdents(); }
171  
172  public String getFileNameC(){ return sFilePathC; } 
173  
174  /**Returns the source path where the file is found. 
175   * It is only a info, where the file comes from, not to process.
176   */
177  private String getJavaSrcPathInfo(){ return sJavaSrcPath; }
178  
179  public String toString()
180  { String info= (sJavaSrcPath!=null ? sJavaSrcPath: "noJavaSrc") + "/" + this.itsPkg.getPkgPath() 
181        + this.sFileName 
182    + (bToTranslateToC ? " -> " + this.getFileNameC() : " : " + this.sStcPath );
183    return info;
184  }  
185
186  public String getPkgPath(){ return itsPkg.getPkgPath(); }
187  
188  
189  
190  public String getClassCNamePrefix(){ return sPrefixClassNameC; }
191
192  public String getClassCNameSuffix(){ return sSuffixClassNameC; }
193  
194  @Override public void setClassData(ClassData data)
195  { //assert(classData == null);  //set only one time.
196    assert(sPublicClassName.equals(data.sClassNameJava));
197    classData = data;
198  }
199  
200  public boolean isToTranslate(){ return bToTranslateToC; }
201
202  public void setToTranslate(File fileJava){ 
203        bToTranslateToC = true;
204        this.fileJava = fileJava;
205  }
206
207  
208  
209  public boolean isTranslated(){ return classData != null; }
210  
211  
212  public final File getFileJava()
213  {
214    return fileJava;
215  }
216
217  public LocalIdents xxxgetLocalIdents()
218  {
219    if(classData != null){
220      return classData.classLevelIdents;
221    } else {
222      return null;  //no local idents available.
223    }
224  }
225
226        /**Gets the local idents of the givenclass of the file. 
227         * The file may be translated or not. If it isn't translated, it will be translated now
228         * respectively the structure-file (stc) is translated. 
229         * @param sClassName name of the class in file, it may the public class or another one.
230   * implements {@link org.vishia.java2C.JavaSources.ClassDataOrJavaSrcFile#getLocalIdents(java.lang.String)} 
231         * */
232  public LocalIdents getLocalIdents(String sClassName)
233  {
234        if(classData == null){
235                /**An inner type of a class in file is given. The file isn't translate,
236                 * therefore the localIdents doesn't exist. */
237          if( true ){ //isToTranslate()){
238        //assert(!isTranslated()); //elsewhere the localIdents should exist
239        JavaSrcTreeFile javaFile = this;
240        try
241        { /**If a identifier is found, but it has not ClassData, it is a non-translated file.
242           * Than run the first pass to get the ClassData. It may be that a stc-file is read.
243           */
244          classData = Java2C_Main.singleton.runRequestedFirstPass(javaFile, sClassName);
245        } 
246        catch (FileNotFoundException e){ throw new IllegalArgumentException("file not found: " + javaFile.toString()); }
247        catch (IOException e){ throw new IllegalArgumentException("file error: " + javaFile.toString()); }
248        catch (ParseException e)
249        { //e.printStackTrace();
250          throw new IllegalArgumentException("parse exception: " + e.getMessage() + " in "+ javaFile.toString()); 
251        }
252        catch (InstantiationException e){ throw new IllegalArgumentException("instanciation exception: " + javaFile.toString()); }
253        catch (IllegalAccessException e){ throw new IllegalArgumentException("illegal access: " + javaFile.toString()); }
254        //catch (IllegalArgumentException e){ throw new IllegalArgumentException("file not found: " + javaFile.toString()); }
255        
256      }
257    }
258    return classData.classLevelIdents;
259  }
260
261  
262  /**Implements {@link JavaSources.ClassDataOrJavaSrcFile#getJavaPkg()}
263   */
264  public JavaSrcTreePkg getJavaPkg()
265  {
266    return null; // it isn't a JavaSrcTreePkg
267  }
268
269  /**Implements {@link JavaSources.ClassDataOrJavaSrcFile#getTypeName()}
270   */
271  public String getTypeName()
272  {
273    return sPublicClassName;
274  }
275
276        /* (non-Javadoc)
277         * @see org.vishia.java2C.JavaSources.ClassDataOrJavaSrcFile#getReplaceCinfo()
278         */
279        @Override
280        public Set getReplaceCinfo() {
281                return replaceCinfo;
282        }
283  
284
285}
286
287