package act.controller.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.util.DestroyableBase;
import org.osgl.$;
import org.osgl.util.C;
import org.osgl.util.S;
import javax.enterprise.context.ApplicationScoped;
import java.lang.annotation.Annotation;
import java.util.List;
import static act.Destroyable.Util.destroyAll;
/**
* Aggregate interception meta info. This structure is used in
* {@link ControllerClassMetaInfo} and
* {@link ActionMethodMetaInfo}
*/
@ApplicationScoped
public class GroupInterceptorMetaInfo extends DestroyableBase {
private C.List<InterceptorMethodMetaInfo> beforeList = C.newList();
private C.List<InterceptorMethodMetaInfo> afterList = C.newList();
private C.List<InterceptorMethodMetaInfo> catchList = C.newList();
private C.List<InterceptorMethodMetaInfo> finallyList = C.newList();
public GroupInterceptorMetaInfo() {}
public GroupInterceptorMetaInfo(GroupInterceptorMetaInfo copy) {
mergeFrom(copy);
}
@Override
protected void releaseResources() {
destroyAll(beforeList, ApplicationScoped.class);
destroyAll(afterList, ApplicationScoped.class);
destroyAll(catchList, ApplicationScoped.class);
destroyAll(finallyList, ApplicationScoped.class);
beforeList.clear();
afterList.clear();
catchList.clear();
finallyList.clear();
super.releaseResources();
}
public void addBefore(InterceptorMethodMetaInfo before) {
beforeList.add(before);
}
public void addAfter(InterceptorMethodMetaInfo after) {
afterList.add(after);
}
public void addCatch(CatchMethodMetaInfo cat) {
catchList.add(cat);
}
public void addFinally(InterceptorMethodMetaInfo after) {
finallyList.add(after);
}
public void add(InterceptorMethodMetaInfo info, Class<? extends Annotation> interceptorType) {
InterceptorType.of(interceptorType).addToGroup(info, this);
}
public void add(InterceptorMethodMetaInfo info, InterceptorType type) {
type.addToGroup(info, this);
}
public C.List<InterceptorMethodMetaInfo> beforeList() {
return C.list(beforeList);
}
public C.List<InterceptorMethodMetaInfo> afterList() {
return C.list(afterList);
}
@SuppressWarnings("unchecked")
public C.List<CatchMethodMetaInfo> catchList() {
return C.list((List) catchList);
}
public C.List<InterceptorMethodMetaInfo> finallyList() {
return C.list(finallyList);
}
private C.List<InterceptorMethodMetaInfo> allList() {
return beforeList().lazy().append(afterList()).append((List<CatchMethodMetaInfo>)catchList()).append(finallyList());
}
public InterceptorMethodMetaInfo find(String methodName, String className) {
for (InterceptorMethodMetaInfo info : allList()) {
String infoMethodName = info.name();
String infoClassName = info.classInfo().className();
if (S.eq(methodName, infoMethodName) && S.eq(className, infoClassName)) {
return info;
}
}
return null;
}
public void mergeFrom(GroupInterceptorMetaInfo info, ControllerClassMetaInfo targetController) {
mergeList(beforeList, targetController.convertDerived(info.beforeList));
mergeList(afterList, targetController.convertDerived(info.afterList));
mergeList(catchList, targetController.convertDerived(info.catchList));
mergeList(finallyList, targetController.convertDerived(info.finallyList));
}
public void mergeFrom(GroupInterceptorMetaInfo info) {
mergeList(beforeList, info.beforeList);
mergeList(afterList, info.afterList);
mergeList(catchList, info.catchList);
mergeList(finallyList, info.finallyList);
}
public void mergeFrom(GroupInterceptorMetaInfo classInterceptors, String actionName) {
classInterceptors.beforeList.each(_F.mergeInto(this.beforeList, actionName));
classInterceptors.afterList.each(_F.mergeInto(this.afterList, actionName));
classInterceptors.catchList.each(_F.mergeInto(this.catchList, actionName));
classInterceptors.finallyList.each(_F.mergeInto(this.finallyList, actionName));
beforeList = beforeList.sorted();
afterList = afterList.sorted();
catchList = catchList.sorted();
finallyList = finallyList.sorted();
}
@Override
public String toString() {
S.Buffer sb = S.buffer();
appendList("BEFORE", beforeList, sb);
appendList("AFTER", afterList, sb);
appendList("CATCH", catchList, sb);
appendList("FINALLY", finallyList, sb);
return sb.toString();
}
private static <T> void mergeList(List<? super T> toList, List<? extends T> fromList) {
for (T t : fromList) {
if (!toList.contains(t)) {
toList.add(t);
}
}
}
private void appendList(String label, List<?> list, S.Buffer sb) {
if (list.isEmpty()) {
return;
}
if (sb.length() > 0) {
sb.append("\n");
}
sb.append(label).append("\n").append(S.join("\n", list));
}
private enum _F {
;
static $.Visitor<InterceptorMethodMetaInfo> mergeInto(final C.List<InterceptorMethodMetaInfo> toList, final String actionName) {
return new $.Visitor<InterceptorMethodMetaInfo>() {
@Override
public void visit(InterceptorMethodMetaInfo info) throws $.Break {
info.mergeInto(toList, actionName);
}
};
}
}
}