001package Torello.Browser.JsonAST; 002 003import Torello.Java.StrCSV; 004 005import Torello.Java.ReadOnly.ReadOnlySet; 006import Torello.Java.ReadOnly.ReadOnlyTreeSet; 007 008import java.util.TreeSet; 009import javax.json.JsonObject; 010 011/** 012 * There are two implementation methods of the "Check Keys" feature in this class. The first 013 * "Check Key Method" may be used with any of the six {@link Entity} subclasses: 014 * {@link PPR}, {@link TCE}, {@link TypeNode}, {@link CommandNode} & {@link EventNode}. 015 * 016 * <BR /><BR />The second variant of "Check Keys" may be used on {@link JsonObject JsonObjects} 017 * which have been retrieved from the (top level) {@code "domains"} array, and are to be 018 * extracted and parsed into instance of class {@link Domain}. 019 * 020 * <BR /><BR />For both of these methods, all that is occuring is an "assertion statement", nothing 021 * more, nor anything less. The assertion being promulgated is to make sure that only Json 022 * Properties which match exactly with a well-known and well-documented sub-list of expected 023 * property names occur. The intention is two fold. 024 * 025 * <BR /><BR />The first goal is to make sure to catch any unexpected changes that might ever occur 026 * in future versions of the CDP JSON spec files. The second is to help understand, exactly, (nail 027 * down) what is and is not guaranteed to be true about a 40K line long {@code '.json'} File. The 028 * tests in these two methods help make obvious / elucidate what is absolutely true when parsing 029 * these files! 030 * 031 * <BR /><BR />That's really all this is. 032 */ 033@Torello.JavaDoc.Annotations.StaticFunctional 034@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="CONSTRUCTOR_JDHBI") 035public class Helper$CheckKeys 036{ 037 private Helper$CheckKeys() { } 038 039 private static final ReadOnlySet<String> expectedEntityObjKeys = new ReadOnlyTreeSet<>( 040 String::compareTo, 041 "type", 042 "items", 043 "enum", 044 "description", 045 "optional", "experimental", "deprecated" 046 ); 047 048 static void entityCheck( 049 final Entity THIS, 050 final JsonObject jo, 051 final ReadOnlySet<String> subClassExpectedKeys 052 ) 053 { 054 final TreeSet<String> keys = new TreeSet<>(jo.keySet()); 055 056 for (final String k : expectedEntityObjKeys) keys.remove(k); 057 058 // The subclass inheriting this class will have more keys 059 for (final String k : subClassExpectedKeys) keys.remove(k); 060 061 if (keys.size() != 0) THIS.verifyThrow( 062 "Entity had unrecognized Map (JsonObject) Properties: " + 063 StrCSV.toCSV(keys, key -> '[' + key + ']', true, null) 064 ); 065 } 066 067 private static final ReadOnlySet<String> expectedDomainObjKeys = new ReadOnlyTreeSet<>( 068 String::compareTo, 069 "domain", "description", 070 "experimental", "deprecated", 071 "types", "commands", "events", 072 "dependencies" 073 ); 074 075 static void domainCheck(final JsonObject jo, final String domainNamme) 076 { 077 final TreeSet<String> keys = new TreeSet<>(jo.keySet()); 078 079 for (final String k : expectedDomainObjKeys) keys.remove(k); 080 081 if (keys.size() != 0) throw new ASTError( 082 "Domain JsonObjec had unrecognized Map (JsonObject) Properties: " + 083 StrCSV.toCSV(keys, key -> '[' + key + ']', true, null) 084 ); 085 } 086}