package act.db.di;
/*-
* #%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.Act;
import act.app.ActionContext;
import act.app.App;
import act.db.Dao;
import act.handler.DelegateRequestHandler;
import act.handler.RequestHandler;
import act.handler.builtin.controller.RequestHandlerProxy;
import act.inject.param.ParamValueLoaderService;
import act.util.ActContext;
import org.osgl.$;
import org.osgl.inject.ValueLoader;
import org.osgl.mvc.result.NotFound;
import org.osgl.util.*;
import javax.validation.constraints.NotNull;
import java.util.Collection;
public class FindBy extends ValueLoader.Base {
private String bindName;
private Dao dao;
private StringValueResolver resolver;
private boolean findOne;
private boolean byId;
private String querySpec;
private Class<?> rawType;
private boolean notNull;
@Override
protected void initialized() {
App app = App.instance();
rawType = spec.rawType();
notNull = spec.hasAnnotation(NotNull.class);
findOne = !(Collection.class.isAssignableFrom(rawType));
dao = app.dbServiceManager().dao(findOne ? rawType : (Class) spec.typeParams().get(0));
byId = (Boolean) options.get("byId");
resolver = app.resolverManager().resolver(byId ? dao.idType() : (Class) options.get("fieldType"));
if (null == resolver) {
throw new IllegalArgumentException("Cannot find String value resolver for type: " + dao.idType());
}
bindName = S.string(value());
if (S.blank(bindName)) {
bindName = ParamValueLoaderService.bindName(spec);
}
if (!byId) {
querySpec = S.string(options.get("value"));
if (S.blank(querySpec)) {
querySpec = bindName;
}
}
}
@Override
public Object get() {
ActContext ctx = ActContext.Base.currentContext();
E.illegalStateIf(null == ctx);
String value = resolve(bindName, ctx);
if (S.blank(value)) {
return ensureNotNull(null, "null");
}
Object by = resolver.resolve(value);
ensureNotNull(by, value);
if (null == by) {
return null;
}
Collection col = findOne ? null : (Collection) App.instance().getInstance(rawType);
if (byId) {
Object bean = dao.findById(by);
if (findOne) {
return ensureNotNull(bean, value);
} else {
col.add(bean);
return col;
}
} else {
if (findOne) {
Object found = dao.findOneBy(Keyword.of(querySpec).javaVariable(), by);
return ensureNotNull(found, value);
} else {
col.addAll(C.list(dao.findBy(Keyword.of(querySpec).javaVariable(), by)));
return col;
}
}
}
private Object ensureNotNull(Object obj, String value) {
if (notNull) {
if (null == obj) {
if (!Act.isDev()) {
throw NotFound.get();
}
ActionContext ctx = ActionContext.current();
if (null == ctx) {
throw NotFound.get();
}
RequestHandler handler = ctx.handler();
if (handler instanceof DelegateRequestHandler) {
handler = ((DelegateRequestHandler) handler).realHandler();
}
if (handler instanceof RequestHandlerProxy) {
RequestHandlerProxy proxy = $.cast(handler);
throw proxy.notFoundOnMethod(S.fmt("%s not found by %s", spec.name(), value));
}
throw NotFound.get();
}
}
return obj;
}
private static String resolve(String bindName, ActContext ctx) {
String value = ctx.paramVal(bindName);
if (S.notBlank(value)) {
return value;
}
Keyword keyword = Keyword.of(bindName);
if (keyword.tokens().size() > 1) {
return resolve(keyword, ctx);
} else {
keyword = Keyword.of(bindName + " id");
return resolve(keyword, ctx);
}
}
private static String resolve(Keyword keyword, ActContext ctx) {
String value = ctx.paramVal(keyword.underscore());
if (S.notBlank(value)) {
return value;
}
value = ctx.paramVal(keyword.javaVariable());
if (S.notBlank(value)) {
return value;
}
return null;
}
}