Просмотр исходного кода

Merge branch 'feature/增加组织和群组查询接口' into 'develop'

[人员组织]增加组织和群组查询接口

See merge request o2oa/o2oa!1649
o2null 5 лет назад
Родитель
Сommit
b29a906aba

+ 10 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/factory/IdentityFactory.java

@@ -159,4 +159,14 @@ public class IdentityFactory extends AbstractFactory {
 		return list;
 		return list;
 	}
 	}
 
 
+	public Long countByUnit(String unitId) throws Exception {
+		EntityManager em = this.entityManagerContainer().get(Identity.class);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<Long> cq = cb.createQuery(Long.class);
+		Root<Identity> root = cq.from(Identity.class);
+		Predicate p = cb.equal(root.get(Identity_.unit), unitId);
+		Long count = em.createQuery(cq.select(cb.count(root)).where(p)).getSingleResult();
+		return count;
+	}
+
 }
 }

+ 224 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/group/ActionListWithGroupTree.java

@@ -0,0 +1,224 @@
+package com.x.organization.assemble.express.jaxrs.group;
+
+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.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.organization.assemble.express.Business;
+import com.x.organization.core.entity.Group;
+import com.x.organization.core.entity.Unit;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class ActionListWithGroupTree extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			ActionResult<List<Wo>> result = new ActionResult<>();
+			Business business = new Business(emc);
+			CacheKey cacheKey = new CacheKey(this.getClass(), wi.getGroupList());
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				result.setData((List<Wo>) optional.get());
+			} else {
+				List<Wo> wos = this.list(business, wi);
+				CacheManager.put(cacheCategory, cacheKey, wos);
+				result.setData(wos);
+			}
+			return result;
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("群组")
+		private List<String> groupList = new ArrayList<>();
+
+		public List<String> getGroupList() {
+			return groupList;
+		}
+
+		public void setGroupList(List<String> groupList) {
+			this.groupList = groupList;
+		}
+
+	}
+
+	public static class Wo extends Group {
+
+		private static final long serialVersionUID = -4928566515131577808L;
+
+		static WrapCopier<Group, Wo> copier = WrapCopierFactory.wo(Group.class, Wo.class, ListTools.toList(Group.id_FIELDNAME, Group.distinguishedName_FIELDNAME),
+				null);
+
+		@FieldDescribe("直接下级组织数量")
+		private Long subDirectGroupCount = 0L;
+
+		@FieldDescribe("直接下级用户数量")
+		private Long subDirectPersonCount = 0L;
+
+		@FieldDescribe("直接下级身份数量")
+		private Long subDirectIdentityCount = 0L;
+
+		@FieldDescribe("直接下级组织数量")
+		private Long subDirectOrgCount = 0L;
+
+		@FieldDescribe("直接下级组织")
+		private List<WoUnit> subUnits = new ArrayList<>();
+
+		@FieldDescribe("直接下级群组")
+		private List<Wo> subGroups = new ArrayList<>();
+
+		public List<Wo> getSubGroups() {
+			return subGroups;
+		}
+
+		public void setSubGroups(List<Wo> subGroups) {
+			this.subGroups = subGroups;
+		}
+
+		public Long getSubDirectGroupCount() {
+			return subDirectGroupCount;
+		}
+
+		public void setSubDirectGroupCount(Long subDirectGroupCount) {
+			this.subDirectGroupCount = subDirectGroupCount;
+		}
+
+		public Long getSubDirectPersonCount() {
+			return subDirectPersonCount;
+		}
+
+		public void setSubDirectPersonCount(Long subDirectPersonCount) {
+			this.subDirectPersonCount = subDirectPersonCount;
+		}
+
+		public Long getSubDirectIdentityCount() {
+			return subDirectIdentityCount;
+		}
+
+		public void setSubDirectIdentityCount(Long subDirectIdentityCount) {
+			this.subDirectIdentityCount = subDirectIdentityCount;
+		}
+
+		public Long getSubDirectOrgCount() {
+			return subDirectOrgCount;
+		}
+
+		public void setSubDirectOrgCount(Long subDirectOrgCount) {
+			this.subDirectOrgCount = subDirectOrgCount;
+		}
+
+		public List<WoUnit> getSubUnits() {
+			return subUnits;
+		}
+
+		public void setSubUnits(List<WoUnit> subUnits) {
+			this.subUnits = subUnits;
+		}
+	}
+
+	public static class WoUnit extends Unit {
+
+		private static final long serialVersionUID = -5469947686711876763L;
+
+		static WrapCopier<Unit, WoUnit> copier = WrapCopierFactory.wo(Unit.class, WoUnit.class,
+				ListTools.toList(Unit.id_FIELDNAME, Unit.distinguishedName_FIELDNAME, Unit.levelName_FIELDNAME),
+				null);
+
+		@FieldDescribe("直接下级身份成员数量")
+		private Long subDirectUnitCount = 0L;
+
+		@FieldDescribe("直接下级组织数量")
+		private Long subDirectIdentityCount = 0L;
+
+		@FieldDescribe("直接下级组织")
+		private List<WoUnit> subUnits = new ArrayList<>();
+
+		public Long getSubDirectUnitCount() {
+			return subDirectUnitCount;
+		}
+
+		public void setSubDirectUnitCount(Long subDirectUnitCount) {
+			this.subDirectUnitCount = subDirectUnitCount;
+		}
+
+		public Long getSubDirectIdentityCount() {
+			return subDirectIdentityCount;
+		}
+
+		public void setSubDirectIdentityCount(Long subDirectIdentityCount) {
+			this.subDirectIdentityCount = subDirectIdentityCount;
+		}
+
+		public List<WoUnit> getSubUnits() {
+			return subUnits;
+		}
+
+		public void setSubUnits(List<WoUnit> subUnits) {
+			this.subUnits = subUnits;
+		}
+	}
+
+	private List<Wo> list(Business business, Wi wi) throws Exception {
+		List<Group> os = business.group().pick(ListTools.trim(wi.getGroupList(), false, true));
+		List<Wo> wos = Wo.copier.copy(os);
+		Map<String, Wo> map = wos.stream().collect(Collectors.toMap(Wo::getId, Wo->Wo));
+		listSub(business, os, map);
+		return wos;
+	}
+
+	private void listSub(Business business, List<Group> groups, Map<String, Wo> groupMap) throws Exception {
+		for (Group group : groups){
+			Wo wo = groupMap.get(group.getId());
+			if(group.getGroupList()!=null && !group.getGroupList().isEmpty()){
+				List<Group> os = business.entityManagerContainer().list(Group.class, group.getGroupList());
+				List<Wo> wos = Wo.copier.copy(os);
+				Map<String, Wo> map = wos.stream().collect(Collectors.toMap(Wo::getId, Wo->Wo));
+				listSub(business, os, map);
+				wo.setSubGroups(wos);
+				wo.setSubDirectGroupCount((long)wos.size());
+			}
+			if(group.getUnitList()!=null && !group.getUnitList().isEmpty()){
+				List<Unit> os = business.unit().pick(group.getUnitList());
+				List<WoUnit> wos = WoUnit.copier.copy(os);
+				Map<String, WoUnit> map = wos.stream().collect(Collectors.toMap(WoUnit::getId, WoUnit->WoUnit));
+				listSubUnit(business, os, map);
+				wo.setSubUnits(wos);
+				wo.setSubDirectOrgCount((long)wos.size());
+			}
+			wo.setSubDirectIdentityCount((long)group.getIdentityList().size());
+			wo.setSubDirectPersonCount((long)group.getPersonList().size());
+
+		}
+	}
+
+	private void listSubUnit(Business business, List<Unit> units, Map<String, WoUnit> unitMap) throws Exception {
+		for (Unit unit : units){
+			WoUnit woUnit = unitMap.get(unit.getId());
+			List<Unit> os = business.unit().listSubDirectObject(unit);
+			if(!os.isEmpty()){
+				List<WoUnit> wos = WoUnit.copier.copy(os);
+				Map<String, WoUnit> map = wos.stream().collect(Collectors.toMap(WoUnit::getId, WoUnit->WoUnit));
+				listSubUnit(business, os, map);
+				woUnit.setSubUnits(wos);
+				woUnit.setSubDirectUnitCount((long)wos.size());
+			}
+			woUnit.setSubDirectIdentityCount(business.identity().countByUnit(unit.getId()));
+		}
+	}
+
+}

+ 123 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/group/ActionListWithIdentity.java

@@ -0,0 +1,123 @@
+package com.x.organization.assemble.express.jaxrs.group;
+
+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.project.annotation.FieldDescribe;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.organization.assemble.express.Business;
+import com.x.organization.core.entity.Identity;
+import org.apache.commons.lang3.BooleanUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+class ActionListWithIdentity extends BaseAction {
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			CacheKey cacheKey = new CacheKey(this.getClass(), wi.getIdentityList(),
+					wi.getRecursiveGroupFlag(), wi.getReferenceFlag(), wi.getRecursiveOrgFlag());
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				result.setData((Wo) optional.get());
+			} else {
+				Wo wo = this.list(business, wi);
+				CacheManager.put(cacheCategory, cacheKey, wo);
+				result.setData(wo);
+			}
+			return result;
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("个人")
+		private List<String> identityList = new ArrayList<>();
+
+		@FieldDescribe("是否递归查询上级群组,默认true")
+		private Boolean recursiveGroupFlag = true;
+
+		@FieldDescribe("是否包含查找身份归属组织成员的所属群组,默认false")
+		private Boolean referenceFlag = false;
+
+		@FieldDescribe("是否递归身份归属组织的上级组织所属群组,前提referenceFlag为true,默认false")
+		private Boolean recursiveOrgFlag = false;
+
+		public List<String> getIdentityList() {
+			return identityList;
+		}
+
+		public void setIdentityList(List<String> identityList) {
+			this.identityList = identityList;
+		}
+
+		public Boolean getReferenceFlag() {
+			return referenceFlag;
+		}
+
+		public void setReferenceFlag(Boolean referenceFlag) {
+			this.referenceFlag = referenceFlag;
+		}
+
+		public Boolean getRecursiveGroupFlag() {
+			return recursiveGroupFlag;
+		}
+
+		public void setRecursiveGroupFlag(Boolean recursiveGroupFlag) {
+			this.recursiveGroupFlag = recursiveGroupFlag;
+		}
+
+		public Boolean getRecursiveOrgFlag() {
+			return recursiveOrgFlag;
+		}
+
+		public void setRecursiveOrgFlag(Boolean recursiveOrgFlag) {
+			this.recursiveOrgFlag = recursiveOrgFlag;
+		}
+	}
+
+	public static class Wo extends WoGroupAbstract {
+
+	}
+
+	private Wo list(Business business, Wi wi) throws Exception {
+		List<Identity> os = business.identity().pick(wi.getIdentityList());
+		List<String> groupIds = new ArrayList<>();
+		for (Identity identity : os) {
+			groupIds.addAll(business.group().listSupDirectWithIdentity(identity.getId()));
+			if (BooleanUtils.isTrue(wi.getReferenceFlag())) {
+				groupIds.addAll(business.group().listSupDirectWithUnit(identity.getUnit()));
+				if (BooleanUtils.isTrue(wi.getRecursiveOrgFlag())) {
+					List<String> orgIds = business.unit().listSupNested(identity.getUnit());
+					for (String orgId : orgIds) {
+						groupIds.addAll(business.group().listSupDirectWithUnit(orgId));
+					}
+				}
+			}
+		}
+		groupIds = ListTools.trim(groupIds, true, true);
+		List<String> groupIds2 = new ArrayList<>();
+		groupIds2.addAll(groupIds);
+		if (!BooleanUtils.isFalse(wi.getRecursiveGroupFlag())) {
+			for (String groupId : groupIds) {
+				groupIds2.addAll(business.group().listSupNested(groupId));
+			}
+			groupIds2 = ListTools.trim(groupIds2, true, true);
+		}
+		List<String> values = business.group().listGroupDistinguishedNameSorted(groupIds2);
+		Wo wo = new Wo();
+		wo.getGroupList().addAll(values);
+		return wo;
+	}
+
+}

+ 129 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/group/ActionListWithIdentityObject.java

@@ -0,0 +1,129 @@
+package com.x.organization.assemble.express.jaxrs.group;
+
+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.project.annotation.FieldDescribe;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.organization.assemble.express.Business;
+import com.x.organization.core.entity.Group;
+import com.x.organization.core.entity.Identity;
+import org.apache.commons.lang3.BooleanUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+class ActionListWithIdentityObject extends BaseAction {
+
+	@SuppressWarnings("unchecked")
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			ActionResult<List<Wo>> result = new ActionResult<>();
+			Business business = new Business(emc);
+			CacheKey cacheKey = new CacheKey(this.getClass(),  wi.getIdentityList() ,
+					wi.getRecursiveGroupFlag(), wi.getReferenceFlag(), wi.getRecursiveOrgFlag());
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				result.setData((List<Wo>) optional.get());
+			} else {
+				List<Wo> wos = this.list(business, wi);
+				CacheManager.put(cacheCategory, cacheKey, wos);
+				result.setData(wos);
+			}
+			return result;
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("身份")
+		private List<String> identityList = new ArrayList<>();
+
+		@FieldDescribe("是否递归查询上级群组,默认true")
+		private Boolean recursiveGroupFlag = true;
+
+		@FieldDescribe("是否包含查找身份归属组织成员的所属群组,默认false")
+		private Boolean referenceFlag = false;
+
+		@FieldDescribe("是否递归身份归属组织的上级组织所属群组,前提referenceFlag为true,默认false")
+		private Boolean recursiveOrgFlag = false;
+
+		public List<String> getIdentityList() {
+			return identityList;
+		}
+
+		public void setIdentityList(List<String> identityList) {
+			this.identityList = identityList;
+		}
+
+		public Boolean getReferenceFlag() {
+			return referenceFlag;
+		}
+
+		public void setReferenceFlag(Boolean referenceFlag) {
+			this.referenceFlag = referenceFlag;
+		}
+
+		public Boolean getRecursiveGroupFlag() {
+			return recursiveGroupFlag;
+		}
+
+		public void setRecursiveGroupFlag(Boolean recursiveGroupFlag) {
+			this.recursiveGroupFlag = recursiveGroupFlag;
+		}
+
+		public Boolean getRecursiveOrgFlag() {
+			return recursiveOrgFlag;
+		}
+
+		public void setRecursiveOrgFlag(Boolean recursiveOrgFlag) {
+			this.recursiveOrgFlag = recursiveOrgFlag;
+		}
+	}
+
+	public static class Wo extends com.x.base.core.project.organization.Group {
+
+	}
+
+	private List<Wo> list(Business business, Wi wi) throws Exception {
+		List<Wo> wos = new ArrayList<>();
+		List<Identity> os = business.identity().pick(wi.getIdentityList());
+		List<String> groupIds = new ArrayList<>();
+		for (Identity identity : os) {
+			groupIds.addAll(business.group().listSupDirectWithIdentity(identity.getId()));
+			if (BooleanUtils.isTrue(wi.getReferenceFlag())) {
+				groupIds.addAll(business.group().listSupDirectWithUnit(identity.getUnit()));
+				if (BooleanUtils.isTrue(wi.getRecursiveOrgFlag())) {
+					List<String> orgIds = business.unit().listSupNested(identity.getUnit());
+					for (String orgId : orgIds) {
+						groupIds.addAll(business.group().listSupDirectWithUnit(orgId));
+					}
+				}
+			}
+		}
+		groupIds = ListTools.trim(groupIds, true, true);
+		List<String> groupIds2 = new ArrayList<>();
+		groupIds2.addAll(groupIds);
+		if (!BooleanUtils.isFalse(wi.getRecursiveGroupFlag())) {
+			for (String groupId : groupIds) {
+				groupIds2.addAll(business.group().listSupNested(groupId));
+			}
+			groupIds2 = ListTools.trim(groupIds2, true, true);
+		}
+
+		List<Group> list = business.group().pick(groupIds2);
+		list = business.group().sort(list);
+		for (Group o : list) {
+			wos.add(this.convert(business, o, Wo.class));
+		}
+		return wos;
+	}
+
+}

+ 54 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/group/GroupAction.java

@@ -263,4 +263,58 @@ public class GroupAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 	}
 
 
+	@JaxrsMethodDescribe(value = "批量查询人员身份所在的群组.", action = ActionListWithIdentity.class)
+	@POST
+	@Path("list/identity")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithIdentity(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+							   JsonElement jsonElement) {
+		ActionResult<ActionListWithIdentity.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithIdentity().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
+	@JaxrsMethodDescribe(value = "批量查询人员身份所在的群组对象.", action = ActionListWithIdentityObject.class)
+	@POST
+	@Path("list/identity/object")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithIdentityObject(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+									 JsonElement jsonElement) {
+		ActionResult<List<ActionListWithIdentityObject.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithIdentityObject().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
+	@JaxrsMethodDescribe(value = "批量查询群组的嵌套下级群组信息-树形模式.", action = ActionListWithGroupTree.class)
+	@POST
+	@Path("list/group/tree")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithGroupTree(@Suspended final AsyncResponse asyncResponse,
+											 @Context HttpServletRequest request, JsonElement jsonElement) {
+		ActionResult<List<ActionListWithGroupTree.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithGroupTree().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 }
 }

+ 131 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/unit/ActionListWithUnitTree.java

@@ -0,0 +1,131 @@
+package com.x.organization.assemble.express.jaxrs.unit;
+
+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.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.organization.assemble.express.Business;
+import com.x.organization.core.entity.Identity;
+import com.x.organization.core.entity.Identity_;
+import com.x.organization.core.entity.Unit;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class ActionListWithUnitTree extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			ActionResult<List<Wo>> result = new ActionResult<>();
+			Business business = new Business(emc);
+			CacheKey cacheKey = new CacheKey(this.getClass(), wi.getUnitList());
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				result.setData((List<Wo>) optional.get());
+			} else {
+				List<Wo> wos = this.list(business, wi);
+				CacheManager.put(cacheCategory, cacheKey, wos);
+				result.setData(wos);
+			}
+			return result;
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("组织")
+		private List<String> unitList;
+
+		public List<String> getUnitList() {
+			return unitList;
+		}
+
+		public void setUnitList(List<String> unitList) {
+			this.unitList = unitList;
+		}
+
+	}
+
+	public static class Wo extends Unit {
+
+		private static final long serialVersionUID = -1067995706582209831L;
+
+		static WrapCopier<Unit, Wo> copier = WrapCopierFactory.wo(Unit.class, Wo.class,
+				ListTools.toList(Unit.id_FIELDNAME, Unit.distinguishedName_FIELDNAME, Unit.levelName_FIELDNAME),
+				null);
+
+		@FieldDescribe("直接下级身份成员数量")
+		private Long subDirectUnitCount = 0L;
+
+		@FieldDescribe("直接下级组织数量")
+		private Long subDirectIdentityCount = 0L;
+
+		@FieldDescribe("直接下级组织")
+		private List<Wo> subUnits = new ArrayList<>();
+
+		public Long getSubDirectUnitCount() {
+			return subDirectUnitCount;
+		}
+
+		public void setSubDirectUnitCount(Long subDirectUnitCount) {
+			this.subDirectUnitCount = subDirectUnitCount;
+		}
+
+		public Long getSubDirectIdentityCount() {
+			return subDirectIdentityCount;
+		}
+
+		public void setSubDirectIdentityCount(Long subDirectIdentityCount) {
+			this.subDirectIdentityCount = subDirectIdentityCount;
+		}
+
+		public List<Wo> getSubUnits() {
+			return subUnits;
+		}
+
+		public void setSubUnits(List<Wo> subUnits) {
+			this.subUnits = subUnits;
+		}
+	}
+
+	private List<Wo> list(Business business, Wi wi) throws Exception {
+		List<Unit> os = business.unit().pick(wi.getUnitList());
+		List<Wo> wos = Wo.copier.copy(os);
+		Map<String, Wo> map = wos.stream().collect(Collectors.toMap(Wo::getId, Wo->Wo));
+		listSub(business, os, map);
+		return wos;
+	}
+
+	private void listSub(Business business, List<Unit> units, Map<String, Wo> unitMap) throws Exception {
+		for (Unit unit : units){
+			Wo wo = unitMap.get(unit.getId());
+			List<Unit> os = business.unit().listSubDirectObject(unit);
+			if(!os.isEmpty()){
+				List<Wo> wos = Wo.copier.copy(os);
+				Map<String, Wo> map = wos.stream().collect(Collectors.toMap(Wo::getId, Wo->Wo));
+				listSub(business, os, map);
+				wo.setSubUnits(wos);
+				wo.setSubDirectUnitCount((long)wos.size());
+			}
+			wo.setSubDirectIdentityCount(business.identity().countByUnit(unit.getId()));
+		}
+	}
+
+}

+ 18 - 0
o2server/x_organization_assemble_express/src/main/java/com/x/organization/assemble/express/jaxrs/unit/UnitAction.java

@@ -567,4 +567,22 @@ public class UnitAction extends StandardJaxrsAction {
 		}
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 	}
+
+	@JaxrsMethodDescribe(value = "批量查询组织的嵌套下级组织信息-树形模式.", action = ActionListWithUnitTree.class)
+	@POST
+	@Path("list/unit/tree")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithUnitTree(@Suspended final AsyncResponse asyncResponse,
+								  @Context HttpServletRequest request, JsonElement jsonElement) {
+		ActionResult<List<ActionListWithUnitTree.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithUnitTree().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
 }
 }