001package org.galaxyproject.gxformat2.v19_09.utils;
002
003import java.util.HashMap;
004import java.util.List;
005import java.util.Map;
006
007public interface Loader<T> {
008
009  abstract T load(
010      final Object doc,
011      final String baseUri,
012      final LoadingOptions loadingOptions,
013      final String docRoot);
014
015  default T load(final Object doc, final String baseUri, final LoadingOptions loadingOptions) {
016    return load(doc, baseUri, loadingOptions, null);
017  }
018
019  default T documentLoad(
020      final String doc, final String baseUri, final LoadingOptions loadingOptions) {
021    return load(doc, baseUri, loadingOptions);
022  }
023
024  default T documentLoad(
025      final Map<String, Object> doc_, final String baseUri_, final LoadingOptions loadingOptions_) {
026    Map<String, Object> doc = doc_;
027    LoadingOptions loadingOptions = loadingOptions_;
028    if (doc.containsKey("$namespaces")) {
029      final Map<String, String> namespaces = (Map<String, String>) doc.get("$namespaces");
030      loadingOptions =
031          new LoadingOptionsBuilder().copiedFrom(loadingOptions).setNamespaces(namespaces).build();
032      doc = copyWithoutKey(doc, "$namespaces");
033    }
034    String baseUri = baseUri_;
035    if (doc.containsKey("$base")) {
036      baseUri = (String) doc.get("$base");
037    }
038    if (doc.containsKey("$graph")) {
039      return load(doc.get("$graph"), baseUri, loadingOptions);
040    } else {
041      return load(doc, baseUri, loadingOptions, baseUri);
042    }
043  }
044
045  default T documentLoad(
046      final List<Object> doc, final String baseUri, final LoadingOptions loadingOptions) {
047    return load(doc, baseUri, loadingOptions);
048  }
049
050  default T documentLoadByUrl(final String url, final LoadingOptions loadingOptions) {
051    if (loadingOptions.idx.containsKey(url)) {
052      return documentLoad(loadingOptions.idx.get(url), url, loadingOptions);
053    }
054
055    final String text = loadingOptions.fetcher.fetchText(url);
056    final Map<String, Object> result = YamlUtils.mapFromString(text);
057    loadingOptions.idx.put(url, result);
058    final LoadingOptionsBuilder urlLoadingOptions =
059        new LoadingOptionsBuilder().copiedFrom(loadingOptions).setFileUri(url);
060    return documentLoad(result, url, urlLoadingOptions.build());
061  }
062
063  default T loadField(
064      final Object val_, final String baseUri, final LoadingOptions loadingOptions) {
065    Object val = val_;
066    if (val instanceof Map) {
067      Map<String, Object> valMap = (Map<String, Object>) val;
068      if (valMap.containsKey("$import")) {
069        if (loadingOptions.fileUri == null) {
070          throw new ValidationException("Cannot load $import without fileuri");
071        }
072        return documentLoadByUrl(
073            loadingOptions.fetcher.urlJoin(loadingOptions.fileUri, (String) valMap.get("$import")),
074            loadingOptions);
075      } else if (valMap.containsKey("$include")) {
076        if (loadingOptions.fileUri == null) {
077          throw new ValidationException("Cannot load $import without fileuri");
078        }
079        val =
080            loadingOptions.fetcher.fetchText(
081                loadingOptions.fetcher.urlJoin(
082                    loadingOptions.fileUri, (String) valMap.get("$include")));
083      }
084    }
085    return load(val, baseUri, loadingOptions);
086  }
087
088  private Map<String, Object> copyWithoutKey(final Map<String, Object> doc, final String key) {
089    final Map<String, Object> result = new HashMap();
090    for (final Map.Entry<String, Object> entry : doc.entrySet()) {
091      if (!entry.getKey().equals(key)) {
092        result.put(entry.getKey(), entry.getValue());
093      }
094    }
095    return result;
096  }
097
098  public static <T> T validateOfJavaType(final Class<T> clazz, final Object doc) {
099    if (!clazz.isInstance(doc)) {
100      String className = "null";
101      if (doc != null) {
102        className = doc.getClass().getName();
103      }
104      final String message =
105          String.format(
106              "Expected object with Java type of %s but got %s", clazz.getName(), className);
107      throw new ValidationException(message);
108    }
109    return (T) doc;
110  }
111}