Browse Source

ParamDefinition.normalizeParams

dsehnal 4 years ago
parent
commit
2e770cb733
1 changed files with 80 additions and 2 deletions
  1. 80 2
      src/mol-util/param-definition.ts

+ 80 - 2
src/mol-util/param-definition.ts

@@ -77,7 +77,8 @@ export namespace ParamDefinition {
         type: 'select'
         /** array of (value, label) tuples */
         options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[]
-        cycle?: boolean
+        cycle?: boolean,
+        _optionSet?: Set<T>
     }
     export function Select<T>(defaultValue: T, options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[], info?: Info & { cycle?: boolean }): Select<T> {
         return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options, cycle: info?.cycle }, info);
@@ -87,7 +88,8 @@ export namespace ParamDefinition {
         type: 'multi-select'
         /** array of (value, label) tuples */
         options: readonly (readonly [E, string])[],
-        emptyValue?: string
+        emptyValue?: string,
+        _optionSet?: Set<T>
     }
     export function MultiSelect<E extends string, T = E[]>(defaultValue: T, options: readonly (readonly [E, string])[], info?: Info & { emptyValue?: string }): MultiSelect<E, T> {
         // TODO: check if default value is a subset of options?
@@ -548,6 +550,82 @@ export namespace ParamDefinition {
         }
     }
 
+    function normalizeParam(p: Any, value: any, defaultIfUndefined: boolean): any {
+        if (value === void 0 || value === null) {
+            return defaultIfUndefined ? p.defaultValue : void 0;
+        }
+
+        if (typeof p.defaultValue !== typeof value) {
+            return p.defaultValue;
+        }
+
+        if (p.type === 'group') {
+            const ret = { ...value };
+            for (const key of Object.keys(p.params)) {
+                const param = p.params[key];
+                if (ret[key] === void 0) {
+                    if (defaultIfUndefined) ret[key] = param.defaultValue;
+                } else {
+                    ret[key] = normalizeParam(param, ret[key], defaultIfUndefined);
+                }
+            }
+            return ret;
+        } else if (p.type === 'mapped') {
+            const v = value as NamedParams;
+            if (typeof v.name !== 'string') {
+                return p.defaultValue;
+            }
+            if (typeof v.params === 'undefined') {
+                return defaultIfUndefined ? p.defaultValue : void 0;
+            }
+
+            const options = p.select._optionSet ?? (p.select._optionSet = new Set(p.select.options.map(o => o[0])));
+            if (!options.has(v.name)) {
+                return p.defaultValue;
+            }
+
+            const param = p.map(v.name);
+            return {
+                name: v.name,
+                params: normalizeParam(param, v.params, defaultIfUndefined)
+            };
+        } else if (p.type === 'select') {
+            const options = p._optionSet ?? (p._optionSet = new Set(p.options.map(o => o[0])));
+            if (!options.has(value)) return p.defaultValue;
+            return value;
+        } else if (p.type === 'multi-select') {
+            const options = p._optionSet ?? (p._optionSet = new Set(p.options.map(o => o[0])));
+            if (!Array.isArray(value)) return p.defaultValue;
+            const ret = value.filter(function (this: Set<any>, v: any) { return this.has(v); }, options);
+            if (value.length > 0 && ret.length === 0) return p.defaultValue;
+            return ret;
+        } else if (p.type === 'object-list') {
+            if (!Array.isArray(value)) return p.defaultValue;
+            return value.map(v => normalizeParams(p.element, v, defaultIfUndefined));
+        }
+
+        // TODO: validate/normalize all param types "properly"??
+
+        return value;
+    }
+
+    export function normalizeParams(p: Params, value: any, defaultIfUndefined = true) {
+        if (typeof value !== 'object') {
+            return defaultIfUndefined ? getDefaultValues(p) : value;
+        }
+
+        const ret = { ...value };
+        for (const key of Object.keys(p)) {
+            const param = p[key];
+            if (ret[key] === void 0) {
+                if (defaultIfUndefined) ret[key] = param.defaultValue;
+            } else {
+                ret[key] = normalizeParam(param, ret[key], defaultIfUndefined);
+            }
+        }
+        return ret;
+    }
+
     /**
      * Map an object to a list of [K, string][] to be used as options, stringToWords for key used by default (or identity of null).
      *