package org.phenoscape.io.nexml_1_0;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Logger;
import org.nexml.x10.AbstractBlock;
import org.nexml.x10.AbstractStates;
import org.nexml.x10.Annotated;
import org.nexml.x10.Dict;
import org.nexml.x10.NexmlDocument;
import org.nexml.x10.StandardCells;
import org.nexml.x10.StandardFormat;
import org.nexml.x10.Taxa;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class NeXMLUtil_1_0 {
public static String COMMENT_KEY = "phenex_comment";
public static String FIGURE_KEY = "phenex_figure_ref";
public static String MATRIX_TAXON_KEY = "phenex_matrix_taxon_name";
public static Taxa findOrCreateTaxa(NexmlDocument doc, String id) {
for (Taxa taxaBlock : doc.getNexml().getOtusArray()) {
if (taxaBlock.getId().equals(id)) return taxaBlock;
}
// no taxa block was found, so create one for that id
final Taxa newTaxa = doc.getNexml().insertNewOtus(0);
newTaxa.setId(id);
return newTaxa;
}
public static AbstractBlock findOrCreateCharactersBlock(NexmlDocument doc, String id) {
for (AbstractBlock block : doc.getNexml().getCharactersArray()) {
if (block.getId().equals(id)) return block;
}
// no characters block was found, so create one for that id
final AbstractBlock newBlock = StandardCells.Factory.newInstance();
newBlock.addNewFormat();
newBlock.setId(id);
final AbstractBlock[] currentBlocksArray = doc.getNexml().getCharactersArray();
final List<AbstractBlock> currentBlocks = new ArrayList<AbstractBlock>(Arrays.asList(currentBlocksArray));
currentBlocks.add(newBlock);
doc.getNexml().setCharactersArray(currentBlocks.toArray(currentBlocksArray));
// need to find it again, as a copy is made and we'll be making more edits
return findOrCreateCharactersBlock(doc, id);
}
public static AbstractStates findOrCreateStates(StandardFormat format, String id) {
for (AbstractStates abstractStates : format.getStatesArray()) {
if (abstractStates.getId().equals(id)) return abstractStates;
}
// no states block was found, so create one for that id
final AbstractStates newStates = format.addNewStates();
newStates.setId(id);
return newStates;
}
public static Element getFirstChildWithTagName(Element parent, String tagName) {
final NodeList elements = parent.getElementsByTagName(tagName);
return (elements.getLength() > 0) ? (Element)(elements.item(0)) : null;
}
public static Element getFirstChildWithTagNameNS(Element parent, String namespaceURI, String localName) {
final NodeList elements = parent.getElementsByTagNameNS(namespaceURI, localName);
return (elements.getLength() > 0) ? (Element)(elements.item(0)) : null;
}
public static Dict findOrCreateMetadataDict(NexmlDocument doc) {
final Document dom = doc.getNexml().getDomNode().getOwnerDocument();
final Element any = dom.createElement("any");
any.appendChild(dom.createElement("curators"));
any.appendChild(dom.createElement("publication"));
any.appendChild(dom.createElement("publicationNotes"));
final Dict newDict = findOrCreateDict(doc.getNexml(), "phenex-metadata", any);
return newDict;
}
public static Dict findOrCreateDict(Annotated node, String key, Element defaultValue) {
for (Dict dict : node.getDictArray()) {
final String[] keys = dict.getKeyArray();
if ((keys.length > 0) && (keys[0].equals(key))) {
return dict;
}
}
// no such dict was found, so create
final Dict newDict = node.addNewDict();
newDict.setKeyArray(new String[] {key});
newDict.getDomNode().appendChild(defaultValue);
return newDict;
}
public static void removeDict(Annotated node, Dict dict) {
final List<Dict> dicts = new ArrayList<Dict>(Arrays.asList(node.getDictArray()));
dicts.remove(dict);
node.setDictArray(dicts.toArray(new Dict[] {}));
}
public static Element getDictValueNode(Dict dict) {
final NodeList children = dict.getDomNode().getChildNodes();
int elementsFound = 0;
for (int i = 0; i < children.getLength(); i++) {
final Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
elementsFound++;
if (elementsFound == 2) {
return (Element)child;
}
}
}
return null;
}
public static String getTextContent(Node node) {
// this method is useful when DOM Level 3 "getTextContent" is not implemented
if (node.getNodeType() == Node.TEXT_NODE) { return ((CharacterData)node).getData(); }
final StringBuffer pieces = new StringBuffer();
final NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
final Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE) {
pieces.append(((CharacterData)child).getData());
} else {
pieces.append(getTextContent(child));
}
}
return pieces.toString();
}
public static void setTextContent(Element node, String text) {
// this method is useful when DOM Level 3 "setTextContent" is not implemented
final NodeList children = node.getChildNodes();
for (int i = (children.getLength() - 1); i > -1; i--) {
node.removeChild(children.item(i));
}
node.appendChild(node.getOwnerDocument().createTextNode(text));
}
public static void clearChildren(Element node) {
final NodeList children = node.getChildNodes();
for (int i = (children.getLength() - 1); i > -1; i--) {
final Node child = children.item(i);
node.removeChild(child);
}
}
@SuppressWarnings("unused")
private static Logger log() {
return Logger.getLogger(NeXMLUtil_1_0.class);
}
}