code: @SuppressWarnings("unchecked") // Generics are not the strong suit of Hipster4j.
      public ChainTransform getTransform(final Class from, final Class<?> to) {
          if(from.equals(to)) {
              return ChainTransform.identity(to);
          }
  
          final SearchProblem problem = GraphSearchProblem.startingFrom(from).in(graph).extractCostFromEdges(new Function<DataTransformer, Double>() {
              @Override
              public Double apply(final DataTransformer transformer) {
                  return new Double(transformer.cost());
              }
          }).build();
  
          final List<Class<?>> path = (List<Class<?>>)Hipster.createDijkstra(problem).search(to).getOptimalPaths().get(0);
          if(path == null || !path.get(path.size() - 1).equals(to)) {
              return null;
          }
  
          final List<DataTransformer> transform = new LinkedList<>();
          for(int i = 1; i < path.size(); i++) {
              transform.add(cheapest.get(path.get(i - 1)).get(path.get(i)));
          }
          return new ChainTransform(from, to, path, transform);
      }
docs: Attempts to find the best {@link com.merakianalytics.datapipelines.ChainTransform} to get from a type to another
  
  @param from
  the type to convert from
  @param to
  the type to convert to
  @return the best {@link com.merakianalytics.datapipelines.ChainTransform} between the types, or null if there is none