/** * Loads definitions of all agents * * @param node */ @SuppressWarnings("unchecked") private void loadAgents(Node root, ClassLoader classLoader) throws Exception { ArrayList<Node> list = XmlDocUtils.getChildrenByTagName(root, "agents"); // No agents if (list.size() < 1) return; list = XmlDocUtils.getChildrenByTagName(list.get(0), "agent"); Class<? extends Agent> agentType; for (int i = 0; i < list.size(); i++) { Node node = list.get(i); // Agent's priority int priority = XmlDocUtils.getIntegerValue(node, "priority", Observer.LOW_PRIORITY); // Agent's step time RationalNumber time = RationalNumber.parse(XmlDocUtils.getValue(node, "time", "1")); // Agent's class String className = node.getTextContent().trim(); if (classLoader != null) { agentType = (Class<Agent>) classLoader.loadClass(className); } else { agentType = (Class<Agent>) Class.forName(className); } // Add agent's definition to the model addAgentType(agentType, time, priority); } }
/** * Loads model methods * * @param model * @param root */ private void loadMethods(SparkModel model, Node root) { ArrayList<Node> nodes = XmlDocUtils.getChildrenByTagName(root, "methods"); if (nodes.size() > 0) nodes = XmlDocUtils.getChildrenByTagName(nodes.get(0), "method"); for (int i = 0; i < nodes.size(); i++) { ModelMethod method = ModelMethod.loadMethod(model, nodes.get(i)); if (!addMethod(method)) { logger.error("Method " + method.getName() + " is already defined"); } } }
/** Creates a chart panel based on the given xml-node */ public SparkChartPanel(WindowManager manager, Node node) { this.xmlNode = node; int interval = XmlDocUtils.getIntegerValue(node, "interval", 1); String stype = XmlDocUtils.getValue(node, "chart-type", ChartType.LINE_CHART.toString()); String location = XmlDocUtils.getValue(node, "location", null); ChartType type = ChartType.valueOf(stype); init(manager, interval, location, type); addSeries(node); }
/** * Adds a chart information to the existing chart panel * * @param node */ public void addSeries(Node node) { // TODO: everything could be done with expressions only String varNames = XmlDocUtils.getValue(node, "variable", null); String label = XmlDocUtils.getValue(node, "label", ""); String expressions = XmlDocUtils.getValue(node, "expressions", null); String exprLabels = XmlDocUtils.getValue(node, "expr-labels", ""); // Single variables if (varNames != null) { String[] names = varNames.split(";"); String[] labels = label.split(";"); int i = 0; for (String name : names) { if (name == null || name.length() == 0) continue; label = labels[i]; name = name.trim(); addSeries(name, label); if (i < labels.length - 1) i += 1; } } // Expressions if (expressions != null) { String[] exprs = expressions.split(";"); String[] labels = exprLabels.split(";"); int i = 0; for (String expr : exprs) { if (expr == null || expr.length() == 0) continue; label = labels[i]; UserFunction f; try { f = UserFunction.create(expr); } catch (Exception ex) { ex.printStackTrace(); continue; } addSeries(f, label); if (i < labels.length - 1) i += 1; } } }
/** * Internal method for loading a model from the given xml document * * @param xmlDoc * @param rootPath * @return */ private SparkModel load(Document xmlDoc, File rootPath) throws Exception { SparkModel model = null; ClassLoader classLoader = null; ArrayList<Node> nodes; Node root = xmlDoc.getFirstChild(); Node node; if (root == null) throw new Exception("No root node in the xml document"); root = XmlDocUtils.getChildByTagName(root, "model"); if (root == null) throw new Exception("No model node in the xml document"); /* Load class path */ classLoader = setupClassPath(rootPath); /* Load main model class */ nodes = XmlDocUtils.getChildrenByTagName(root, "setup"); if (nodes.size() != 1) throw new Exception("The model class must be uniquely specified"); node = nodes.get(0); String setupName = node.getTextContent().trim(); if (classLoader != null) { model = (SparkModel) classLoader.loadClass(setupName).newInstance(); } else { model = (SparkModel) Class.forName(setupName).newInstance(); } startConstruction(model); /* Load basic parameters */ loadBasicModelParameters(root); /* Load agents */ loadAgents(root, classLoader); /* Load variables */ loadVariables(model, root); /* Load methods */ loadMethods(model, root); return model; }
/** * Loads model variables * * @param model * @param root */ private void loadVariables(SparkModel model, Node root) { ArrayList<Node> nodes = XmlDocUtils.getChildrenByTagName(root, "variables"); if (nodes.size() > 0) nodes = XmlDocUtils.getChildrenByTagName(nodes.get(0), "variable"); for (int i = 0; i < nodes.size(); i++) { ModelVariable var = null; try { var = ModelVariable.loadVariable(model, nodes.get(i)); } catch (Exception e) { logger.error("Cannot create a variable"); continue; } if (!addModelVariable(var)) { logger.error("A variable " + var.getName() + " is already declared"); } } }
/** * Loads basic model parameters * * @param model * @param root */ private void loadBasicModelParameters(Node root) { /* Load tick size */ RationalNumber tickTime = RationalNumber.parse(XmlDocUtils.getValue(root, "tick", "1")); // Set model's tick time setTickTime(tickTime); // Set model's default observer and execution mode ArrayList<Node> nodes = XmlDocUtils.getChildrenByTagName(root, "setup"); String defaultObserver = XmlDocUtils.getValue(nodes.get(0), "observer", ObserverFactory.DEFAULT_OBSERVER_NAME); int defaultExecutionMode = ExecutionMode.SERIAL_MODE; try { defaultExecutionMode = ExecutionMode.parse(XmlDocUtils.getValue(nodes.get(0), "mode", "serial")); } catch (Exception e) { logger.error(e); } setDefaultObserver(defaultObserver, defaultExecutionMode); }
/** Updates XML node */ public void updateXML( SparkWindow location, Document xmlModelDoc, Node interfaceNode, File xmlModelFile) { // TODO: update an existing node (when an editing mode is implemented) // Existing problem: separate chart nodes from xml-document are combined // in one // chart panel now. Saving the existing chart panel will result in an // inconsistency. if (xmlNode != null) return; // Variable names and labels StringBuilder varNames = new StringBuilder(); StringBuilder labels = new StringBuilder(); // Expressions and their labels StringBuilder exprs = new StringBuilder(); StringBuilder exprLabels = new StringBuilder(); boolean firstVarFlag = true; boolean firstExprFlag = true; for (SeriesInfo info : series) { if (info.varName == null) { if (!firstExprFlag) { exprs.append(';'); exprLabels.append(';'); } exprs.append(info.function.toString()); exprLabels.append(info.label); firstExprFlag = false; } else { if (!firstVarFlag) { varNames.append(';'); labels.append(';'); } varNames.append(info.varName); labels.append(info.label); firstVarFlag = false; } } // Create a new xml-node xmlNode = xmlModelDoc.createElement("user-chart"); // location XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "location", location.getName()); // chart-type XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "chart-type", type); // name // TODO: name != location in general XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "name", location.getName()); // interval XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "interval", 1); // variables XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "variable", varNames.toString()); // labels XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "label", labels.toString()); if (exprs.length() > 0) { XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "expressions", exprs.toString()); XmlDocUtils.addAttr(xmlModelDoc, xmlNode, "expr-labels", exprLabels.toString()); } // Add this node to the document interfaceNode.appendChild(xmlNode); }