You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
666 lines
27 KiB
666 lines
27 KiB
package de.superx.bianalysis.metadata; |
|
|
|
import java.io.BufferedReader; |
|
import java.io.File; |
|
import java.io.FileReader; |
|
import java.io.FilenameFilter; |
|
import java.sql.Connection; |
|
import java.sql.ResultSet; |
|
import java.sql.Statement; |
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.Optional; |
|
import java.util.stream.Collectors; |
|
|
|
import javax.sql.DataSource; |
|
|
|
import org.apache.commons.lang.exception.ExceptionUtils; |
|
import org.apache.log4j.Logger; |
|
import org.springframework.jdbc.core.JdbcTemplate; |
|
|
|
import com.fasterxml.jackson.core.util.DefaultIndenter; |
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
|
import com.fasterxml.jackson.databind.JsonMappingException; |
|
import com.fasterxml.jackson.databind.ObjectMapper; |
|
import com.fasterxml.jackson.databind.json.JsonMapper; |
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; |
|
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; |
|
|
|
import de.superx.bianalysis.FaultyMetadataException; |
|
import de.superx.bianalysis.StoredReport; |
|
import de.superx.bianalysis.metadata.models.json.MetaDimension; |
|
import de.superx.bianalysis.metadata.models.json.MetaDimensionAttribute; |
|
import de.superx.bianalysis.metadata.models.json.MetaFact; |
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
|
import de.superx.bianalysis.metadata.models.yml.MetaYml; |
|
import de.superx.bianalysis.metadata.models.yml.MetaYmlModel; |
|
import de.superx.bianalysis.metadata.models.yml.MetaYmlModelColumns; |
|
import de.superx.bianalysis.service.DbMetaAdapter; |
|
import de.superx.util.PathAndFileUtils; |
|
|
|
/** |
|
* Provides functionality for updating the tables in the metadata schema. |
|
* The tables are updated by reading the metadata information from various |
|
* metaimport.json files and transforming that information into executable sql. |
|
* |
|
* The BIAnalysis Tool uses the tables to read information about the different |
|
* meta objects and more importantly to figure out their relationships, e.g. what |
|
* dimension is part of which facttable or which attribute belongs to which |
|
* dimension. |
|
* |
|
* To learn more about the metadata concept for the BIAnalysis Tool see: |
|
* doc\bi_analysis\metadaten.adoc |
|
* |
|
*/ |
|
public final class MetadataImporter { |
|
|
|
/** |
|
* Each file containing metadata information must have the following file suffix. |
|
*/ |
|
private static final String METAIMPORT_FILE_SUFFIX = "_metaimport.json"; |
|
|
|
protected static final String CONFORMED_DIMENSIONS_FILE_SUFFIX = "conformed_dimensions" + METAIMPORT_FILE_SUFFIX; |
|
|
|
/** |
|
* Holds all Metaimport objects with which this instance was initalized. |
|
* (One MetaImport object corresponds to exactly one deserialized json file) |
|
*/ |
|
private List<MetaJson> metaImports = new ArrayList<>(); |
|
|
|
public List<String> errorMessages = new ArrayList<>(); |
|
|
|
/** |
|
* SQL String for deleting from all metadata tables except 'custom' releases. |
|
*/ |
|
public static final String TRUNCATE_METADATA_SQL = |
|
"DELETE FROM metadata.facttable WHERE is_custom = false; " + |
|
"DELETE FROM metadata.measure WHERE is_custom = false; " + |
|
"DELETE FROM metadata.measure_filter WHERE is_custom = false; " + |
|
"DELETE FROM metadata.dimension WHERE is_custom = false; " + |
|
"DELETE FROM metadata.dimension_attribute WHERE is_custom = false; "; |
|
|
|
private static Logger log = Logger.getLogger(MetadataImporter.class); |
|
|
|
private boolean shouldReadYMLDoc = true; |
|
|
|
private String ymlDir = ""; |
|
|
|
public MetadataImporter() {} |
|
|
|
public MetadataImporter(String ymlDir) {this.ymlDir = ymlDir;} |
|
|
|
public void deserializeMetadataFromStrings(String... values) { |
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
|
List<MetaImportConformedDimensions> conformedDimension = new ArrayList<>(); |
|
|
|
for (String value : values) { |
|
MetaJson meta = null; |
|
try{ |
|
if(value.contains("conformed_dimensions")) { |
|
meta = mapper.readValue(value, MetaImportConformedDimensions.class); |
|
conformedDimension.add((MetaImportConformedDimensions) meta); |
|
} else { |
|
meta = mapper.readValue(value, MetaImport.class); |
|
} |
|
} catch(Exception e) { |
|
throw(new RuntimeException(e)); |
|
} |
|
if(meta != null) { |
|
meta.setFile(null); |
|
metaImports.add(meta); |
|
} |
|
} |
|
|
|
// gather all conformed dimensions |
|
List<MetaDimension> confDims = new ArrayList<>(); |
|
for (MetaImportConformedDimensions conf : conformedDimension) { |
|
confDims.addAll(conf.conformedDimensions); |
|
} |
|
|
|
// resolve conformed references ('ref_to' attributes) |
|
for (MetaJson metaJson : metaImports) { |
|
if (conformedDimension.size() > 0 && metaJson instanceof MetaImport) { |
|
((MetaImport) metaJson).setConformedDimensions(confDims); |
|
} |
|
try { |
|
metaJson.init(); |
|
metaJson.setNamespaceToMetaObjects(); |
|
} catch (Exception e) { |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
} |
|
|
|
if(shouldReadYMLDoc) { |
|
addDescriptionsFromYMLFiles(); |
|
} |
|
} |
|
|
|
/** |
|
* Calling this method initalizes the MetadataImporter by deserializing all unique meta objects |
|
* from the provided json files. Faulty json files are ignored. |
|
* |
|
* @param paths Path(s) to the metadata file(s). A path can point to a directory or a file. |
|
* Multiple paths and/or directories can be provided. |
|
*/ |
|
public void deserializeMetadataFromJsonFiles(String... paths) { |
|
|
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
|
List<MetaImportConformedDimensions> conformedDimension = new ArrayList<>(); |
|
|
|
for (String path : paths) { |
|
List<File> metaFiles = readMetaImportFiles(path); |
|
for (File file : metaFiles) { |
|
MetaJson meta = null; |
|
try{ |
|
if(file.getName().endsWith(CONFORMED_DIMENSIONS_FILE_SUFFIX)) { |
|
meta = mapper.readValue(file, MetaImportConformedDimensions.class); |
|
conformedDimension.add((MetaImportConformedDimensions) meta); |
|
} else { |
|
meta = mapper.readValue(file, MetaImport.class); |
|
} |
|
} catch(JsonMappingException e) { |
|
String message = "Could not deserialize metadata from file: " + file.getName() + "\n"; |
|
message += e.getMessage(); |
|
errorMessages.add(message); |
|
} catch(Exception e) { |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
if(meta != null) { |
|
log.info("Read metadata from file: " + file.getName()); |
|
meta.setFile(file); |
|
metaImports.add(meta); |
|
} |
|
} |
|
} |
|
|
|
// gather all conformed dimensions |
|
List<MetaDimension> confDims = new ArrayList<>(); |
|
for (MetaImportConformedDimensions conf : conformedDimension) { |
|
confDims.addAll(conf.conformedDimensions); |
|
} |
|
|
|
// resolve conformed references ('ref_to' attributes) |
|
for (MetaJson metaJson : metaImports) { |
|
if (conformedDimension.size() > 0 && metaJson instanceof MetaImport) { |
|
((MetaImport) metaJson).setConformedDimensions(confDims); |
|
} |
|
try { |
|
metaJson.init(); |
|
metaJson.setNamespaceToMetaObjects(); |
|
} catch (Exception e) { |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
} |
|
|
|
if(shouldReadYMLDoc) { |
|
addDescriptionsFromYMLFiles(); |
|
} |
|
|
|
} |
|
|
|
public List<String> readStoredReports() { |
|
List<String> result = new ArrayList<>(); |
|
try { |
|
String dir = PathAndFileUtils.getStoredReportDir("hisinone"); |
|
File[] files = new File(dir).listFiles(); |
|
if(files == null) { |
|
return result; |
|
} |
|
for (File file : files) { |
|
try { |
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
|
StoredReport report = mapper.readValue(file, StoredReport.class); |
|
UpsertStringBuilder builder = new UpsertStringBuilder() |
|
.forTable("metadata", "rw_report_definitions") |
|
.withIntCol("id", Integer.valueOf(report.id)) |
|
.withStringCol("name", report.name) |
|
.withStringCol("definition", report.definition) |
|
.withIntCol("show_total_column", Integer.valueOf(report.showTotalColumn)); |
|
result.add(builder.build(true)); |
|
} catch (JsonMappingException e) { |
|
String message = "Could not deserialize stored report from file: " + file.getName() + "\n"; |
|
message += e.getMessage(); |
|
errorMessages.add(message); |
|
} |
|
} |
|
// After inserting the stored reports with a fixed id we need to re-sync the |
|
// id column of the rw_report_definitions table |
|
if(result.size() != 0) { |
|
result.add("SELECT setval(pg_get_serial_sequence('metadata.rw_report_definitions', 'id')," |
|
+ "(SELECT max(id) FROM metadata.rw_report_definitions ));"); |
|
} |
|
} catch(Exception e) { |
|
errorMessages.add("Unable to read stored report:\n"); |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
return result; |
|
} |
|
|
|
public void addDescriptionsFromYMLFiles() { |
|
String dir = ymlDir; |
|
if(ymlDir == null || ymlDir.isBlank()) { |
|
dir = PathAndFileUtils.getDbtModelsDirectory("hisinone"); |
|
} |
|
HashMap<String, String> map = getMarkdownDefinitions(dir); |
|
addYMLDescriptionsToMetaObjects(dir, map); |
|
} |
|
|
|
public void addYMLDescriptionsToMetaObjects(String ymlDir, HashMap<String, String> mdDefs){ |
|
log.info("Adding descriptions from yml files"); |
|
HashMap<String, String> descriptions = createDescriptions(new File(ymlDir), mdDefs); |
|
List<MetaObject> objs = getAllMetaObjectsWithConformed(); |
|
for (MetaObject metaObj : objs ) { |
|
String docIdentifier = null; |
|
try { |
|
docIdentifier = metaObj.getDocIdentifier(); |
|
} catch (FaultyMetadataException e) { |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
if(docIdentifier == null || docIdentifier.isBlank()) { |
|
continue; |
|
} |
|
// only use yml doc if json description does not exist |
|
if(metaObj.getDescription() == null || metaObj.getDescription().isBlank()) { |
|
String desc = descriptions.get(docIdentifier); |
|
if(desc == null) { |
|
log.warn("Missing yml description for: " + docIdentifier); |
|
} else { |
|
metaObj.setDescription(desc); |
|
if(desc.isBlank()) { |
|
log.warn("Empty yml description for MetaObject: " + docIdentifier); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
private HashMap<String, String> createDescriptions(File startDir, HashMap<String, String> mdDefs){ |
|
HashMap<String, String> result = new HashMap<>(); |
|
for (MetaYml yml : getDescriptionYMLs(startDir)) { |
|
for (MetaYmlModel model : yml.getModels()) { |
|
String modelName = model.getName(); |
|
String modelDesc = model.getDescription(); |
|
result.put(modelName, getDescription(modelDesc, mdDefs)); |
|
for (MetaYmlModelColumns column : model.getColumns()) { |
|
String colName = column.getName(); |
|
String colDesc = column.getDescription(); |
|
result.put(modelName + "." + colName, getDescription(colDesc, mdDefs)); |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
private static String getDescription(String desc, HashMap<String, String> mdDefs) { |
|
if(desc == null) { |
|
return ""; |
|
} |
|
if(desc.startsWith("{{")) { |
|
String[] parts = desc.split("\""); |
|
String docRef = parts[1]; |
|
return mdDefs.get(docRef); |
|
} |
|
return desc; |
|
} |
|
|
|
private List<MetaYml> getDescriptionYMLs(File startDir){ |
|
List<MetaYml> ymls = new ArrayList<>(); |
|
List<String> files = getFiles(startDir, "", ".yml"); |
|
ObjectMapper mapperYml = new ObjectMapper(new YAMLFactory()); |
|
for (String f : files) { |
|
File file = new File(startDir + File.separator + f); |
|
MetaYml doc = null; |
|
try { |
|
doc = mapperYml.readValue(file, MetaYml.class); |
|
} catch (Exception e) { |
|
String message = "Could not read documentation from file: " + file.getName() + "\n"; |
|
errorMessages.add(message); |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
if(doc != null) { |
|
log.info("Read documentation from file: " + file.getName()); |
|
ymls.add(doc); |
|
} |
|
} |
|
return ymls; |
|
} |
|
|
|
|
|
/** |
|
* Gathers all metadata json files. |
|
* |
|
* @param path A path to a metadata json file or a directory containing metadata json files. |
|
* @return A list of files matching the metadata json suffix. |
|
*/ |
|
private static List<File> readMetaImportFiles(String path) { |
|
File metaimportPath = new File(PathAndFileUtils.getDbtJsonPath(path)); |
|
List<File> metaimportFiles = new ArrayList<>(); |
|
if (metaimportPath.isDirectory()) { |
|
metaimportPath.list(new FilenameFilter() { |
|
@Override |
|
public boolean accept(File dir, String name) { |
|
if (name.endsWith(METAIMPORT_FILE_SUFFIX)) { |
|
File file = new File(dir.getAbsolutePath() + File.separator + name); |
|
metaimportFiles.add(file); |
|
return true; |
|
} |
|
return false; |
|
} |
|
}); |
|
} else { |
|
metaimportFiles.add(metaimportPath); |
|
} |
|
return metaimportFiles; |
|
} |
|
|
|
private static List<String> getFiles(File startDir, String subDir, String extension) { |
|
List<String> filtered = new ArrayList<String>(); |
|
for (File file : startDir.listFiles()) { |
|
String name = file.getName(); |
|
if(file.isDirectory()) { |
|
filtered.addAll(getFiles(file, subDir + File.separator + name, extension)); |
|
} |
|
String filename = name.strip().toLowerCase(); |
|
if(filename.endsWith(extension)) { |
|
filtered.add(subDir + File.separator + name); |
|
} |
|
} |
|
return filtered; |
|
} |
|
|
|
/* |
|
|
|
/** |
|
* Generates the sql upsert strings for all unique, deserialized MetaObjects. |
|
* |
|
* @param hasOnConflictConstruct If set to true generates upsert strings with the postgres-specific "ON CONFLICT" clause. |
|
* @return All the generated upserts from the metadata files. |
|
*/ |
|
public List<String> getAllUpsertStrings(boolean hasOnConflictConstruct) { |
|
|
|
List<String> upsertStmts = new ArrayList<>(); |
|
List<Identifier> ids = new ArrayList<>(); |
|
|
|
for (MetaJson meta : metaImports) { |
|
for(MetaObject obj: meta.getMetaObjects()) { |
|
Identifier id = obj.getId(); |
|
if(id == null) { |
|
String message = String.format("Missing ID for Element '%s' in file: %s.", obj.getCaption(), meta.getFile().getAbsolutePath()); |
|
errorMessages.add(message); |
|
continue; |
|
} |
|
if(ids.contains(id)) { |
|
String message = String.format("Duplicate ID '%s'. Ignoring Element '%s'.", obj.getCaption(), obj.getId().composedId); |
|
errorMessages.add(message); |
|
continue; |
|
} |
|
ids.add(obj.getId()); |
|
String stmt = obj.getUpsertBuilder().build(hasOnConflictConstruct); |
|
upsertStmts.add(stmt); |
|
} |
|
} |
|
return upsertStmts; |
|
} |
|
|
|
public void updateMetadataForH2Database(DataSource dataSource) throws Exception { |
|
String metaFilesDir = String.join(File.separator, new String[] {"test", "resources", "db", "fixtures", "bianalysis", "metadata"}); |
|
deserializeMetadataFromJsonFiles(metaFilesDir); |
|
JdbcTemplate jt = new JdbcTemplate(dataSource); |
|
String upserts = String.join("\n", getAllUpsertStrings(false).toString()); |
|
jt.execute(upserts); |
|
} |
|
|
|
/** |
|
* Updates tables in the metadata schema. |
|
* |
|
* @param metaPath Location of the metadata file or directory. |
|
* @param dataSource The datasource on which the sql is executed. |
|
* @throws Exception |
|
*/ |
|
public void updateMetadataSchema(String project, DataSource dataSource) throws Exception { |
|
String metaFilesDir = PathAndFileUtils.getReportGeneratorDir(project); |
|
deserializeMetadataFromJsonFiles(metaFilesDir); |
|
|
|
try (Connection con = dataSource.getConnection()) { |
|
try (Statement st = con.createStatement()) { |
|
log.info("Update Metadata for BIAnalysis."); |
|
st.execute(TRUNCATE_METADATA_SQL); |
|
List<String> upserts = getAllUpsertStrings(true); |
|
upserts.addAll(readStoredReports()); |
|
for (String sql : upserts) { |
|
log.info(sql); |
|
try (Statement stUpsert = con.createStatement()) { |
|
stUpsert.execute(sql); |
|
} catch (Exception e) { |
|
throw e; |
|
} |
|
} |
|
} |
|
|
|
|
|
// execute sql in "attributes_sql" in metadata files to build the attributes |
|
// dynamically |
|
|
|
List<Identifier> ids = getAllIds(); |
|
|
|
List<MetaDimensionAttribute> generatedAttributes = new ArrayList<>(); |
|
List<MetaDimensionAttribute> co = new ArrayList<>(); |
|
|
|
for (MetaJson i : this.metaImports) { |
|
for (MetaObject obj : i.getMetaObjects()) { |
|
if (!(obj instanceof MetaDimension)) continue; |
|
MetaDimension dim = (MetaDimension) obj; |
|
|
|
String attributesSql = ""; |
|
if (dim.getAttributesSql() != null && !dim.getAttributesSql().isEmpty()) { |
|
attributesSql = dim.getAttributesSql(); |
|
} else if((dim.getRefTo() != null && dim.getConformedDimension().getAttributesSql() != null)) { |
|
attributesSql = dim.getConformedDimension().getAttributesSql(); |
|
} else { |
|
continue; |
|
} |
|
|
|
try (Statement stAttr = con.createStatement(); ResultSet rs = stAttr.executeQuery(attributesSql)) { |
|
int numAttributes = 0; |
|
while (rs.next()) { |
|
|
|
MetaDimensionAttribute attribute = new MetaDimensionAttribute(); |
|
attribute.setDimension(dim); |
|
attribute.setCaption(rs.getString("caption")); |
|
attribute.setDimColumn(rs.getString("dim_column")); |
|
attribute.setDefaultRelease(DbMetaAdapter.getCustomDefaultReleaseForCurrentDate()); |
|
attribute.setPosition(Integer.valueOf(numAttributes)); |
|
|
|
// create a new 'on the fly' identifier for the new metadata |
|
// attribute |
|
Identifier id = Identifier.getNewIdentifierValue(ids, dim.getNamespace()); |
|
ids.add(id); |
|
Integer val = Integer.valueOf(id.value.intValue() + numAttributes); |
|
attribute.setId(new Identifier(dim.getNamespace() + ":" +val)); |
|
attribute.setNamespace(id.namespace); |
|
numAttributes++; |
|
|
|
generatedAttributes.add(attribute); |
|
|
|
if(attribute.getDimension().getConformedDimension() == null) { |
|
co.add(attribute); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
// TODO figure out better solution for orgunits |
|
for (MetaDimensionAttribute metaDimensionAttribute : generatedAttributes) { |
|
if(metaDimensionAttribute.getDimension().getConformedDimension() != null) { |
|
for (MetaDimensionAttribute confA : co) { |
|
if(confA.getDimColumn().equals(metaDimensionAttribute.getDimColumn())) { |
|
metaDimensionAttribute.setConfDimAttrRef(confA); |
|
} |
|
} |
|
} |
|
String stmt = metaDimensionAttribute.getUpsertBuilder().build(true); |
|
try (Statement stUpsert = con.createStatement()) { |
|
stUpsert.execute(stmt); |
|
} |
|
} |
|
|
|
} |
|
} |
|
|
|
|
|
public static void writeYmlToFile(MetaYml yml, File file) { |
|
YAMLFactory yf = new YAMLFactory() |
|
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES) |
|
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER); |
|
ObjectMapper mapper = new ObjectMapper(yf); |
|
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF); |
|
DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); |
|
printer.indentObjectsWith(indenter); |
|
printer.indentArraysWith(indenter); |
|
try { |
|
mapper.writer(printer).writeValue(file, yml); |
|
} catch (Exception e) { |
|
throw new RuntimeException(e); |
|
} |
|
} |
|
|
|
public static String writeYmlToString(MetaYml yml) { |
|
YAMLFactory yf = new YAMLFactory() |
|
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES) |
|
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER); |
|
ObjectMapper mapper = new ObjectMapper(yf); |
|
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF); |
|
DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); |
|
printer.indentObjectsWith(indenter); |
|
printer.indentArraysWith(indenter); |
|
try { |
|
//mapper.writer(printer).writeValue(file, yml); |
|
return mapper.writer(printer).writeValueAsString(yml); |
|
} catch (Exception e) { |
|
throw new RuntimeException(e); |
|
} |
|
} |
|
|
|
public String getPrintableErrorMessages() { |
|
String output = ""; |
|
if(!errorMessages.isEmpty()) { |
|
output += "The following errors occured:\n"; |
|
for (String message : errorMessages) { |
|
output += message + "\n"; |
|
} |
|
} |
|
return output; |
|
} |
|
|
|
public HashMap<String, String> getMarkdownDefinitions(String ymlDir) { |
|
List<String> files = getFiles(new File(ymlDir), "", ".md"); |
|
HashMap<String, String> map = new HashMap<>(); |
|
for (String file : files) { |
|
try { |
|
try (BufferedReader br = new BufferedReader(new FileReader(ymlDir + File.separator + file))) { |
|
String line; |
|
String key = null; |
|
boolean readHeading = false; |
|
while ((line = br.readLine()) != null) { |
|
if (line.startsWith("{% docs ")) { |
|
int startIndex = line.indexOf("docs"); // find "docs" |
|
if(startIndex == -1) { |
|
throw new RuntimeException("docs not found"); |
|
} |
|
startIndex += "docs".length(); // move start index to after "docs" |
|
int endIndex = line.indexOf('%', startIndex); // find next % starting from "docs" |
|
if(endIndex == -1) { |
|
throw new RuntimeException("No % found after docs"); |
|
} |
|
key = line.substring(startIndex, endIndex).trim(); |
|
map.put(key, ""); |
|
} else if(key != null && line.startsWith("# ")) { |
|
readHeading = true; |
|
} else { |
|
if(readHeading && !line.isBlank()) { |
|
map.put(key, line); |
|
key = null; |
|
readHeading = false; |
|
} |
|
} |
|
} |
|
} |
|
} catch (Exception e) { |
|
String message = "ERROR getting markdown definitions from file: " + file + "\n"; |
|
errorMessages.add(message); |
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
|
} |
|
} |
|
return map; |
|
} |
|
|
|
public Optional<MetaImport> getMetaImport(String fileName) { |
|
return metaImports.stream() |
|
.filter(json -> (json instanceof MetaImport) && json.file.getName().equals(fileName)) |
|
.map(json -> (MetaImport) json) |
|
.findFirst(); |
|
} |
|
|
|
public Optional<MetaJson> getMetaJson(String fileName) { |
|
return metaImports.stream() |
|
.filter(json -> json.file.getName().equals(fileName)) |
|
.findFirst(); |
|
} |
|
|
|
public List<MetaImport> getMetaImports() { |
|
return metaImports.stream() |
|
.filter(json -> (json instanceof MetaImport)) |
|
.map(json -> (MetaImport) json) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
public List<MetaImportConformedDimensions> getMetaImportsConformed() { |
|
return metaImports.stream() |
|
.filter(json -> (json instanceof MetaImportConformedDimensions)) |
|
.map(json -> (MetaImportConformedDimensions) json) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
public List<MetaJson> getMetaJsons() { |
|
return metaImports.stream().collect(Collectors.toList()); |
|
} |
|
|
|
public List<MetaObject> getAllMetaObjects(){ |
|
return metaImports.stream() |
|
.filter(json -> (json instanceof MetaImport)) |
|
.map(meta -> ((MetaImport) meta).getMetaObjects()) |
|
.flatMap(List::stream) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
public List<MetaObject> getAllMetaObjectsWithConformed(){ |
|
return metaImports.stream() |
|
.map(meta -> meta.getMetaObjects()) |
|
.flatMap(List::stream) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
public List<MetaFact> getAllFactTables(){ |
|
return metaImports.stream() |
|
.filter(json -> (json instanceof MetaImport)) |
|
.map(meta -> ((MetaImport) meta).facts) |
|
.flatMap(List::stream) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
public void setShouldReadYMLDoc(boolean shouldReadYMLDoc) { |
|
this.shouldReadYMLDoc = shouldReadYMLDoc; |
|
} |
|
|
|
public List<Identifier> getAllIds() { |
|
return metaImports.stream() |
|
.map(meta -> meta.getIds()) |
|
.flatMap(List::stream) |
|
.collect(Collectors.toList()); |
|
} |
|
|
|
|
|
}
|
|
|