/** * create new instance of src object, connecting all inputs from src object Note if input is a * SubstModel, it is duplicated as well. * * @param src object to be copied * @param i index used to extend ID with. * @return copy of src object */ private Object duplicate(BEASTInterface src, int i) { if (src == null) { return null; } BEASTInterface copy; try { copy = src.getClass().newInstance(); copy.setID(src.getID() + "_" + i); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException( "Programmer error: every object in the model should have a default constructor that is publicly accessible: " + src.getClass().getName()); } for (Input<?> input : src.listInputs()) { if (input.get() != null) { if (input.get() instanceof List) { // handle lists // ((List)copy.getInput(input.getName())).clear(); for (Object o : (List<?>) input.get()) { if (o instanceof BEASTInterface) { // make sure it is not already in the list copy.setInputValue(input.getName(), o); } } } else if (input.get() instanceof SubstitutionModel) { // duplicate subst models BEASTInterface substModel = (BEASTInterface) duplicate((BEASTInterface) input.get(), i); copy.setInputValue(input.getName(), substModel); } else { // it is some other value copy.setInputValue(input.getName(), input.get()); } } } copy.initAndValidate(); return copy; }
/** * produce elements for a beast object with name name, putting results in buf. It tries to create * XML conforming to the XML transformation rules (see XMLParser) that is moderately readable. */ @SuppressWarnings("rawtypes") void beastObjectToXML( BEASTInterface beastObject, StringBuffer buf, String name, boolean isTopLevel) throws Exception { // determine element name, default is input, otherswise find one of the defaults String elementName = "input"; for (String key : element2ClassMap.keySet()) { String className = element2ClassMap.get(key); Class _class = Class.forName(className); if (_class.equals(beastObject.getClass())) { elementName = key; } } // if (beastObject instanceof Alignment) { // elementName = XMLParser.DATA_ELEMENT; // } // if (beastObject instanceof Sequence) { // elementName = XMLParser.SEQUENCE_ELEMENT; // } // if (beastObject instanceof State) { // elementName = XMLParser.STATE_ELEMENT; // } // if (beastObject instanceof Distribution) { // elementName = XMLParser.DISTRIBUTION_ELEMENT; // } // if (beastObject instanceof Logger) { // elementName = XMLParser.LOG_ELEMENT; // } // if (beastObject instanceof Operator) { // elementName = XMLParser.OPERATOR_ELEMENT; // } // if (beastObject instanceof RealParameter) { // elementName = XMLParser.REAL_PARAMETER_ELEMENT; // } // if (beastObject instanceof Tree) { // elementName = XMLParser.TREE_ELEMENT; // } if (isTopLevel) { elementName = XMLParser.RUN_ELEMENT; } for (int i = 0; i < indent; i++) { buf.append(" "); } indent++; // open element buf.append("<").append(elementName); boolean skipInputs = false; if (isDone.stream().anyMatch(x -> x == beastObject)) { // XML is already produced, we can idref it buf.append(" idref='" + normalise(beastObject.getID()) + "'"); skipInputs = true; } else { // see whether a reasonable id can be generated if (beastObject.getID() != null && !beastObject.getID().equals("")) { String id = beastObject.getID(); // ensure ID is unique if (IDs.contains(id)) { int k = 1; while (IDs.contains(id + k)) { k++; } id = id + k; } buf.append(" id='" + normalise(id) + "'"); IDs.add(id); } isDone.add(beastObject); } String className = beastObject.getClass().getName(); if (skipInputs == false && (!element2ClassMap.containsKey(elementName) || !element2ClassMap.get(elementName).equals(className))) { // only add spec element if it cannot be deduced otherwise (i.e., by idref or default mapping buf.append(" spec='" + className + "'"); } if (name != null && !name.equals(elementName)) { // only add name element if it differs from element = default name buf.append(" name='" + name + "'"); } if (!skipInputs) { // process inputs of this beast object // first, collect values as attributes List<Input<?>> inputs = beastObject.listInputs(); for (Input<?> input : inputs) { Object value = input.get(); inputToXML(input, value, beastObject, buf, true); } // next, collect values as input elements StringBuffer buf2 = new StringBuffer(); for (Input input : inputs) { Object value = input.get(); inputToXML(input, value, beastObject, buf2, false); } if (buf2.length() == 0) { // if nothing was added by the inputs, close element indent--; buf.append("/>\n"); } else { // add contribution of inputs if (buf2.indexOf("<") >= 0) { buf.append(">\n"); buf.append(buf2); indent--; for (int i = 0; i < indent; i++) { buf.append(" "); } } else { buf.append(">"); buf.append(buf2.toString().trim()); indent--; } // add closing element buf.append("</" + elementName + ">\n"); } } else { // close element indent--; buf.append("/>\n"); } if (indent < 2) { buf.append("\n"); } } // pluginToXML
/** * Produce JSON fragment for a beast object with given name, putting results in buf. It tries to * create JSON conforming to the JSON transformation rules (see JSONParser) that is moderately * readable. */ void beastObjectToJSON( BEASTInterface beastObject, Class<?> defaultType, StringBuffer buf, String name, boolean isTopLevel) throws Exception { // determine element name, default is input, otherwise find one of the defaults String indent = ""; for (int i = 0; i < indentCount; i++) { indent += "\t"; // buf.append(" "); } indentCount++; // open element boolean needsComma = false; if (name != null) { // buf.append((indentCount == 1 ? "" : indent.substring(1)) + " \"" + name + "\": {"); buf.append((indentCount == 1 ? "" : indent.substring(1)) + " " + name + ": {"); } else { buf.append(indent + "{"); } boolean skipInputs = false; if (isDone.contains(beastObject)) { // JSON is already produced, we can idref it buf.append((needsComma == true) ? ",\n" + indent + " " : ""); buf.append("idref: \"" + beastObject.getID() + "\" "); needsComma = true; skipInputs = true; } else { // see whether a reasonable id can be generated if (beastObject.getID() != null && !beastObject.getID().equals("")) { String id = beastObject.getID(); // ensure ID is unique if (IDs.contains(id)) { int k = 1; while (IDs.contains(id + k)) { k++; } id = id + k; } buf.append((needsComma == true) ? ",\n" + indent + " " : ""); buf.append("id: \"" + normalise(null, id) + "\""); needsComma = true; IDs.add(id); } isDone.add(beastObject); } String className = beastObject.getClass().getName(); if (skipInputs == false) { // only add spec element if it cannot be deduced otherwise (i.e., by idref) if (defaultType != null && !defaultType.getName().equals(className)) { buf.append((needsComma == true) ? ",\n" + indent + " " : ""); // buf.append("\"spec\": \"" + className + "\""); buf.append("spec: \"" + className + "\""); needsComma = true; } } if (!skipInputs) { // process inputs of this beastObject // first, collect values as attributes List<Input<?>> inputs = beastObject.listInputs(); // List<InputType> inputs = XMLParserUtils.listInputs(beastObject.getClass(), beastObject); for (Input<?> input : inputs) { StringBuffer buf2 = new StringBuffer(); Object value = input.get(); inputToJSON(input, value, beastObject, buf2, true, indent); if (buf2.length() > 0) { buf.append((needsComma == true) ? "," : ""); buf.append(buf2); needsComma = true; } } // next, collect values as input elements StringBuffer buf2 = new StringBuffer(); for (Input<?> input : inputs) { StringBuffer buf3 = new StringBuffer(); Object value = input.get(); inputToJSON(input, value, beastObject, buf3, false, indent); if (buf3.length() > 0) { buf2.append((needsComma == true) ? ",\n" : "\n"); buf2.append(buf3); needsComma = true; } } if (buf2.length() != 0) { buf.append(buf2); } indentCount--; if (needsComma) { buf.append("\n" + indent); } needsComma = true; } else { // close element indentCount--; buf.append(""); needsComma = true; } // if (m_nIndent < 2) { // collapse newlines if there are no sub-objects String str = buf.toString(); if (str.indexOf('}') < 0 && str.length() < 1024) { str = str.replaceAll("\\s+", " "); buf.delete(0, buf.length()); buf.append(indent); buf.append(str); } buf.append("}"); // } } // beastObjectToJSON