private static Catalog read(InputStream is) {
		Gson parser = new Gson();
		Catalog catalog = parser.fromJson(new InputStreamReader(is), Catalog.class);
		if (catalog != null) {
			// Validate the result (Gson can't do this)
			if (catalog.catalogs == null) {
				catalog.catalogs = new HashMap<>();
			}
			if (catalog.aliases == null) {
				catalog.aliases = new HashMap<>();
			}
			if (catalog.templates == null) {
				catalog.templates = new HashMap<>();
			}
			for (String catName : catalog.catalogs.keySet()) {
				CatalogRef cat = catalog.catalogs.get(catName);
				cat.catalog = catalog;
				check(cat.catalogRef != null, "Missing required attribute 'catalogs.catalogRef'");
			}
			for (String aliasName : catalog.aliases.keySet()) {
				Alias alias = catalog.aliases.get(aliasName);
				alias.catalog = catalog;
				check(alias.scriptRef != null, "Missing required attribute 'aliases.script-ref'");
			}
			for (String tplName : catalog.templates.keySet()) {
				Template tpl = catalog.templates.get(tplName);
				tpl.catalog = catalog;
				check(tpl.fileRefs != null, "Missing required attribute 'templates.file-refs'");
				check(!tpl.fileRefs.isEmpty(), "Attribute 'templates.file-refs' has no elements");
			}
		} else {
			catalog = Catalog.empty();
		}
		return catalog;
	}
Returns a Catalog containing all the aliases from local catalog files merged
into one. This follows the system where aliases that are "nearest" have
priority.

@param includeImplicits Determines if the implicit catalogs should be merged
                        or not
@return a Catalog object
src/main/java/dev/jbang/catalog/Catalog.java