public Context(Controller controller, BlockBase root, Line block, int line, Dictionary<string, Variable> variables) { Controller = controller; Root = root; Block = block; Line = line; Variables = variables; }
private void validateScript(Controller c, Script s, Dictionary<string, Variable> vars, StringBuilder output) { // if script has never been validated, but has errors, then do not validate, they are parse errors. if (s.Valid == BlockBase.Validation.NeverRan && s.Log.ErrorCount > 0) { s.SetValid(false); // will set valid to failed. return; } s.SetValid(true); if (s.List) { vars.Clear(); s.ExecuteAsList(new Context(c, s, s, 0, vars), output); } else { c.Add(s); while (c.next(output)) { } } s.SetValid(false); }
public void Validate() { var log = new Logger("Validator"); using (new LogTimed(log, "Starting", "Finished")) { // dummy variables used to run scripts without effecting user data. var p = new Personality(this, "tmpValidator", "tmpValidator"); var c = new Controller(this, "DUMMY"); c.AddPersonality(p); var output = new StringBuilder(); var vars = new Dictionary<string, Variable>(); personControlLock.EnterReadLock(); try { if (personalities.Count == 0) log.Error(StringsScripting.No_personalities); if (inputReplace == null || inputReplace.Count == 0) log.Warning(StringsScripting.No_input_replace); } finally { personControlLock.ExitReadLock(); } if (allscripts.IsEmpty) log.Error(StringsScripting.No_scripts); // validate startup scripts. scriptsLock.EnterReadLock(); try { foreach (var s in setupPersonality) validateScript(c, s, vars, output); foreach (var s in setupController) validateScript(c, s, vars, output); } finally { scriptsLock.ExitReadLock(); } // validate all other scripts. foreach (var s in allscripts.GetAll()) if (s.IsSet) validateScript(c, s, vars, output); } // ToDo 2: Scripts can change inbetwen here and validation, so we could be dirty but dirty being false. Dirty = false; }
/// <summary> /// Parses raw lines in to the system. /// </summary> private void parseScriptGroup(List<string> rawLines, string filePath, string fileKey, Logger fileLog) { // split-up the lines in to indatation based blocks. var group = new GroupInfo(filePath, fileKey, fileLog); scriptsLock.EnterWriteLock(); scriptGroups.Add(group); scriptsLock.ExitWriteLock(); var blocks = group.Blocks; int currentLine = 0; string blockKey = null; string[] blockTags = null; string[] blockResponses = null; int blockLine = 0; while (currentLine < rawLines.Count) { string str = rawLines[currentLine]; int indent = 0; fileLog.SetId(currentLine); if (parseCutLine(ref str, ref indent)) // line empty? { if (indent == 0) // indent 0 defines what the key of the upcoming object is. { List<string[]> args; parseBlockStart(str, out blockKey, out args, fileLog); blockTags = null; blockResponses = null; if (args.Count > 0) blockTags = KeyClean(args[0], fileLog); if (args.Count > 1) blockResponses = SanitizeInputReplace(args[1]); blockLine = currentLine; // make sure key is a valid type. var rootKey = KeySplit(blockKey)[0]; if (rootKey != "script" && rootKey != "list" && rootKey != "setup" && rootKey != "personality") { fileLog.Error(string.Format(StringsScripting.Formatted_Error_Invalid_root_type, rootKey), currentLine); break; } ++currentLine; } else if (indent > 0) { if (blockKey == null) { fileLog.Error(StringsScripting.Invalid_Indentation, currentLine); break; } var log = new Logger(fileKey + "." + blockKey); var lines = parseBlock(rawLines, ref currentLine, indent, log); if (lines == null) blocks.Add(new BlockBase(blockKey, null, blockTags, group, log)); else { // Figureout type of script, then add it. var keySplit = KeySplit(blockKey); if (keySplit.Length == 2) { if (keySplit[1] == null || keySplit[1].Length == 0) { fileLog.Warning(StringsScripting.Warning_Empty_sub_key); continue; } var key = fileKey + '.' + keySplit[1]; switch (keySplit[0]) { case "setup": scriptsLock.EnterWriteLock(); try { if (keySplit[1] == "controller") setupController.Add(new Script(this, false, blockKey, lines, blockTags, group, log)); else if (keySplit[1] == "personality") setupPersonality.Add(new Script(this, false, blockKey, lines, blockTags, group, log)); //else //ToDo : Error unknown setup type. } finally { scriptsLock.ExitWriteLock(); } // ToDo : Remove error from strings. //if (blockTags != null && blockTags.Length > 0) // fileLog.Warning(StringsScripting.Setup_has_tags, blockLine); // warn if has responses if (blockResponses != null && blockResponses.Length >= 0) fileLog.Warning(StringsScripting.Setup_has_responses, blockLine); break; case "script": case "list": { var script = new Script(this, keySplit[0] == "list", blockKey, lines, blockTags, group, log); blocks.Add(script); addScript(keySplit[0], fileKey, keySplit[1], script, blockTags, blockResponses); } break; case "personality": { key = keySplit[1]; // does personality already exist? Personality p = null; Variable<Personality> vP = null; if (personalities.TryGetValue(key, out vP)) p = vP.Value; // if not create new. else p = CreatePersonality(key); // run through the script to fill the personalities variables. var script = new Script(this, false, blockKey, lines, null, group, log); var c = new Controller(this, "DUMMY"); c.AddPersonality(p); var sb = new StringBuilder(); validateScript(c, script, null, sb); runThroughScript(c, script, sb); } break; default: fileLog.Error(string.Format(StringsScripting.Formatted_Error_Invalid_root_type, keySplit[0]), blockLine); return; } } else { fileLog.Error(string.Format(StringsScripting.Formatted_Error_Invalid_root_type, keySplit[0]), blockLine); break; } } } } else ++currentLine; } return; }
/// <summary> Add script to controller, call next until false. </summary> /// <returns> false if valid is not passed </returns> private bool runThroughScript(Controller c, BlockBase s, StringBuilder sb) { if (s.Valid != BlockBase.Validation.Passed) return false; c.Add(s); bool AutoFill = c.AutoFill; c.AutoFill = false; while (c.next(sb)) { } c.AutoFill = AutoFill; return true; }
/// <summary> Runs all setup scripts on the controller. </summary> private void runAllSetupOn(Controller c, StringBuilder sb) { scriptsLock.EnterReadLock(); try { foreach (var s in setupController) runThroughScript(c, s, sb); } finally { scriptsLock.ExitReadLock(); } }
/// <summary> Runs all setup scripts on the personality. </summary> private void runAllSetupOn(Personality p, StringBuilder sb) { var c = new Controller(this, "DUMMY"); c.AddPersonality(p); scriptsLock.EnterReadLock(); try { foreach (var s in setupPersonality) runThroughScript(c, s, sb); } finally { scriptsLock.ExitReadLock(); } }
public void RemoveController(Controller c) { if (c == null) return; c.stop(); personControlLock.EnterWriteLock(); try { controllers.Remove(c); } finally { personControlLock.ExitWriteLock(); } }
/// <summary> /// Creates a new controller for the given personality. /// </summary> /// <param name="p"></param> /// <returns></returns> public Controller CreateController(string id, Logger log = null) { if (log == null) log = new Logger("CreateController[" + id + "]"); personControlLock.EnterWriteLock(); try { var c = new Controller(this, id); controllers.Add(c); // run setups if (Dirty) Logger.Log(log, Logger.Level.Error, StringsScripting.Log_VM_Dirty); else { personControlLock.EnterReadLock(); scriptsLock.EnterReadLock(); try { runAllSetupOn(c, new StringBuilder()); } finally { scriptsLock.ExitReadLock(); personControlLock.ExitReadLock(); } } c.AddFromStartQuery(log); return c; } finally { personControlLock.ExitWriteLock(); } }