/** * * Copyright 2014 The Darks ORM Project (Liu lihua) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package darks.orm.core.config.sqlmap; import java.util.Iterator; import java.util.List; import org.dom4j.Attribute; import org.dom4j.Element; import org.dom4j.Node; import darks.orm.app.QueryEnumType; import darks.orm.core.aspect.jython.PythonBuilder; import darks.orm.core.data.tags.AbstractTag; import darks.orm.core.data.tags.RootTag; import darks.orm.core.data.tags.TagsFactory; import darks.orm.core.data.tags.impl.TextTag; import darks.orm.core.data.xml.AspectData; import darks.orm.core.data.xml.AspectData.AspectType; import darks.orm.core.data.xml.DMLData; import darks.orm.core.data.xml.DMLData.DMLType; import darks.orm.core.data.xml.DMLQueryData; import darks.orm.core.data.xml.DMLQueryData.DMLQueryDataType; import darks.orm.core.data.xml.DMLUpdateData; import darks.orm.core.factory.TransformFactory; import darks.orm.exceptions.ConfigException; import darks.orm.log.Logger; import darks.orm.log.LoggerFactory; import darks.orm.util.StringHelper; @SuppressWarnings("unchecked") public class DMLConfigReader { private static final Logger logger = LoggerFactory.getLogger(DMLConfigReader.class); private SqlMapConfiguration sqlMapConfig; public DMLConfigReader(SqlMapConfiguration sqlMapConfig) { this.sqlMapConfig = sqlMapConfig; } /** * Read sqlmap DML xml element * * @param element Xml element */ public void reader(Element element) { String namesp = element.attributeValue("namespace"); if (namesp == null) namesp = ""; try { for (Iterator<Element> it = element.elementIterator(); it.hasNext();) { Element el = it.next(); String name = el.getName().trim(); if ("Query".equalsIgnoreCase(name)) { readQuery(el, namesp); } else if ("Update".equalsIgnoreCase(name)) { readUpdate(el, namesp); } else if ("tag".equalsIgnoreCase(name)) { readTag(el, namesp); } } } catch (Exception e) { throw new ConfigException(e.getMessage(), e); } } /** * Read and parse extern tags * * @param element tag element * @param namesp namespace * @throws Exception */ private void readTag(Element element, String namesp) throws Exception { String id = element.attributeValue("id"); if (id == null || "".equals(id.trim())) { return; } RootTag rootTag = new RootTag(); if (!"".equals(namesp)) { if (!namesp.endsWith(".")) namesp += "."; } parseSqlTag(rootTag, element, namesp); sqlMapConfig.addTag(namesp + id, rootTag); } /** * Read and parse query tags * * @param element Query tag element * @param namesp namespace * @throws Exception */ private DMLData readQuery(Element element, String namesp) throws Exception { if (!"".equals(namesp)) { if (!namesp.endsWith(".")) namesp += "."; } DMLData dmlData = new DMLData(); dmlData.setType(DMLType.Query); DMLQueryData queryData = new DMLQueryData(); queryData.setQueryType(QueryEnumType.Auto); queryData.setAutoCascade(true); dmlData.setQueryData(queryData); try { for (Iterator<Attribute> it = element.attributeIterator(); it.hasNext();) { Attribute attr = it.next(); readQueryAttribute(attr, dmlData, queryData); } } catch (Exception e) { throw new ConfigException(e.getMessage(), e); } if (queryData.getResultClass() == null) { throw new ConfigException("Sqlmap query " + dmlData.getId() + " loss result class config"); } if (dmlData.getId() == null) return null; RootTag rootTag = new RootTag(); parseSqlTag(rootTag, element, namesp); dmlData.setSqlTag(rootTag); String sql = element.getTextTrim(); if (sql != null && !"".equals(sql)) { queryData.setQueryDataType(DMLQueryDataType.Simple); queryData.setSQL(sql); } else { if (!readConstitute(element, queryData)) { if (!readSelect(element, queryData, "")) { return null; } } } AspectData aspectData = parseAspectXml(element); queryData.setAspectData(aspectData); sqlMapConfig.addDMLData(namesp + dmlData.getId(), dmlData); return dmlData; } private void readQueryAttribute(Attribute attr, DMLData dmlData, DMLQueryData queryData) throws Exception { String name = attr.getName().trim(); String value = attr.getValue().trim(); if ("id".equalsIgnoreCase(name)) { dmlData.setId(value); } else if ("resultType".equalsIgnoreCase(name)) { queryData.setResultType(value); Class<?> cls = TransformFactory.getInstance().stringToEntityClass(value); if (cls == null) { throw new ConfigException(value + " does not exists"); } queryData.setResultClass(cls); } else if ("autoCascade".equalsIgnoreCase(name)) { if ("true".equalsIgnoreCase(value)) queryData.setAutoCascade(true); else if ("false".equalsIgnoreCase(value)) queryData.setAutoCascade(false); } else if ("alias".equalsIgnoreCase(name)) { queryData.setAlias(value); } else if ("attribute".equalsIgnoreCase(name)) { queryData.setAttribute(value); } else if ("queryType".equalsIgnoreCase(name)) { if ("object".equalsIgnoreCase(value)) queryData.setQueryType(QueryEnumType.Object); else if ("list".equalsIgnoreCase(value)) queryData.setQueryType(QueryEnumType.List); else if ("page".equalsIgnoreCase(value)) queryData.setQueryType(QueryEnumType.Page); else queryData.setQueryType(QueryEnumType.Auto); } else if ("cache".equalsIgnoreCase(name)) { if ("auto".equalsIgnoreCase(value)) dmlData.setAutoCache(true); else if ("manual".equalsIgnoreCase(value)) dmlData.setAutoCache(false); } else if ("cacheId".equalsIgnoreCase(name)) { dmlData.setCacheId(value); } else if ("values".equalsIgnoreCase(name)) { queryData.setValuesParam(StringHelper.parseParamFlag(value)); } else if ("page".equalsIgnoreCase(name)) { queryData.setPageParam(StringHelper.parseParamFlag(value)); } else if ("pageSize".equalsIgnoreCase(name)) { queryData.setPageSizeParam(StringHelper.parseParamFlag(value)); } } /** * Read constitute query * * @param element query element * @param queryData Query data * @return If success, return true */ private boolean readConstitute(Element element, DMLQueryData queryData) { queryData.setQueryDataType(DMLQueryDataType.Constitute); Element queryElement = element.element("query"); Element cstElement = element.element("constitute"); if (queryElement == null || cstElement == null) return false; String sql = queryElement.getTextTrim(); if (sql == null || "".equals(sql)) return false; queryData.setSQL(sql); List<Element> items = cstElement.elements("item"); for (Element item : items) { String value = item.attributeValue("value"); if (value == null || "".equals(value)) continue; String exsql = item.getTextTrim(); if (exsql == null) exsql = ""; queryData.addSQL(value, exsql); } return true; } /** * Read select query * * @param element query element * @param queryData Query data * @param pVal Parent values * @return If success, return true */ private boolean readSelect(Element element, DMLQueryData queryData, String pVal) { queryData.setQueryDataType(DMLQueryDataType.Select); List<Element> selects = element.elements("select"); if (selects == null || selects.size() == 0) return false; for (Element sel : selects) { String value = sel.attributeValue("value"); if (value == null || "".equals(value)) continue; List<Element> chsel = sel.elements("select"); if (chsel.size() > 0) { readSelect(sel, queryData, pVal + value + "@"); } else { String sql = sel.getTextTrim(); String key = pVal + value; if (key.endsWith("@")) { key = key.substring(0, key.length() - 1); } queryData.addSQL(key, sql); } } return true; } /** * Read and parse update tags * * @param element Update tag * @param namesp namespace * @throws Exception */ private DMLData readUpdate(Element element, String namesp) throws Exception { if (!"".equals(namesp)) { if (!namesp.endsWith(".")) namesp += "."; } DMLData dmlData = new DMLData(); String sql = element.getTextTrim(); dmlData.setType(DMLType.Update); DMLUpdateData updateData = new DMLUpdateData(); RootTag rootTag = new RootTag(); parseSqlTag(rootTag, element, namesp); dmlData.setSqlTag(rootTag); updateData.setSql(sql); for (Iterator<Attribute> it = element.attributeIterator(); it.hasNext();) { try { Attribute at = it.next(); String name = at.getName().trim(); String value = at.getValue().trim(); if ("id".equalsIgnoreCase(name)) { dmlData.setId(value); } } catch (Exception e) { logger.error(e.getMessage(), e); } } if (dmlData.getId() == null) return null; AspectData aspectData = parseAspectXml(element); updateData.setAspectData(aspectData); dmlData.setUpdateData(updateData); sqlMapConfig.addDMLData(namesp + dmlData.getId(), dmlData); return dmlData; } /** * Read and parse aspect XMLs file * * @param element Aspect tags * @return Aspect data */ private AspectData parseAspectXml(Element element) { Element aspectEl = element.element("aspect"); if (aspectEl == null) return null; AspectData aspectData = new AspectData(); boolean isNext = false; Element jythonEl = aspectEl.element("jython"); if (jythonEl != null) { aspectData.setAspectType(AspectType.JYTHON); Attribute attr = jythonEl.attribute("className"); if (attr == null) return null; aspectData.setClassName(attr.getValue().trim()); String text = jythonEl.getText(); if (text == null || "".equals(text.trim())) { String before = jythonEl.elementText("before"); String after = jythonEl.elementText("after"); if (before == null || "".equals(before.trim())) { if (after == null || "".equals(after.trim())) return null; } text = PythonBuilder.buildBody(aspectData.getClassName(), before, after); } aspectData.setContent(text); isNext = true; } Element pyfileEl = aspectEl.element("pyfile"); if (pyfileEl != null && isNext == false) { aspectData.setAspectType(AspectType.PYFILE); Attribute attr = pyfileEl.attribute("className"); if (attr == null) return null; aspectData.setClassName(attr.getValue().trim()); aspectData.setContent(pyfileEl.getTextTrim()); isNext = true; } Element javaClassEl = aspectEl.element("javaClass"); if (javaClassEl != null && isNext == false) { aspectData.setAspectType(AspectType.JAVACLASS); aspectData.setClassName(javaClassEl.getTextTrim()); isNext = true; } Element jsEl = aspectEl.element("javascript"); if (jsEl != null && isNext == false) { aspectData.setAspectType(AspectType.JAVASCRIPT); aspectData.setContent(jsEl.getTextTrim()); isNext = true; } Element jsfileEl = aspectEl.element("jsfile"); if (jsfileEl != null && isNext == false) { aspectData.setAspectType(AspectType.JSFILE); aspectData.setContent(jsfileEl.getTextTrim()); isNext = true; } if (isNext) { return aspectData; } return null; } private void parseSqlTag(AbstractTag parent, Element el, String namesp) throws Exception { AbstractTag prevTag = null; List<Node> list = el.content(); Iterator<Node> it = list.iterator(); while (it.hasNext()) { Node node = it.next(); switch (node.getNodeType()) { case Node.ELEMENT_NODE: Element childEl = (Element) node; prevTag = parseElementTag(parent, node, childEl, namesp, prevTag); break; case Node.CDATA_SECTION_NODE: case Node.TEXT_NODE: String text = node.getText().replaceAll("\n|\t", " ").trim(); if (!"".equals(text)) { TextTag tag = new TextTag(text, prevTag); parent.addChild(tag); prevTag = tag; } break; } } } private AbstractTag parseElementTag(AbstractTag parent, Node node, Element childEl, String namesp, AbstractTag prevTag) throws Exception { if ("include".equals(node.getName())) { String id = childEl.attributeValue("refid"); if (id.indexOf(".") < 0) { id = namesp + id; } AbstractTag externTag = sqlMapConfig.getTag(id); if (externTag != null) { prevTag = externTag; parent.addChild(externTag); } } else { AbstractTag childTag = TagsFactory.createTag(childEl, prevTag); if (childTag != null) { if (childTag.parseElement(childEl)) { prevTag = childTag; parent.addChild(childTag); parseSqlTag(childTag, childEl, namesp); } } } return prevTag; } public SqlMapConfiguration getSqlMapConfig() { return sqlMapConfig; } public void setSqlMapConfig(SqlMapConfiguration sqlMapConfig) { this.sqlMapConfig = sqlMapConfig; } }