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.app.ActionContext;
import org.osgl.$;
import org.osgl.util.S;
/**
* Keep all information required to inject {@link ActionContext}
* into the controller action handler
*/
public class ActContextInjection<T> {
/**
* Define how framework should inject AppContext to the
* controller action handler
*/
public enum InjectType {
/**
* Inject AppContext into controller instance field. This injection
* is used when both of the following requirements are met
* <ul>
* <li>The controller has a field with type {@link ActionContext}</li>
* <li>The action handler method is not {@code static}</li>
* </ul>
* <p>Framework must instantiate an new instance of the
* controller before calling the action handler method</p>
*/
FIELD,
/**
* Pass AppContext via controller action method call. This injection
* is used when there are parameter of type AppContext in the action
* handler method signature
*/
PARAM,
/**
* Save AppContext to {@link org.osgl.concurrent.ContextLocal}. If none of
* the {@link #FIELD} and {@link #PARAM} can be used to inject the
* {@code AppContext}, then framework shall call {@link ActionContext#saveLocal}
* method to save the app context instance into thread local variable, such that the
* application developer could use {@link ActionContext#current} method to
* access the current application context
*/
LOCAL;
public boolean isLocal() {
return this == LOCAL;
}
public boolean isField() {
return this == FIELD;
}
public boolean isParam() {
return this == PARAM;
}
}
private InjectType type;
protected T v;
private ActContextInjection(InjectType type, T v) {
this.type = type;
this.v = v;
}
public InjectType injectVia() {
return type;
}
@Override
public int hashCode() {
return $.hc(type, v);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof ActContextInjection) {
ActContextInjection that = (ActContextInjection) obj;
return that.type == type && $.eq(that.v, v);
}
return false;
}
@Override
public String toString() {
return S.concat("inject[", type.name().toLowerCase(), ", ", S.string(v), "]");
}
public static class FieldActContextInjection extends ActContextInjection<String> {
public FieldActContextInjection(String fieldName) {
super(InjectType.FIELD, fieldName);
}
public String fieldName() {
return v;
}
}
public static class ParamAppContextInjection extends ActContextInjection<Integer> {
private int lvLookupIdx;
public ParamAppContextInjection(Integer paramIndex) {
super(InjectType.PARAM, paramIndex);
}
public int paramIndex() {
return v;
}
public ParamAppContextInjection lvLookupIdx(int index) {
this.lvLookupIdx = index;
return this;
}
public int lvLookupIdx() {
return lvLookupIdx;
}
}
public static class LocalAppContextInjection extends ActContextInjection<Void> {
public LocalAppContextInjection() {
super(InjectType.LOCAL, null);
}
@Override
public String toString() {
return "inject[local]";
}
}
}