package com.freetmp.mbg.plugin.page;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Element;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import java.util.ArrayList;
import java.util.List;
/**
* Created by LiuPin on 2015/2/4.
*/
public class SQLServerPaginationPlugin extends AbstractPaginationPlugin {
int findElementIndex(List<Element> elements, String name, String key, String value) {
int index = -1;
for (int i = 0; i < elements.size(); i++) {
Element element = elements.get(i);
if (element instanceof XmlElement) {
XmlElement xe = (XmlElement) element;
if (matched(xe, name, key, value)) {
index = i;
break;
}
}
}
return index;
}
boolean matched(XmlElement element, String name, String key, String value) {
if (element == null) return false;
if (name.trim().equals(element.getName().trim())) {
List<Attribute> attributes = element.getAttributes();
if (attributes != null) {
for (Attribute attribute : attributes) {
if (StringUtils.equals(attribute.getName().trim(), key.trim())
&& StringUtils.equals(attribute.getValue().trim(), value.trim())) {
return true;
}
}
}
}
return false;
}
Element findElement(List<Element> elements, String name, String key, String value) {
int index = findElementIndex(elements, name, key, value);
Element element = elements.get(index);
return element;
}
@Override
public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
XmlElement orderBy = (XmlElement) findElement(element.getElements(), "if", "test", "orderByClause != null");
XmlElement baseColumnList = (XmlElement) findElement(element.getElements(), "include", "refid", introspectedTable.getBaseColumnListId());
XmlElement prefix = buildPrefix(baseColumnList);
XmlElement inner = buildInner(orderBy, introspectedTable);
XmlElement suffix = buildSuffix(orderBy);
List<Element> elements = element.getElements();
List<Element> newElements = new ArrayList<>();
newElements.add(prefix);
for (Element e : elements) {
if(e != orderBy) {
newElements.add(e);
if( e == baseColumnList){
newElements.add(inner);
}
}
}
newElements.add(suffix);
elements.clear();
elements.addAll(newElements);
return true;
}
private XmlElement buildInner(XmlElement orderBy, IntrospectedTable introspectedTable) {
// generate order by clause, first check if user provided order by clause, if provided just use it
// otherwise use the default primary key for order by clause
XmlElement newOrderBy = new XmlElement("choose");
XmlElement when = new XmlElement("when");
when.addAttribute(new Attribute("test", "orderByClause != null"));
for (Element e : orderBy.getElements()) {
when.addElement(e);
}
newOrderBy.addElement(when);
XmlElement otherwise = new XmlElement("otherwise");
StringBuilder sb = new StringBuilder();
sb.append(" order by ");
List<IntrospectedColumn> columns = introspectedTable.getPrimaryKeyColumns();
for (IntrospectedColumn column : columns) {
sb.append(MyBatis3FormattingUtilities.getAliasedEscapedColumnName(column)).append(", ");
}
sb.setLength(sb.length() - 2);
otherwise.addElement(new TextElement(sb.toString()));
newOrderBy.addElement(otherwise);
XmlElement inner = new XmlElement("if");
inner.addAttribute(new Attribute("test", "limit != null and limit>=0 and offset != null"));
inner.addElement(new TextElement(" , ROW_NUMBER() over ( "));
inner.addElement(newOrderBy);
inner.addElement(new TextElement(" ) as row_num "));
return inner;
}
private XmlElement buildSuffix(XmlElement orderBy) {
XmlElement suffix = new XmlElement("choose");
XmlElement when = new XmlElement("when");
when.addAttribute(new Attribute("test", "limit != null and limit>=0 and offset != null"));
when.addElement(new TextElement(" ) as tmp where tmp.row_num between #{offset} and #{limit} + #{offset} order by row_num"));
suffix.addElement(when);
XmlElement otherwise = new XmlElement("otherwise");
otherwise.addElement(orderBy);
suffix.addElement(otherwise);
return suffix;
}
private XmlElement buildPrefix(XmlElement baseColumnList) {
XmlElement prefix = new XmlElement("if");
prefix.addAttribute(new Attribute("test", "limit != null and limit>=0 and offset != null"));
prefix.addElement(new TextElement("select "));
prefix.addElement(baseColumnList);
prefix.addElement(new TextElement(" from ( "));
return prefix;
}
}