All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.simiacryptus.util.io.HtmlNotebookOutput Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*
 * Copyright (c) 2018 by Andrew Charneski.
 *
 * The author licenses this file to you under the
 * Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance
 * with the License.  You may obtain a copy
 * of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.simiacryptus.util.io;

import com.simiacryptus.util.FileNanoHTTPD;
import com.simiacryptus.util.TableOutput;
import com.simiacryptus.util.Util;
import com.simiacryptus.util.lang.CodeUtil;
import com.simiacryptus.util.lang.TimedResult;
import com.simiacryptus.util.lang.UncheckedSupplier;
import com.simiacryptus.util.test.SysOutInterceptor;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Base64;
import java.util.UUID;

/**
 * The type Html notebook output.
 */
@Deprecated
public class HtmlNotebookOutput implements NotebookOutput {
  private static final Logger log = LoggerFactory.getLogger(com.simiacryptus.util.io.HtmlNotebookOutput.class);
  
  /**
   * The constant DEFAULT_ROOT.
   */
  @javax.annotation.Nonnull
  public static String DEFAULT_ROOT = "https://github.com/SimiaCryptus/utilities/tree/master/";
  /**
   * The Working dir.
   */
  public final File workingDir;
  @javax.annotation.Nonnull
  private final PrintStream primaryOut;
  private int maxOutSize = 8 * 1024;
  private int maxImageSize = 1600;
  /**
   * The Source root.
   */
  public String sourceRoot = com.simiacryptus.util.io.HtmlNotebookOutput.DEFAULT_ROOT;
  /**
   * The Excerpt number.
   */
  int excerptNumber = 0;
  
  /**
   * Instantiates a new Html notebook output.
   *
   * @param parentDirectory the parent directory
   * @param out             the out
   */
  public HtmlNotebookOutput(final File parentDirectory, @javax.annotation.Nonnull final OutputStream out) {
    primaryOut = new PrintStream(out);
    workingDir = parentDirectory;
    out("");
  }
  
  /**
   * Create html notebook output.
   *
   * @param parentDirectory the parent directory
   * @return the html notebook output
   * @throws FileNotFoundException the file not found exception
   */
  public static com.simiacryptus.util.io.HtmlNotebookOutput create(final File parentDirectory) throws FileNotFoundException {
    @javax.annotation.Nonnull final FileOutputStream out = new FileOutputStream(new File(parentDirectory, "index.html"));
    return new com.simiacryptus.util.io.HtmlNotebookOutput(parentDirectory, out) {
      @Override
      public void close() throws IOException {
        out.close();
      }
    };
  }
  
  
  @Override
  public void close() throws IOException {
    out("");
    if (null != primaryOut) {
      primaryOut.close();
    }
  }
  
  @javax.annotation.Nonnull
  @SuppressWarnings("unchecked")
  @Override
  public  T code(@javax.annotation.Nonnull final UncheckedSupplier fn, final int maxLog, final int framesNo) {
    try {
      final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
      final StackTraceElement callingFrame = stackTrace[framesNo];
      final String sourceCode = CodeUtil.getInnerText(callingFrame);
      @javax.annotation.Nonnull final SysOutInterceptor.LoggedResult> result = SysOutInterceptor.withOutput(() -> {
        long priorGcMs = ManagementFactory.getGarbageCollectorMXBeans().stream().mapToLong(x -> x.getCollectionTime()).sum();
        final long start = System.nanoTime();
        try {
          @Nullable Object result1 = null;
          try {
            result1 = fn.get();
          } catch (@javax.annotation.Nonnull final RuntimeException e) {
            throw e;
          } catch (@javax.annotation.Nonnull final Exception e) {
            throw new RuntimeException(e);
          }
          long gcTime = ManagementFactory.getGarbageCollectorMXBeans().stream().mapToLong(x -> x.getCollectionTime()).sum() - priorGcMs;
          return new TimedResult(result1, System.nanoTime() - start, gcTime);
        } catch (@javax.annotation.Nonnull final Throwable e) {
          long gcTime = ManagementFactory.getGarbageCollectorMXBeans().stream().mapToLong(x -> x.getCollectionTime()).sum() - priorGcMs;
          return new TimedResult(e, System.nanoTime() - start, gcTime);
        }
      });
      try {
        @javax.annotation.Nonnull final URI resolved = URI.create(sourceRoot).resolve(Util.pathTo(CodeUtil.projectRoot, CodeUtil.findFile(callingFrame)));
        out("

Code from %s:%s executed in %.2f seconds:
", resolved, callingFrame.getLineNumber(), callingFrame.getFileName(), callingFrame.getLineNumber(), result.obj.seconds()); } catch (@javax.annotation.Nonnull final Exception e) { out("

Code from %s:%s executed in %.2f seconds:
", callingFrame.getFileName(), callingFrame.getLineNumber(), result.obj.seconds()); } out("

");
      out(sourceCode);
      out("
"); if (!result.log.isEmpty()) { out("Logging:
"); out("
");
        out(summarize(maxLog, result.log));
        out("
"); } out(""); final Object eval = result.obj.result; if (null != eval) { out("Returns:
"); String str; boolean escape; if (eval instanceof Throwable) { @javax.annotation.Nonnull final ByteArrayOutputStream out = new ByteArrayOutputStream(); ((Throwable) eval).printStackTrace(new PrintStream(out)); str = new String(out.toByteArray(), "UTF-8"); escape = true;// } else if (eval instanceof Component) { str = image(Util.toImage((Component) eval), "Result"); escape = false; } else if (eval instanceof BufferedImage) { str = image((BufferedImage) eval, "Result"); escape = false; } else if (eval instanceof TableOutput) { str = ((TableOutput) eval).toHtmlTable(); escape = false; } else { str = eval.toString(); escape = true; } if (escape) { out("
" + summarize(maxLog, str) + "
"); } else { out(summarize(maxLog, str)); } if (escape) { } out("\n\n"); if (eval instanceof Throwable) { throw new RuntimeException((Throwable) result.obj.result); } } out("

"); return (T) eval; } catch (@javax.annotation.Nonnull final IOException e) { throw new RuntimeException(e); } } @javax.annotation.Nonnull @Override public OutputStream file(@javax.annotation.Nonnull final CharSequence name) { try { return new FileOutputStream(new File(getResourceDir(), name.toString())); } catch (@javax.annotation.Nonnull final FileNotFoundException e) { throw new RuntimeException(e); } } @javax.annotation.Nonnull @Override public String file(final CharSequence data, final CharSequence caption) { return file(data, excerptNumber++ + ".txt", caption); } @javax.annotation.Nonnull @Override public CharSequence file(byte[] data, @javax.annotation.Nonnull CharSequence filename, CharSequence caption) { try { IOUtils.write(data, new FileOutputStream(new File(getResourceDir(), filename.toString()))); } catch (@javax.annotation.Nonnull final IOException e) { throw new RuntimeException(e); } return "" + caption + ""; } @javax.annotation.Nonnull @Override public String file(final CharSequence data, @javax.annotation.Nonnull final CharSequence fileName, final CharSequence caption) { try { IOUtils.write(data, new FileOutputStream(new File(getResourceDir(), fileName.toString())), Charset.forName("UTF-8")); } catch (@javax.annotation.Nonnull final IOException e) { throw new RuntimeException(e); } return "" + caption + ""; } /** * Gets resource dir. * * @return the resource dir */ @javax.annotation.Nonnull public File getResourceDir() { @javax.annotation.Nonnull final File etc = new File(workingDir, "etc"); etc.mkdirs(); return etc; } /** * Gets source root. * * @return the source root */ public CharSequence getSourceRoot() { return sourceRoot; } /** * Sets source root. * * @param sourceRoot the source root * @return the source root */ @javax.annotation.Nonnull public com.simiacryptus.util.io.HtmlNotebookOutput setSourceRoot(final String sourceRoot) { this.sourceRoot = sourceRoot; return this; } @Override public void h1(final CharSequence fmt, final Object... args) { out("

" + fmt + "

", args); } @Override public void h2(final CharSequence fmt, final Object... args) { out("

" + fmt + "

", args); } @Override public void h3(final CharSequence fmt, final Object... args) { out("

" + fmt + "

", args); } @javax.annotation.Nonnull @Override public String image(@Nullable final BufferedImage rawImage, final CharSequence caption) { if (null == rawImage) return ""; new ByteArrayOutputStream(); @javax.annotation.Nonnull final CharSequence thisImage = UUID.randomUUID().toString().substring(0, 8); @javax.annotation.Nonnull final File file = new File(getResourceDir(), "img" + thisImage + ".png"); @javax.annotation.Nonnull final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); try { ImageIO.write(rawImage, "png", buffer); final CharSequence pngSrc = Base64.getEncoder().encodeToString(buffer.toByteArray()); if (pngSrc.length() < 4 * 1024) { return "" + caption + ""; } else { @Nullable final BufferedImage stdImage = Util.maximumSize(rawImage, getMaxImageSize()); if (stdImage != rawImage) { ImageIO.write(rawImage, "png", new File(getResourceDir(), "raw" + thisImage + ".png")); } ImageIO.write(stdImage, "png", file); return "" + caption + ""; } } catch (IOException e) { throw new RuntimeException(e); } } @Override public CharSequence link(@javax.annotation.Nonnull final File file, final CharSequence text) { @Nullable String path = null; try { path = workingDir.getCanonicalFile().toPath().relativize(file.getCanonicalFile().toPath()).normalize().toString().replaceAll("\\\\", "/"); } catch (@javax.annotation.Nonnull final IOException e) { throw new RuntimeException(e); } return String.format("%s", path, text); } @Override public void out(@javax.annotation.Nonnull final String fmt, @javax.annotation.Nonnull final Object... args) { @javax.annotation.Nonnull final String msg = 0 == args.length ? fmt : String.format(fmt, args); primaryOut.println(msg); primaryOut.flush(); log.info(msg); } @Override public void p(final CharSequence fmt, final Object... args) { out("

" + fmt + "

", args); } @Nullable @Override public CharSequence getFrontMatterProperty(CharSequence key) { return null; } @javax.annotation.Nonnull @Override public CharSequence getName() { return "www"; } /** * Summarize string. * * @param maxLog the max log * @param string the string * @return the string */ @javax.annotation.Nonnull public String summarize(final int maxLog, @javax.annotation.Nonnull final String string) { if (string.length() > maxLog * 2) { @javax.annotation.Nonnull final CharSequence left = string.substring(0, maxLog); @javax.annotation.Nonnull final CharSequence right = string.substring(string.length() - maxLog); final CharSequence link = String.format(file(string, "\n...skipping %s bytes...\n"), string.length() - 2 * maxLog); return left.toString() + link + right; } else { return string; } } public int getMaxOutSize() { return maxOutSize; } @Override public FileNanoHTTPD getHttpd() { return null; } public int getMaxImageSize() { return maxImageSize; } public HtmlNotebookOutput setMaxImageSize(int maxImageSize) { this.maxImageSize = maxImageSize; return this; } public HtmlNotebookOutput setMaxOutSize(int maxOutSize) { this.maxOutSize = maxOutSize; return this; } }