SymbolPrinter.java

  1. package com.jeantessier.classreader;

  2. import java.io.*;
  3. import java.util.*;
  4. import java.util.stream.*;

  5. public abstract class SymbolPrinter {
  6.     private static final Map<Class<? extends Visitable>, Collection<String>> HEADERS = Map.of(
  7.             Classfile.class, List.of("symbol type", "symbol", "simple name"),
  8.             Field_info.class, List.of("symbol type", "symbol", "class", "name", "type"),
  9.             Method_info.class, List.of("symbol type", "symbol", "class", "name", "signature", "return type", "parameter types"),
  10.             LocalVariable.class, List.of("symbol type", "symbol", "method", "name", "type"),
  11.             InnerClass.class, List.of("symbol type", "symbol", "outer class", "inner name")
  12.     );

  13.     private final PrintWriter out;

  14.     public SymbolPrinter(PrintWriter out) {
  15.         this.out = out;
  16.     }

  17.     public PrintWriter getOut() {
  18.         return out;
  19.     }

  20.     public abstract void print(SymbolGatherer gatherer) throws IOException;

  21.     protected Stream<String> getHeadersFor(Class<? extends Visitable> visitableClass) {
  22.         if (Classfile.class.isAssignableFrom(visitableClass)) {
  23.             return HEADERS.get(Classfile.class).stream();
  24.         } else if (Field_info.class.isAssignableFrom(visitableClass)) {
  25.             return HEADERS.get(Field_info.class).stream();
  26.         } else if (Method_info.class.isAssignableFrom(visitableClass)) {
  27.             return HEADERS.get(Method_info.class).stream();
  28.         } else if (LocalVariable.class.isAssignableFrom(visitableClass)) {
  29.             return HEADERS.get(LocalVariable.class).stream();
  30.         } else if (InnerClass.class.isAssignableFrom(visitableClass)) {
  31.             return HEADERS.get(InnerClass.class).stream();
  32.         } else {
  33.             return Stream.empty();
  34.         }
  35.     }

  36.     protected Stream<String> getHeadersFor(Visitable visitable) {
  37.         return getHeadersFor(visitable.getClass());
  38.     }

  39.     protected Stream<?> getValuesFor(Visitable visitable) {
  40.         if (visitable instanceof Classfile classfile) {
  41.             return Stream.of(
  42.                     "class name",
  43.                     classfile,
  44.                     classfile.getSimpleName()
  45.             );
  46.         } else if (visitable instanceof Field_info field) {
  47.             return Stream.of(
  48.                     "field name",
  49.                     field,
  50.                     field.getClassfile(),
  51.                     field.getName(),
  52.                     field.getType()
  53.             );
  54.         } else if (visitable instanceof Method_info method) {
  55.             return Stream.of(
  56.                     "method name",
  57.                     method,
  58.                     method.getClassfile(),
  59.                     method.getName(),
  60.                     method.getSignature(),
  61.                     method.getReturnType(),
  62.                     method.getParameterTypes()
  63.             );
  64.         } else if (visitable instanceof LocalVariable localVariable) {
  65.             return Stream.of(
  66.                     "local variable name",
  67.                     localVariable,
  68.                     localVariable.getMethod(),
  69.                     localVariable.getName(),
  70.                     localVariable.getType()
  71.             );
  72.         } else if (visitable instanceof InnerClass innerClass) {
  73.             return Stream.of(
  74.                     "inner class name",
  75.                     innerClass,
  76.                     innerClass.getOuterClassInfo(),
  77.                     innerClass.getInnerName()
  78.             );
  79.         } else {
  80.             return Stream.empty();
  81.         }
  82.     }

  83.     protected Map<String, ?> visitableToRecord(Visitable visitable) {
  84.         Map<String, ? super Object> result = new LinkedHashMap<>();

  85.         List<String> headers = getHeadersFor(visitable).toList();
  86.         List<?> values = getValuesFor(visitable).toList();

  87.         IntStream.range(0, headers.size())
  88.                 .forEach(i -> result.put(headers.get(i), values.get(i)));

  89.         return result;
  90.     }

  91.     protected String format(Stream<?> stream) {
  92.         return stream
  93.                 .map(entry -> "\"" + entry + "\"")
  94.                 .collect(Collectors.joining(", "));
  95.     }
  96. }