package act.cli.meta; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.app.AppClassLoader; import act.asm.Type; import act.sys.meta.SessionVariableAnnoInfo; import act.util.DestroyableBase; import org.osgl.$; import org.osgl.util.C; import org.osgl.util.S; import javax.enterprise.context.ApplicationScoped; import java.util.List; import static act.Destroyable.Util.destroyAll; /** * Stores all class level information to support generating of * {@link act.cli.CommandExecutor command executor} */ @ApplicationScoped public class CommanderClassMetaInfo extends DestroyableBase { private static CommanderClassMetaInfo NULL = new CommanderClassMetaInfo() { @Override protected CommanderClassMetaInfo parent(AppClassLoader classLoader) { return this; } }; public static final String NAME_SEPARATOR = S.COMMON_SEP; private Type type; private Type superType; private boolean isAbstract = false; private C.List<CommandMethodMetaInfo> commands = C.newList(); private C.Map<String, FieldOptionAnnoInfo> fieldOptionAnnoInfoMap = C.newMap(); private C.Map<String, SessionVariableAnnoInfo> fieldSessionVariableAnnoInfoMap = C.newMap(); // commandLookup index command method by method name private C.Map<String, CommandMethodMetaInfo> commandLookup = null; private CommanderClassMetaInfo parent; private String contextPath; public CommanderClassMetaInfo className(String name) { this.type = Type.getObjectType(name); return this; } @Override protected void releaseResources() { destroyAll(commands, ApplicationScoped.class); commands.clear(); if (null != commandLookup) { destroyAll(commandLookup.values(), ApplicationScoped.class); commandLookup.clear(); } if (null != parent) parent.destroy(); super.releaseResources(); } public boolean isCommander() { return !commands.isEmpty(); } public String className() { return type.getClassName(); } public String internalName() { return type.getInternalName(); } public Type type() { return type; } public CommanderClassMetaInfo superType(Type type) { superType = type; return this; } public CommanderClassMetaInfo addFieldOptionAnnotationInfo(FieldOptionAnnoInfo info) { info.paramName(info.fieldName()); fieldOptionAnnoInfoMap.put(info.fieldName(), info); return this; } public CommanderClassMetaInfo addFieldSessionVariableAnnotInfo(String fieldName, SessionVariableAnnoInfo info) { fieldSessionVariableAnnoInfoMap.put(fieldName, info); return this; } public FieldOptionAnnoInfo fieldOptionAnnoInfo(String name) { FieldOptionAnnoInfo info = fieldOptionAnnoInfoMap.get(name); if (null == info && null != parent) { info = parent.fieldOptionAnnoInfo(name); } return info; } public SessionVariableAnnoInfo fieldSessionVariableAnnoInfo(String name) { SessionVariableAnnoInfo info = fieldSessionVariableAnnoInfoMap.get(name); if (null == info && null != parent) { info = parent.fieldSessionVariableAnnoInfo(name); } return info; } public List<FieldOptionAnnoInfo> fieldOptionAnnoInfoList(AppClassLoader appClassLoader) { C.List<FieldOptionAnnoInfo> list = C.list(fieldOptionAnnoInfoMap.values()); CommanderClassMetaInfo p = parent(appClassLoader); if (null != p && NULL != p) { list = list.append(p.fieldOptionAnnoInfoList(appClassLoader)); } return list; } public boolean hasOption(AppClassLoader classLoader) { boolean retVal = !fieldOptionAnnoInfoMap.isEmpty(); if (retVal) { return true; } CommanderClassMetaInfo p = parent(classLoader); if (null != p && NULL != p) { return p.hasOption(classLoader); } return false; } protected CommanderClassMetaInfo parent(AppClassLoader classLoader) { if (null == parent) { CommanderClassMetaInfoManager manager = classLoader.commanderClassMetaInfoManager(); parent = manager.commanderMetaInfo(superType.getClassName()); if (null == parent) { parent = NULL; } } return parent; } public Type superType() { return superType; } public CommanderClassMetaInfo setAbstract() { isAbstract = true; return this; } public boolean isAbstract() { return isAbstract; } public CommanderClassMetaInfo addCommand(CommandMethodMetaInfo info) { commands.add(info); return this; } public CommandMethodMetaInfo command(String name) { if (null == commandLookup) { buildCommandLookup(); } return commandLookup.get(name); } public boolean hasCommand() { return !commands.isEmpty(); } public List<CommandMethodMetaInfo> commandList() { return C.list(commands); } public String contextPath() { return contextPath; } public CommanderClassMetaInfo contextPath(String path) { if (S.blank(path)) { contextPath = "/"; } else { contextPath = path; } return this; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof CommanderClassMetaInfo) { CommanderClassMetaInfo that = $.cast(obj); return $.eq(that.type, this.type); } return false; } @Override public int hashCode() { return $.hc(type); } private void buildCommandLookup() { C.Map<String, CommandMethodMetaInfo> lookup = C.newMap(); for (CommandMethodMetaInfo command : commands) { String[] commandNames = command.commandName().split(NAME_SEPARATOR); for (String commandName : commandNames) { lookup.put(commandName, command); } lookup.put(command.methodName(), command); } commandLookup = lookup; } }