ActionExecuteV2.java 10.9 KB
Newer Older
O
o2sword 已提交
1 2
package com.x.query.assemble.designer.jaxrs.statement;

3
import java.util.ArrayList;
O
o2null 已提交
4 5 6 7 8 9 10
import java.util.List;
import java.util.Objects;

import javax.persistence.EntityManager;
import javax.persistence.Parameter;
import javax.persistence.Query;
import javax.script.Bindings;
11
import javax.script.CompiledScript;
O
o2null 已提交
12 13 14 15
import javax.script.ScriptContext;

import org.apache.commons.lang3.StringUtils;

O
o2sword 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28
import com.google.gson.JsonElement;
import com.x.base.core.container.EntityManagerContainer;
import com.x.base.core.container.factory.EntityManagerContainerFactory;
import com.x.base.core.entity.JpaObject;
import com.x.base.core.entity.dynamic.DynamicBaseEntity;
import com.x.base.core.entity.dynamic.DynamicEntity;
import com.x.base.core.project.exception.ExceptionAccessDenied;
import com.x.base.core.project.exception.ExceptionEntityNotExist;
import com.x.base.core.project.http.ActionResult;
import com.x.base.core.project.http.EffectivePerson;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.script.AbstractResources;
29 30
import com.x.base.core.project.scripting.JsonScriptingExecutor;
import com.x.base.core.project.scripting.ScriptingFactory;
O
o2sword 已提交
31
import com.x.base.core.project.tools.ListTools;
O
o2sword 已提交
32 33 34 35 36 37 38 39 40 41
import com.x.base.core.project.webservices.WebservicesClient;
import com.x.organization.core.express.Organization;
import com.x.query.assemble.designer.Business;
import com.x.query.assemble.designer.ThisApplication;
import com.x.query.core.entity.schema.Statement;
import com.x.query.core.entity.schema.Table;
import com.x.query.core.express.statement.Runtime;

class ActionExecuteV2 extends BaseAction {

42
	private static final Logger LOGGER = LoggerFactory.getLogger(ActionExecuteV2.class);
O
o2sword 已提交
43

44 45 46
	private static final String[] pageKeys = { "GROUP BY", " COUNT(" };
	private static final String JOIN_KEY = " JOIN ";
	private static final String JOIN_ON_KEY = " ON ";
O
o2sword 已提交
47

O
o2sword 已提交
48 49 50
	ActionResult<Object> execute(EffectivePerson effectivePerson, String flag, String mode, Integer page, Integer size,
			JsonElement jsonElement) throws Exception {

R
Ray 已提交
51 52 53 54 55
		LOGGER.debug("execute:{}, flag:{}, page:{}, size:{}.", effectivePerson::getDistinguishedName, () -> flag,
				() -> page, () -> size);
		ClassLoader classLoader = Business.getDynamicEntityClassLoader();
		Thread.currentThread().setContextClassLoader(classLoader);

O
o2sword 已提交
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
			ActionResult<Object> result = new ActionResult<>();
			Business business = new Business(emc);
			Statement statement = emc.flag(flag, Statement.class);
			if (null == statement) {
				throw new ExceptionEntityNotExist(flag, Statement.class);
			}
			if (!business.executable(effectivePerson, statement)) {
				throw new ExceptionAccessDenied(effectivePerson, statement);
			}

			Runtime runtime = this.runtime(effectivePerson, jsonElement, business, page, size);

			Object data = null;
			Object count = null;
71 72 73 74
			switch (mode) {
			case Statement.MODE_DATA:
				switch (Objects.toString(statement.getFormat(), "")) {
				case Statement.FORMAT_SCRIPT:
R
Ray 已提交
75
					data = this.script(effectivePerson, business, classLoader, statement, runtime, mode);
O
o2sword 已提交
76
					break;
77
				default:
R
Ray 已提交
78
					data = this.jpql(business, classLoader, statement, runtime, mode);
79 80 81 82 83 84 85
					break;
				}
				result.setData(data);
				break;
			case Statement.MODE_COUNT:
				switch (Objects.toString(statement.getFormat(), "")) {
				case Statement.FORMAT_SCRIPT:
R
Ray 已提交
86
					count = this.script(effectivePerson, business, classLoader, statement, runtime, mode);
87 88
					break;
				default:
R
Ray 已提交
89
					count = this.jpql(business, classLoader, statement, runtime, mode);
90 91 92 93 94 95 96 97
					break;
				}
				result.setData(count);
				result.setCount((Long) count);
				break;
			default:
				switch (Objects.toString(statement.getFormat(), "")) {
				case Statement.FORMAT_SCRIPT:
R
Ray 已提交
98 99 100
					data = this.script(effectivePerson, business, classLoader, statement, runtime, Statement.MODE_DATA);
					count = this.script(effectivePerson, business, classLoader, statement, runtime,
							Statement.MODE_COUNT);
O
o2sword 已提交
101 102
					break;
				default:
R
Ray 已提交
103 104
					data = this.jpql(business, classLoader, statement, runtime, Statement.MODE_DATA);
					count = this.jpql(business, classLoader, statement, runtime, Statement.MODE_COUNT);
105 106 107 108
					break;
				}
				result.setData(data);
				result.setCount((Long) count);
O
o2sword 已提交
109 110 111 112 113
			}
			return result;
		}
	}

R
Ray 已提交
114 115
	private Object script(EffectivePerson effectivePerson, Business business, ClassLoader classLoader,
			Statement statement, Runtime runtime, String mode) throws Exception {
O
o2sword 已提交
116
		Object data = null;
117
		ScriptContext scriptContext = this.scriptContext(effectivePerson, runtime);
O
o2sword 已提交
118
		String scriptText = statement.getScriptText();
119
		if (Statement.MODE_COUNT.equals(mode)) {
O
o2sword 已提交
120 121
			scriptText = statement.getCountScriptText();
		}
122 123
		CompiledScript cs = ScriptingFactory.functionalizationCompile(scriptText);
		String jpql = JsonScriptingExecutor.evalString(cs, scriptContext);
R
Ray 已提交
124
		Class<? extends JpaObject> cls = this.clazz(business, classLoader, statement);
O
o2sword 已提交
125
		EntityManager em;
126 127
		if (StringUtils.equalsIgnoreCase(statement.getEntityCategory(), Statement.ENTITYCATEGORY_DYNAMIC)
				&& StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
O
o2sword 已提交
128
			em = business.entityManagerContainer().get(DynamicBaseEntity.class);
129
		} else {
O
o2sword 已提交
130 131
			em = business.entityManagerContainer().get(cls);
		}
O
o2sword 已提交
132 133 134
		jpql = this.joinSql(jpql, business);
		Query query;
		String upJpql = jpql.toUpperCase();
R
Ray 已提交
135
		LOGGER.debug("script jpql:{}.", jpql);
136
		if (upJpql.indexOf(JOIN_KEY) > -1 && upJpql.indexOf(JOIN_ON_KEY) > -1) {
O
o2sword 已提交
137
			query = em.createNativeQuery(jpql);
138
		} else {
O
o2sword 已提交
139 140
			query = em.createQuery(jpql);
		}
O
o2sword 已提交
141 142 143 144 145 146
		for (Parameter<?> p : query.getParameters()) {
			if (runtime.hasParameter(p.getName())) {
				query.setParameter(p.getName(), runtime.getParameter(p.getName()));
			}
		}
		if (StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
147
			if (Statement.MODE_COUNT.equals(mode)) {
O
o2sword 已提交
148
				data = query.getSingleResult();
149 150
			} else {
				if (isPageSql(jpql)) {
151 152 153
					query.setFirstResult((runtime.page - 1) * runtime.size);
					query.setMaxResults(runtime.size);
				}
O
o2sword 已提交
154 155 156 157 158 159 160 161 162 163
				data = query.getResultList();
			}
		} else {
			business.entityManagerContainer().beginTransaction(cls);
			data = query.executeUpdate();
			business.entityManagerContainer().commit();
		}
		return data;
	}

R
Ray 已提交
164 165
	private Object jpql(Business business, ClassLoader classLoader, Statement statement, Runtime runtime, String mode)
			throws Exception {
O
o2sword 已提交
166
		Object data = null;
R
Ray 已提交
167
		Class<? extends JpaObject> cls = this.clazz(business, classLoader, statement);
O
o2sword 已提交
168
		EntityManager em;
169 170
		if (StringUtils.equalsIgnoreCase(statement.getEntityCategory(), Statement.ENTITYCATEGORY_DYNAMIC)
				&& StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
O
o2sword 已提交
171
			em = business.entityManagerContainer().get(DynamicBaseEntity.class);
172
		} else {
O
o2sword 已提交
173 174
			em = business.entityManagerContainer().get(cls);
		}
O
o2sword 已提交
175
		String jpql = statement.getData();
176
		if (Statement.MODE_COUNT.equals(mode)) {
O
o2sword 已提交
177 178 179 180 181
			jpql = statement.getCountData();
		}
		jpql = this.joinSql(jpql, business);
		Query query;
		String upJpql = jpql.toUpperCase();
R
Ray 已提交
182
		LOGGER.debug("jpql:{}.", jpql);
183
		if (upJpql.indexOf(JOIN_KEY) > -1 && upJpql.indexOf(JOIN_ON_KEY) > -1) {
O
o2sword 已提交
184
			query = em.createNativeQuery(jpql);
R
Ray 已提交
185
			if (runtime.getParameters().size() > 0) {
186
				List<Object> values = new ArrayList<>(runtime.getParameters().values());
R
Ray 已提交
187 188
				for (int i = 0; i < values.size(); i++) {
					query.setParameter(i + 1, values.get(i));
189 190
				}
			}
191
		} else {
O
o2sword 已提交
192
			query = em.createQuery(jpql);
O
o2sword 已提交
193 194 195 196 197 198 199
		}
		for (Parameter<?> p : query.getParameters()) {
			if (runtime.hasParameter(p.getName())) {
				query.setParameter(p.getName(), runtime.getParameter(p.getName()));
			}
		}
		if (StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
200
			if (Statement.MODE_COUNT.equals(mode)) {
O
o2sword 已提交
201
				data = query.getSingleResult();
202 203
			} else {
				if (isPageSql(jpql)) {
204 205 206
					query.setFirstResult((runtime.page - 1) * runtime.size);
					query.setMaxResults(runtime.size);
				}
O
o2sword 已提交
207 208 209 210 211 212 213 214 215 216
				data = query.getResultList();
			}
		} else {
			business.entityManagerContainer().beginTransaction(cls);
			data = Integer.valueOf(query.executeUpdate());
			business.entityManagerContainer().commit();
		}
		return data;
	}

217
	private boolean isPageSql(String sql) {
218 219 220 221 222 223 224 225 226
		sql = sql.toUpperCase().replaceAll("\\s{1,}", " ");
		for (String key : pageKeys) {
			if (sql.indexOf(key) > -1) {
				return false;
			}
		}
		return true;
	}

R
Ray 已提交
227 228 229
	@SuppressWarnings("unchecked")
	private Class<? extends JpaObject> clazz(Business business, ClassLoader classLoader, Statement statement)
			throws Exception {
O
o2sword 已提交
230 231 232
		Class<? extends JpaObject> cls = null;
		if (StringUtils.equals(Statement.ENTITYCATEGORY_OFFICIAL, statement.getEntityCategory())
				|| StringUtils.equals(Statement.ENTITYCATEGORY_CUSTOM, statement.getEntityCategory())) {
R
Ray 已提交
233
			cls = (Class<? extends JpaObject>) classLoader.loadClass(statement.getEntityClassName());
O
o2sword 已提交
234 235 236 237 238 239
		} else {
			Table table = business.entityManagerContainer().flag(statement.getTable(), Table.class);
			if (null == table) {
				throw new ExceptionEntityNotExist(statement.getTable(), Table.class);
			}
			DynamicEntity dynamicEntity = new DynamicEntity(table.getName());
R
Ray 已提交
240
			cls = (Class<? extends JpaObject>) classLoader.loadClass(dynamicEntity.className());
O
o2sword 已提交
241 242 243 244
		}
		return cls;
	}

245 246
	private ScriptContext scriptContext(EffectivePerson effectivePerson, Runtime runtime) throws Exception {
		ScriptContext scriptContext = ScriptingFactory.scriptContextEvalInitialServiceScript();
O
o2sword 已提交
247 248 249 250 251 252
		Resources resources = new Resources();
		resources.setContext(ThisApplication.context());
		resources.setApplications(ThisApplication.context().applications());
		resources.setWebservicesClient(new WebservicesClient());
		resources.setOrganization(new Organization(ThisApplication.context()));
		Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
R
Ray 已提交
253 254 255
		bindings.put(ScriptingFactory.BINDING_NAME_SERVICE_RESOURCES, resources);
		bindings.put(ScriptingFactory.BINDING_NAME_SERVICE_EFFECTIVEPERSON, effectivePerson);
		bindings.put(ScriptingFactory.BINDING_NAME_SERVICE_PARAMETERS, gson.toJson(runtime.getParameters()));
O
o2sword 已提交
256 257 258
		return scriptContext;
	}

259
	private String joinSql(String sql, Business business) throws Exception {
O
o2sword 已提交
260
		String upSql = sql.toUpperCase();
261
		if (upSql.indexOf(JOIN_KEY) > -1 && upSql.indexOf(JOIN_ON_KEY) > -1) {
O
o2sword 已提交
262 263
			sql = sql.replaceAll("\\.", ".x");
			sql = sql.replaceAll("\\.x\\*", ".*");
264 265 266 267 268
			List<Table> tables = business.entityManagerContainer().fetchEqual(Table.class,
					ListTools.toList(Table.name_FIELDNAME), Table.status_FIELDNAME, Table.STATUS_build);
			for (Table table : tables) {
				sql = sql.replaceAll(" " + table.getName() + " ",
						" " + DynamicEntity.TABLE_PREFIX + table.getName().toUpperCase() + " ");
O
o2sword 已提交
269 270 271 272 273
			}
		}
		return sql;
	}

O
o2sword 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287
	public static class Resources extends AbstractResources {

		private Organization organization;

		public Organization getOrganization() {
			return organization;
		}

		public void setOrganization(Organization organization) {
			this.organization = organization;
		}

	}

288
}