Compare commits

...

4 Commits

Author SHA1 Message Date
Joshua Darnell bc2ed0439d
Update LICENSE 2023-03-19 12:43:49 -07:00
darnjo 717fee2751 #100: Migrate to Flattened DD Sheet Format 2023-03-14 03:25:09 -07:00
darnjo 109335688a Merge branch 'main' into 100-migrate-dd-reference-sheet-format-to-flattened-sheet
Updated to version 1.2.1 to support multi-release JARs.
2023-03-13 17:33:42 -07:00
darnjo 5d8c746a1d #100: Refactor to support flattened sheets 2023-03-13 17:25:02 -07:00
51 changed files with 24150 additions and 47731 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ build/
*.log
*.iml
.run/
.DS_Store

View File

@ -1,13 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="generateDDAcceptanceTests" type="Application" factoryName="Application">
<option name="ALTERNATIVE_JRE_PATH" value="1.8" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="org.reso.commander.App" />
<module name="web-api-commander.main" />
<option name="PROGRAM_PARAMETERS" value="--generateDDAcceptanceTests" />
<option name="WORKING_DIRECTORY" value="." />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

22
LICENSE
View File

@ -1,21 +1,5 @@
MIT License
By downloading this resource, you agree to the RESO EULA.
Copyright (c) 2019 Joshua Darnell
https://www.reso.org/eula/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Copyright (c) 2019 RESO (dev@reso.org)

View File

@ -73,7 +73,6 @@ jar {
exclude 'META-INF/*.DSA'
}
// don't suppress warnings or deprecation notices
tasks.withType(JavaCompile).configureEach {
options.compilerArgs << '-Xlint:unchecked'

View File

@ -61,9 +61,6 @@ usage: java -jar web-api-commander
using numeric keys.
--generateReferenceEDMX Generates reference metadata in EDMX
format.
--generateResourceInfoModels Generates Java Models for the Web API
Reference Server in the current
directory.
--getMetadata Fetches metadata from <serviceRoot>
using <bearerToken> and saves results
in <outputFile>.

View File

@ -18,17 +18,6 @@ New Cucumber BDD acceptance tests will be generated and placed in a timestamped
To update the current tests, copy the newly generated ones into the [Data Dictionary BDD `.features` directory](src/main/java/org/reso/certification/features/data-dictionary/v1-7-0), run the `./gradlew build` task, and if everything works as expected, commit the newly generated tests.
## Generating RESO Web API Reference Server Data Models
The RESO Commander can be used to generate data models for the Web API Reference server from the currently approved [Data Dictionary Spreadsheet](src/main/resources/RESODataDictionary-1.7.xlsx).
The Commander project's copy of the sheet needs to be updated with a copy of the [DD Google Sheet](https://docs.google.com/spreadsheets/d/1SZ0b6T4_lz6ti6qB2Je7NSz_9iNOaV_v9dbfhPwWgXA/edit?usp=sharing) prior to generating reference metadata.
```
$ java -jar path/to/web-api-commander.jar --generateResourceInfoModels
```
New ResourceInfo Models for the Web API Reference Server will be generated and placed in a timestamped directory relative to your current path.
## Generating RESO Data Dictionary Reference Metadata
In addition to generating DD acceptance tests, the RESO Commander can generate reference metadata based on the current reference [Data Dictionary Spreadsheet](src/main/resources/RESODataDictionary-1.7.xlsx).

View File

@ -1,2 +1,3 @@
org.gradle.jvmargs=-Xmx28g
org.gradle.warning.mode=all
org.gradle.java.installations.auto-detect=true

View File

@ -4,7 +4,7 @@
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/5.2.1/userguide/multi_project_builds.html
* in the user manual at https://docs.gradle.org/8.0.2/userguide/multi_project_builds.html
* This project uses @Incubating APIs which are subject to change.
*/
rootProject.setName('web-api-commander')
rootProject.name = 'web-api-commander'

View File

@ -2,7 +2,6 @@ package org.reso.certification.codegen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Sheet;
import org.reso.commander.common.Utils;
import org.reso.models.ReferenceStandardLookup;
import org.reso.models.ReferenceStandardField;
@ -17,63 +16,57 @@ import static org.reso.certification.containers.WebAPITestContainer.SINGLE_SPACE
public class BDDProcessor extends WorksheetProcessor {
private static final Logger LOG = LogManager.getLogger(BDDProcessor.class);
private static final String
FEATURE_EXTENSION = ".feature",
LOCKED_WITH_ENUMERATIONS_KEY = "Locked with Enumerations";
private static final String FEATURE_EXTENSION = ".feature";
private static final int EXAMPLES_PADDING_AMOUNT = 6;
public void processResourceSheet(Sheet sheet) {
super.processResourceSheet(sheet);
markup.append(BDDTemplates.buildHeaderInfo(sheet.getSheetName(), startTimestamp));
}
@Override
void processNumber(ReferenceStandardField row) {
markup.append(BDDTemplates.buildNumberTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildNumberTest(row));
}
@Override
void processStringListSingle(ReferenceStandardField row) {
markup.append(BDDTemplates.buildStringListSingleTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildStringListSingleTest(row));
}
@Override
void processString(ReferenceStandardField row) {
markup.append(BDDTemplates.buildStringTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildStringTest(row));
}
@Override
void processBoolean(ReferenceStandardField row) {
markup.append(BDDTemplates.buildBooleanTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildBooleanTest(row));
}
@Override
void processStringListMulti(ReferenceStandardField row) {
markup.append(BDDTemplates.buildStringListMultiTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildStringListMultiTest(row));
}
@Override
void processDate(ReferenceStandardField row) {
markup.append(BDDTemplates.buildDateTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildDateTest(row));
}
@Override
void processTimestamp(ReferenceStandardField row) {
markup.append(BDDTemplates.buildTimestampTest(row));
resourceTemplates.get(row.getResourceName()).append(BDDTemplates.buildTimestampTest(row));
}
@Override
void processCollection(ReferenceStandardField row) {
LOG.debug("Collection Type is not supported!");
void processExpansion(ReferenceStandardField field) {
//TODO: DD 2.0
}
@Override
void generateOutput() {
LOG.info("Using reference worksheet: " + REFERENCE_WORKSHEET);
LOG.info("Generating BDD .feature files for the following resources: " + resourceTemplates.keySet().toString());
resourceTemplates.forEach((resourceName, content) -> {
LOG.info("Generating BDD .feature files for the following resources: " + resourceTemplates.keySet());
resourceTemplates.forEach((resourceName, buffer) -> {
//put in local directory rather than relative to where the input file is
Utils.createFile(getDirectoryName(), resourceName.toLowerCase() + FEATURE_EXTENSION, content);
Utils.createFile(getDirectoryName(), resourceName.toLowerCase() + FEATURE_EXTENSION,
BDDTemplates.buildHeaderInfo(resourceName, startTimestamp) + buffer.toString());
});
}
@ -112,8 +105,8 @@ public class BDDProcessor extends WorksheetProcessor {
//use this to add each field name tag
//tags.add(field.getStandardName());
if (field.getParentResourceName() != null && field.getParentResourceName().length() > 0) {
tags.add(field.getParentResourceName());
if (field.getResourceName() != null && field.getResourceName().length() > 0) {
tags.add(field.getResourceName());
}
tags.addAll(field.getPropertyTypes());
@ -133,7 +126,7 @@ public class BDDProcessor extends WorksheetProcessor {
if (field.getSynonyms().size() > 0) {
template += " Given that the following synonyms for \"" + field.getStandardName()
+ "\" DO NOT exist in the \"" + field.getParentResourceName() + "\" metadata\n" +
+ "\" DO NOT exist in the \"" + field.getResourceName() + "\" metadata\n" +
field.getSynonyms().stream()
.map(synonym -> padLeft("| " + synonym + " |\n", EXAMPLES_PADDING_AMOUNT)).collect(Collectors.joining());
}
@ -146,7 +139,7 @@ public class BDDProcessor extends WorksheetProcessor {
return "\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Boolean\" data type\n";
}
@ -156,7 +149,7 @@ public class BDDProcessor extends WorksheetProcessor {
return "\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Date\" data type\n";
}
@ -179,7 +172,7 @@ public class BDDProcessor extends WorksheetProcessor {
"\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Decimal\" data type\n";
//TODO Length is actually scale for Decimal fields by the DD! :/
@ -203,7 +196,7 @@ public class BDDProcessor extends WorksheetProcessor {
return "\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Integer\" data type\n";
}
@ -215,7 +208,7 @@ public class BDDProcessor extends WorksheetProcessor {
markup
.append(padLeft("| ", EXAMPLES_PADDING_AMOUNT))
.append(lookup.getLookupValue()).append(" | ")
.append(lookup.getLookupDisplayName()).append(" |\n");
.append(lookup.getLegacyODataValue()).append(" |\n");
}
if (markup.length() > 0) markup.insert(0, padLeft("| lookupValue | lookupDisplayName |\n", EXAMPLES_PADDING_AMOUNT));
return markup.toString();
@ -227,11 +220,12 @@ public class BDDProcessor extends WorksheetProcessor {
public static String buildStringListMultiTest(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
return
"\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Multiple Enumeration\" data type\n";
}
@ -242,7 +236,7 @@ public class BDDProcessor extends WorksheetProcessor {
"\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Single Enumeration\" data type\n";
}
@ -252,7 +246,7 @@ public class BDDProcessor extends WorksheetProcessor {
"\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"String\" data type\n";
if (field.getSuggestedMaxLength() != null)
@ -268,7 +262,7 @@ public class BDDProcessor extends WorksheetProcessor {
return "\n " + buildTags(field).stream().map(tag -> "@" + tag).collect(Collectors.joining(SINGLE_SPACE)) + "\n" +
" Scenario: " + field.getStandardName() + "\n" +
generateSynonymsMarkup(field) +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getParentResourceName() + "\" metadata\n" +
" When \"" + field.getStandardName() + "\" exists in the \"" + field.getResourceName() + "\" metadata\n" +
" Then \"" + field.getStandardName() + "\" MUST be \"Timestamp\" data type\n";
}
}

View File

@ -10,8 +10,8 @@ public class DDCacheProcessor extends WorksheetProcessor {
new AtomicReference<>(Collections.synchronizedMap(new LinkedHashMap<>()));
private void addToFieldCache(ReferenceStandardField field) {
standardFieldCache.get().putIfAbsent(field.getParentResourceName(), new LinkedHashMap<>());
standardFieldCache.get().get(field.getParentResourceName()).put(field.getStandardName(), field);
standardFieldCache.get().putIfAbsent(field.getResourceName(), new LinkedHashMap<>());
standardFieldCache.get().get(field.getResourceName()).put(field.getStandardName(), field);
}
public Map<String, Map<String, ReferenceStandardField>> getStandardFieldCache() {
@ -54,8 +54,8 @@ public class DDCacheProcessor extends WorksheetProcessor {
}
@Override
void processCollection(ReferenceStandardField field) {
addToFieldCache(field);
void processExpansion(ReferenceStandardField field) {
//TODO: DD 2.0
}
@Override

View File

@ -16,40 +16,72 @@ import static org.reso.certification.codegen.EDMXProcessor.EMPTY_STRING;
import static org.reso.certification.containers.WebAPITestContainer.SINGLE_SPACE;
import static org.reso.commander.common.DataDictionaryMetadata.v1_7.*;
//TODO: move to central lib
public class DDLProcessor extends WorksheetProcessor {
private static final Logger LOG = LogManager.getLogger(DDLProcessor.class);
private static final String PADDING = " ";
private static final int STRING_KEY_SIZE = 64;
private static final int DEFAULT_VARCHAR_SIZE = 255;
private final boolean useKeyNumeric;
public DDLProcessor() {
this.useKeyNumeric = false;
}
public DDLProcessor(boolean useKeyNumeric) {
this.useKeyNumeric = useKeyNumeric;
}
private String buildFieldMarkup(String fieldName, String typeMarkup) {
StringBuilder fieldMarkup = new StringBuilder();
public static String buildDbTableName(String resourceName) {
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, resourceName).replace("o_u_i_d", "ouid");
}
if (markup.length() > 0) {
private static String buildCreateLookupStatement(boolean useKeyNumeric) {
return
"\n\n/**\n" +
" This creates the Lookup resource, as described in RESO RCP-032, \n" +
" with an optional numeric key. \n\n" +
" SEE: https://reso.atlassian.net/wiki/spaces/RESOWebAPIRCP/pages/2275152879/RCP+-+WEBAPI-032+Lookup+and+RelatedLookup+Resources+for+Lookup+Metadata\n" +
"**/\n" +
"CREATE TABLE IF NOT EXISTS lookup ( \n" +
" LookupKey VARCHAR(" + STRING_KEY_SIZE + ") NOT NULL, \n" +
" LookupKeyNumeric BIGINT NOT NULL AUTO_INCREMENT, \n" +
" LookupName VARCHAR(255) NOT NULL, \n" +
" LookupValue VARCHAR(255) NOT NULL, \n" +
" StandardLookupValue VARCHAR(255) DEFAULT NULL, \n" +
" LegacyODataValue VARCHAR(128) DEFAULT NULL, \n" +
" ModificationTimestamp DATETIME DEFAULT CURRENT_TIMESTAMP, \n" +
" PRIMARY KEY (LookupKey" + (useKeyNumeric ? "Numeric" : EMPTY_STRING) + ")\n" +
") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
}
/**
* Add treatments for any SQL replacements that need to be done here
* <p>
* For instance, 'Order' is used by the DD in the Media resource, but it's a SQL keyword.
*
* @param sql SQL statement to be sanitized
* @return sanitized SQL statement
*/
private static String sanitizeSql(String sql) {
return sql
.replaceAll("\\bOrder\\b", "`Order`");
}
private String buildFieldMarkup(ReferenceStandardField field, String typeMarkup) {
StringBuilder fieldMarkup = new StringBuilder();
String resourceName = field.getResourceName(), fieldName = field.getStandardName();
if (resourceTemplates.get(resourceName).length() > 0) {
fieldMarkup.append(", ");
}
fieldMarkup.append("\n")
.append(PADDING)
.append(fieldName)
.append(SINGLE_SPACE)
.append(typeMarkup);
.append(PADDING)
.append(fieldName)
.append(SINGLE_SPACE)
.append(typeMarkup);
//if the current field is a key field then append NOT NULL depending on which key it is
if ((useKeyNumeric && isPrimaryKeyNumericField(sheet.getSheetName(), fieldName))) {
if ((useKeyNumeric && isPrimaryKeyNumericField(resourceName, fieldName))) {
fieldMarkup.append(SINGLE_SPACE).append("NOT NULL AUTO_INCREMENT");
} else if (isPrimaryKeyField(sheet.getSheetName(), fieldName)) {
} else if (isPrimaryKeyField(field.getResourceName(), fieldName)) {
fieldMarkup.append(SINGLE_SPACE).append("NOT NULL");
} else if (!typeMarkup.contains("DEFAULT")) {
fieldMarkup.append(SINGLE_SPACE).append("DEFAULT NULL");
@ -82,51 +114,50 @@ public class DDLProcessor extends WorksheetProcessor {
}
}
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processStringListSingle(ReferenceStandardField field) {
String typeMarkup = useKeyNumeric ? "BIGINT" : "VARCHAR(" + STRING_KEY_SIZE + ")";
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processString(ReferenceStandardField field) {
String typeMarkup = !field.getStandardName().contains("Key") && field.getSuggestedMaxLength() > 80 ? "TEXT":
"VARCHAR" + (field.getSuggestedMaxLength() != null ? "(" + field.getSuggestedMaxLength() + ")" : EMPTY_STRING);
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
int length = field.getSuggestedMaxLength() != null ? field.getSuggestedMaxLength() : DEFAULT_VARCHAR_SIZE;
String typeMarkup = !field.getStandardName().contains("Key") && length > 80 ? "TEXT" :
"VARCHAR" + "(" + length + ")";
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processBoolean(ReferenceStandardField field) {
String typeMarkup = "TINYINT(1) DEFAULT FALSE";
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processStringListMulti(ReferenceStandardField field) {
String typeMarkup = useKeyNumeric ? "BIGINT" : "VARCHAR(" + STRING_KEY_SIZE + ")";
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processDate(ReferenceStandardField field) {
String typeMarkup = "DATE";
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processTimestamp(ReferenceStandardField field) {
String typeMarkup = "DATETIME";
markup.append(buildFieldMarkup(field.getStandardName(), typeMarkup));
resourceTemplates.get(field.getResourceName()).append(buildFieldMarkup(field, typeMarkup));
}
@Override
void processCollection(ReferenceStandardField field) {
//NOTE: NOT IMPLEMENTED FOR DDL CREATION SCRIPTS
//A Collection is actually a list of known values from a joined resource
//this is handled by StandardResources
void processExpansion(ReferenceStandardField field) {
//Does not apply in this case...
}
@Override
@ -134,27 +165,25 @@ public class DDLProcessor extends WorksheetProcessor {
StringBuilder content = new StringBuilder();
content
.append("/**\n")
.append(PADDING).append("RESO Data Dictionary 1.7 Database Generation (DDL) Script\n")
.append(PADDING).append("Autogenerated on: ").append(Utils.getIsoTimestamp()).append("\n")
.append(PADDING).append("This content is covered by RESO's EULA. SEE: https://www.reso.org/eula/\n")
.append(PADDING).append("For questions or comments, please contact dev@reso.org\n")
.append("**/\n\n");
.append("/**\n")
.append(PADDING).append("RESO Data Dictionary 1.7 Database Generation (DDL) Script\n")
.append(PADDING).append("Autogenerated on: ").append(Utils.getIsoTimestamp()).append("\n")
.append(PADDING).append("This content is covered by RESO's EULA. SEE: https://www.reso.org/eula/\n")
.append(PADDING).append("For questions or comments, please contact dev@reso.org\n")
.append("**/\n\n");
content.append("CREATE DATABASE IF NOT EXISTS reso_data_dictionary_1_7;\n");
content.append("USE reso_data_dictionary_1_7;");
resourceTemplates.forEach((resourceName, templateContent) -> {
content
.append("\n\n")
.append("CREATE TABLE IF NOT EXISTS ")
//exception for ouid so it doesn't become o_u_i_d
.append(buildDbTableName(resourceName))
.append(" ( ")
.append(templateContent).append(",\n")
.append(PADDING).append(PADDING).append(buildPrimaryKeyMarkup(resourceName)).append("\n")
.append(") ENGINE=MyISAM DEFAULT CHARSET=utf8;");
});
resourceTemplates.forEach((resourceName, buffer) -> content
.append("\n\n")
.append("CREATE TABLE IF NOT EXISTS ")
//exception for ouid so it doesn't become o_u_i_d
.append(buildDbTableName(resourceName))
.append(" ( ")
.append(buffer.toString()).append(",\n")
.append(PADDING).append(PADDING).append(buildPrimaryKeyMarkup(resourceName)).append("\n")
.append(") ENGINE=MyISAM DEFAULT CHARSET=utf8;"));
LOG.info(sanitizeSql(content.toString()));
@ -164,34 +193,10 @@ public class DDLProcessor extends WorksheetProcessor {
LOG.info(this::buildInsertLookupsStatement);
}
public static String buildDbTableName(String resourceName) {
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, resourceName).replace("o_u_i_d", "ouid");
}
private static String buildCreateLookupStatement(boolean useKeyNumeric) {
return
"\n\n/**\n" +
" This creates the Lookup resource, as described in RESO RCP-032, \n" +
" with an optional numeric key. \n\n" +
" SEE: https://reso.atlassian.net/wiki/spaces/RESOWebAPIRCP/pages/2275152879/RCP+-+WEBAPI-032+Lookup+and+RelatedLookup+Resources+for+Lookup+Metadata\n" +
"**/\n" +
"CREATE TABLE IF NOT EXISTS lookup ( \n" +
" LookupKey VARCHAR(" + STRING_KEY_SIZE + ") NOT NULL, \n" +
" LookupKeyNumeric BIGINT NOT NULL AUTO_INCREMENT, \n" +
" LookupName VARCHAR(255) NOT NULL, \n" +
" LookupValue VARCHAR(255) NOT NULL, \n" +
" StandardLookupValue VARCHAR(255) DEFAULT NULL, \n" +
" LegacyOdataValue VARCHAR(128) DEFAULT NULL, \n" +
" ModificationTimestamp DATETIME DEFAULT CURRENT_TIMESTAMP, \n" +
" PRIMARY KEY (LookupKey" + (useKeyNumeric ? "Numeric" : EMPTY_STRING) + ")\n" +
") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
}
/**
* INSERT INTO tbl_name (a,b,c)
* VALUES(1,2,3), (4,5,6), (7,8,9);
* VALUES(1,2,3), (4,5,6), (7,8,9);
*
* @return a string containing the insert statements for the current lookups in the Data Dictionary.
*/
private String buildInsertLookupsStatement() {
@ -201,15 +206,14 @@ public class DDLProcessor extends WorksheetProcessor {
StringBuilder content = new StringBuilder("\n\n")
.append("INSERT INTO lookup (LookupKey, LookupName, LookupValue, StandardLookupValue, LegacyOdataValue) VALUES");
standardFieldsMap.forEach((resourceName, standardFieldMap) -> {
standardFieldMap.forEach((standardName, referenceStandardField) -> {
String inserts = buildLookupValueInserts(referenceStandardField);
if (inserts.length() > 0) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(),
(markupMap.keySet().size() > 0 ? ", " : EMPTY_STRING) + PADDING + inserts);
}
});
});
standardFieldsMap.forEach((resourceName, standardFieldMap) ->
standardFieldMap.forEach((standardName, referenceStandardField) -> {
String inserts = buildLookupValueInserts(referenceStandardField);
if (inserts.length() > 0) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(),
(markupMap.keySet().size() > 0 ? ", " : EMPTY_STRING) + PADDING + inserts);
}
}));
markupMap.forEach((lookupStandardName, markup) -> content.append(markup));
return content.append(";").toString();
@ -229,7 +233,7 @@ public class DDLProcessor extends WorksheetProcessor {
fieldHash.set(sha256()
.hashString(
standardField.getLookupName()
+ lookup.getLookupDisplayName()
+ lookup.getLegacyODataValue()
+ lookup.getLookupValue(), StandardCharsets.UTF_8)
.toString());
@ -238,52 +242,12 @@ public class DDLProcessor extends WorksheetProcessor {
.append(PADDING).append("(")
.append("\"").append(fieldHash.get()).append("\"")
.append(", ").append("\"").append(standardField.getLookupName()).append("\"")
.append(", ").append("\"").append(lookup.getLookupDisplayName()).append("\"")
.append(", ").append("\"").append(lookup.getLookupDisplayName()).append("\"")
.append(", ").append("\"").append(lookup.getLegacyODataValue()).append("\"")
.append(", ").append("\"").append(lookup.getLegacyODataValue()).append("\"")
.append(", ").append("\"").append(lookup.getLookupValue()).append("\"")
.append(")");
});
}
return content.toString();
}
// private String buildNavigationPropertyMarkup(String resourceName) {
// StringBuilder content = new StringBuilder();
// List<ReferenceStandardRelationship> referenceStandardRelationships =
// this.getStandardRelationships().stream().filter(referenceStandardRelationship
// -> referenceStandardRelationship.getTargetResource().contentEquals(resourceName)).collect(Collectors.toList());
// for (ReferenceStandardRelationship referenceStandardRelationship : referenceStandardRelationships) {
// //LOG.info(referenceStandardRelationship);
//
// if (referenceStandardRelationship.getTargetResourceKey() != null) {
// content.append("<NavigationProperty")
// .append(" Name=\"").append(referenceStandardRelationship.getTargetStandardName()).append("\"")
// .append(" Type=\"org.reso.metadata.").append(referenceStandardRelationship.getSourceResource()).append("\"")
// .append(" />");
// } else {
// content.append("<NavigationProperty")
// .append(" Name=\"").append(referenceStandardRelationship.getTargetStandardName()).append("\"")
// .append(" Type=\"Collection(org.reso.metadata.").append(referenceStandardRelationship.getSourceResource()).append(")\"")
// .append(" />");
// }
// }
//
// return content.toString();
// }
/**
* Add treatments for any SQL replacements that need to be done here
*
* For instance, 'Order' is used by the DD in the Media resource, but it's a SQL keyword.
* @param sql SQL statement to be sanitized
* @return sanitized SQL statement
*/
private static String sanitizeSql(String sql) {
return sql
.replaceAll("\\bOrder\\b", "`Order`");
}
}

View File

@ -4,7 +4,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.reso.commander.common.DataDictionaryMetadata;
import static org.reso.certification.codegen.WorksheetProcessor.REFERENCE_WORKSHEET;
import static org.reso.certification.codegen.WorksheetProcessor.buildWellKnownStandardFieldHeaderMap;
@ -24,51 +23,35 @@ public class DataDictionaryCodeGenerator {
*/
public DataDictionaryCodeGenerator(WorksheetProcessor processor) {
this.processor = processor;
processor.setReferenceResource(REFERENCE_WORKSHEET);
processor.setDataDictionarySpecification(REFERENCE_WORKSHEET);
workbook = processor.getReferenceWorkbook();
processor.buildEnumerationMap();
}
/**
* Generates Data Dictionary references for local workbook instance using the configured WorksheetProcessor
*
* TODO: convert to .parallelStream()
*/
public void processWorksheets() {
Sheet currentWorksheet, standardResourcesWorksheet;
int sheetIndex, rowIndex;
final int ROW_HEADER_INDEX = 0, FIRST_ROW_INDEX = 1;
final String STANDARD_RELATIONSHIPS_WORKSHEET = "Standard Relationships";
final Sheet fieldsWorksheet;
final int FIRST_ROW_INDEX = 1;
final String FIELDS_WORKSHEET = "Fields";
try {
standardResourcesWorksheet = workbook.getSheet(STANDARD_RELATIONSHIPS_WORKSHEET);
assert standardResourcesWorksheet != null;
fieldsWorksheet = workbook.getSheet(FIELDS_WORKSHEET);
assert fieldsWorksheet != null;
processor.buildStandardRelationships(standardResourcesWorksheet);
processor.wellKnownStandardFieldHeaderMap = buildWellKnownStandardFieldHeaderMap(fieldsWorksheet);
//workbook consists of many sheets, process only the ones that have the name of a well-known resource
for (sheetIndex = ROW_HEADER_INDEX; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
currentWorksheet = workbook.getSheetAt(sheetIndex);
if (DataDictionaryMetadata.v1_7.WELL_KNOWN_RESOURCES.contains(currentWorksheet.getSheetName()) && currentWorksheet.getPhysicalNumberOfRows() > 1) {
processor.beforeResourceSheetProcessed(currentWorksheet);
processor.wellKnownStandardFieldHeaderMap = buildWellKnownStandardFieldHeaderMap(currentWorksheet);
processor.processResourceSheet(currentWorksheet);
//starts at row 1 to skip header row
for (rowIndex = FIRST_ROW_INDEX; rowIndex < currentWorksheet.getPhysicalNumberOfRows(); rowIndex++) {
if (currentWorksheet.getRow(rowIndex) != null) {
processor.processResourceRow(currentWorksheet.getRow(rowIndex));
}
}
processor.afterResourceSheetProcessed(currentWorksheet);
//starts at row 1 to skip header row
for (int rowIndex = FIRST_ROW_INDEX; rowIndex < fieldsWorksheet.getPhysicalNumberOfRows(); rowIndex++) {
if (fieldsWorksheet.getRow(rowIndex) != null) {
processor.processResourceRow(fieldsWorksheet.getRow(rowIndex));
}
}
processor.generateOutput();
} catch (Exception ex) {
LOG.info(ex);
LOG.error(ex);
}
}
}

View File

@ -2,11 +2,9 @@ package org.reso.certification.codegen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Sheet;
import org.reso.commander.common.Utils;
import org.reso.models.ReferenceStandardField;
import org.reso.models.ReferenceStandardLookup;
import org.reso.models.ReferenceStandardRelationship;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
@ -19,37 +17,32 @@ import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Objects;
import static org.reso.commander.common.DataDictionaryMetadata.v1_7.getKeyFieldForResource;
import static org.reso.commander.common.Utils.wrapColumns;
//TODO: switch to build an XML document rather than creating it as a string
public class EDMXProcessor extends WorksheetProcessor {
private static final Logger LOG = LogManager.getLogger(EDMXProcessor.class);
final static String EMPTY_STRING = "";
final static String RESO_NAMESPACE = "org.reso.metadata";
String openEntityTypeTag = null, closeEntityTypeTag = null, keyMarkup = null;
final static String openingDataServicesTag =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<!-- This file was autogenerated from " + REFERENCE_WORKSHEET + " on: " + Utils.getIsoTimestamp() + " -->"
+ "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" Version=\"4.0\">"
+ "<edmx:DataServices>";
final static String closingDataServicesTag = "</edmx:DataServices></edmx:Edmx>";
private static final Logger LOG = LogManager.getLogger(EDMXProcessor.class);
@Override
public void processResourceSheet(Sheet sheet) {
super.processResourceSheet(sheet);
openEntityTypeTag = "<EntityType Name=\"" + sheet.getSheetName() + "\">";
closeEntityTypeTag = "</EntityType>";
private static String sanitizeXml(String input) {
return input.replace("&", "&amp;")
.replace(">", "&gt;")
.replace("<", "&lt;")
.replace("'", "&apos;")
.replace("\"", "&quot;");
}
//TODO: add KeyNumeric handler
private String getKeyMarkup(String resourceName) {
if (resourceName == null) return null;
@ -61,60 +54,63 @@ public class EDMXProcessor extends WorksheetProcessor {
+ "</Key>" : null;
}
@Override
public void afterResourceSheetProcessed(Sheet sheet) {
assert sheet != null && sheet.getSheetName() != null;
String resourceName = sheet.getSheetName();
String templateContent =
openEntityTypeTag
+ getKeyMarkup(resourceName)
+ markup.toString()
+ buildNavigationPropertyMarkup(resourceName)
+ closeEntityTypeTag;
resourceTemplates.put(resourceName, templateContent);
resetMarkupBuffer();
}
@Override
void processNumber(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildNumberMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildNumberMember(field));
}
@Override
void processStringListSingle(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildEnumTypeSingleMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildEnumTypeSingleMember(field));
}
@Override
void processString(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildStringMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildStringMember(field));
}
@Override
void processBoolean(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildBooleanMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildBooleanMember(field));
}
@Override
void processStringListMulti(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildEnumTypeMultiMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildEnumTypeMultiMember(field));
}
@Override
void processDate(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildDateMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildDateMember(field));
}
@Override
void processTimestamp(ReferenceStandardField field) {
markup.append(EDMXTemplates.buildDateTimeWithOffsetMember(field));
resourceTemplates.get(field.getResourceName()).append(EDMXTemplates.buildDateTimeWithOffsetMember(field));
}
@Override
void processCollection(ReferenceStandardField field) {
LOG.debug("Collection Type is not supported at this time!");
void processExpansion(ReferenceStandardField field) {
StringBuilder content = new StringBuilder();
final String simpleDataType = field.getSimpleDataType().trim();
content.append("<NavigationProperty")
.append(" Name=\"").append(field.getStandardName()).append("\"");
if (simpleDataType.compareTo(WELL_KNOWN_DATA_TYPES.COLLECTION) == 0) {
content.append(" Type=\"Collection(org.reso.metadata.").append(field.getSourceResource()).append(")\"");
} else if (simpleDataType.compareTo(WELL_KNOWN_DATA_TYPES.RESOURCE) == 0) {
content.append(" Type=\"org.reso.metadata.").append(field.getSourceResource()).append("\"");
} else {
//unsupported type, just exit without adding content
LOG.error("ERROR: Unsupported simple data type for Expansion fields: '{}'", simpleDataType);
return;
}
content.append(" />");
resourceTemplates.get(field.getResourceName()).append(content);
}
@Override
@ -122,9 +118,9 @@ public class EDMXProcessor extends WorksheetProcessor {
try {
final String output =
openingDataServicesTag
+ buildEntityTypeMarkup()
+ buildEnumTypeMarkup()
+ closingDataServicesTag;
+ buildEntityTypeMarkup()
+ buildEnumTypeMarkup()
+ closingDataServicesTag;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
@ -144,12 +140,12 @@ public class EDMXProcessor extends WorksheetProcessor {
lsSerializer.write(document, formattedOutput);
final String formattedOutputString = stringWriter.toString(),
filename = getReferenceResource().replace(".xlsx", ".xml");
filename = getDataDictionarySpecification().replace(".xlsx", ".xml");
LOG.info("Writing " + formattedOutputString.getBytes().length + " bytes to file: " + filename + "...");
//write content of the string to the same directory as the source file
Utils.createFile(getDirectoryName(), filename, stringWriter.toString());
Utils.createFile(getDirectoryName(), filename, output);
LOG.info("XML Metadata file written!");
@ -175,9 +171,12 @@ public class EDMXProcessor extends WorksheetProcessor {
StringBuilder content = new StringBuilder();
content.append("<Schema xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" Namespace=\"" + RESO_NAMESPACE + "\">");
//iterate through each of the found resources and generate their edm:EntityType content content
resourceTemplates.forEach((resourceName, templateContent) -> {
content.append(templateContent);
//iterate through each of the found resources and generate their edm:EntityType content
resourceTemplates.forEach((resourceName, buffer) -> {
content.append("<EntityType Name=\"").append(resourceName).append("\">");
content.append(getKeyMarkup(resourceName));
content.append(buffer.toString());
content.append("</EntityType>");
});
//nest entity container in main namespace
@ -195,17 +194,15 @@ public class EDMXProcessor extends WorksheetProcessor {
StringBuilder content =
new StringBuilder("<Schema xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" Namespace=\"" + RESO_NAMESPACE + ".enums\">");
standardFieldsMap.forEach((resourceName, standardFieldMap) -> {
standardFieldMap.forEach((standardName, referenceStandardField) -> {
if (referenceStandardField.isSingleEnumeration()) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(), buildSingleEnumTypeMarkup(referenceStandardField));
}
standardFieldsMap.forEach((resourceName, standardFieldMap) -> standardFieldMap.forEach((standardName, referenceStandardField) -> {
if (referenceStandardField.isSingleEnumeration()) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(), buildSingleEnumTypeMarkup(referenceStandardField));
}
if (referenceStandardField.isMultipleEnumeration()) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(), buildMultipleEnumTypeMarkup(referenceStandardField));
}
});
});
if (referenceStandardField.isMultipleEnumeration()) {
markupMap.putIfAbsent(referenceStandardField.getLookupName(), buildMultipleEnumTypeMarkup(referenceStandardField));
}
}));
markupMap.forEach((lookupStandardName, markup) -> content.append(markup));
@ -214,30 +211,6 @@ public class EDMXProcessor extends WorksheetProcessor {
return content.toString();
}
private String buildNavigationPropertyMarkup(String resourceName) {
StringBuilder content = new StringBuilder();
List<ReferenceStandardRelationship> referenceStandardRelationships =
this.getStandardRelationships().stream().filter(referenceStandardRelationship
-> referenceStandardRelationship.getTargetResource().contentEquals(resourceName)).collect(Collectors.toList());
for (ReferenceStandardRelationship referenceStandardRelationship : referenceStandardRelationships) {
//LOG.info(referenceStandardRelationship);
if (referenceStandardRelationship.getTargetResourceKey() != null) {
content.append("<NavigationProperty")
.append(" Name=\"").append(referenceStandardRelationship.getTargetStandardName()).append("\"")
.append(" Type=\"org.reso.metadata.").append(referenceStandardRelationship.getSourceResource()).append("\"")
.append(" />");
} else {
content.append("<NavigationProperty")
.append(" Name=\"").append(referenceStandardRelationship.getTargetStandardName()).append("\"")
.append(" Type=\"Collection(org.reso.metadata.").append(referenceStandardRelationship.getSourceResource()).append(")\"")
.append(" />");
}
}
return content.toString();
}
private String buildSingleEnumTypeMarkup(ReferenceStandardField standardField) {
StringBuilder content = new StringBuilder();
@ -245,21 +218,19 @@ public class EDMXProcessor extends WorksheetProcessor {
content.append("<EnumType Name=\"").append(standardField.getLookupName()).append("\">");
//iterate through each of the lookup values and generate their edm:EnumType content
getEnumerations().get(standardField.getLookupName()).forEach(lookup -> {
content
.append("<Member Name=\"").append(lookup.getLookupValue()).append("\">")
.append(EDMXTemplates.buildDisplayNameAnnotation(lookup.getLookupDisplayName()))
.append(EDMXTemplates.buildDDWikiUrlAnnotation(lookup.getWikiPageUrl()))
.append(EDMXTemplates.buildDescriptionAnnotation(lookup.getDefinition()))
.append("</Member>");
});
getEnumerations().get(standardField.getLookupName()).forEach(lookup -> content
.append("<Member Name=\"").append(lookup.getLegacyODataValue()).append("\">")
.append(EDMXTemplates.buildDisplayNameAnnotation(lookup.getLookupName()))
.append(EDMXTemplates.buildDDWikiUrlAnnotation(lookup.getWikiPageUrl()))
.append(EDMXTemplates.buildDescriptionAnnotation(lookup.getDefinition()))
.append("</Member>"));
content.append("</EnumType>");
} else {
content
.append("<!-- TODO: implement if you are using the single-valued enumeration \"")
.append(standardField.getLookupName()).append("\" -->")
.append("<EnumType Name=\"").append(standardField.getLookupName()).append("\">")
.append("\n<!-- TODO: implement if you are using the single-valued enumeration \"")
.append(standardField.getLookupName()).append("\" -->")
.append("<Member Name=\"Sample").append(standardField.getLookupName()).append("EnumValue").append("\"/>")
.append("</EnumType>");
}
@ -273,50 +244,41 @@ public class EDMXProcessor extends WorksheetProcessor {
content.append("<EnumType Name=\"").append(standardField.getLookupName()).append("\">");
//iterate through each of the lookup values and generate their edm:EnumType content
getEnumerations().get(standardField.getLookupName()).forEach(lookup -> {
content
.append("<Member Name=\"").append(lookup.getLookupValue()).append("\">")
.append(EDMXTemplates.buildDisplayNameAnnotation(lookup.getLookupDisplayName()))
.append(EDMXTemplates.buildDDWikiUrlAnnotation(lookup.getWikiPageUrl()))
.append(EDMXTemplates.buildDescriptionAnnotation(lookup.getDefinition()))
.append("</Member>");
});
getEnumerations().get(standardField.getLookupName()).forEach(lookup -> content
.append("<Member Name=\"").append(lookup.getLegacyODataValue()).append("\">")
.append(EDMXTemplates.buildDisplayNameAnnotation(lookup.getLegacyODataValue()))
.append(EDMXTemplates.buildDDWikiUrlAnnotation(lookup.getWikiPageUrl()))
.append(EDMXTemplates.buildDescriptionAnnotation(lookup.getDefinition()))
.append("</Member>"));
content.append("</EnumType>");
} else {
content
.append("<!-- TODO: implement if you are using the multi-valued enumeration \"").append(standardField.getLookupName()).append("\" -->")
.append("<EnumType Name=\"").append(standardField.getLookupName()).append("\">")
.append("\n<!-- TODO: implement if you are using the multi-valued enumeration \"").append(standardField.getLookupName()).append("\" -->")
.append("<Member Name=\"Sample").append(standardField.getStandardName()).append("EnumValue").append("\">")
.append(EDMXTemplates.buildDDWikiUrlAnnotation(standardField.getWikiPageUrl()))
.append(EDMXTemplates.buildDescriptionAnnotation(standardField.getDefinition()))
.append("<Member Name=\"Sample").append(standardField.getStandardName()).append("EnumValue").append("\"/>")
.append("</Member>")
.append("</EnumType>");
}
return content.toString();
}
private static String sanitizeXml(String input) {
return input.replace("&", "&amp;")
.replace(">", "&gt;")
.replace("<", "&lt;")
.replace("'", "&apos;")
.replace("\"", "&quot;");
}
public static final class EDMXTemplates {
public static String buildDisplayNameAnnotation(String content) {
if (content == null || content.length() <= 0) return EMPTY_STRING;
if (content == null || content.length() == 0) return EMPTY_STRING;
return String.format("<Annotation Term=\"RESO.OData.Metadata.StandardName\" String=\"%1$s\" />", sanitizeXml(content));
}
//wrapColumns(referenceStandardField.getDefinition().replaceAll("--", "-"), " ")
public static String buildDescriptionAnnotation(String content) {
if (content == null || content.length() <= 0) return EMPTY_STRING;
if (content == null || content.length() == 0) return EMPTY_STRING;
return String.format("<Annotation Term=\"Core.Description\" String=\"%1$s\" />", sanitizeXml(content));
}
public static String buildDDWikiUrlAnnotation(String content) {
if (content == null || content.length() <= 0) return EMPTY_STRING;
if (content == null || content.length() == 0) return EMPTY_STRING;
return String.format("<Annotation Term=\"RESO.DDWikiUrl\" String=\"%1$s\" />", sanitizeXml(content));
}
@ -377,28 +339,29 @@ public class EDMXProcessor extends WorksheetProcessor {
}
public static String buildEnumTypeSingleMember(ReferenceStandardField field) {
if (field == null || field.getLookup() == null) return EMPTY_STRING;
if (!field.getLookup().toLowerCase().contains("lookups")) return EMPTY_STRING;
if (field == null || field.getLookupName() == null) return EMPTY_STRING;
if (field.getLookupName().trim().length() == 0) return EMPTY_STRING;
String lookupName = field.getLookup().replace("Lookups", "").trim();
return ""
+ "<Property Name=\"" + field.getStandardName() + "\" Type=\"" + RESO_NAMESPACE + ".enums." + lookupName + "\" >"
+ buildDisplayNameAnnotation(field.getDisplayName())
+ buildDDWikiUrlAnnotation(field.getWikiPageUrl())
+ buildDescriptionAnnotation(field.getDefinition())
+ "</Property>";
return
"<Property Name=\"" + field.getStandardName()
+ "\" Type=\"" + RESO_NAMESPACE + ".enums." + field.getLookupName() + "\" >"
+ buildDisplayNameAnnotation(field.getDisplayName())
+ buildDDWikiUrlAnnotation(field.getWikiPageUrl())
+ buildDescriptionAnnotation(field.getDefinition())
+ "</Property>";
}
public static String buildEnumTypeMultiMember(ReferenceStandardField field) {
if (field == null || field.getLookup() == null) return EMPTY_STRING;
if (!field.getLookup().toLowerCase().contains("lookups")) return EMPTY_STRING;
return ""
+ "<Property Name=\"" + field.getStandardName()
+ "\" Type=\"Collection(" + RESO_NAMESPACE + ".enums." + field.getLookupName() + ")\">"
+ buildDisplayNameAnnotation(field.getDisplayName())
+ buildDDWikiUrlAnnotation(field.getWikiPageUrl())
+ buildDescriptionAnnotation(field.getDefinition())
+ "</Property>";
if (field == null || field.getLookupName() == null) return EMPTY_STRING;
if (field.getLookupName().trim().length() == 0) return EMPTY_STRING;
return
"<Property Name=\"" + field.getStandardName()
+ "\" Type=\"Collection(" + RESO_NAMESPACE + ".enums." + field.getLookupName() + ")\">"
+ buildDisplayNameAnnotation(field.getDisplayName())
+ buildDDWikiUrlAnnotation(field.getWikiPageUrl())
+ buildDescriptionAnnotation(field.getDefinition())
+ "</Property>";
}

View File

@ -1,249 +0,0 @@
package org.reso.certification.codegen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Sheet;
import org.reso.commander.common.Utils;
import org.reso.models.ReferenceStandardField;
import static org.reso.certification.codegen.DDLProcessor.buildDbTableName;
import static org.reso.certification.containers.WebAPITestContainer.EMPTY_STRING;
public class ResourceInfoProcessor extends WorksheetProcessor {
final static String
ANNOTATION_TERM_DISPLAY_NAME = "RESO.OData.Metadata.StandardName",
ANNOTATION_TERM_DESCRIPTION = "Core.Description",
ANNOTATION_TERM_URL = "RESO.DDWikiUrl";
private static final Logger LOG = LogManager.getLogger(ResourceInfoProcessor.class);
private static final String
FILE_EXTENSION = ".java";
public void processResourceSheet(Sheet sheet) {
super.processResourceSheet(sheet);
markup.append(ResourceInfoTemplates.buildClassInfo(sheet.getSheetName(), null));
}
@Override
void processNumber(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildNumberMarkup(row));
}
@Override
void processStringListSingle(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildStringListSingleMarkup(row));
}
@Override
void processString(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildStringMarkup(row));
}
@Override
void processBoolean(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildBooleanMarkup(row));
}
@Override
void processStringListMulti(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildStringListMultiMarkup(row));
}
@Override
void processDate(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildDateMarkup(row));
}
@Override
void processTimestamp(ReferenceStandardField row) {
markup.append(ResourceInfoTemplates.buildTimestampMarkup(row));
}
@Override
void processCollection(ReferenceStandardField row) {
LOG.debug("Collection Type is not supported!");
}
@Override
void generateOutput() {
LOG.info("Using reference worksheet: " + REFERENCE_WORKSHEET);
LOG.info("Generating ResourceInfo .java files for the following resources: " + resourceTemplates.keySet().toString());
resourceTemplates.forEach((resourceName, content) -> {
//put in local directory rather than relative to where the input file is
Utils.createFile(getDirectoryName(), resourceName + "Definition" + FILE_EXTENSION, content);
});
}
@Override
String getDirectoryName() {
return startTimestamp + "-ResourceInfoModels";
}
@Override
public void afterResourceSheetProcessed(Sheet sheet) {
assert sheet != null && sheet.getSheetName() != null;
String resourceName = sheet.getSheetName();
String templateContent =
markup.toString() + "\n" +
" return " + resourceName + "Definition.fieldList;\n" +
" }\n" +
"}";
resourceTemplates.put(resourceName, templateContent);
resetMarkupBuffer();
}
public static final class ResourceInfoTemplates {
/**
* Contains various templates used for test generation
* TODO: add a formatter rather than using inline spaces
*/
public static String buildClassInfo(String resourceName, String generatedTimestamp) {
if (resourceName == null) return null;
if (generatedTimestamp == null) generatedTimestamp = Utils.getIsoTimestamp();
final String definitionName = resourceName + "Definition";
return "package org.reso.service.data.definition;\n" + "\n" +
"import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;\n" +
"import org.reso.service.data.meta.FieldInfo;\n" +
"import org.reso.service.data.meta.ResourceInfo;\n" + "\n" +
"import java.util.ArrayList;\n" + "\n" +
"// This class was autogenerated on: " + generatedTimestamp + "\n" +
"public class " + definitionName + " extends ResourceInfo {\n" +
" private static ArrayList<FieldInfo> fieldList = null;\n" + "\n" +
" public " + definitionName + "() {" + "\n" +
" this.tableName = " + buildDbTableName(resourceName) + ";\n" +
" this.resourcesName = " + resourceName + ";\n" +
" this.resourceName = " + resourceName + ";\n" +
" }\n" + "\n" +
" public ArrayList<FieldInfo> getFieldList() {\n" +
" return " + definitionName + ".getStaticFieldList();\n" +
" }\n" + "\n" +
" public static ArrayList<FieldInfo> getStaticFieldList() {\n" +
" if (null != " + definitionName + ".fieldList) {\n" +
" return " + definitionName + ".fieldList;\n" +
" }\n" + "\n" +
" ArrayList<FieldInfo> list = new ArrayList<FieldInfo>();\n" +
" " + definitionName + ".fieldList = list;\n" +
" FieldInfo fieldInfo = null;\n";
}
public static String buildBooleanMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
//TODO: refactor into one method that takes a type name and returns the appropriate content
return "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.Boolean.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n" +
" list.add(fieldInfo);" +
"\n";
}
public static String buildDateMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
return "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.Date.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n" +
" list.add(fieldInfo);" +
"\n";
}
/**
* Provides special routing for Data Dictionary numeric types, which may be Integer or Decimal
*
* @param field the numeric field to build type markup for
* @return a string containing specific markup for the given field
*/
public static String buildNumberMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
if (field.getSuggestedMaxPrecision() != null) return buildDecimalMarkup(field);
else return buildIntegerMarkup(field);
}
public static String buildDecimalMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
return "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.Decimal.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n" +
" list.add(fieldInfo);" +
"\n";
//TODO: Length is actually scale for Decimal fields by the DD! :/
//TODO: Add setScale property to Decimal types in FieldInfo
//TODO: Precision is actually Scale for Decimal fields by the DD! :/
//TODO: Add setPrecision property to Decimal types in FieldInfo
}
public static String buildIntegerMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
return "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.Int64.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n" +
" list.add(fieldInfo);" +
"\n";
}
private static String buildStandardEnumerationMarkup(String lookupName) {
//TODO: add code to build Lookups
return "\n /* TODO: buildStandardEnumerationMarkup */\n";
}
public static String buildStringListMultiMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
//TODO: add multi lookup handler
return "\n /* TODO: buildStringListMultiMarkup */\n";
}
public static String buildStringListSingleMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
//TODO: add single lookup handler
return "\n /* TODO: buildStringListSingleMarkup */\n";
}
public static String buildStringMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
String content = "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.String.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n";
if (field.getSuggestedMaxLength() != null) {
content +=
" fieldInfo.setMaxLength(" + field.getSuggestedMaxLength() + ");\n";
}
content +=
" list.add(fieldInfo);" + "\n";
return content;
}
public static String buildTimestampMarkup(ReferenceStandardField field) {
if (field == null) return EMPTY_STRING;
return "\n" +
" fieldInfo = new FieldInfo(\"" + field.getStandardName() + "\", EdmPrimitiveTypeKind.DateTime.getFullQualifiedName());\n" +
" fieldInfo.addAnnotation(\"" + field.getDisplayName() + "\", \"" + ANNOTATION_TERM_DISPLAY_NAME + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getDefinition() + "\", \"" + ANNOTATION_TERM_DESCRIPTION + "\");\n" +
" fieldInfo.addAnnotation(\"" + field.getWikiPageUrl() + "\", \"" + ANNOTATION_TERM_URL + "\");\n" +
" list.add(fieldInfo);" +
"\n";
}
}
}

View File

@ -10,75 +10,43 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.reso.commander.common.Utils;
import org.reso.models.ReferenceStandardField;
import org.reso.models.ReferenceStandardLookup;
import org.reso.models.ReferenceStandardRelationship;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import static org.junit.Assert.assertTrue;
import static org.reso.certification.codegen.WorksheetProcessor.WELL_KNOWN_DATA_TYPES.*;
import static org.reso.certification.codegen.WorksheetProcessor.WELL_KNOWN_FIELD_HEADERS.COLLECTION;
import static org.reso.certification.codegen.WorksheetProcessor.WELL_KNOWN_FIELD_HEADERS.STANDARD_NAME;
import static org.reso.commander.common.DataDictionaryMetadata.v1_7.LOOKUP_FIELDS_AND_VALUES;
import static org.reso.commander.common.DataDictionaryMetadata.v1_7.LOOKUPS;
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
public abstract class WorksheetProcessor {
private static final Logger LOG = LogManager.getLogger(WorksheetProcessor.class);
//TODO: make this a dynamic property based on DD version
public static final String REFERENCE_WORKSHEET = "RESODataDictionary-1.7.xlsx";
static final Map<String, String> resourceTemplates = new LinkedHashMap<>();
static final Map<String, StringBuffer> resourceTemplates = new LinkedHashMap<>();
static final Map<String, Set<ReferenceStandardLookup>> standardEnumerationsMap = new LinkedHashMap<>();
static final Map<String, Map<String, ReferenceStandardField>> standardFieldsMap = new LinkedHashMap<>(new LinkedHashMap<>());
private static final Logger LOG = LogManager.getLogger(WorksheetProcessor.class);
String referenceDocument = null;
StringBuffer markup;
Sheet sheet;
String startTimestamp;
String dataDictionarySpecification = null;
String startTimestamp;
Map<String, Integer> wellKnownStandardFieldHeaderMap = new LinkedHashMap<>();
Map<String, Integer> wellKnownStandardEnumerationHeaderMap = new LinkedHashMap<>();
private final List<ReferenceStandardRelationship> referenceStandardRelationships = new ArrayList<>();
static final int
TARGET_RESOURCE = 0,
TARGET_RESOURCE_KEY = 1,
TARGET_STANDARD_NAME = 2,
CARDINALITY = 3,
SOURCE_RESOURCE = 4,
SOURCE_RESOURCE_KEY = 5;
public WorksheetProcessor() {
LOG.info("Using Data Dictionary Reference sheet: " + REFERENCE_WORKSHEET);
startTimestamp = Utils.getTimestamp();
markup = new StringBuffer();
}
public static Map<String, Integer> buildWellKnownStandardFieldHeaderMap(Sheet sheet) {
Map<String, Integer> headerMap = new LinkedHashMap<>();
sheet.getRow(0).cellIterator().forEachRemaining(cell ->
headerMap.put(cell.getStringCellValue(), cell.getColumnIndex()));
headerMap.put(cell.getStringCellValue(), cell.getColumnIndex()));
return headerMap;
}
public Integer getWellKnownStandardFieldIndex(String wellKnownStandardFieldKey) {
return wellKnownStandardFieldHeaderMap.get(wellKnownStandardFieldKey);
}
public Integer getWellKnownStandardEnumerationIndex(String wellKnownStandardEnumerationKey) {
return wellKnownStandardEnumerationHeaderMap.get(wellKnownStandardEnumerationKey);
}
public void buildWellKnownStandardEnumerationHeaderMap(Sheet sheet) {
wellKnownStandardEnumerationHeaderMap = new LinkedHashMap<>();
sheet.getRow(0).cellIterator().forEachRemaining(cell ->
wellKnownStandardEnumerationHeaderMap.put(cell.getStringCellValue(), cell.getColumnIndex()));
}
public List<ReferenceStandardRelationship> getStandardRelationships() {
return this.referenceStandardRelationships;
}
public static Integer getIntegerValue(Integer index, Row row, Integer defaultValue) {
if (index == null || !(index >= 0)) return defaultValue;
Integer value;
@ -144,9 +112,9 @@ public abstract class WorksheetProcessor {
//LOG.info("Cell index is: " + index + ", cell value is: " + cellValue);
value = Arrays.stream(cellValue
.replace(" ", "").split(","))
.map(String::trim)
.filter(item -> item.length() > 0)
.collect(Collectors.toList());
.map(String::trim)
.filter(item -> item.length() > 0)
.collect(Collectors.toList());
}
} catch (Exception ex) {
value = defaultValue;
@ -158,83 +126,6 @@ public abstract class WorksheetProcessor {
return getArrayValue(index, row, new ArrayList<>());
}
public ReferenceStandardRelationship deserializeStandardRelationshipRow(Row row) {
ReferenceStandardRelationship referenceStandardRelationship = null;
try {
referenceStandardRelationship = ReferenceStandardRelationship.Builder.build(
row.getCell(TARGET_RESOURCE).getStringCellValue(),
row.getCell(TARGET_RESOURCE_KEY, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue(),
row.getCell(TARGET_STANDARD_NAME).getStringCellValue(),
ReferenceStandardRelationship.Cardinality.stream().filter(cardinality ->
cardinality.getRelationshipType().contentEquals(
row.getCell(CARDINALITY).getStringCellValue())).findFirst().orElseThrow(Exception::new),
row.getCell(SOURCE_RESOURCE).getStringCellValue(),
row.getCell(SOURCE_RESOURCE_KEY).getStringCellValue()
);
} catch (Exception ex) {
LOG.error(ex);
}
return referenceStandardRelationship;
}
public ReferenceStandardField deserializeStandardFieldRow(Row row) {
return new ReferenceStandardField.Builder()
.setStandardName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.STANDARD_NAME), row))
.setDisplayName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.DISPLAY_NAME), row))
.setDefinition(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.DEFINITION), row))
.setGroups(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.GROUPS), row))
.setSimpleDataType(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SIMPLE_DATA_TYPE), row))
.setSuggestedMaxLength(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SUGGESTED_MAX_LENGTH), row))
.setSynonyms(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SYNONYM), row))
.setElementStatus(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.ELEMENT_STATUS), row))
.setBedes(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.BEDES), row))
.setCertificationLevel(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.CERTIFICATION_LEVEL), row))
.setRecordId(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.RECORD_ID), row))
.setLookupStatus(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.LOOKUP_STATUS), row))
.setLookup(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.LOOKUP), row))
.setCollection(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.COLLECTION), row))
.setSuggestedMaxPrecision(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SUGGESTED_MAX_PRECISION), row))
.setRepeatingElement(getBooleanValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.REPEATING_ELEMENT), row))
.setPropertyTypes(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.PROPERTY_TYPES), row))
.setPayloads(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.PAYLOADS), row))
.setSpanishStandardName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SPANISH_STANDARD_NAME), row))
.setStatusChangeDate(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.STATUS_CHANGE_DATE), row))
.setRevisedDate(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.REVISED_DATE), row))
.setAddedInVersion(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.ADDED_IN_VERSION), row))
.setWikiPageTitle(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_TITLE), row))
.setWikiPageURL(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_URL), row))
.setWikiPageID(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_ID), row))
.build();
}
public ReferenceStandardLookup deserializeStandardEnumerationRow(Row row) {
return new ReferenceStandardLookup.Builder()
.setLookupField(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_FIELD), row))
.setLookupValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_VALUE), row))
.setLookupDisplayName(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_DISPLAY_NAME), row))
.setDefinition(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.DEFINITION), row))
.setLookupDisplayNameSynonyms(getArrayValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_DISPLAY_NAME_SYNONYMS), row))
.setBedes(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.BEDES), row))
.setReferences(getArrayValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.REFERENCES), row))
.setElementStatus(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.ELEMENT_STATUS), row))
.setLookupId(getIntegerValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_ID), row))
.setLookupFieldId(getIntegerValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_FIELD_ID), row))
.setSpanishLookupField(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.SPANISH_LOOKUP_FIELD), row))
.setSpanishLookupValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.SPANISH_LOOKUP_VALUE), row))
.setStatusChangeDate(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.STATUS_CHANGE_DATE), row))
.setRevisedDate(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.REVISED_DATE), row))
.setAddedInVersion(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.ADDED_IN_VERSION), row))
.setWikiPageTitle(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.WIKI_PAGE_TITLE), row))
.setWikiPageUrl(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.WIKI_PAGE_URL), row))
.build();
}
void processResourceSheet(Sheet sheet) {
this.sheet = sheet;
}
abstract void processNumber(ReferenceStandardField field);
abstract void processStringListSingle(ReferenceStandardField field);
@ -249,91 +140,148 @@ public abstract class WorksheetProcessor {
abstract void processTimestamp(ReferenceStandardField field);
abstract void processCollection(ReferenceStandardField field);
abstract void processExpansion(ReferenceStandardField field);
abstract void generateOutput();
public void processResourceRow(Row row) {
assertTrue(getDefaultErrorMessage("sheet name was null but was expected to contain a resource name!"),
sheet != null && sheet.getSheetName() != null);
public Integer getWellKnownStandardFieldIndex(String wellKnownStandardFieldKey) {
return wellKnownStandardFieldHeaderMap.get(wellKnownStandardFieldKey);
}
//if there's no field in the standard name column, don't process the row
if (row.getCell(getWellKnownStandardFieldIndex(STANDARD_NAME)) == null) return;
public Integer getWellKnownStandardEnumerationIndex(String wellKnownStandardEnumerationKey) {
return wellKnownStandardEnumerationHeaderMap.get(wellKnownStandardEnumerationKey);
}
public void buildWellKnownStandardEnumerationHeaderMap(Sheet sheet) {
wellKnownStandardEnumerationHeaderMap = new LinkedHashMap<>();
sheet.getRow(0).cellIterator().forEachRemaining(cell ->
wellKnownStandardEnumerationHeaderMap.put(cell.getStringCellValue(), cell.getColumnIndex()));
}
public ReferenceStandardField deserializeStandardFieldRow(Row row) {
return new ReferenceStandardField.Builder()
.setResourceName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.RESOURCE_NAME), row))
.setStandardName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.STANDARD_NAME), row))
.setDisplayName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.DISPLAY_NAME), row))
.setDefinition(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.DEFINITION), row))
.setGroups(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.GROUPS), row))
.setSimpleDataType(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SIMPLE_DATA_TYPE), row))
.setSourceResource(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SOURCE_RESOURCE), row))
.setSuggestedMaxLength(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SUGGESTED_MAX_LENGTH), row))
.setSuggestedMaxPrecision(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SUGGESTED_MAX_PRECISION), row))
.setSynonyms(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SYNONYMS), row))
.setElementStatus(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.ELEMENT_STATUS), row))
.setBedes(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.BEDES), row))
.setRecordId(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.RECORD_ID), row))
.setLookupStatus(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.LOOKUP_STATUS), row))
.setLookupName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.LOOKUP_NAME), row))
.setRepeatingElement(getBooleanValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.REPEATING_ELEMENT), row))
.setPropertyTypes(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.PROPERTY_TYPES), row))
.setPayloads(getArrayValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.PAYLOADS), row))
.setSpanishDisplayName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.SPANISH_DISPLAY_NAME), row))
.setFrenchCanadianDisplayName(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.FRENCH_CANADIAN_DISPLAY_NAME), row))
.setStatusChangeDate(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.STATUS_CHANGE_DATE), row))
.setRevisedDate(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.REVISED_DATE), row))
.setAddedInVersion(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.ADDED_IN_VERSION), row))
.setWikiPageTitle(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_TITLE), row))
.setWikiPageURL(getStringValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_URL), row))
.setWikiPageID(getIntegerValue(getWellKnownStandardFieldIndex(WELL_KNOWN_FIELD_HEADERS.WIKI_PAGE_ID), row))
.build();
}
public ReferenceStandardLookup deserializeStandardEnumerationRow(Row row) {
return new ReferenceStandardLookup.Builder()
.setLookupName(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_NAME), row))
.setLookupValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.STANDARD_LOOKUP_VALUE), row))
.setLegacyODataValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LEGACY_ODATA_VALUE), row))
.setDefinition(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.DEFINITION), row))
.setLookupDisplayNameSynonyms(getArrayValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.SYNONYMS), row))
.setBedes(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.BEDES), row))
.setReferences(getArrayValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.REFERENCES), row))
.setElementStatus(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.ELEMENT_STATUS), row))
.setLookupId(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_ID), row))
.setLookupNameId(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.LOOKUP_NAME_ID), row))
.setSpanishLookupValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.SPANISH_LOOKUP_VALUE), row))
.setFrenchCanadianLookupValue(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.FRENCH_CANADIAN_LOOKUP_VALUE), row))
.setStatusChangeDate(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.STATUS_CHANGE_DATE), row))
.setRevisedDate(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.REVISED_DATE), row))
.setAddedInVersion(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.ADDED_IN_VERSION), row))
.setWikiPageTitle(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.WIKI_PAGE_TITLE), row))
.setWikiPageUrl(getStringValue(getWellKnownStandardEnumerationIndex(WELL_KNOWN_ENUMERATION_HEADERS.WIKI_PAGE_URL), row))
.build();
}
public void processResourceRow(Row row) {
ReferenceStandardField referenceStandardField = deserializeStandardFieldRow(row);
referenceStandardField.setParentResourceName(sheet.getSheetName());
//add empty top-level resource name map
standardFieldsMap.putIfAbsent(sheet.getSheetName(), new LinkedHashMap<>());
standardFieldsMap.putIfAbsent(referenceStandardField.getResourceName(), new LinkedHashMap<>());
//add a resource, standard field
standardFieldsMap.get(sheet.getSheetName()).put(referenceStandardField.getStandardName(), referenceStandardField);
//add a resource standard field
standardFieldsMap.get(referenceStandardField.getResourceName()).put(referenceStandardField.getStandardName(), referenceStandardField);
//now that row has been processed, extract field type and assemble the template
switch (referenceStandardField.getSimpleDataType()) {
case NUMBER:
processNumber(referenceStandardField);
break;
case STRING_LIST_SINGLE:
processStringListSingle(referenceStandardField);
break;
case STRING:
processString(referenceStandardField);
break;
case BOOLEAN:
processBoolean(referenceStandardField);
break;
case STRING_LIST_MULTI:
processStringListMulti(referenceStandardField);
break;
case DATE:
processDate(referenceStandardField);
break;
case TIMESTAMP:
processTimestamp(referenceStandardField);
break;
case COLLECTION:
processCollection(referenceStandardField);
break;
default:
if (referenceStandardField.getSimpleDataType() != null)
LOG.debug("Data type: " + referenceStandardField.getSimpleDataType() + " is not supported!");
resourceTemplates.putIfAbsent(referenceStandardField.getResourceName(), new StringBuffer());
//handle expanded fields
if (referenceStandardField.isExpansion()) {
processExpansion(referenceStandardField);
} else {
//now that row has been processed, extract field type and assemble the template
switch (referenceStandardField.getSimpleDataType()) {
case NUMBER:
processNumber(referenceStandardField);
break;
case STRING_LIST_SINGLE:
processStringListSingle(referenceStandardField);
break;
case STRING:
processString(referenceStandardField);
break;
case BOOLEAN:
processBoolean(referenceStandardField);
break;
case STRING_LIST_MULTI:
processStringListMulti(referenceStandardField);
break;
case DATE:
processDate(referenceStandardField);
break;
case TIMESTAMP:
processTimestamp(referenceStandardField);
break;
default:
if (referenceStandardField.getSimpleDataType() != null)
LOG.debug("Data type: " + referenceStandardField.getSimpleDataType() + " is not supported!");
}
}
}
String getDirectoryName() {
return startTimestamp + "-" + getReferenceResource()
.toLowerCase().substring(0, getReferenceResource().lastIndexOf("."));
return startTimestamp + "-" + getDataDictionarySpecification()
.toLowerCase().substring(0, getDataDictionarySpecification().lastIndexOf("."));
}
public String getReferenceResource() {
return referenceDocument;
public String getDataDictionarySpecification() {
return dataDictionarySpecification;
}
public void setReferenceResource(String referenceResource) {
this.referenceDocument = referenceResource;
public void setDataDictionarySpecification(String dataDictionarySpecification) {
this.dataDictionarySpecification = dataDictionarySpecification;
}
public Workbook getReferenceWorkbook() {
try {
return new XSSFWorkbook(Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(getReferenceResource())));
return new XSSFWorkbook(Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(getDataDictionarySpecification())));
} catch (Exception ex) {
LOG.error(getDefaultErrorMessage(ex));
}
return null;
}
public void beforeResourceSheetProcessed(Sheet sheet) {
//Add any before events here
}
public void afterResourceSheetProcessed(Sheet sheet) {
resourceTemplates.put(sheet.getSheetName(), markup.toString());
resetMarkupBuffer();
}
public void buildEnumerationMap() {
Sheet sheet = getReferenceWorkbook().getSheet(LOOKUP_FIELDS_AND_VALUES);
Sheet sheet = getReferenceWorkbook().getSheet(LOOKUPS);
buildWellKnownStandardEnumerationHeaderMap(sheet);
AtomicReference<ReferenceStandardLookup> standardEnumeration = new AtomicReference<>();
@ -342,36 +290,18 @@ public abstract class WorksheetProcessor {
if (row.getRowNum() > 0) {
standardEnumeration.set(deserializeStandardEnumerationRow(row));
if (!standardEnumerationsMap.containsKey(standardEnumeration.get().getLookupField())) {
standardEnumerationsMap.put(standardEnumeration.get().getLookupField(), new LinkedHashSet<>());
if (!standardEnumerationsMap.containsKey(standardEnumeration.get().getLookupName())) {
standardEnumerationsMap.put(standardEnumeration.get().getLookupName(), new LinkedHashSet<>());
}
standardEnumerationsMap.get(standardEnumeration.get().getLookupField()).add(standardEnumeration.get());
standardEnumerationsMap.get(standardEnumeration.get().getLookupName()).add(standardEnumeration.get());
}
});
}
//TODO: convert to parallel stream
public void buildStandardRelationships(Sheet worksheet) {
int FIRST_ROW_INDEX = 1;
Row currentRow;
for(int rowIndex = FIRST_ROW_INDEX; rowIndex < worksheet.getPhysicalNumberOfRows(); rowIndex++) {
currentRow = worksheet.getRow(rowIndex);
if (currentRow.getCell(TARGET_RESOURCE, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().length() > 0
&& !currentRow.getCell(TARGET_RESOURCE_KEY, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().toLowerCase().contains("keynumeric")
&& !currentRow.getCell(SOURCE_RESOURCE_KEY, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().toLowerCase().contains("keynumeric")) {
referenceStandardRelationships.add(deserializeStandardRelationshipRow(currentRow));
}
}
}
public Map<String, Set<ReferenceStandardLookup>> getEnumerations() {
return standardEnumerationsMap;
}
public void resetMarkupBuffer() {
markup = new StringBuffer();
}
public static final class WELL_KNOWN_DATA_TYPES {
public static final String
NUMBER = "Number",
@ -381,7 +311,8 @@ public abstract class WorksheetProcessor {
BOOLEAN = "Boolean",
DATE = "Date",
TIMESTAMP = "Timestamp",
COLLECTION = "Collection";
COLLECTION = "Collection",
RESOURCE = "Resource";
}
/**
@ -389,31 +320,32 @@ public abstract class WorksheetProcessor {
*/
public static final class WELL_KNOWN_FIELD_HEADERS {
public static final String
RESOURCE_NAME = "ResourceName",
STANDARD_NAME = "StandardName",
DISPLAY_NAME = "DisplayName",
DEFINITION = "Definition",
GROUPS = "Groups",
SIMPLE_DATA_TYPE = "SimpleDataType",
SOURCE_RESOURCE = "SourceResource",
SUGGESTED_MAX_LENGTH = "SugMaxLength",
SYNONYM = "Synonym",
ELEMENT_STATUS = "ElementStatus",
BEDES = "BEDES",
CERTIFICATION_LEVEL = "CertificationLevel",
RECORD_ID = "RecordID",
LOOKUP_STATUS = "LookupStatus",
LOOKUP = "Lookup",
COLLECTION = "Collection",
SUGGESTED_MAX_PRECISION = "SugMaxPrecision",
SYNONYMS = "Synonyms",
FRENCH_CANADIAN_DISPLAY_NAME = "FrenchCanadianDisplayName",
SPANISH_DISPLAY_NAME = "SpanishDisplayName",
ELEMENT_STATUS = "ElementStatus",
RECORD_ID = "RecordId",
LOOKUP_STATUS = "LookupStatus",
LOOKUP_NAME = "LookupName",
REPEATING_ELEMENT = "RepeatingElement",
PROPERTY_TYPES = "PropertyTypes",
PAYLOADS = "Payloads",
SPANISH_STANDARD_NAME = "SpanishStandardName",
STATUS_CHANGE_DATE = "StatusChangeDate",
REVISED_DATE = "RevisedDate",
ADDED_IN_VERSION = "AddedInVersion",
WIKI_PAGE_TITLE = "Wiki Page Title",
WIKI_PAGE_URL = "Wiki Page URL",
WIKI_PAGE_ID = "Wiki Page ID";
WIKI_PAGE_TITLE = "WikiPageTitle",
WIKI_PAGE_URL = "WikiPageUrl",
WIKI_PAGE_ID = "WikiPageId",
BEDES = "BEDES";
}
/**
@ -421,22 +353,22 @@ public abstract class WorksheetProcessor {
*/
public static final class WELL_KNOWN_ENUMERATION_HEADERS {
public static final String
LOOKUP_FIELD = "LookupField",
LOOKUP_VALUE = "LookupValue",
LOOKUP_DISPLAY_NAME = "LookupDisplayName",
DEFINITION = "Definition",
LOOKUP_DISPLAY_NAME_SYNONYMS = "LookupDisplayNameSynonyms",
BEDES = "BEDES",
REFERENCES = "References",
ELEMENT_STATUS = "ElementStatus",
LOOKUP_ID = "LookupID",
LOOKUP_FIELD_ID = "LookupFieldID",
SPANISH_LOOKUP_FIELD = "SpanishLookupField",
SPANISH_LOOKUP_VALUE = "SpanishLookupValue",
STATUS_CHANGE_DATE = "StatusChangeDate",
REVISED_DATE = "RevisedDate",
ADDED_IN_VERSION = "AddedInVersion",
WIKI_PAGE_TITLE = "Wiki Page Title",
WIKI_PAGE_URL = "Wiki Page URL";
LOOKUP_NAME = "LookupName",
STANDARD_LOOKUP_VALUE = "StandardLookupValue",
LEGACY_ODATA_VALUE = "LegacyODataValue",
DEFINITION = "Definition",
REFERENCES = "References",
SYNONYMS = "Synonyms",
FRENCH_CANADIAN_LOOKUP_VALUE = "FrenchCanadianLookupValue",
SPANISH_LOOKUP_VALUE = "SpanishLookupValue",
ELEMENT_STATUS = "ElementStatus",
LOOKUP_NAME_ID = "LookupNameId",
LOOKUP_ID = "LookupID",
STATUS_CHANGE_DATE = "StatusChangeDate",
REVISED_DATE = "RevisedDate",
ADDED_IN_VERSION = "AddedInVersion",
WIKI_PAGE_TITLE = "Wiki Page Title",
WIKI_PAGE_URL = "Wiki Page URL",
BEDES = "BEDES";
}
}

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: ContactListingNotes
Background:
@ -18,22 +18,12 @@ Feature: ContactListingNotes
Then "ContactKey" MUST be "String" data type
And "ContactKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListingNotes
Scenario: ContactKeyNumeric
When "ContactKeyNumeric" exists in the "ContactListingNotes" metadata
Then "ContactKeyNumeric" MUST be "Integer" data type
@ContactListingNotes
Scenario: ContactListingNotesKey
When "ContactListingNotesKey" exists in the "ContactListingNotes" metadata
Then "ContactListingNotesKey" MUST be "String" data type
And "ContactListingNotesKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListingNotes
Scenario: ContactListingNotesKeyNumeric
When "ContactListingNotesKeyNumeric" exists in the "ContactListingNotes" metadata
Then "ContactListingNotesKeyNumeric" MUST be "Integer" data type
@ContactListingNotes
Scenario: ListingId
When "ListingId" exists in the "ContactListingNotes" metadata
@ -46,11 +36,6 @@ Feature: ContactListingNotes
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListingNotes
Scenario: ListingKeyNumeric
When "ListingKeyNumeric" exists in the "ContactListingNotes" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@ContactListingNotes
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "ContactListingNotes" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: ContactListings
Background:
@ -28,11 +28,6 @@ Feature: ContactListings
Then "ContactKey" MUST be "String" data type
And "ContactKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListings
Scenario: ContactKeyNumeric
When "ContactKeyNumeric" exists in the "ContactListings" metadata
Then "ContactKeyNumeric" MUST be "Integer" data type
@ContactListings
Scenario: ContactListingPreference
When "ContactListingPreference" exists in the "ContactListings" metadata
@ -44,11 +39,6 @@ Feature: ContactListings
Then "ContactListingsKey" MUST be "String" data type
And "ContactListingsKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListings
Scenario: ContactListingsKeyNumeric
When "ContactListingsKeyNumeric" exists in the "ContactListings" metadata
Then "ContactListingsKeyNumeric" MUST be "Integer" data type
@ContactListings
Scenario: ContactLoginId
When "ContactLoginId" exists in the "ContactListings" metadata
@ -87,11 +77,6 @@ Feature: ContactListings
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@ContactListings
Scenario: ListingKeyNumeric
When "ListingKeyNumeric" exists in the "ContactListings" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@ContactListings
Scenario: ListingModificationTimestamp
When "ListingModificationTimestamp" exists in the "ContactListings" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Contacts
Background:
@ -72,13 +72,6 @@ Feature: Contacts
Then "ContactKey" MUST be "String" data type
And "ContactKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Contacts
Scenario: ContactKeyNumeric
Given that the following synonyms for "ContactKeyNumeric" DO NOT exist in the "Contacts" metadata
| RID |
When "ContactKeyNumeric" exists in the "Contacts" metadata
Then "ContactKeyNumeric" MUST be "Integer" data type
@Contacts
Scenario: ContactLoginId
When "ContactLoginId" exists in the "Contacts" metadata
@ -397,13 +390,6 @@ Feature: Contacts
Then "OwnerMemberKey" MUST be "String" data type
And "OwnerMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Contacts
Scenario: OwnerMemberKeyNumeric
Given that the following synonyms for "OwnerMemberKeyNumeric" DO NOT exist in the "Contacts" metadata
| OwnerAgentKeyNumeric |
When "OwnerMemberKeyNumeric" exists in the "Contacts" metadata
Then "OwnerMemberKeyNumeric" MUST be "Integer" data type
@Contacts
Scenario: Pager
When "Pager" exists in the "Contacts" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Field
Background:

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: HistoryTransactional
Background:
@ -33,13 +33,6 @@ Feature: HistoryTransactional
Then "ChangedByMemberKey" MUST be "String" data type
And "ChangedByMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@HistoryTransactional
Scenario: ChangedByMemberKeyNumeric
Given that the following synonyms for "ChangedByMemberKeyNumeric" DO NOT exist in the "HistoryTransactional" metadata
| ChangedByAgentKeyNumeric |
When "ChangedByMemberKeyNumeric" exists in the "HistoryTransactional" metadata
Then "ChangedByMemberKeyNumeric" MUST be "Integer" data type
@HistoryTransactional
Scenario: ClassName
When "ClassName" exists in the "HistoryTransactional" metadata
@ -52,11 +45,6 @@ Feature: HistoryTransactional
Then "FieldKey" MUST be "String" data type
And "FieldKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@HistoryTransactional
Scenario: FieldKeyNumeric
When "FieldKeyNumeric" exists in the "HistoryTransactional" metadata
Then "FieldKeyNumeric" MUST be "Integer" data type
@HistoryTransactional
Scenario: FieldName
When "FieldName" exists in the "HistoryTransactional" metadata
@ -69,11 +57,6 @@ Feature: HistoryTransactional
Then "HistoryTransactionalKey" MUST be "String" data type
And "HistoryTransactionalKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@HistoryTransactional
Scenario: HistoryTransactionalKeyNumeric
When "HistoryTransactionalKeyNumeric" exists in the "HistoryTransactional" metadata
Then "HistoryTransactionalKeyNumeric" MUST be "Integer" data type
@HistoryTransactional
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "HistoryTransactional" metadata
@ -142,14 +125,6 @@ Feature: HistoryTransactional
Then "ResourceRecordKey" MUST be "String" data type
And "ResourceRecordKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@HistoryTransactional
Scenario: ResourceRecordKeyNumeric
Given that the following synonyms for "ResourceRecordKeyNumeric" DO NOT exist in the "HistoryTransactional" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ResourceRecordKeyNumeric" exists in the "HistoryTransactional" metadata
Then "ResourceRecordKeyNumeric" MUST be "Integer" data type
@HistoryTransactional
Scenario: SourceSystemHistoryKey
Given that the following synonyms for "SourceSystemHistoryKey" DO NOT exist in the "HistoryTransactional" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: InternetTracking
Background:
@ -42,11 +42,6 @@ Feature: InternetTracking
Then "ActorKey" MUST be "String" data type
And "ActorKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@InternetTracking
Scenario: ActorKeyNumeric
When "ActorKeyNumeric" exists in the "InternetTracking" metadata
Then "ActorKeyNumeric" MUST be "Integer" data type
@InternetTracking
Scenario: ActorLatitude
When "ActorLatitude" exists in the "InternetTracking" metadata
@ -147,11 +142,6 @@ Feature: InternetTracking
Then "EventKey" MUST be "String" data type
And "EventKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@InternetTracking
Scenario: EventKeyNumeric
When "EventKeyNumeric" exists in the "InternetTracking" metadata
Then "EventKeyNumeric" MUST be "Integer" data type
@InternetTracking
Scenario: EventLabel
When "EventLabel" exists in the "InternetTracking" metadata
@ -214,11 +204,6 @@ Feature: InternetTracking
Then "ObjectKey" MUST be "String" data type
And "ObjectKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@InternetTracking
Scenario: ObjectKeyNumeric
When "ObjectKeyNumeric" exists in the "InternetTracking" metadata
Then "ObjectKeyNumeric" MUST be "Integer" data type
@InternetTracking
Scenario: ObjectOriginatingSystemID
When "ObjectOriginatingSystemID" exists in the "InternetTracking" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Lookup
Background:

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Media
Background:
@ -28,13 +28,6 @@ Feature: Media
Then "ChangedByMemberKey" MUST be "String" data type
And "ChangedByMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Media
Scenario: ChangedByMemberKeyNumeric
Given that the following synonyms for "ChangedByMemberKeyNumeric" DO NOT exist in the "Media" metadata
| ChangedByAgentKeyNumeric |
When "ChangedByMemberKeyNumeric" exists in the "Media" metadata
Then "ChangedByMemberKeyNumeric" MUST be "Integer" data type
@Media
Scenario: ClassName
When "ClassName" exists in the "Media" metadata
@ -88,14 +81,6 @@ Feature: Media
Then "MediaKey" MUST be "String" data type
And "MediaKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Media @IDX
Scenario: MediaKeyNumeric
Given that the following synonyms for "MediaKeyNumeric" DO NOT exist in the "Media" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "MediaKeyNumeric" exists in the "Media" metadata
Then "MediaKeyNumeric" MUST be "Integer" data type
@Media @IDX
Scenario: MediaModificationTimestamp
Given that the following synonyms for "MediaModificationTimestamp" DO NOT exist in the "Media" metadata
@ -204,14 +189,6 @@ Feature: Media
Then "ResourceRecordKey" MUST be "String" data type
And "ResourceRecordKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Media @IDX
Scenario: ResourceRecordKeyNumeric
Given that the following synonyms for "ResourceRecordKeyNumeric" DO NOT exist in the "Media" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ResourceRecordKeyNumeric" exists in the "Media" metadata
Then "ResourceRecordKeyNumeric" MUST be "Integer" data type
@Media @IDX
Scenario: ShortDescription
Given that the following synonyms for "ShortDescription" DO NOT exist in the "Media" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Member
Background:
@ -46,13 +46,6 @@ Feature: Member
Then "MemberAORkey" MUST be "String" data type
And "MemberAORkey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Member
Scenario: MemberAORkeyNumeric
Given that the following synonyms for "MemberAORkeyNumeric" DO NOT exist in the "Member" metadata
| AgentAORkeyNumeric |
When "MemberAORkeyNumeric" exists in the "Member" metadata
Then "MemberAORkeyNumeric" MUST be "Integer" data type
@Member
Scenario: MemberAddress1
Given that the following synonyms for "MemberAddress1" DO NOT exist in the "Member" metadata
@ -180,13 +173,6 @@ Feature: Member
Then "MemberKey" MUST be "String" data type
And "MemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Member @IDX
Scenario: MemberKeyNumeric
Given that the following synonyms for "MemberKeyNumeric" DO NOT exist in the "Member" metadata
| AgentKeyNumeric |
When "MemberKeyNumeric" exists in the "Member" metadata
Then "MemberKeyNumeric" MUST be "Integer" data type
@Member
Scenario: MemberLanguages
Given that the following synonyms for "MemberLanguages" DO NOT exist in the "Member" metadata
@ -432,11 +418,6 @@ Feature: Member
Then "OfficeKey" MUST be "String" data type
And "OfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Member @IDX
Scenario: OfficeKeyNumeric
When "OfficeKeyNumeric" exists in the "Member" metadata
Then "OfficeKeyNumeric" MUST be "Integer" data type
@Member @IDX
Scenario: OfficeMlsId
When "OfficeMlsId" exists in the "Member" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Office
Background:
@ -29,11 +29,6 @@ Feature: Office
Then "MainOfficeKey" MUST be "String" data type
And "MainOfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Office @IDX
Scenario: MainOfficeKeyNumeric
When "MainOfficeKeyNumeric" exists in the "Office" metadata
Then "MainOfficeKeyNumeric" MUST be "Integer" data type
@Office @IDX
Scenario: MainOfficeMlsId
When "MainOfficeMlsId" exists in the "Office" metadata
@ -62,11 +57,6 @@ Feature: Office
Then "OfficeAORkey" MUST be "String" data type
And "OfficeAORkey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Office
Scenario: OfficeAORkeyNumeric
When "OfficeAORkeyNumeric" exists in the "Office" metadata
Then "OfficeAORkeyNumeric" MUST be "Integer" data type
@Office @IDX
Scenario: OfficeAddress1
When "OfficeAddress1" exists in the "Office" metadata
@ -96,11 +86,6 @@ Feature: Office
Then "OfficeBrokerKey" MUST be "String" data type
And "OfficeBrokerKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Office @IDX
Scenario: OfficeBrokerKeyNumeric
When "OfficeBrokerKeyNumeric" exists in the "Office" metadata
Then "OfficeBrokerKeyNumeric" MUST be "Integer" data type
@Office
Scenario: OfficeBrokerMlsId
When "OfficeBrokerMlsId" exists in the "Office" metadata
@ -144,22 +129,12 @@ Feature: Office
Then "OfficeKey" MUST be "String" data type
And "OfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Office @IDX
Scenario: OfficeKeyNumeric
When "OfficeKeyNumeric" exists in the "Office" metadata
Then "OfficeKeyNumeric" MUST be "Integer" data type
@Office
Scenario: OfficeManagerKey
When "OfficeManagerKey" exists in the "Office" metadata
Then "OfficeManagerKey" MUST be "String" data type
And "OfficeManagerKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Office
Scenario: OfficeManagerKeyNumeric
When "OfficeManagerKeyNumeric" exists in the "Office" metadata
Then "OfficeManagerKeyNumeric" MUST be "Integer" data type
@Office
Scenario: OfficeManagerMlsId
When "OfficeManagerMlsId" exists in the "Office" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: OpenHouse
Background:
@ -36,14 +36,6 @@ Feature: OpenHouse
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OpenHouse @IDX
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "OpenHouse" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "OpenHouse" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@OpenHouse @IDX
Scenario: ModificationTimestamp
Given that the following synonyms for "ModificationTimestamp" DO NOT exist in the "OpenHouse" metadata
@ -83,11 +75,6 @@ Feature: OpenHouse
Then "OpenHouseKey" MUST be "String" data type
And "OpenHouseKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OpenHouse @IDX
Scenario: OpenHouseKeyNumeric
When "OpenHouseKeyNumeric" exists in the "OpenHouse" metadata
Then "OpenHouseKeyNumeric" MUST be "Integer" data type
@OpenHouse @IDX
Scenario: OpenHouseRemarks
When "OpenHouseRemarks" exists in the "OpenHouse" metadata
@ -164,13 +151,6 @@ Feature: OpenHouse
Then "ShowingAgentKey" MUST be "String" data type
And "ShowingAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OpenHouse @IDX
Scenario: ShowingAgentKeyNumeric
Given that the following synonyms for "ShowingAgentKeyNumeric" DO NOT exist in the "OpenHouse" metadata
| ShowingMemberKeyNumeric |
When "ShowingAgentKeyNumeric" exists in the "OpenHouse" metadata
Then "ShowingAgentKeyNumeric" MUST be "Integer" data type
@OpenHouse
Scenario: ShowingAgentLastName
Given that the following synonyms for "ShowingAgentLastName" DO NOT exist in the "OpenHouse" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: OtherPhone
Background:
@ -44,11 +44,6 @@ Feature: OtherPhone
Then "OtherPhoneKey" MUST be "String" data type
And "OtherPhoneKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OtherPhone
Scenario: OtherPhoneKeyNumeric
When "OtherPhoneKeyNumeric" exists in the "OtherPhone" metadata
Then "OtherPhoneKeyNumeric" MUST be "Integer" data type
@OtherPhone
Scenario: OtherPhoneNumber
When "OtherPhoneNumber" exists in the "OtherPhone" metadata
@ -88,11 +83,3 @@ Feature: OtherPhone
When "ResourceRecordKey" exists in the "OtherPhone" metadata
Then "ResourceRecordKey" MUST be "String" data type
And "ResourceRecordKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OtherPhone
Scenario: ResourceRecordKeyNumeric
Given that the following synonyms for "ResourceRecordKeyNumeric" DO NOT exist in the "OtherPhone" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ResourceRecordKeyNumeric" exists in the "OtherPhone" metadata
Then "ResourceRecordKeyNumeric" MUST be "Integer" data type

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: OUID
Background:
@ -28,13 +28,6 @@ Feature: OUID
Then "ChangedByMemberKey" MUST be "String" data type
And "ChangedByMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OUID
Scenario: ChangedByMemberKeyNumeric
Given that the following synonyms for "ChangedByMemberKeyNumeric" DO NOT exist in the "OUID" metadata
| ChangedByAgentKeyNumeric |
When "ChangedByMemberKeyNumeric" exists in the "OUID" metadata
Then "ChangedByMemberKeyNumeric" MUST be "Integer" data type
@OUID
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "OUID" metadata
@ -69,11 +62,6 @@ Feature: OUID
Then "OrganizationAorOuidKey" MUST be "String" data type
And "OrganizationAorOuidKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OUID
Scenario: OrganizationAorOuidKeyNumeric
When "OrganizationAorOuidKeyNumeric" exists in the "OUID" metadata
Then "OrganizationAorOuidKeyNumeric" MUST be "Integer" data type
@OUID
Scenario: OrganizationCarrierRoute
Given that the following synonyms for "OrganizationCarrierRoute" DO NOT exist in the "OUID" metadata
@ -273,11 +261,6 @@ Feature: OUID
Then "OrganizationUniqueIdKey" MUST be "String" data type
And "OrganizationUniqueIdKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@OUID
Scenario: OrganizationUniqueIdKeyNumeric
When "OrganizationUniqueIdKeyNumeric" exists in the "OUID" metadata
Then "OrganizationUniqueIdKeyNumeric" MUST be "Integer" data type
@OUID
Scenario: OriginalEntryTimestamp
When "OriginalEntryTimestamp" exists in the "OUID" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Property
Background:
@ -394,13 +394,6 @@ Feature: Property
Then "BuyerAgentKey" MUST be "String" data type
And "BuyerAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: BuyerAgentKeyNumeric
Given that the following synonyms for "BuyerAgentKeyNumeric" DO NOT exist in the "Property" metadata
| BuyerMemberKeyNumeric |
When "BuyerAgentKeyNumeric" exists in the "Property" metadata
Then "BuyerAgentKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: BuyerAgentLastName
Given that the following synonyms for "BuyerAgentLastName" DO NOT exist in the "Property" metadata
@ -557,11 +550,6 @@ Feature: Property
Then "BuyerOfficeKey" MUST be "String" data type
And "BuyerOfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: BuyerOfficeKeyNumeric
When "BuyerOfficeKeyNumeric" exists in the "Property" metadata
Then "BuyerOfficeKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: BuyerOfficeMlsId
When "BuyerOfficeMlsId" exists in the "Property" metadata
@ -598,11 +586,6 @@ Feature: Property
Then "BuyerTeamKey" MUST be "String" data type
And "BuyerTeamKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: BuyerTeamKeyNumeric
When "BuyerTeamKeyNumeric" exists in the "Property" metadata
Then "BuyerTeamKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: BuyerTeamName
When "BuyerTeamName" exists in the "Property" metadata
@ -762,13 +745,6 @@ Feature: Property
Then "CoBuyerAgentKey" MUST be "String" data type
And "CoBuyerAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: CoBuyerAgentKeyNumeric
Given that the following synonyms for "CoBuyerAgentKeyNumeric" DO NOT exist in the "Property" metadata
| CoBuyerMemberKeyNumeric |
When "CoBuyerAgentKeyNumeric" exists in the "Property" metadata
Then "CoBuyerAgentKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: CoBuyerAgentLastName
Given that the following synonyms for "CoBuyerAgentLastName" DO NOT exist in the "Property" metadata
@ -920,11 +896,6 @@ Feature: Property
Then "CoBuyerOfficeKey" MUST be "String" data type
And "CoBuyerOfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: CoBuyerOfficeKeyNumeric
When "CoBuyerOfficeKeyNumeric" exists in the "Property" metadata
Then "CoBuyerOfficeKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: CoBuyerOfficeMlsId
When "CoBuyerOfficeMlsId" exists in the "Property" metadata
@ -1025,13 +996,6 @@ Feature: Property
Then "CoListAgentKey" MUST be "String" data type
And "CoListAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: CoListAgentKeyNumeric
Given that the following synonyms for "CoListAgentKeyNumeric" DO NOT exist in the "Property" metadata
| CoListMemberKey |
When "CoListAgentKeyNumeric" exists in the "Property" metadata
Then "CoListAgentKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: CoListAgentLastName
Given that the following synonyms for "CoListAgentLastName" DO NOT exist in the "Property" metadata
@ -1183,11 +1147,6 @@ Feature: Property
Then "CoListOfficeKey" MUST be "String" data type
And "CoListOfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: CoListOfficeKeyNumeric
When "CoListOfficeKeyNumeric" exists in the "Property" metadata
Then "CoListOfficeKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: CoListOfficeMlsId
When "CoListOfficeMlsId" exists in the "Property" metadata
@ -2245,13 +2204,6 @@ Feature: Property
Then "ListAgentKey" MUST be "String" data type
And "ListAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: ListAgentKeyNumeric
Given that the following synonyms for "ListAgentKeyNumeric" DO NOT exist in the "Property" metadata
| ListMemberKeyNumeric |
When "ListAgentKeyNumeric" exists in the "Property" metadata
Then "ListAgentKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: ListAgentLastName
Given that the following synonyms for "ListAgentLastName" DO NOT exist in the "Property" metadata
@ -2403,11 +2355,6 @@ Feature: Property
Then "ListOfficeKey" MUST be "String" data type
And "ListOfficeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: ListOfficeKeyNumeric
When "ListOfficeKeyNumeric" exists in the "Property" metadata
Then "ListOfficeKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: ListOfficeMlsId
When "ListOfficeMlsId" exists in the "Property" metadata
@ -2466,11 +2413,6 @@ Feature: Property
Then "ListTeamKey" MUST be "String" data type
And "ListTeamKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: ListTeamKeyNumeric
When "ListTeamKeyNumeric" exists in the "Property" metadata
Then "ListTeamKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: ListTeamName
When "ListTeamName" exists in the "Property" metadata
@ -2513,14 +2455,6 @@ Feature: Property
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO @IDX
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "Property" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "Property" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@Property @RESI @RLSE @RINC @LAND @MOBI @FARM @COMS @COML @BUSO
Scenario: ListingService
Given that the following synonyms for "ListingService" DO NOT exist in the "Property" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: PropertyGreenVerification
Background:
@ -18,11 +18,6 @@ Feature: PropertyGreenVerification
Then "GreenBuildingVerificationKey" MUST be "String" data type
And "GreenBuildingVerificationKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyGreenVerification @IDX
Scenario: GreenBuildingVerificationKeyNumeric
When "GreenBuildingVerificationKeyNumeric" exists in the "PropertyGreenVerification" metadata
Then "GreenBuildingVerificationKeyNumeric" MUST be "Integer" data type
@PropertyGreenVerification @IDX
Scenario: GreenBuildingVerificationType
Given that the following synonyms for "GreenBuildingVerificationType" DO NOT exist in the "PropertyGreenVerification" metadata
@ -119,14 +114,6 @@ Feature: PropertyGreenVerification
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyGreenVerification @IDX
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "PropertyGreenVerification" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "PropertyGreenVerification" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@PropertyGreenVerification @IDX
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "PropertyGreenVerification" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: PropertyPowerProduction
Background:
@ -31,14 +31,6 @@ Feature: PropertyPowerProduction
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyPowerProduction
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "PropertyPowerProduction" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "PropertyPowerProduction" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@PropertyPowerProduction
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "PropertyPowerProduction" metadata
@ -60,11 +52,6 @@ Feature: PropertyPowerProduction
Then "PowerProductionKey" MUST be "String" data type
And "PowerProductionKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyPowerProduction
Scenario: PowerProductionKeyNumeric
When "PowerProductionKeyNumeric" exists in the "PropertyPowerProduction" metadata
Then "PowerProductionKeyNumeric" MUST be "Integer" data type
@PropertyPowerProduction
Scenario: PowerProductionSize
When "PowerProductionSize" exists in the "PropertyPowerProduction" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: PropertyRooms
Background:
@ -31,14 +31,6 @@ Feature: PropertyRooms
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyRooms
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "PropertyRooms" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "PropertyRooms" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@PropertyRooms
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "PropertyRooms" metadata
@ -84,11 +76,6 @@ Feature: PropertyRooms
Then "RoomKey" MUST be "String" data type
And "RoomKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyRooms
Scenario: RoomKeyNumeric
When "RoomKeyNumeric" exists in the "PropertyRooms" metadata
Then "RoomKeyNumeric" MUST be "Integer" data type
@PropertyRooms
Scenario: RoomLength
When "RoomLength" exists in the "PropertyRooms" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: PropertyUnitTypes
Background:
@ -31,14 +31,6 @@ Feature: PropertyUnitTypes
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyUnitTypes
Scenario: ListingKeyNumeric
Given that the following synonyms for "ListingKeyNumeric" DO NOT exist in the "PropertyUnitTypes" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ListingKeyNumeric" exists in the "PropertyUnitTypes" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@PropertyUnitTypes
Scenario: ModificationTimestamp
When "ModificationTimestamp" exists in the "PropertyUnitTypes" metadata
@ -90,11 +82,6 @@ Feature: PropertyUnitTypes
Then "UnitTypeKey" MUST be "String" data type
And "UnitTypeKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@PropertyUnitTypes
Scenario: UnitTypeKeyNumeric
When "UnitTypeKeyNumeric" exists in the "PropertyUnitTypes" metadata
Then "UnitTypeKeyNumeric" MUST be "Integer" data type
@PropertyUnitTypes
Scenario: UnitTypeProForma
When "UnitTypeProForma" exists in the "PropertyUnitTypes" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Prospecting
Background:
@ -55,11 +55,6 @@ Feature: Prospecting
Then "ContactKey" MUST be "String" data type
And "ContactKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Prospecting
Scenario: ContactKeyNumeric
When "ContactKeyNumeric" exists in the "Prospecting" metadata
Then "ContactKeyNumeric" MUST be "Integer" data type
@Prospecting
Scenario: DailySchedule
When "DailySchedule" exists in the "Prospecting" metadata
@ -126,11 +121,6 @@ Feature: Prospecting
Then "OwnerMemberKey" MUST be "String" data type
And "OwnerMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Prospecting
Scenario: OwnerMemberKeyNumeric
When "OwnerMemberKeyNumeric" exists in the "Prospecting" metadata
Then "OwnerMemberKeyNumeric" MUST be "Integer" data type
@Prospecting
Scenario: ProspectingKey
Given that the following synonyms for "ProspectingKey" DO NOT exist in the "Prospecting" metadata
@ -140,14 +130,6 @@ Feature: Prospecting
Then "ProspectingKey" MUST be "String" data type
And "ProspectingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Prospecting
Scenario: ProspectingKeyNumeric
Given that the following synonyms for "ProspectingKeyNumeric" DO NOT exist in the "Prospecting" metadata
| AutoMailKeyNumeric |
| AutoEmailKeyNumeric |
When "ProspectingKeyNumeric" exists in the "Prospecting" metadata
Then "ProspectingKeyNumeric" MUST be "Integer" data type
@Prospecting
Scenario: ReasonActiveOrDisabled
When "ReasonActiveOrDisabled" exists in the "Prospecting" metadata
@ -159,11 +141,6 @@ Feature: Prospecting
Then "SavedSearchKey" MUST be "String" data type
And "SavedSearchKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Prospecting
Scenario: SavedSearchKeyNumeric
When "SavedSearchKeyNumeric" exists in the "Prospecting" metadata
Then "SavedSearchKeyNumeric" MUST be "Integer" data type
@Prospecting
Scenario: ScheduleType
When "ScheduleType" exists in the "Prospecting" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Queue
Background:
@ -51,11 +51,6 @@ Feature: Queue
Then "QueueTransactionKey" MUST be "String" data type
And "QueueTransactionKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Queue
Scenario: QueueTransactionKeyNumeric
When "QueueTransactionKeyNumeric" exists in the "Queue" metadata
Then "QueueTransactionKeyNumeric" MUST be "Integer" data type
@Queue
Scenario: QueueTransactionType
When "QueueTransactionType" exists in the "Queue" metadata
@ -88,14 +83,6 @@ Feature: Queue
Then "ResourceRecordKey" MUST be "String" data type
And "ResourceRecordKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Queue
Scenario: ResourceRecordKeyNumeric
Given that the following synonyms for "ResourceRecordKeyNumeric" DO NOT exist in the "Queue" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ResourceRecordKeyNumeric" exists in the "Queue" metadata
Then "ResourceRecordKeyNumeric" MUST be "Integer" data type
@Queue
Scenario: SourceSystemID
Given that the following synonyms for "SourceSystemID" DO NOT exist in the "Queue" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Rules
Background:
@ -23,11 +23,6 @@ Feature: Rules
Then "FieldKey" MUST be "String" data type
And "FieldKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Rules
Scenario: FieldKeyNumeric
When "FieldKeyNumeric" exists in the "Rules" metadata
Then "FieldKeyNumeric" MUST be "Integer" data type
@Rules
Scenario: FieldName
When "FieldName" exists in the "Rules" metadata
@ -128,11 +123,6 @@ Feature: Rules
Then "RuleKey" MUST be "String" data type
And "RuleKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Rules
Scenario: RuleKeyNumeric
When "RuleKeyNumeric" exists in the "Rules" metadata
Then "RuleKeyNumeric" MUST be "Integer" data type
@Rules
Scenario: RuleName
When "RuleName" exists in the "Rules" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: SavedSearch
Background:
@ -25,13 +25,6 @@ Feature: SavedSearch
Then "MemberKey" MUST be "String" data type
And "MemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@SavedSearch
Scenario: MemberKeyNumeric
Given that the following synonyms for "MemberKeyNumeric" DO NOT exist in the "SavedSearch" metadata
| AgentKeyNumeric |
When "MemberKeyNumeric" exists in the "SavedSearch" metadata
Then "MemberKeyNumeric" MUST be "Integer" data type
@SavedSearch
Scenario: MemberMlsId
Given that the following synonyms for "MemberMlsId" DO NOT exist in the "SavedSearch" metadata
@ -121,11 +114,6 @@ Feature: SavedSearch
Then "SavedSearchKey" MUST be "String" data type
And "SavedSearchKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@SavedSearch
Scenario: SavedSearchKeyNumeric
When "SavedSearchKeyNumeric" exists in the "SavedSearch" metadata
Then "SavedSearchKeyNumeric" MUST be "Integer" data type
@SavedSearch
Scenario: SavedSearchName
When "SavedSearchName" exists in the "SavedSearch" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Showing
Background:
@ -48,11 +48,6 @@ Feature: Showing
Then "ListingKey" MUST be "String" data type
And "ListingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Showing
Scenario: ListingKeyNumeric
When "ListingKeyNumeric" exists in the "Showing" metadata
Then "ListingKeyNumeric" MUST be "Integer" data type
@Showing
Scenario: ListingOriginatingSystemID
When "ListingOriginatingSystemID" exists in the "Showing" metadata
@ -111,11 +106,6 @@ Feature: Showing
Then "ShowingAgentKey" MUST be "String" data type
And "ShowingAgentKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Showing
Scenario: ShowingAgentKeyNumeric
When "ShowingAgentKeyNumeric" exists in the "Showing" metadata
Then "ShowingAgentKeyNumeric" MUST be "Integer" data type
@Showing
Scenario: ShowingAgentMlsID
When "ShowingAgentMlsID" exists in the "Showing" metadata
@ -139,11 +129,6 @@ Feature: Showing
Then "ShowingKey" MUST be "String" data type
And "ShowingKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Showing
Scenario: ShowingKeyNumeric
When "ShowingKeyNumeric" exists in the "Showing" metadata
Then "ShowingKeyNumeric" MUST be "Integer" data type
@Showing
Scenario: ShowingOriginatingSystemID
When "ShowingOriginatingSystemID" exists in the "Showing" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: SocialMedia
Background:
@ -56,14 +56,6 @@ Feature: SocialMedia
Then "ResourceRecordKey" MUST be "String" data type
And "ResourceRecordKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@SocialMedia
Scenario: ResourceRecordKeyNumeric
Given that the following synonyms for "ResourceRecordKeyNumeric" DO NOT exist in the "SocialMedia" metadata
| SystemUniqueID |
| ImmediateSourceID |
When "ResourceRecordKeyNumeric" exists in the "SocialMedia" metadata
Then "ResourceRecordKeyNumeric" MUST be "Integer" data type
@SocialMedia
Scenario: SocialMediaKey
Given that the following synonyms for "SocialMediaKey" DO NOT exist in the "SocialMedia" metadata
@ -73,11 +65,6 @@ Feature: SocialMedia
Then "SocialMediaKey" MUST be "String" data type
And "SocialMediaKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@SocialMedia
Scenario: SocialMediaKeyNumeric
When "SocialMediaKeyNumeric" exists in the "SocialMedia" metadata
Then "SocialMediaKeyNumeric" MUST be "Integer" data type
@SocialMedia
Scenario: SocialMediaType
Given that the following synonyms for "SocialMediaType" DO NOT exist in the "SocialMedia" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: TeamMembers
Background:
@ -20,13 +20,6 @@ Feature: TeamMembers
Then "MemberKey" MUST be "String" data type
And "MemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@TeamMembers
Scenario: MemberKeyNumeric
Given that the following synonyms for "MemberKeyNumeric" DO NOT exist in the "TeamMembers" metadata
| AgentKeyNumeric |
When "MemberKeyNumeric" exists in the "TeamMembers" metadata
Then "MemberKeyNumeric" MUST be "Integer" data type
@TeamMembers
Scenario: MemberLoginId
Given that the following synonyms for "MemberLoginId" DO NOT exist in the "TeamMembers" metadata
@ -112,11 +105,6 @@ Feature: TeamMembers
Then "TeamKey" MUST be "String" data type
And "TeamKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@TeamMembers
Scenario: TeamKeyNumeric
When "TeamKeyNumeric" exists in the "TeamMembers" metadata
Then "TeamKeyNumeric" MUST be "Integer" data type
@TeamMembers
Scenario: TeamMemberKey
Given that the following synonyms for "TeamMemberKey" DO NOT exist in the "TeamMembers" metadata
@ -125,13 +113,6 @@ Feature: TeamMembers
Then "TeamMemberKey" MUST be "String" data type
And "TeamMemberKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@TeamMembers
Scenario: TeamMemberKeyNumeric
Given that the following synonyms for "TeamMemberKeyNumeric" DO NOT exist in the "TeamMembers" metadata
| TeamAgentKeyNumeric |
When "TeamMemberKeyNumeric" exists in the "TeamMembers" metadata
Then "TeamMemberKeyNumeric" MUST be "Integer" data type
@TeamMembers
Scenario: TeamMemberNationalAssociationId
Given that the following synonyms for "TeamMemberNationalAssociationId" DO NOT exist in the "TeamMembers" metadata

View File

@ -1,4 +1,4 @@
# This file was autogenerated on: 20211212171220893
# This file was autogenerated on: 20230314030610239
Feature: Teams
Background:
@ -142,22 +142,12 @@ Feature: Teams
Then "TeamKey" MUST be "String" data type
And "TeamKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Teams
Scenario: TeamKeyNumeric
When "TeamKeyNumeric" exists in the "Teams" metadata
Then "TeamKeyNumeric" MUST be "Integer" data type
@Teams
Scenario: TeamLeadKey
When "TeamLeadKey" exists in the "Teams" metadata
Then "TeamLeadKey" MUST be "String" data type
And "TeamLeadKey" length SHOULD be equal to the RESO Suggested Max Length of 255
@Teams
Scenario: TeamLeadKeyNumeric
When "TeamLeadKeyNumeric" exists in the "Teams" metadata
Then "TeamLeadKeyNumeric" MUST be "Integer" data type
@Teams
Scenario: TeamLeadLoginId
When "TeamLeadLoginId" exists in the "Teams" metadata

View File

@ -151,11 +151,11 @@ public class LookupResource {
final ArrayList<String> fieldsWithMissingAnnotations = new ArrayList<>();
lookupFields.forEach(referenceStandardField -> {
LOG.debug("Standard Field: { "
+ "resourceName: \"" + referenceStandardField.getParentResourceName() + "\""
+ "resourceName: \"" + referenceStandardField.getResourceName() + "\""
+ ", standardName: \"" + referenceStandardField.getStandardName() + "\""
+ ", lookupName: \"" + referenceStandardField.getLookupName() + "\" }");
EdmElement foundElement = getEdmElement(container.get().getEdm(), referenceStandardField.getParentResourceName(), referenceStandardField.getStandardName());
EdmElement foundElement = getEdmElement(container.get().getEdm(), referenceStandardField.getResourceName(), referenceStandardField.getStandardName());
final boolean isStringDataType = foundElement != null &&
foundElement.getType().getFullQualifiedName().toString().contentEquals(EdmPrimitiveTypeKind.String.getFullQualifiedName().toString());

View File

@ -29,7 +29,7 @@ import static org.reso.commander.common.XMLMetadataToJSONSchemaSerializer.conver
* - Bearer Tokens
* - Client Credentials (in-progress)
* <p>
* Exposes several different actions for working with OData-based WebAPI servers.
* Exposes several actions for working with OData-based WebAPI servers.
* This application is structured so that the App class is an OData WebAPI consumer
* using the Commander class, which contains the actual methods for working with OData.
* <p>
@ -52,7 +52,7 @@ public class App {
String serviceRoot = null, bearerToken = null, clientId = null, clientSecret = null,
authorizationUri = null, tokenUri = null, redirectUri = null, scope = null;
String inputFilename, outputFile, uri;
boolean useEdmEnabledClient = false, useKeyNumeric = false;
boolean useEdmEnabledClient, useKeyNumeric;
int pageLimit, pageSize;
//created with the commanderBuilder throughout the initialization body
@ -80,7 +80,7 @@ public class App {
}
//if we're running a batch, initialize variables from the settings file rather than from command line options
Settings settings = null;
Settings settings;
LOG.debug("Service Root is: " + commanderBuilder.serviceRoot);
@ -124,15 +124,15 @@ public class App {
.substring(inputFilename.contains(File.separator) ? inputFilename.lastIndexOf(File.separator) : 0)
.replace(RESOSCRIPT_EXTENSION, "") + "-" + getTimestamp(new Date());
String resolvedUrl = null;
String resolvedUrl;
Request request = null;
Request request;
//this is an integer so it can be nullable in cases where we don't care about the response code assertion
//this is an integer, so it can be nullable in cases where we don't care about the response code assertion
Integer responseCode = null;
String outputFilePath;
ODataTransportWrapper wrapper = null;
ODataTransportWrapper wrapper;
for (int i = 0; i < numRequests; i++) {
try {
@ -170,7 +170,7 @@ public class App {
LOG.info("Request " + request.getRequestId() + " has an empty URL. Skipping...");
}
} catch (Exception ex) {
LOG.error("Exception thrown in RUN_RESOSCRIPT Action. Exception is: \n" + ex.toString());
LOG.error("Exception thrown in RUN_RESOSCRIPT Action. Exception is: \n" + ex);
LOG.error("Stack trace:");
Arrays.stream(ex.getStackTrace()).forEach(stackTraceElement -> LOG.error(stackTraceElement.toString()));
}
@ -205,7 +205,8 @@ public class App {
}
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.GENERATE_METADATA_REPORT)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GENERATE_METADATA_REPORT);
LOG.info(generateMetadataReport(deserializeEdmFromPath(inputFilename, commander.getClient()), inputFilename));
generateMetadataReport(deserializeEdmFromPath(inputFilename, commander.getClient()), inputFilename);
LOG.info("Metadata report generated!");
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.VALIDATE_METADATA)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.VALIDATE_METADATA);
@ -222,14 +223,6 @@ public class App {
} catch (Exception ex) {
LOG.error(getDefaultErrorMessage(ex));
}
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.GENERATE_RESOURCE_INFO_MODELS)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GENERATE_RESOURCE_INFO_MODELS);
try {
DataDictionaryCodeGenerator generator = new DataDictionaryCodeGenerator(new ResourceInfoProcessor());
generator.processWorksheets();
} catch (Exception ex) {
LOG.error(getDefaultErrorMessage(ex));
}
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.GENERATE_REFERENCE_EDMX)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GENERATE_REFERENCE_EDMX);
try {
@ -270,8 +263,8 @@ public class App {
LOG.info("RESOScript: " + inputFilename);
LOG.info(REPORT_DIVIDER + "\n\n");
String resolvedUrl = null;
Request request = null;
String resolvedUrl;
Request request;
for (int i = 0; i < numRequests; i++) {
try {
request = settings.getRequestsAsList().get(i);
@ -293,7 +286,7 @@ public class App {
LOG.info("Request " + request.getRequestId() + " has an empty URL. Skipping...");
}
} catch (Exception ex) {
LOG.error("Exception thrown in RUN_RESOSCRIPT Action. Exception is: \n" + ex.toString());
LOG.error("Exception thrown in RUN_RESOSCRIPT Action. Exception is: \n" + ex);
LOG.error("Stack trace:");
Arrays.stream(ex.getStackTrace()).forEach(stackTraceElement -> LOG.error(stackTraceElement.toString()));
}
@ -319,7 +312,7 @@ public class App {
return false;
}
/**
/*
* Validates the metadata in inputFilename in the following ways:
* - de-serializes it into a native Edm object, which will fail if given metadata isn't valid
* - verifies whether the given EDMX file is a valid service document
@ -537,8 +530,6 @@ public class App {
.desc("Generates acceptance tests in the current directory.").build())
.addOption(Option.builder().argName("j").longOpt(ACTIONS.GENERATE_JSON_SCHEMAS_FROM_XML_METADATA)
.desc("Generates JSON Schema documents from the given XML metadata.").build())
.addOption(Option.builder().argName("i").longOpt(ACTIONS.GENERATE_RESOURCE_INFO_MODELS)
.desc("Generates Java Models for the Web API Reference Server in the current directory.").build())
.addOption(Option.builder().argName("r").longOpt(ACTIONS.GENERATE_REFERENCE_EDMX)
.desc("Generates reference metadata in EDMX format.").build())
.addOption(Option.builder().argName("k").longOpt(ACTIONS.GENERATE_REFERENCE_DDL)
@ -582,7 +573,6 @@ public class App {
public static final String VALIDATE_METADATA = "validateMetadata";
public static final String SAVE_GET_REQUEST = "saveGetRequest";
public static final String GENERATE_METADATA_REPORT = "generateMetadataReport";
public static final String GENERATE_RESOURCE_INFO_MODELS = "generateResourceInfoModels";
}
}
}

View File

@ -14,6 +14,8 @@ public class DataDictionaryMetadata {
private static final Logger LOG = LogManager.getLogger(DataDictionaryMetadata.class);
public static final class v1_7 {
public static final String LOOKUPS = "Lookups";
//TODO: clean up
public static final Set<String> WELL_KNOWN_RESOURCES = new LinkedHashSet<>(Arrays.asList(
PROPERTY,
@ -43,7 +45,6 @@ public class DataDictionaryMetadata {
FIELD,
LOOKUP
));
public static final String LOOKUP_FIELDS_AND_VALUES = "Lookup Fields and Values";
//TODO: clean up
public static class WELL_KNOWN_RESOURCE_KEYS {

View File

@ -3,35 +3,38 @@ package org.reso.models;
import java.util.List;
/**
* Defines a standard field according to the Data Dictionary specification
* Matches the format of the Data Dictionary worksheet:
* @see <a href="https://docs.google.com/spreadsheets/d/1_59Iqr7AQ51rEFa7p0ND-YhJjEru8gY-D_HM1yy5c6w/edit#gid=544946974" />
*
*/
public class ReferenceStandardField {
private String resourceName;
private String standardName;
private String displayName;
private String parentResourceName;
private String definition;
private List<String> groups;
private String simpleDataType;
private String sourceResource;
private Integer suggestedMaxLength;
private List<String> synonyms;
private String elementStatus;
private String bedes;
private String certificationLevel;
private Integer recordId;
private String lookupStatus;
private String lookup;
private String collection;
private Integer suggestedMaxPrecision;
private List<String> synonyms;
private String frenchCanadianDisplayName;
private String spanishDisplayName;
private String elementStatus;
private String recordId;
private String lookupStatus;
private String lookupName;
private Boolean repeatingElement;
private List<String> propertyTypes;
private List<String> payloads;
private String spanishStandardName;
private String statusChangeDate;
private String revisedDate;
private String addedInVersion;
private String wikiPageTitle;
private String wikiPageUrl;
private Integer wikiPageId;
private String bedes;
private ReferenceStandardField() { /* private constructor use Builder instead */ }
@ -46,6 +49,10 @@ public class ReferenceStandardField {
return getSimpleDataType().trim().contentEquals(DATA_TYPE_NAME);
}
public Boolean isExpansion() {
return getSourceResource() != null && getSourceResource().trim().length() > 0;
}
public String getStandardName() {
return standardName;
}
@ -54,8 +61,8 @@ public class ReferenceStandardField {
return displayName;
}
public String getParentResourceName(){
return parentResourceName;
public String getResourceName(){
return resourceName;
}
public String getDefinition() {
@ -70,6 +77,10 @@ public class ReferenceStandardField {
return simpleDataType;
}
public String getSourceResource() {
return sourceResource;
}
public Integer getSuggestedMaxLength() {
return suggestedMaxLength;
}
@ -86,11 +97,7 @@ public class ReferenceStandardField {
return bedes;
}
public String getCertificationLevel() {
return certificationLevel;
}
public Integer getRecordId() {
public String getRecordId() {
return recordId;
}
@ -98,22 +105,16 @@ public class ReferenceStandardField {
return lookupStatus;
}
public String getLookup() {
return lookup;
}
public String getLookupName() {
String lookupName = getLookup()
String parsedLookupName = lookupName
.replace("<n/a>", "")
.replace("Lookups", "").trim();
if (lookupName.length() == 0) return null;
return lookupName;
}
public String getCollection() {
return collection;
if (parsedLookupName.length() == 0) {
return null;
} else {
return parsedLookupName;
}
}
public Integer getSuggestedMaxPrecision() {
@ -132,8 +133,12 @@ public class ReferenceStandardField {
return payloads;
}
public String getSpanishStandardName() {
return spanishStandardName;
public String getSpanishDisplayName() {
return spanishDisplayName;
}
public String getFrenchCanadianDisplayName() {
return frenchCanadianDisplayName;
}
public String getStatusChangeDate() {
@ -160,8 +165,8 @@ public class ReferenceStandardField {
return wikiPageId;
}
public void setParentResourceName(String parentResourceName) {
this.parentResourceName = parentResourceName;
public void setResourceName() {
this.resourceName = resourceName;
}
public static class Builder {
@ -177,8 +182,8 @@ public class ReferenceStandardField {
return this;
}
public Builder setParentResourceName(String parentResourceName) {
referenceStandardField.parentResourceName = parentResourceName;
public Builder setResourceName(String resourceName) {
referenceStandardField.resourceName = resourceName;
return this;
}
@ -217,18 +222,13 @@ public class ReferenceStandardField {
return this;
}
public Builder setCertificationLevel(String certificationLevel) {
referenceStandardField.certificationLevel = certificationLevel;
return this;
}
public Builder setRecordId(Integer recordId) {
public Builder setRecordId(String recordId) {
referenceStandardField.recordId = recordId;
return this;
}
public Builder setLookup(String lookup) {
referenceStandardField.lookup = lookup;
public Builder setLookupName(String lookupName) {
referenceStandardField.lookupName = lookupName;
return this;
}
@ -237,11 +237,6 @@ public class ReferenceStandardField {
return this;
}
public Builder setCollection(String collection) {
referenceStandardField.collection = collection;
return this;
}
public Builder setSuggestedMaxPrecision(Integer suggestedMaxPrecision) {
referenceStandardField.suggestedMaxPrecision = suggestedMaxPrecision;
return this;
@ -262,8 +257,8 @@ public class ReferenceStandardField {
return this;
}
public Builder setSpanishStandardName(String spanishStandardName) {
referenceStandardField.spanishStandardName = spanishStandardName;
public Builder setSpanishDisplayName(String spanishDisplayName) {
referenceStandardField.spanishDisplayName = spanishDisplayName;
return this;
}
@ -297,6 +292,16 @@ public class ReferenceStandardField {
return this;
}
public Builder setSourceResource(String sourceResource) {
referenceStandardField.sourceResource = sourceResource;
return this;
}
public Builder setFrenchCanadianDisplayName(String frenchCanadianDisplayName) {
referenceStandardField.frenchCanadianDisplayName = frenchCanadianDisplayName;
return this;
}
public ReferenceStandardField build() {
return referenceStandardField;
}

View File

@ -3,17 +3,17 @@ package org.reso.models;
import java.util.List;
public class ReferenceStandardLookup {
private String lookupField;
private String lookupName;
private String lookupValue;
private String lookupDisplayName;
private String legacyODataValue;
private String definition;
List<String> lookupDisplayNameSynonyms;
private String bedes;
private List<String> references;
private String elementStatus;
private Integer lookupId;
private Integer lookupFieldId;
private String spanishLookupField;
private String lookupId;
private String lookupNameId;
private String frenchCanadianLookupValue;
private String spanishLookupValue;
private String statusChangeDate;
private String revisedDate;
@ -25,16 +25,16 @@ public class ReferenceStandardLookup {
//default constructor is private, use Builder instead
}
public String getLookupField() {
return lookupField;
public String getLookupName() {
return lookupName;
}
public String getLookupValue() {
return lookupValue;
}
public String getLookupDisplayName() {
return lookupDisplayName;
public String getLegacyODataValue() {
return legacyODataValue;
}
public String getDefinition() {
@ -57,16 +57,16 @@ public class ReferenceStandardLookup {
return elementStatus;
}
public Integer getLookupId() {
public String getLookupId() {
return lookupId;
}
public Integer getLookupFieldId() {
return lookupFieldId;
public String getLookupNameId() {
return lookupNameId;
}
public String getSpanishLookupField() {
return spanishLookupField;
public String getFrenchCanadianLookupValue() {
return frenchCanadianLookupValue;
}
public String getSpanishLookupValue() {
@ -96,8 +96,8 @@ public class ReferenceStandardLookup {
public static class Builder {
ReferenceStandardLookup referenceStandardLookup = new ReferenceStandardLookup();
public Builder setLookupField(String lookupField) {
referenceStandardLookup.lookupField = lookupField;
public Builder setLookupName(String lookupName) {
referenceStandardLookup.lookupName = lookupName;
return this;
}
@ -106,8 +106,8 @@ public class ReferenceStandardLookup {
return this;
}
public Builder setLookupDisplayName(String lookupDisplayName) {
referenceStandardLookup.lookupDisplayName = lookupDisplayName;
public Builder setLegacyODataValue(String legacyODataValue) {
referenceStandardLookup.legacyODataValue = legacyODataValue;
return this;
}
@ -136,18 +136,18 @@ public class ReferenceStandardLookup {
return this;
}
public Builder setLookupId(Integer lookupId) {
public Builder setLookupId(String lookupId) {
referenceStandardLookup.lookupId = lookupId;
return this;
}
public Builder setLookupFieldId(Integer lookupFieldId) {
referenceStandardLookup.lookupFieldId = lookupFieldId;
public Builder setLookupNameId(String lookupNameId) {
referenceStandardLookup.lookupNameId = lookupNameId;
return this;
}
public Builder setSpanishLookupField(String spanishLookupField) {
referenceStandardLookup.spanishLookupField = spanishLookupField;
public Builder setFrenchCanadianLookupValue(String frenchCanadianLookupValue) {
referenceStandardLookup.frenchCanadianLookupValue = frenchCanadianLookupValue;
return this;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff