package org.zstack.tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.Platform;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.cloudbus.MessageSafe;
import org.zstack.core.componentloader.PluginRegistry;
import org.zstack.core.db.*;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.core.defer.Defer;
import org.zstack.core.defer.Deferred;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.AbstractService;
import org.zstack.header.apimediator.ApiMessageInterceptionException;
import org.zstack.header.apimediator.GlobalApiMessageInterceptor;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.header.message.APICreateMessage;
import org.zstack.header.message.APIMessage;
import org.zstack.header.message.Message;
import org.zstack.header.query.APIQueryReply;
import org.zstack.header.tag.*;
import org.zstack.query.QueryFacade;
import org.zstack.utils.*;
import org.zstack.utils.function.Function;
import org.zstack.utils.logging.CLogger;
import static org.zstack.core.Platform.argerr;
import static org.zstack.core.Platform.operr;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.metamodel.EntityType;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import static org.zstack.utils.CollectionDSL.list;
import static org.zstack.utils.CollectionUtils.removeDuplicateFromList;
public class TagManagerImpl extends AbstractService implements TagManager,
SoftDeleteEntityExtensionPoint, GlobalApiMessageInterceptor, SystemTagLifeCycleExtension,
HardDeleteEntityExtensionPoint {
private static final CLogger logger = Utils.getLogger(TagManagerImpl.class);
@Autowired
protected DatabaseFacade dbf;
@Autowired
protected CloudBus bus;
@Autowired
private QueryFacade qf;
@Autowired
protected ErrorFacade errf;
@Autowired
private PluginRegistry pluginRgty;
private List<SystemTag> systemTags = new ArrayList<>();
private Map<String, List<SystemTag>> resourceTypeSystemTagMap = new HashMap<>();
private Map<String, Class> resourceTypeClassMap = new HashMap<>();
private Map<Class, Class> resourceTypeCreateMessageMap = new HashMap<>();
private Map<String, List<SystemTagCreateMessageValidator>> createMessageValidators = new HashMap<>();
private Map<String, List<SystemTagLifeCycleExtension>> lifeCycleExtensions = new HashMap<>();
private List<Class> autoDeleteTagClasses;
private void initSystemTags() throws IllegalAccessException {
List<Class> classes = BeanUtils.scanClass("org.zstack", TagDefinition.class);
for (Class clz : classes) {
List<Field> fields = FieldUtils.getAllFields(clz);
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
continue;
}
if (!SystemTag.class.isAssignableFrom(f.getType())) {
continue;
}
f.setAccessible(true);
SystemTag stag = (SystemTag) f.get(null);
if (stag == null) {
throw new CloudRuntimeException(String.format("%s.%s defines a null system tag",
f.getDeclaringClass(), f.getName()));
}
if (PatternedSystemTag.class.isAssignableFrom(f.getType())) {
PatternedSystemTag ptag = new PatternedSystemTag(stag.getTagFormat(), stag.getResourceClass());
ptag.setValidators(stag.getValidators());
f.set(null, ptag);
systemTags.add(ptag);
stag = ptag;
} else if (EphemeralSystemTag.class.isAssignableFrom(f.getType())) {
// pass
// ephemeral tag is not needed to inject and validate
systemTags.add(stag);
} else {
SystemTag sstag = new SystemTag(stag.getTagFormat(), stag.getResourceClass());
sstag.setValidators(stag.getValidators());
f.set(null, sstag);
systemTags.add(sstag);
stag = sstag;
}
stag.setTagMgr(this);
List<SystemTag> lst = resourceTypeSystemTagMap.get(stag.getResourceClass().getSimpleName());
if (lst == null) {
lst = new ArrayList<>();
resourceTypeSystemTagMap.put(stag.getResourceClass().getSimpleName(), lst);
}
lst.add(stag);
}
}
}
void init() {
for (EntityType<?> entity : dbf.getEntityManager().getMetamodel().getEntities()) {
Class type = entity.getJavaType();
String name = type.getSimpleName();
resourceTypeClassMap.put(name, type);
logger.debug(String.format("discovered tag resource type[%s], class[%s]", name, type));
}
try {
// this makes sure DatabaseFacade is injected into every SystemTag object
initSystemTags();
} catch (Exception e) {
throw new CloudRuntimeException(e);
}
List<Class> createMessageClass = BeanUtils.scanClass("org.zstack", TagResourceType.class);
for (Class cmsgClz : createMessageClass) {
TagResourceType at = (TagResourceType) cmsgClz.getAnnotation(TagResourceType.class);
Class resType = at.value();
if (!resourceTypeClassMap.values().contains(resType)) {
throw new CloudRuntimeException(String.format(
"tag resource type[%s] defined in @TagResourceType of class[%s] is not a VO entity",
resType.getName(), cmsgClz.getName()));
}
resourceTypeCreateMessageMap.put(cmsgClz, resType);
}
autoDeleteTagClasses = BeanUtils.scanClass("org.zstack", AutoDeleteTag.class);
List<String> clzNames = CollectionUtils.transformToList(autoDeleteTagClasses, new Function<String, Class>() {
@Override
public String call(Class arg) {
return arg.getSimpleName();
}
});
logger.debug(String.format("tags of following resources are auto-deleting enabled: %s", clzNames));
}
private void populateExtensions() {
for (SystemTagLifeCycleExtension ext : pluginRgty.getExtensionList(SystemTagLifeCycleExtension.class)) {
for (String resType : ext.getResourceTypeOfSystemTags()) {
if (!resourceTypeClassMap.containsKey(resType)) {
throw new CloudRuntimeException(String.format("%s returns a unknown resource type[%s] for system tag",
ext.getClass(), resType));
}
List<SystemTagLifeCycleExtension> lst = lifeCycleExtensions.get(resType);
if (lst == null) {
lst = new ArrayList<>();
lifeCycleExtensions.put(resType, lst);
}
lst.add(ext);
}
}
}
private boolean isTagExisting(String resourceUuid, String tag, TagType type, String resourceType) {
if (type == TagType.User) {
return Q.New(UserTagVO.class).eq(UserTagVO_.resourceType, resourceType)
.eq(UserTagVO_.tag, tag)
.eq(UserTagVO_.resourceUuid, resourceUuid)
.isExists();
} else {
return Q.New(SystemTagVO.class).eq(SystemTagVO_.resourceType, resourceType)
.eq(SystemTagVO_.tag, tag)
.eq(SystemTagVO_.resourceUuid, resourceUuid)
.isExists();
}
}
@Transactional
private TagInventory createTag(String resourceUuid, String tag, TagType type, String resourceType) {
if (!resourceTypeClassMap.keySet().contains(resourceType)) {
throw new IllegalArgumentException(String.format("no resource type[%s] found for tag", resourceType));
}
if (isTagExisting(resourceUuid, tag, type, resourceType)) {
throw new OperationFailureException(operr("Duplicated Tag[tag:%s, type:%s, resourceType:%s, resourceUuid:%s]",
tag, type, resourceType, resourceUuid));
}
if (type == TagType.User) {
UserTagVO vo = new UserTagVO();
vo.setResourceType(resourceType);
vo.setResourceUuid(resourceUuid);
vo.setUuid(Platform.getUuid());
vo.setTag(tag);
vo.setType(type);
dbf.getEntityManager().persist(vo);
dbf.getEntityManager().flush();
dbf.getEntityManager().refresh(vo);
return UserTagInventory.valueOf(vo);
} else {
SystemTagVO vo = new SystemTagVO();
vo.setResourceType(resourceType);
vo.setUuid(Platform.getUuid());
vo.setResourceUuid(resourceUuid);
vo.setInherent(true);
vo.setTag(tag);
vo.setType(type);
preTagCreated(SystemTagInventory.valueOf(vo));
dbf.getEntityManager().persist(vo);
dbf.getEntityManager().flush();
dbf.getEntityManager().refresh(vo);
SystemTagInventory stag = SystemTagInventory.valueOf(vo);
fireTagCreated(list(stag));
return stag;
}
}
@Override
@Deferred
@Transactional
public SystemTagInventory createNonInherentSystemTag(String resourceUuid, String tag, String resourceType) {
if (isTagExisting(resourceUuid, tag, TagType.System, resourceType)) {
return null;
}
validateSystemTag(resourceUuid, resourceType, tag);
SystemTagVO vo = new SystemTagVO();
vo.setResourceType(resourceType);
vo.setUuid(Platform.getUuid());
vo.setResourceUuid(resourceUuid);
vo.setInherent(false);
vo.setTag(tag);
vo.setType(TagType.System);
preTagCreated(SystemTagInventory.valueOf(vo));
dbf.getEntityManager().persist(vo);
dbf.getEntityManager().flush();
dbf.getEntityManager().refresh(vo);
SystemTagInventory inv = SystemTagInventory.valueOf(vo);
final SystemTagVO finalVo = vo;
Defer.guard(() -> dbf.remove(finalVo));
fireTagCreated(list(inv));
return inv;
}
@Override
public SystemTagInventory createInherentSystemTag(String resourceUuid, String tag, String resourceType) {
if (isTagExisting(resourceUuid, tag, TagType.System, resourceType)) {
return null;
}
validateSystemTag(resourceUuid, resourceType, tag);
SystemTagVO vo = new SystemTagVO();
vo.setResourceType(resourceType);
vo.setUuid(Platform.getUuid());
vo.setResourceUuid(resourceUuid);
vo.setInherent(true);
vo.setTag(tag);
vo.setType(TagType.System);
preTagCreated(SystemTagInventory.valueOf(vo));
vo = dbf.persistAndRefresh(vo);
SystemTagInventory inv = SystemTagInventory.valueOf(vo);
fireTagCreated(list(inv));
return inv;
}
@Override
public void createInherentSystemTags(List<String> sysTags, String resourceUuid, String resourceType) {
for (String tag : sysTags) {
createInherentSystemTag(resourceUuid, tag, resourceType);
}
}
@Override
public void createNonInherentSystemTags(List<String> sysTags, String resourceUuid, String resourceType) {
for (String tag : sysTags) {
createNonInherentSystemTag(resourceUuid, tag, resourceType);
}
}
@Override
@Transactional
public void createTagsFromAPICreateMessage(APICreateMessage msg, String resourceUuid, String resourceType) {
if (msg.getSystemTags() != null && !msg.getSystemTags().isEmpty()) {
for (String sysTag : msg.getSystemTags()) {
if (TagConstant.isEphemeralTag(sysTag)) {
continue;
}
createNonInherentSystemTag(resourceUuid, sysTag, resourceType);
}
}
if (msg.getUserTags() != null && !msg.getUserTags().isEmpty()) {
for (String utag : msg.getUserTags()) {
createUserTag(resourceUuid, utag, resourceType);
}
}
}
@Override
public TagInventory createSysTag(String resourceUuid, String tag, String resourceType) {
validateSystemTag(resourceUuid, resourceType, tag);
return createTag(resourceUuid, tag, TagType.System, resourceType);
}
@Override
public TagInventory createUserTag(String resourceUuid, String tag, String resourceType) {
return createTag(resourceUuid, tag, TagType.User, resourceType);
}
@Override
public TagInventory createSysTag(String resourceUuid, Enum tag, String resourceType) {
validateSystemTag(resourceUuid, resourceType, tag.toString());
return createSysTag(resourceUuid, tag.toString(), resourceType);
}
@Override
public TagInventory createUserTag(String resourceUuid, Enum tag, String resourceType) {
return createUserTag(resourceUuid, tag.toString(), resourceType);
}
@Override
@Transactional
public void copySystemTag(String srcResourceUuid, String srcResourceType, String dstResourceUuid, String dstResourceType) {
String sql = "select stag" +
" from SystemTagVO stag" +
" where stag.resourceUuid = :ruuid" +
" and stag.resourceType = :rtype" +
" and stag.inherent = :ih";
TypedQuery<SystemTagVO> srcq = dbf.getEntityManager().createQuery(sql, SystemTagVO.class);
srcq.setParameter("ruuid", srcResourceUuid);
srcq.setParameter("rtype", srcResourceType);
srcq.setParameter("ih", false);
List<SystemTagVO> srctags = srcq.getResultList();
if (srctags.isEmpty()) {
return;
}
for (SystemTagVO stag : srctags) {
SystemTagVO ntag = new SystemTagVO(stag);
ntag.setUuid(Platform.getUuid());
ntag.setResourceType(dstResourceType);
ntag.setResourceUuid(dstResourceUuid);
dbf.getEntityManager().persist(ntag);
}
}
@Override
public SystemTagInventory updateSystemTag(String tagUuid, String newTag) {
SystemTagVO vo = dbf.findByUuid(tagUuid, SystemTagVO.class);
SystemTagInventory old = SystemTagInventory.valueOf(vo);
if (!vo.getTag().equals(newTag)) {
vo.setTag(newTag);
SystemTagInventory n = ObjectUtils.copy(new SystemTagInventory(), old);
n.setTag(newTag);
preTagUpdated(old, n);
vo = dbf.updateAndRefresh(vo);
SystemTagInventory nt = SystemTagInventory.valueOf(vo);
fireTagUpdated(old, nt);
return SystemTagInventory.valueOf(vo);
} else {
return old;
}
}
@Override
public List<String> findSystemTags(String resourceUuid) {
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.select(SystemTagVO_.tag);
q.add(SystemTagVO_.resourceUuid, SimpleQuery.Op.EQ, resourceUuid);
return q.listValue();
}
@Override
public List<String> findUserTags(String resourceUuid) {
SimpleQuery<UserTagVO> q = dbf.createQuery(UserTagVO.class);
q.select(UserTagVO_.tag);
q.add(UserTagVO_.resourceUuid, SimpleQuery.Op.EQ, resourceUuid);
return q.listValue();
}
private boolean hasTag(String resourceUuid, String tag, TagType tagType) {
if (tagType == TagType.System) {
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.add(SystemTagVO_.resourceUuid, SimpleQuery.Op.EQ, resourceUuid);
q.add(SystemTagVO_.tag, SimpleQuery.Op.EQ, tag);
return q.isExists();
} else {
SimpleQuery<UserTagVO> q = dbf.createQuery(UserTagVO.class);
q.add(UserTagVO_.resourceUuid, SimpleQuery.Op.EQ, resourceUuid);
q.add(UserTagVO_.tag, SimpleQuery.Op.EQ, tag);
return q.isExists();
}
}
@Override
public boolean hasSystemTag(String resourceUuid, String tag) {
return hasTag(resourceUuid, tag, TagType.System);
}
@Override
public boolean hasSystemTag(String resourceUuid, Enum tag) {
return hasTag(resourceUuid, tag.toString(), TagType.System);
}
@Override
public void deleteSystemTag(String tag, String resourceUuid, String resourceType, Boolean inherit) {
deleteSystemTag(tag, resourceUuid, resourceType, inherit, false);
}
private void deleteSystemTag(String tag, String resourceUuid, String resourceType, Boolean inherit, boolean useLike) {
DebugUtils.Assert(tag != null || resourceUuid != null || resourceType != null,
"tag, resourceUuid, resourceType cannot all be null");
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
if (tag != null) {
if (useLike) {
q.add(SystemTagVO_.tag, Op.LIKE, tag);
} else {
q.add(SystemTagVO_.tag, Op.EQ, tag);
}
}
if (resourceUuid != null) {
q.add(SystemTagVO_.resourceUuid, Op.EQ, resourceUuid);
}
if (resourceType != null) {
q.add(SystemTagVO_.resourceType, Op.EQ, resourceType);
}
if (inherit != null) {
q.add(SystemTagVO_.inherent, Op.EQ, inherit);
}
List<SystemTagVO> vos = q.list();
if (!vos.isEmpty()) {
for (SystemTagVO vo : vos) {
preTagDeleted(SystemTagInventory.valueOf(vo));
}
}
dbf.removeCollection(vos, SystemTagVO.class);
if (!vos.isEmpty()) {
fireTagDeleted(SystemTagInventory.valueOf(vos));
}
}
@Override
public void deleteSystemTagUseLike(String tag, String resourceUuid, String resourceType, Boolean inherit) {
deleteSystemTag(tag, resourceUuid, resourceType, inherit, true);
}
void fireTagDeleted(List<SystemTagInventory> tags) {
for (SystemTagInventory tag : tags) {
List<SystemTagLifeCycleExtension> exts = lifeCycleExtensions.get(tag.getResourceType());
if (exts != null) {
for (SystemTagLifeCycleExtension ext : exts) {
try {
ext.tagDeleted(tag);
} catch (Exception e) {
logger.warn(String.format("unhandled exception when calling %s", ext.getClass()));
}
}
}
}
}
void fireTagCreated(List<SystemTagInventory> tags) {
for (SystemTagInventory tag : tags) {
List<SystemTagLifeCycleExtension> exts = lifeCycleExtensions.get(tag.getResourceType());
if (exts != null) {
for (SystemTagLifeCycleExtension ext : exts) {
try {
ext.tagCreated(tag);
} catch (Exception e) {
logger.warn(String.format("unhandled exception when calling %s", ext.getClass()));
}
}
}
}
}
private void fireTagUpdated(SystemTagInventory old, SystemTagInventory newTag) {
List<SystemTagLifeCycleExtension> exts = lifeCycleExtensions.get(old.getResourceType());
if (exts != null) {
for (SystemTagLifeCycleExtension ext : exts) {
try {
ext.tagUpdated(old, newTag);
} catch (Exception e) {
logger.warn(String.format("unhandled exception when calling %s", ext.getClass()));
}
}
}
}
@Override
@MessageSafe
public void handleMessage(Message msg) {
if (msg instanceof APIMessage) {
handleApiMessage((APIMessage) msg);
} else {
handleLocalMessage(msg);
}
}
private void handleLocalMessage(Message msg) {
bus.dealWithUnknownMessage(msg);
}
private void handleApiMessage(APIMessage msg) {
if (msg instanceof APIQueryTagMsg) {
handle((APIQueryTagMsg) msg);
} else if (msg instanceof APICreateUserTagMsg) {
handle((APICreateUserTagMsg) msg);
} else if (msg instanceof APICreateSystemTagMsg) {
handle((APICreateSystemTagMsg) msg);
} else if (msg instanceof APIDeleteTagMsg) {
handle((APIDeleteTagMsg) msg);
} else if (msg instanceof APIUpdateSystemTagMsg) {
handle((APIUpdateSystemTagMsg) msg);
} else {
bus.dealWithUnknownMessage(msg);
}
}
@Deferred
private void handle(APIUpdateSystemTagMsg msg) {
APIUpdateSystemTagEvent evt = new APIUpdateSystemTagEvent(msg.getId());
evt.setInventory(updateSystemTag(msg.getUuid(), msg.getTag()));
bus.publish(evt);
}
private void handle(APICreateSystemTagMsg msg) {
APICreateSystemTagEvent evt = new APICreateSystemTagEvent(msg.getId());
SystemTagInventory inv = createNonInherentSystemTag(msg.getResourceUuid(), msg.getTag(), msg.getResourceType());
evt.setInventory(inv);
bus.publish(evt);
}
private void handle(APICreateUserTagMsg msg) {
APICreateUserTagEvent evt = new APICreateUserTagEvent(msg.getId());
UserTagInventory inv = (UserTagInventory) createUserTag(msg.getResourceUuid(), msg.getTag(), msg.getResourceType());
evt.setInventory(inv);
bus.publish(evt);
}
private void handle(APIDeleteTagMsg msg) {
APIDeleteTagEvent evt = new APIDeleteTagEvent(msg.getId());
SystemTagVO stag = dbf.findByUuid(msg.getUuid(), SystemTagVO.class);
if (stag != null) {
preTagDeleted(SystemTagInventory.valueOf(stag));
}
dbf.removeByPrimaryKey(msg.getUuid(), SystemTagVO.class);
dbf.removeByPrimaryKey(msg.getUuid(), UserTagVO.class);
if (stag != null) {
fireTagDeleted(list(SystemTagInventory.valueOf(stag)));
}
bus.publish(evt);
}
private void handle(APIQueryTagMsg msg) {
Class tagClass = msg.isSystemTag() ? SystemTagInventory.class : UserTagInventory.class;
if (msg.isCount()) {
APIQueryReply reply = new APIQueryReply();
long count = qf.count(msg, tagClass);
reply.setTotal(count);
bus.reply(msg, reply);
} else {
List invs = qf.query(msg, tagClass);
APIQueryTagReply reply = new APIQueryTagReply();
reply.setInventories(invs);
bus.reply(msg, reply);
}
}
@Override
public Collection<String> getManagedEntityNames() {
return resourceTypeClassMap.keySet();
}
@Override
public void validateSystemTag(String resourceUuid, String resourceType, String tag) {
boolean checked = false;
for (SystemTag stag : systemTags) {
if (stag.isMatch(tag)) {
checked = true;
stag.validate(resourceUuid, resourceTypeClassMap.get(resourceType), tag);
}
}
if (!checked) {
throw new ApiMessageInterceptionException(argerr("no system tag matches %s", tag));
}
}
@Override
public void installCreateMessageValidator(String resourceType, SystemTagCreateMessageValidator validator) {
if (!resourceTypeClassMap.containsKey(resourceType)) {
throw new CloudRuntimeException(String.format("cannot find resource type[%s] in tag system ", resourceType));
}
List<SystemTagCreateMessageValidator> validators = createMessageValidators.get(resourceType);
if (validators == null) {
validators = new ArrayList<SystemTagCreateMessageValidator>();
createMessageValidators.put(resourceType, validators);
}
validators.add(validator);
}
@Override
public String getId() {
return bus.makeLocalServiceId(TagConstant.SERVICE_ID);
}
@Override
public boolean start() {
populateExtensions();
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public List<Class> getEntityClassForSoftDeleteEntityExtension() {
return autoDeleteTagClasses;
}
private List<String> getResourceTypes(Class entityClass) {
List<String> types = new ArrayList<>();
while (entityClass != Object.class) {
types.add(entityClass.getSimpleName());
entityClass = entityClass.getSuperclass();
}
return types;
}
@Transactional
private void postDelete(Collection entityIds, Class entityClass) {
List<String> rtypes = getResourceTypes(entityClass);
String sql = "delete from SystemTagVO s" +
" where s.resourceType in (:resourceTypes)" +
" and s.resourceUuid in (:resourceUuids)";
Query q = dbf.getEntityManager().createQuery(sql);
q.setParameter("resourceTypes", rtypes);
q.setParameter("resourceUuids", entityIds);
q.executeUpdate();
sql = "delete from UserTagVO s" +
" where s.resourceType in (:resourceTypes)" +
" and s.resourceUuid in (:resourceUuids)";
q = dbf.getEntityManager().createQuery(sql);
q.setParameter("resourceTypes", rtypes);
q.setParameter("resourceUuids", entityIds);
q.executeUpdate();
}
@Override
public void postSoftDelete(Collection entityIds, Class entityClass) {
postDelete(entityIds, entityClass);
}
@Override
public List<Class> getMessageClassToIntercept() {
return list((Class) APICreateMessage.class);
}
@Override
public InterceptorPosition getPosition() {
return InterceptorPosition.FRONT;
}
private boolean isCheckSystemTags(APIMessage msg) {
if (msg.getSystemTags() == null) {
return false;
}
if (msg.getSystemTags().isEmpty()) {
return false;
}
for (String s : msg.getSystemTags()) {
if (!TagConstant.isEphemeralTag(s)) {
return true;
}
}
return false;
}
@Override
public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException {
APICreateMessage cmsg = (APICreateMessage) msg;
if (isCheckSystemTags(msg)) {
cmsg.setSystemTags(removeDuplicateFromList(cmsg.getSystemTags()));
for (String tag : cmsg.getSystemTags()) {
boolean checked = false;
for (SystemTag stag : systemTags) {
if (stag.isMatch(tag)) {
checked = true;
break;
}
}
if (!checked) {
throw new ApiMessageInterceptionException(argerr("no system tag matches %s", tag));
}
}
Class resourceType = resourceTypeCreateMessageMap.get(cmsg.getClass());
if (resourceType == null) {
throw new ApiMessageInterceptionException(errf.stringToInternalError(
String.format("API message[%s] doesn't define resource type by @TagResourceType",
cmsg.getClass().getName())
));
}
List<SystemTagCreateMessageValidator> validators = createMessageValidators.get(resourceType.getSimpleName());
if (validators != null && !validators.isEmpty()) {
for (SystemTagCreateMessageValidator validator : validators) {
validator.validateSystemTagInCreateMessage(cmsg);
}
}
}
return msg;
}
private boolean isTagMatch(SystemTagInventory t, SystemTag s) {
return s.isMatch(t.getTag());
}
@Override
public List<String> getResourceTypeOfSystemTags() {
List<String> lst = new ArrayList<>();
lst.addAll(resourceTypeClassMap.keySet());
return lst;
}
void preTagCreated(SystemTagInventory tag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(tag.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(tag, stag)) {
stag.callCreatedJudger(tag);
}
}
}
}
@Override
public void tagCreated(SystemTagInventory tag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(tag.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(tag, stag)) {
stag.callTagCreatedListener(tag);
}
}
}
}
void preTagDeleted(SystemTagInventory tag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(tag.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(tag, stag)) {
stag.callDeletedJudger(tag);
}
}
}
}
@Override
public void tagDeleted(SystemTagInventory tag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(tag.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(tag, stag)) {
stag.callTagDeletedListener(tag);
}
}
}
}
private void preTagUpdated(SystemTagInventory old, SystemTagInventory newTag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(old.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(old, stag) && isTagMatch(newTag, stag)) {
stag.callUpdatedJudger(old, newTag);
}
}
}
}
@Override
public void tagUpdated(SystemTagInventory old, SystemTagInventory newTag) {
List<SystemTag> tags = resourceTypeSystemTagMap.get(old.getResourceType());
if (tags != null) {
for (SystemTag stag : tags) {
if (isTagMatch(old, stag) && isTagMatch(newTag, stag)) {
stag.callTagUpdatedListener(old, newTag);
}
}
}
}
@Override
public List<Class> getEntityClassForHardDeleteEntityExtension() {
return autoDeleteTagClasses;
}
@Override
public void postHardDelete(Collection entityIds, Class entityClass) {
postDelete(entityIds, entityClass);
}
}