package com.xrosstools.xunit; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.xrosstools.xunit.def.AdapterDef; import com.xrosstools.xunit.def.BiBranchDef; import com.xrosstools.xunit.def.BranchDef; import com.xrosstools.xunit.def.ChainDef; import com.xrosstools.xunit.def.DecoratorDef; import com.xrosstools.xunit.def.LocatorDef; import com.xrosstools.xunit.def.LoopDef; import com.xrosstools.xunit.def.UnitDef; import com.xrosstools.xunit.def.UnitDefRepo; import com.xrosstools.xunit.def.ValidatorDef; public class XunitFactory implements XunitConstants { public static XunitFactory load(URL url) throws Exception { return load(url.openStream()); } /** * It will first check model file from file path, if it does not exist, it will try classpath then. * @param path * @return * @throws Exception */ public static XunitFactory load(String path) throws Exception { InputStream in; File f = new File(path); if(f.exists()) in = new FileInputStream(f); else { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = XunitFactory.class.getClassLoader(); } in = classLoader.getResource(path).openStream(); } return load(in); } public static XunitFactory load(InputStream in) throws Exception { XunitFactory factory = null; try{ Document doc= DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in); factory = getFromDocument(doc); } finally { try{ if(in != null) in.close(); }catch(Throwable e1){ } } return factory; } private static Set<String> WRAPPED_UNITS = new HashSet<String>(); static { WRAPPED_UNITS.add(DECORATOR_UNIT); WRAPPED_UNITS.add(ADAPTER_UNIT); WRAPPED_UNITS.add(VALID_UNIT); WRAPPED_UNITS.add(INVALID_UNIT); WRAPPED_UNITS.add(LOOP_UNIT); WRAPPED_UNITS.add(BRANCH_UNIT); } private String packageId; private String name; private UnitDefRepo defRepo; public String getPackageId() { return packageId; } public String getName() { return name; } public Unit getUnit(String id) throws Exception{ return defRepo.getUnit(id); } public Processor getProcessor(String id) throws Exception{ return (Processor)getUnit(id); } public Converter getConverter(String id) throws Exception{ return (Converter )getUnit(id); } private static XunitFactory getFromDocument(Document doc){ XunitFactory factory = new XunitFactory(); Element root = doc.getDocumentElement(); factory.packageId = root.getAttribute(PACKAGE_ID); factory.name = root.getAttribute(NAME); factory.defRepo = new UnitDefRepo(factory.createApplicationProperties(doc)); factory.readUnits(doc); return factory; } private Map<String, String> createApplicationProperties(Document doc){ if(doc.getElementsByTagName(PROPERTIES).getLength() == 0) return Collections.emptyMap(); return getProperties(doc.getElementsByTagName(PROPERTIES).item(0)); } private void readUnits(Document doc){ List<Node> unitNodes = getValidChildNodes(doc.getElementsByTagName(UNITS).item(0)); for(int i = 0; i < unitNodes.size(); i++){ String key = getAttribute(unitNodes.get(i), NAME); UnitDef unitDef = createUnitNode(unitNodes.get(i)); defRepo.put(key, unitDef); } } private UnitDef createUnitNode(Node node){ if(node == null) return null; UnitDef unitDef = createPrimaryUnit(node); if(unitDef != null) return unitDef; if(WRAPPED_UNITS.contains(node.getNodeName())) unitDef = createUnitNode(getFirstValidNode(node)); return unitDef; } private UnitDef createPrimaryUnit(Node node){ String nodeName = node.getNodeName(); UnitDef unitDef = null; if(PROCESSOR.equals(nodeName)) unitDef = createProcessorNode(node); if(CONVERTER.equals(nodeName)) unitDef = createConverterNode(node); if(DECORATOR.equals(nodeName)) unitDef = createDecoratorNode(node); if(ADAPTER.equals(nodeName)) unitDef = createAdapterNode(node); else if(VALIDATOR.equals(nodeName)) unitDef = createValidatorNode(node); else if(LOCATOR.equals(nodeName)) unitDef = createLocatorNode(node); else if(CHAIN.equals(nodeName)) unitDef = createChainNode(node); else if(BI_BRANCH.equals(nodeName)) unitDef = createBiBranchNode(node); else if(BRANCH.equals(nodeName)) unitDef = createBranchNode(node); else if(WHILE.equals(nodeName)) unitDef = createPreValidationLoopNode(node); else if(DO_WHILE.equals(nodeName)) unitDef = createPostValidationLoopNode(node); if (unitDef == null) return null; unitDef.setUnitDefRepo(defRepo); unitDef.setName(getAttribute(node, NAME)); unitDef.setDescription(getAttribute(node, DESCRIPTION)); unitDef.setClassName(getAttribute(node, CLASS)); unitDef.setReferenceName(getAttribute(node, REFERENCE)); unitDef.setType(getType(node)); unitDef.setProperties(getProperties(node)); return unitDef; } private LinkedHashMap<String, String> getProperties(Node node){ List<Node> children = getValidChildNodes(node); Node entryNode; LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>(); for(int i = 0; i < children.size(); i++){ if(!isValidNode(children.get(i), PROPERTY)) continue; entryNode = children.get(i); properties.put(getAttribute(entryNode, KEY), getAttribute(entryNode, VALUE)); } return properties; } private BehaviorType getType(Node node){ String nodeName = node.getNodeName(); if(PROCESSOR.equals(nodeName)) return BehaviorType.processor; if(CONVERTER.equals(nodeName)) return BehaviorType.converter; if(LOCATOR.equals(nodeName)) return BehaviorType.locator; if(VALIDATOR.equals(nodeName)) return BehaviorType.validator; return BehaviorType.valueOf(getAttribute(node, TYPE)); } private UnitDef createChildNode(Node node, String name){ NodeList children = node.getChildNodes(); Node found = null; for(int i = 0; i < children.getLength(); i++){ if(!isValidNode(children.item(i), name)) continue; found = children.item(i); break; } return createUnitNode(found); } private UnitDef createProcessorNode(Node node){ UnitDef unitDef = new UnitDef(); return unitDef; } private UnitDef createConverterNode(Node node){ UnitDef unitDef = new UnitDef(); return unitDef; } private UnitDef createDecoratorNode(Node node){ DecoratorDef decoratorDef = new DecoratorDef(); // unitDef.setType(UnitType.valueOf(getAttribute(node, TYPE))); decoratorDef.setClassName(getAttribute(node, CLASS)); decoratorDef.setReferenceName(getAttribute(node, REFERENCE)); decoratorDef.setUnitDef(createChildNode(node, DECORATOR_UNIT)); return decoratorDef; } private UnitDef createAdapterNode(Node node){ AdapterDef adapterDef = new AdapterDef(); adapterDef.setType(BehaviorType.valueOf(getAttribute(node, TYPE))); adapterDef.setClassName(getAttribute(node, CLASS)); adapterDef.setReferenceName(getAttribute(node, REFERENCE)); adapterDef.setUnitDef(createChildNode(node, ADAPTER_UNIT)); return adapterDef; } private UnitDef createValidatorNode(Node node){ ValidatorDef unitDef = new ValidatorDef(); unitDef.setValidLabel(getAttribute(node, VALID_LABEL)); unitDef.setInvalidLabel(getAttribute(node, VALID_LABEL)); return unitDef; } private UnitDef createLocatorNode(Node node){ LocatorDef locatorDef = new LocatorDef(); locatorDef.setDefaultKey(getAttribute(node, DEFAULT_KEY)); return locatorDef; } private UnitDef createChainNode(Node node){ ChainDef chainDef = new ChainDef(); List<Node> children = getValidChildNodes(node); for(int i = 0; i < children.size(); i++){ chainDef.addUnitDef(createUnitNode(children.get(i))); } return chainDef; } private UnitDef createBiBranchNode(Node node){ BiBranchDef biBranchDef = new BiBranchDef(); biBranchDef.setValidatorDef((ValidatorDef)createChildNode(node, VALIDATOR)); biBranchDef.setValidUnitDef(createChildNode(node, VALID_UNIT)); biBranchDef.setInvalidUnitDef(createChildNode(node, INVALID_UNIT)); return biBranchDef; } private UnitDef createBranchNode(Node node){ BranchDef branchDef = new BranchDef(); branchDef.setLocatorDef(createChildNode(node, LOCATOR)); List<Node> children = getValidChildNodes(node); for(int i = 0; i < children.size(); i++){ if(!isValidNode(children.get(i), BRANCH_UNIT)) continue; Node found = children.get(i); UnitDef branchUnit = createUnitNode(found); String key = getAttribute(found, KEY); branchUnit.setKey(key); branchDef.addBranchUnitDef(branchUnit); } return branchDef; } private UnitDef createPreValidationLoopNode(Node node){ LoopDef whileLoop = new LoopDef(true); whileLoop.setValidatorDef((ValidatorDef)createChildNode(node, VALIDATOR)); whileLoop.setUnitDef(createChildNode(node, LOOP_UNIT)); return whileLoop; } private UnitDef createPostValidationLoopNode(Node node){ LoopDef doWhileLoop = new LoopDef(false); doWhileLoop.setValidatorDef((ValidatorDef)createChildNode(node, VALIDATOR)); doWhileLoop.setUnitDef(createChildNode(node, LOOP_UNIT)); return doWhileLoop; } private String getAttribute(Node node, String attributeName){ NamedNodeMap map = node.getAttributes(); for(int i = 0; i < map.getLength(); i++) if(attributeName.equals(map.item(i).getNodeName())) return map.item(i).getNodeValue(); return null; } private boolean isValidNode(Node node) { return !node.getNodeName().equals("#text"); } private boolean isValidNode(Node node, String name) { return node.getNodeName().equals(name); } private Node getFirstValidNode(Node node) { NodeList children = node.getChildNodes(); for(int i = 0; i < children.getLength(); i++){ if(isValidNode(children.item(i))) return children.item(i); } return null; } private List<Node> getValidChildNodes(Node node) { List<Node> nl = new ArrayList<>(); NodeList nodeList = node.getChildNodes(); for(int i = 0; i < nodeList.getLength(); i++){ if(isValidNode(nodeList.item(i))) nl.add(nodeList.item(i)); } return nl; } }