001/*license*\
002   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
003
004   This software is dual-licensed under the:
005   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
006   - Apache Software License (ASL) version 2.0.
007
008   Either license may be applied at your discretion. More information may be found at
009   - http://en.wikipedia.org/wiki/Multi-licensing.
010
011   The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
012   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
013   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
014\*license*/
015package  com.github.aliteralmind.codelet.type;
016   import  java.nio.file.InvalidPathException;
017   import  java.nio.file.Path;
018   import  java.nio.file.Paths;
019   import  com.github.xbn.io.PathMustBe;
020   import  com.github.aliteralmind.codelet.CodeletFormatException;
021   import  com.github.aliteralmind.codelet.CodeletInstance;
022   import  com.github.aliteralmind.codelet.CodeletType;
023   import  com.github.aliteralmind.codelet.CustomizationInstructions;
024   import  com.github.aliteralmind.codelet.TagletOfTypeProcessor;
025   import  com.github.aliteralmind.codelet.TagletTextUtil;
026   import  com.github.xbn.io.PlainTextFileUtil;
027   import  java.nio.file.AccessDeniedException;
028   import  java.nio.file.NoSuchFileException;
029   import  java.util.Iterator;
030   import  static com.github.aliteralmind.codelet.CodeletBaseConfig.*;
031   import  static com.github.xbn.lang.XbnConstants.*;
032/**
033   <P>Reads a {@link com.github.aliteralmind.codelet.CodeletType#FILE_TEXT {@.file.textlet}} taglet and outputs its replacement text.</P>
034
035   @since  0.1.0
036   @author  Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <A HREF="http://codelet.aliteralmind.com">{@code http://codelet.aliteralmind.com}</A>, <A HREF="https://github.com/aliteralmind/codelet">{@code https://github.com/aliteralmind/codelet}</A>
037 **/
038public class FileTextProcessor extends TagletOfTypeProcessor<FileTextTemplate>  {
039   /**
040      <P>Create a new instance from an {@code CodeletInstance}.</P>
041
042      <P>Equal to <CODE>{@link com.github.aliteralmind.codelet.TagletOfTypeProcessor#TagletOfTypeProcessor(CodeletType, CodeletInstance) super}(CodeletType.FILE_TEXT, instance)</CODE>
043    **/
044   public FileTextProcessor(CodeletInstance instance) throws ClassNotFoundException, NoSuchMethodException, NoSuchFileException, AccessDeniedException  {
045      super(CodeletType.FILE_TEXT, instance);
046
047      if(getClassOrFilePortion().contains("("))  {
048         throw  new CodeletFormatException(instance, "File-text taglets cannot contain command-line parameters");
049      }
050
051      Iterator<String> fileTextLineItr = getLineIteratorFromCodeletPath(instance);
052
053//              String strSig = getStringSigForFileText();
054//              SimpleMethodSignature sig = getCustomizerSigFromString(strSig);
055
056      CustomizationInstructions<FileTextTemplate> instructions =
057         ((getCustomizerPortion() != null)
058            ?  getCustomCustomizationInstructions(CodeletType.FILE_TEXT)
059            :  newInstructionsForDefaults(
060                  new CustomizationInstructions<FileTextTemplate>(instance, CodeletType.FILE_TEXT)));
061
062      crashIfClassOrFileCannotUseCustomizer(instructions);
063
064      String fileTextCustomized = instructions.getCustomizedBody(instance, fileTextLineItr);
065
066      FileTextTemplate template = getTemplateFromInstructionsOverrideOrDefault(
067         instructions);
068
069      String finalOutput = template.fillBody(fileTextCustomized).getRendered(instance);
070      setFullyProcessedOutput(finalOutput);
071   }
072      private final Iterator<String> getLineIteratorFromCodeletPath(CodeletInstance instance)  {
073
074         boolean doDebug = isDebugOn(instance, "zzFileTextProcessor.obtainingfile");
075
076         //See CodeletInstance.FILE_TEXT
077
078         if(doDebug)  {
079            debugln("Obtaining line iterator to {@.file.textlet} file (expected file-separator is '" + FILE_SEP + "')...");
080            debugln("   - Raw file path from {@.file.textlet}:  " + getClassOrFilePortion());
081            debugln("   - TagletTextUtil.getFilePath(instance): " + TagletTextUtil.getFilePath(instance));
082         }
083
084         Path path = Paths.get(TagletTextUtil.getFilePath(instance));
085
086         PathMustBe pmb = new PathMustBe().existing().readable();
087//                      String namePost = "TagletTextUtil.getFilePath(instance)]";
088
089         //First assume absolute. This also works if the path is relative to
090         //the directory in which javadoc.exe was invoked.
091
092         if(pmb.isGood(path))  {
093            if(doDebug)  {
094               debugln("   SUCCESS: Path is either absolute, or relative to the directory in which javadoc.exe was invoked.");
095            }
096
097            return  PlainTextFileUtil.getLineIterator(path.toString(), "[path to file]");
098         }
099
100         //It's not absolute or relative to the invoking directory.
101         //It must be relative to the enclosing file, or die.
102
103         String parentPath = instance.getEnclosingFile().getParent();
104
105         if(!parentPath.endsWith(FILE_SEP))  {
106            parentPath += FILE_SEP;
107         }
108
109         if(doDebug)  {
110            debugln("   Path to file is not absolute, and not relative to the javadoc.exe-invoking directory. It MUST be relative to the directory of its enclosing file:");
111            debugln("    - File:   " + instance.getEnclosingFile());
112            debugln("    - Parent: " + parentPath);
113         }
114
115         try  {
116            path = Paths.get(parentPath, path.toString());
117         }  catch(InvalidPathException ipx)  {
118            throw  new InvalidPathException(parentPath + path.toString(), "{@.file.textlet} path is invalid. Not absolute, not relative to javadoc.exe invoking directory, and not relative to enclosing file");
119         }
120
121         return  PlainTextFileUtil.getLineIterator(path.toString(), "[path to {@.file.textlet} file]");
122      }
123   /**
124      <P>Get the string signature for a {@code {@.file.textlet}} taglets only. Except where noted, this does not validate the taglet text or the returned signature.</P>
125
126      <P>This follows the same steps as {@link com.github.aliteralmind.codelet.TagletOfTypeProcessor#getStringSignature() getStringSignature}, except<UL>
127         <LI>The customizer portion of the taglet, when provided, must contain either an underscore ({@code '_'}) postfix or the processor's full function name.</LI>
128         <LI>The {@linkplain com.github.aliteralmind.codelet.CodeletType#getDefaultLineProcNamePrefix() default function name prefix} is {@code "getFileTextConfig_"}</LI>
129      </UL></P>
130
131      @exception  CodeletFormatException  If no function name or underscore-postfix is provided.
132    **/
133   public String getStringSigForFileText()  {
134      String sig = getCustomizerPortion();
135
136      boolean doDebug = isDebugOn(getInstance(),
137         "zzTagletOfTypeProcessor.getCustomizerSigFromString");
138
139      if(sig == null)  {
140         if(doDebug)  {
141            debugln("   No Customizer");
142         }
143         return  null;
144      }
145
146      if(sig.equals("()"))  {
147         throw  new CodeletFormatException(getInstance(), "Customizer portion for a " + CodeletType.FILE_TEXT.getName() + " taglet is equal to \"()\". The processor's function name or underscore-postfix must be specified.");
148      }
149
150      return  getSig2PrnsApnddForNameOrPostfix("", sig, doDebug);
151   }
152}