├── README.md └── playapp ├── .gitignore ├── app ├── Module.java ├── com │ └── nrslib │ │ ├── clArc │ │ ├── UseCaseBus.java │ │ ├── UseCaseBusBuilder.java │ │ ├── inject │ │ │ ├── ServiceCollection.java │ │ │ └── ServiceProvider.java │ │ └── invoke │ │ │ ├── UseCaseInvoker.java │ │ │ └── UseCaseInvokerFactory.java │ │ ├── domain │ │ ├── application │ │ │ ├── account │ │ │ │ └── AccountGetInfoInteractor.java │ │ │ ├── auth │ │ │ │ └── AuthLoginInteractor.java │ │ │ └── user │ │ │ │ ├── UserAddInteractor.java │ │ │ │ ├── UserDeleteInteractor.java │ │ │ │ ├── UserGetDetailInteractor.java │ │ │ │ ├── UserGetListInteractor.java │ │ │ │ └── UserUpdateInteractor.java │ │ ├── context │ │ │ └── UserContext.java │ │ └── model │ │ │ └── user │ │ │ ├── User.java │ │ │ ├── UserDomainService.java │ │ │ ├── UserId.java │ │ │ ├── UserName.java │ │ │ ├── UserRepository.java │ │ │ └── UserRole.java │ │ ├── lib │ │ └── json │ │ │ └── objectLoader │ │ │ ├── JsonsFile.java │ │ │ └── JsonsLoader.java │ │ ├── stubs │ │ ├── account │ │ │ └── StubAccountGetInfoInteractor.java │ │ ├── auth │ │ │ └── StubAuthLoginInteractor.java │ │ ├── jsons │ │ │ ├── AccountGetInfoOutputData.jsons │ │ │ ├── AuthLoginOutputData.jsons │ │ │ ├── UserAddOutputData.jsons │ │ │ ├── UserDeleteOutputData.jsons │ │ │ ├── UserGetDetailOutputData.jsons │ │ │ ├── UserGetListOutputData.jsons │ │ │ └── UserUpdateOutputData.jsons │ │ └── users │ │ │ ├── StubUserAddInteractor.java │ │ │ ├── StubUserDeleteInteractor.java │ │ │ ├── StubUserGetDetailInteractor.java │ │ │ ├── StubUserGetListInteractor.java │ │ │ └── StubUserUpdateInteractor.java │ │ └── usecases │ │ ├── account │ │ ├── commons │ │ │ └── AccountInfo.java │ │ └── getInfo │ │ │ ├── AccountGetInfoInputData.java │ │ │ ├── AccountGetInfoOutputData.java │ │ │ └── AccountGetInfoUseCase.java │ │ ├── auth │ │ └── login │ │ │ ├── AuthLoginInputData.java │ │ │ ├── AuthLoginOutputData.java │ │ │ └── AuthLoginUseCase.java │ │ ├── core │ │ ├── InputData.java │ │ ├── OutputData.java │ │ └── UseCase.java │ │ └── user │ │ ├── add │ │ ├── UserAddInputData.java │ │ ├── UserAddOutputData.java │ │ └── UserAddUseCase.java │ │ ├── common │ │ └── UserData.java │ │ ├── delete │ │ ├── UserDeleteInputData.java │ │ ├── UserDeleteOutputData.java │ │ └── UserDeleteUseCase.java │ │ ├── getDetail │ │ ├── UserGetDetailInputData.java │ │ ├── UserGetDetailOutputData.java │ │ └── UserGetDetailUseCase.java │ │ ├── getList │ │ ├── UserGetListInputData.java │ │ ├── UserGetListOutputData.java │ │ └── UserGetListUseCase.java │ │ └── update │ │ ├── UserUpdateInputData.java │ │ ├── UserUpdateOutputData.java │ │ └── UserUpdateUseCase.java ├── config │ └── inject │ │ ├── DebugDependencyConfig.java │ │ ├── DependencyConfig.java │ │ ├── GuicyServiceProvider.java │ │ └── ProductDependencyConfig.java ├── controllers │ ├── AccountController.java │ ├── Application.java │ ├── AuthController.java │ └── UserController.java ├── gateways │ └── user │ │ └── EBeanUserRepository.java ├── lib │ ├── auth │ │ ├── AppAccountInfo.java │ │ └── LoginService.java │ ├── context │ │ └── HttpSessionUserContext.java │ ├── forClArc │ │ ├── PlayUseCaseInvoker.java │ │ └── PlayUseCaseInvokerFactory.java │ └── view │ │ └── converter │ │ └── user │ │ └── UserRoleConverter.java ├── models │ └── User.java ├── viewmodels │ ├── account │ │ └── AccountIndexViewModel.java │ ├── auth │ │ ├── AuthCheckViewModel.java │ │ └── login │ │ │ └── AuthLoginForm.java │ └── user │ │ ├── UserDetailViewModel.java │ │ ├── UserGetListViewModel.java │ │ ├── add │ │ ├── UserAddForm.java │ │ └── UserAddInputViewModel.java │ │ ├── common │ │ └── UserViewModel.java │ │ └── update │ │ ├── UserUpdateForm.java │ │ └── UserUpdateInputViewModel.java └── views │ ├── account │ └── index.scala.html │ ├── auth │ ├── check.scala.html │ └── login.scala.html │ ├── index.scala.html │ ├── main.scala.html │ └── user │ ├── add │ └── input.scala.html │ ├── detail.scala.html │ ├── index.scala.html │ └── update │ └── input.scala.html ├── build.sbt ├── conf ├── application.conf ├── evolutions │ └── default │ │ └── 1.sql └── routes ├── project ├── build.properties └── plugins.sbt ├── public ├── images │ └── favicon.png ├── javascripts │ ├── bootstrap.min.js │ ├── jquery-1.9.0.min.js │ ├── jquery-3.4.0.min.js │ └── popper.min.js └── stylesheets │ ├── bootstrap.min.css │ └── main.css └── test ├── ApplicationTest.java └── IntegrationTest.java /README.md: -------------------------------------------------------------------------------- 1 | # play-clean-java 2 | 3 | Clean Architecture sample in PlayFramework 4 | 5 | ## 機能 6 | アプリケーションの機能は次のとおりです。 7 | 8 | * ユーザ CRUD 9 | * ログインとログイン情報確認 10 | 11 | # Config 12 | 13 | ## application.conf 14 | 15 | ``` 16 | # My project config: 17 | # project.di = "product" 18 | project.di = "debug" 19 | ``` 20 | 21 | 設定のコメントアウトを変更することでプロダクトモードとデバッグモードが切り替わります。 22 | 23 | * "debug": DebugDependencyConfig が利用されます。 24 | * "product": ProductDependencyConfig が利用されます。 25 | -------------------------------------------------------------------------------- /playapp/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | project/project 3 | project/target 4 | target 5 | tmp 6 | .history 7 | dist 8 | /.idea 9 | /*.iml 10 | /out 11 | /.idea_modules 12 | /.classpath 13 | /.project 14 | /RUNNING_PID 15 | /.settings -------------------------------------------------------------------------------- /playapp/app/Module.java: -------------------------------------------------------------------------------- 1 | import com.google.inject.AbstractModule; 2 | import com.nrslib.clArc.inject.ServiceCollection; 3 | import com.nrslib.clArc.inject.ServiceProvider; 4 | import com.typesafe.config.Config; 5 | import config.inject.DebugDependencyConfig; 6 | import config.inject.DependencyConfig; 7 | import config.inject.GuicyServiceProvider; 8 | import config.inject.ProductDependencyConfig; 9 | import lib.view.converter.user.UserRoleConverter; 10 | import play.Configuration; 11 | import play.Environment; 12 | 13 | public class Module extends AbstractModule implements ServiceCollection { 14 | private final Configuration configuration; 15 | 16 | public Module(Environment environment, Configuration configuration) { 17 | this.configuration = configuration; 18 | } 19 | 20 | @Override 21 | public void addTransient(Class clazz) { 22 | bind(clazz); 23 | } 24 | 25 | @Override 26 | public void addTransient(Class clazzFrom, Class clazzTo) { 27 | bind(clazzFrom).to(clazzTo); 28 | } 29 | 30 | @Override 31 | public void addSingleton(Class clazz) { 32 | bind(clazz).asEagerSingleton(); 33 | } 34 | 35 | @Override 36 | public void addInstance(Class clazz, TInstance instance) { 37 | bind(clazz).toInstance(instance); 38 | } 39 | 40 | @Override 41 | public ServiceProvider buildServiceProvider() { 42 | return new GuicyServiceProvider(); 43 | } 44 | 45 | @Override 46 | protected void configure() { 47 | DependencyConfig dependencyConfig = dependencyConfig(); 48 | dependencyConfig.register(this); 49 | configureCommons(); 50 | } 51 | 52 | private DependencyConfig dependencyConfig(){ 53 | switch (configuration.getString("project.di")){ 54 | case "debug": return new DebugDependencyConfig(); 55 | case "product": return new ProductDependencyConfig(); 56 | default: throw new RuntimeException(); 57 | } 58 | } 59 | 60 | private void configureCommons() { 61 | bind(UserRoleConverter.class); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/UseCaseBus.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc; 2 | 3 | import com.nrslib.clArc.inject.ServiceProvider; 4 | import com.nrslib.clArc.invoke.UseCaseInvoker; 5 | import com.nrslib.clArc.invoke.UseCaseInvokerFactory; 6 | import com.nrslib.usecases.core.InputData; 7 | import com.nrslib.usecases.core.OutputData; 8 | 9 | import java.util.HashMap; 10 | 11 | public class UseCaseBus { 12 | private final HashMap handlerTypes = new HashMap<>(); 13 | private final HashMap invokers = new HashMap<>(); 14 | 15 | private ServiceProvider provider; 16 | private UseCaseInvokerFactory invokerFactory; 17 | 18 | UseCaseBus(){ } 19 | 20 | public , TOutputData extends OutputData> TOutputData handle(TInputData inputData){ 21 | UseCaseInvoker invoker = getInvoker(inputData); 22 | return invoker.invoke(inputData); 23 | } 24 | 25 | void setup(ServiceProvider provider, UseCaseInvokerFactory invokerFactory){ 26 | this.provider = provider; 27 | this.invokerFactory = invokerFactory; 28 | } 29 | 30 | void register(Class inputDataClazz, Class outputDataClazz) { 31 | handlerTypes.put(inputDataClazz, outputDataClazz); 32 | } 33 | 34 | private UseCaseInvoker getInvoker(InputData inputData) { 35 | Class inputDataClazz = inputData.getClass(); 36 | 37 | UseCaseInvoker invoker = invokers.getOrDefault(inputDataClazz, null); 38 | if(invoker != null) { 39 | return invoker; 40 | } 41 | 42 | Class handlerClazz = handlerTypes.getOrDefault(inputDataClazz, null); 43 | if(handlerClazz == null){ 44 | throw new RuntimeException("not registered"); 45 | } 46 | 47 | invoker = invokerFactory.generate(handlerClazz, provider); 48 | invokers.put(inputDataClazz, invoker); 49 | return invoker; 50 | } 51 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/UseCaseBusBuilder.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc; 2 | 3 | import com.nrslib.clArc.inject.ServiceCollection; 4 | import com.nrslib.clArc.invoke.UseCaseInvokerFactory; 5 | import com.nrslib.usecases.core.InputData; 6 | import com.nrslib.usecases.core.UseCase; 7 | 8 | public class UseCaseBusBuilder { 9 | private ServiceCollection services; 10 | private UseCaseBus bus = new UseCaseBus(); 11 | 12 | public UseCaseBusBuilder(ServiceCollection services){ 13 | this.services = services; 14 | } 15 | 16 | public void register(Class inputDataClazz, Class interactorClazz){ 17 | services.addTransient(interactorClazz); 18 | bus.register(inputDataClazz, interactorClazz); 19 | } 20 | 21 | public UseCaseBus build(UseCaseInvokerFactory invokerFactory){ 22 | bus.setup(services.buildServiceProvider(), invokerFactory); 23 | return bus; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/inject/ServiceCollection.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc.inject; 2 | 3 | public interface ServiceCollection { 4 | void addTransient(Class clazz); 5 | void addTransient(Class clazzFrom, Class clazzTo); 6 | void addSingleton(Class clazz); 7 | void addInstance(Class clazz, TInstance instance); 8 | ServiceProvider buildServiceProvider(); 9 | } 10 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/inject/ServiceProvider.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc.inject; 2 | 3 | public interface ServiceProvider { 4 | T getService(Class type); 5 | } 6 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/invoke/UseCaseInvoker.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc.invoke; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | import com.nrslib.usecases.core.OutputData; 5 | 6 | public interface UseCaseInvoker { 7 | public TOutputData invoke(InputData inputData); 8 | } 9 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/clArc/invoke/UseCaseInvokerFactory.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.clArc.invoke; 2 | 3 | import com.nrslib.clArc.inject.ServiceProvider; 4 | 5 | public interface UseCaseInvokerFactory { 6 | UseCaseInvoker generate(Class implementClazz, ServiceProvider provider); 7 | } 8 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/account/AccountGetInfoInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.account; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.context.UserContext; 5 | import com.nrslib.usecases.account.commons.AccountInfo; 6 | import com.nrslib.usecases.account.getInfo.AccountGetInfoInputData; 7 | import com.nrslib.usecases.account.getInfo.AccountGetInfoOutputData; 8 | import com.nrslib.usecases.account.getInfo.AccountGetInfoUseCase; 9 | 10 | public class AccountGetInfoInteractor implements AccountGetInfoUseCase { 11 | @Inject 12 | private UserContext userContext; 13 | 14 | @Override 15 | public AccountGetInfoOutputData handle(AccountGetInfoInputData inputData) { 16 | String id = userContext.getId(); 17 | 18 | // get data from user id 19 | AccountInfo accountInfo = new AccountInfo(id, "mock-user-name"); 20 | 21 | return new AccountGetInfoOutputData(accountInfo); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/auth/AuthLoginInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.auth; 2 | 3 | import com.nrslib.usecases.account.commons.AccountInfo; 4 | import com.nrslib.usecases.auth.login.AuthLoginInputData; 5 | import com.nrslib.usecases.auth.login.AuthLoginOutputData; 6 | import com.nrslib.usecases.auth.login.AuthLoginUseCase; 7 | 8 | public class AuthLoginInteractor implements AuthLoginUseCase { 9 | @Override 10 | public AuthLoginOutputData handle(AuthLoginInputData inputData) { 11 | return new AuthLoginOutputData(true, new AccountInfo("mock-test-id", "mock-test-user")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/user/UserAddInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.user; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.model.user.User; 5 | import com.nrslib.domain.model.user.UserId; 6 | import com.nrslib.domain.model.user.UserName; 7 | import com.nrslib.domain.model.user.UserRepository; 8 | import com.nrslib.usecases.user.add.UserAddInputData; 9 | import com.nrslib.usecases.user.add.UserAddOutputData; 10 | import com.nrslib.usecases.user.add.UserAddUseCase; 11 | import play.db.ebean.Transactional; 12 | 13 | import java.util.UUID; 14 | 15 | @Transactional 16 | public class UserAddInteractor implements UserAddUseCase { 17 | 18 | @Inject 19 | private UserRepository userRepository; 20 | 21 | @Override 22 | public UserAddOutputData handle(UserAddInputData inputData) { 23 | String uuid = UUID.randomUUID().toString(); 24 | 25 | User user = new User( 26 | new UserId(uuid), 27 | new UserName(inputData.getUserName()), 28 | inputData.getRole() 29 | ); 30 | 31 | userRepository.save(user); 32 | 33 | return new UserAddOutputData(uuid); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/user/UserDeleteInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.user; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.model.user.UserId; 5 | import com.nrslib.domain.model.user.UserRepository; 6 | import com.nrslib.usecases.user.delete.UserDeleteInputData; 7 | import com.nrslib.usecases.user.delete.UserDeleteOutputData; 8 | import com.nrslib.usecases.user.delete.UserDeleteUseCase; 9 | import play.db.ebean.Transactional; 10 | 11 | @Transactional 12 | public class UserDeleteInteractor implements UserDeleteUseCase { 13 | @Inject 14 | private UserRepository userRepository; 15 | 16 | @Override 17 | public UserDeleteOutputData handle(UserDeleteInputData inputData) { 18 | UserId targetId = new UserId(inputData.getId()); 19 | 20 | userRepository 21 | .find(targetId) 22 | .ifPresent(x -> userRepository.remove(x)); 23 | 24 | return new UserDeleteOutputData(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/user/UserGetDetailInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.user; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.model.user.UserId; 5 | import com.nrslib.domain.model.user.UserRepository; 6 | import com.nrslib.usecases.user.common.UserData; 7 | import com.nrslib.usecases.user.getDetail.UserGetDetailInputData; 8 | import com.nrslib.usecases.user.getDetail.UserGetDetailOutputData; 9 | import com.nrslib.usecases.user.getDetail.UserGetDetailUseCase; 10 | 11 | import java.util.Optional; 12 | 13 | public class UserGetDetailInteractor implements UserGetDetailUseCase { 14 | @Inject 15 | private UserRepository userRepository; 16 | 17 | @Override 18 | public UserGetDetailOutputData handle(UserGetDetailInputData inputData) { 19 | String inputId = inputData.getUserId(); 20 | UserId targetId = new UserId(inputId); 21 | 22 | Optional optUserData = userRepository.find(targetId) 23 | .map(x -> new UserData(x.getId().getValue(), x.getName().getValue(), x.getRole())); 24 | 25 | return new UserGetDetailOutputData(optUserData); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/user/UserGetListInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.user; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.model.user.User; 5 | import com.nrslib.domain.model.user.UserRepository; 6 | import com.nrslib.usecases.user.common.UserData; 7 | import com.nrslib.usecases.user.getList.UserGetListInputData; 8 | import com.nrslib.usecases.user.getList.UserGetListOutputData; 9 | import com.nrslib.usecases.user.getList.UserGetListUseCase; 10 | 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | public class UserGetListInteractor implements UserGetListUseCase { 15 | @Inject 16 | private UserRepository userRepository; 17 | 18 | public UserGetListOutputData handle(UserGetListInputData inputData) { 19 | List users = userRepository.findAll(); 20 | 21 | List userData = users.stream() 22 | .map(x -> new UserData(x.getId().getValue(), x.getName().getValue(), x.getRole())) 23 | .collect(Collectors.toList()); 24 | 25 | return new UserGetListOutputData(userData); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/application/user/UserUpdateInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.application.user; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.model.user.User; 5 | import com.nrslib.domain.model.user.UserId; 6 | import com.nrslib.domain.model.user.UserName; 7 | import com.nrslib.domain.model.user.UserRepository; 8 | import com.nrslib.usecases.user.update.UserUpdateInputData; 9 | import com.nrslib.usecases.user.update.UserUpdateOutputData; 10 | import com.nrslib.usecases.user.update.UserUpdateUseCase; 11 | import play.db.ebean.Transactional; 12 | 13 | @Transactional 14 | public class UserUpdateInteractor implements UserUpdateUseCase { 15 | @Inject 16 | private UserRepository userRepository; 17 | 18 | @Override 19 | public UserUpdateOutputData handle(UserUpdateInputData inputData) { 20 | UserId targetId = new UserId(inputData.getId()); 21 | User target = userRepository.find(targetId).get(); 22 | 23 | UserName newName = new UserName(inputData.getName()); 24 | target.changeName(newName); 25 | 26 | userRepository.save(target); 27 | 28 | return new UserUpdateOutputData(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/context/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.context; 2 | 3 | public interface UserContext { 4 | public String getId(); 5 | } 6 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/User.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | public class User { 4 | private UserId id; 5 | private UserName name; 6 | private UserRole role; 7 | 8 | public User(UserId id, UserName name, UserRole role) { 9 | this.id = id; 10 | this.name = name; 11 | this.role = role; 12 | } 13 | 14 | public UserId getId() { 15 | return id; 16 | } 17 | 18 | public UserName getName() { 19 | return name; 20 | } 21 | 22 | public UserRole getRole() { return role; } 23 | 24 | public void changeName(UserName name) { 25 | this.name = name; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/UserDomainService.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | import com.google.inject.Inject; 4 | 5 | public class UserDomainService { 6 | @Inject 7 | private UserRepository userRepository; 8 | 9 | public boolean isDuplicated(User user) { 10 | return false; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | public class UserId { 4 | private String value; 5 | 6 | public UserId(String value) { 7 | this.value = value; 8 | } 9 | 10 | public String getValue() { 11 | return value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/UserName.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | public class UserName { 4 | private String value; 5 | 6 | public UserName(String value) { 7 | if (value.length() < 3) throw new RuntimeException(); 8 | if (value.length() > 10) throw new RuntimeException(); 9 | this.value = value; 10 | } 11 | 12 | public String getValue() { 13 | return value; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | public interface UserRepository { 7 | public void save(User user); 8 | public void remove(User user); 9 | public List findAll(); 10 | public Optional find(UserId id); 11 | } 12 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/domain/model/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.domain.model.user; 2 | 3 | public enum UserRole { 4 | ADMIN, 5 | MEMBER 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/lib/json/objectLoader/JsonsFile.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.lib.json.objectLoader; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; 6 | 7 | import java.io.IOException; 8 | import java.lang.reflect.Constructor; 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.lang.reflect.TypeVariable; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.Optional; 18 | import java.util.stream.Collectors; 19 | 20 | public class JsonsFile { 21 | private final Class clazz; 22 | private final Path filePath; 23 | private int current; 24 | 25 | public JsonsFile(Class clazz, String filePath){ 26 | this.clazz = clazz; 27 | this.filePath = Paths.get(filePath); 28 | } 29 | 30 | 31 | class Test { 32 | public Optional data; 33 | } 34 | public T next() { 35 | if (!Files.exists(filePath)) { 36 | return createAnyInstance(); 37 | } 38 | 39 | String content; 40 | try { 41 | content = Files.readAllLines(filePath).stream().collect(Collectors.joining(System.lineSeparator())); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | return createAnyInstance(); 45 | } 46 | 47 | List jsons = splitJsons(content); 48 | String targetJson = current < jsons.size() ? jsons.get(current) : lastOrDefault(jsons); 49 | current++; 50 | 51 | if (targetJson == null) { 52 | return createAnyInstance(); 53 | } 54 | 55 | ObjectMapper mapper = new ObjectMapper(); 56 | mapper.registerModule(new Jdk8Module()); 57 | try { 58 | return mapper.readValue(targetJson, clazz); 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | return createAnyInstance(); 62 | } 63 | } 64 | 65 | private T createAnyInstance() { 66 | Constructor constructor = clazz.getConstructors()[0]; 67 | try { 68 | Object[] args = Arrays.stream(constructor.getParameterTypes()) 69 | .map(x -> { 70 | switch (x.getName()){ 71 | case "java.util.List": return new ArrayList(); 72 | default: return null; 73 | } 74 | 75 | }) 76 | .toArray(); 77 | return (T)constructor.newInstance(args); 78 | } catch (InstantiationException e) { 79 | e.printStackTrace(); 80 | } catch (IllegalAccessException e) { 81 | e.printStackTrace(); 82 | } catch (InvocationTargetException e) { 83 | e.printStackTrace(); 84 | } 85 | 86 | return null; 87 | } 88 | 89 | private List splitJsons(String content) { 90 | List acc = new ArrayList<>(); 91 | StringBuilder sb = new StringBuilder(); 92 | Integer nest = 0; 93 | 94 | for(Character c : content.toCharArray()) { 95 | sb.append(c); 96 | if(c.equals('{')) { 97 | nest++; 98 | }else if(c.equals('}')){ 99 | nest--; 100 | if(nest == 0) { 101 | acc.add(sb.toString()); 102 | sb = new StringBuilder(); 103 | } 104 | } 105 | } 106 | 107 | return acc; 108 | } 109 | 110 | private T lastOrDefault(List source){ 111 | if(source == null) { 112 | return null; 113 | } 114 | 115 | if(source.size() == 0) { 116 | return null; 117 | } 118 | 119 | return source.get(source.size() - 1); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/lib/json/objectLoader/JsonsLoader.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.lib.json.objectLoader; 2 | 3 | import java.io.File; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class JsonsLoader { 8 | private final String fileDirectoryPath; 9 | private Map files = new HashMap<>(); 10 | 11 | public JsonsLoader(String fileDirectoryFullPath) { 12 | this.fileDirectoryPath = fileDirectoryFullPath; 13 | } 14 | 15 | public T generate(Class clazz) { 16 | if(!files.containsKey(clazz)){ 17 | files.put(clazz, createDefaultFiles(clazz)); 18 | } 19 | 20 | JsonsFile jsonsFile = files.get(clazz); 21 | return jsonsFile.next(); 22 | } 23 | 24 | private JsonsFile createDefaultFiles(Class clazz) { 25 | String filePath = new File(fileDirectoryPath, clazz.getSimpleName() + ".jsons").getPath(); 26 | return new JsonsFile<>(clazz, filePath); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/account/StubAccountGetInfoInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.account; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.account.getInfo.AccountGetInfoInputData; 6 | import com.nrslib.usecases.account.getInfo.AccountGetInfoOutputData; 7 | import com.nrslib.usecases.account.getInfo.AccountGetInfoUseCase; 8 | 9 | public class StubAccountGetInfoInteractor implements AccountGetInfoUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public AccountGetInfoOutputData handle(AccountGetInfoInputData inputData) { 15 | return jsonsLoader.generate(AccountGetInfoOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/auth/StubAuthLoginInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.auth; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.auth.login.AuthLoginInputData; 6 | import com.nrslib.usecases.auth.login.AuthLoginOutputData; 7 | import com.nrslib.usecases.auth.login.AuthLoginUseCase; 8 | 9 | public class StubAuthLoginInteractor implements AuthLoginUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public AuthLoginOutputData handle(AuthLoginInputData inputData) { 15 | return jsonsLoader.generate(AuthLoginOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/AccountGetInfoOutputData.jsons: -------------------------------------------------------------------------------- 1 | { 2 | "accountInfo" : { 3 | "id" : "test-id", 4 | "name" : "test-name" 5 | } 6 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/AuthLoginOutputData.jsons: -------------------------------------------------------------------------------- 1 | { 2 | "success" : true, 3 | "accountInfo" : { 4 | "id" : "test-id", 5 | "name" : "test-user-name" 6 | } 7 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/UserAddOutputData.jsons: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrslib/play-clean-java/1ed916fd49d1905ae65c6b9069e7c13562a07746/playapp/app/com/nrslib/stubs/jsons/UserAddOutputData.jsons -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/UserDeleteOutputData.jsons: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrslib/play-clean-java/1ed916fd49d1905ae65c6b9069e7c13562a07746/playapp/app/com/nrslib/stubs/jsons/UserDeleteOutputData.jsons -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/UserGetDetailOutputData.jsons: -------------------------------------------------------------------------------- 1 | { 2 | "userData" : { 3 | "id" : "a", 4 | "name" : "test", 5 | "role" : 0 6 | } 7 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/UserGetListOutputData.jsons: -------------------------------------------------------------------------------- 1 | { 2 | "users" : [ 3 | { 4 | "id" : "1", 5 | "name" : "testuser-1", 6 | "role" : 0 7 | }, 8 | { 9 | "id" : "2", 10 | "name" : "testuser-2", 11 | "role" : 1 12 | }, 13 | { 14 | "id" : "3", 15 | "name" : "testuser-3", 16 | "role" : 1 17 | } 18 | ] 19 | } 20 | { 21 | "users" : [ 22 | { 23 | "id" : "1", 24 | "name" : "testuser-1", 25 | "role" : 0 26 | }, 27 | { 28 | "id" : "2", 29 | "name" : "testuser-2", 30 | "role" : 1 31 | }, 32 | { 33 | "id" : "3", 34 | "name" : "testuser-3", 35 | "role" : 1 36 | }, 37 | { 38 | "id" : "4", 39 | "name" : "testuser-4", 40 | "role" : 1 41 | }, 42 | ] 43 | } 44 | { 45 | "users" : [ 46 | { 47 | "id" : "1", 48 | "name" : "testuser-1", 49 | "role" : 0 50 | }, 51 | { 52 | "id" : "2", 53 | "name" : "testuser-2", 54 | "role" : 1 55 | }, 56 | { 57 | "id" : "3", 58 | "name" : "testuser-3", 59 | "role" : 1 60 | }, 61 | { 62 | "id" : "4", 63 | "name" : "testuser-4", 64 | "role" : 1 65 | }, 66 | { 67 | "id" : "5", 68 | "name" : "testuser-5", 69 | "role" : 1 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/jsons/UserUpdateOutputData.jsons: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/users/StubUserAddInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.users; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.user.add.UserAddInputData; 6 | import com.nrslib.usecases.user.add.UserAddOutputData; 7 | import com.nrslib.usecases.user.add.UserAddUseCase; 8 | 9 | public class StubUserAddInteractor implements UserAddUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public UserAddOutputData handle(UserAddInputData inputData) { 15 | return jsonsLoader.generate(UserAddOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/users/StubUserDeleteInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.users; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.user.delete.UserDeleteInputData; 6 | import com.nrslib.usecases.user.delete.UserDeleteOutputData; 7 | import com.nrslib.usecases.user.delete.UserDeleteUseCase; 8 | 9 | public class StubUserDeleteInteractor implements UserDeleteUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public UserDeleteOutputData handle(UserDeleteInputData inputData) { 15 | return jsonsLoader.generate(UserDeleteOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/users/StubUserGetDetailInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.users; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.user.getDetail.UserGetDetailInputData; 6 | import com.nrslib.usecases.user.getDetail.UserGetDetailOutputData; 7 | import com.nrslib.usecases.user.getDetail.UserGetDetailUseCase; 8 | 9 | public class StubUserGetDetailInteractor implements UserGetDetailUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public UserGetDetailOutputData handle(UserGetDetailInputData inputData) { 15 | return jsonsLoader.generate(UserGetDetailOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/users/StubUserGetListInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.users; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.user.getList.UserGetListInputData; 6 | import com.nrslib.usecases.user.getList.UserGetListOutputData; 7 | import com.nrslib.usecases.user.getList.UserGetListUseCase; 8 | 9 | public class StubUserGetListInteractor implements UserGetListUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public UserGetListOutputData handle(UserGetListInputData inputData) { 15 | return jsonsLoader.generate(UserGetListOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/stubs/users/StubUserUpdateInteractor.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.stubs.users; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 5 | import com.nrslib.usecases.user.update.UserUpdateInputData; 6 | import com.nrslib.usecases.user.update.UserUpdateOutputData; 7 | import com.nrslib.usecases.user.update.UserUpdateUseCase; 8 | 9 | public class StubUserUpdateInteractor implements UserUpdateUseCase { 10 | @Inject 11 | private JsonsLoader jsonsLoader; 12 | 13 | @Override 14 | public UserUpdateOutputData handle(UserUpdateInputData inputData) { 15 | return jsonsLoader.generate(UserUpdateOutputData.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/account/commons/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.account.commons; 2 | 3 | public class AccountInfo { 4 | private String id; 5 | private String name; 6 | 7 | public AccountInfo(String id, String name) { 8 | this.id = id; 9 | this.name = name; 10 | } 11 | 12 | private AccountInfo() {} 13 | 14 | public String getId() { 15 | return id; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/account/getInfo/AccountGetInfoInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.account.getInfo; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class AccountGetInfoInputData implements InputData { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/account/getInfo/AccountGetInfoOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.account.getInfo; 2 | 3 | import com.nrslib.usecases.account.commons.AccountInfo; 4 | import com.nrslib.usecases.core.OutputData; 5 | 6 | public class AccountGetInfoOutputData implements OutputData { 7 | private AccountInfo accountInfo; 8 | 9 | public AccountGetInfoOutputData(AccountInfo accountInfo) { 10 | this.accountInfo = accountInfo; 11 | } 12 | 13 | private AccountGetInfoOutputData() {} 14 | 15 | public AccountInfo getAccountInfo() { 16 | return accountInfo; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/account/getInfo/AccountGetInfoUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.account.getInfo; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface AccountGetInfoUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/auth/login/AuthLoginInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.auth.login; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class AuthLoginInputData implements InputData { 6 | private final String id; 7 | private final String password; 8 | 9 | public AuthLoginInputData(String id, String password) { 10 | this.id = id; 11 | this.password = password; 12 | } 13 | 14 | public String getId() { 15 | return id; 16 | } 17 | 18 | public String getPassword() { 19 | return password; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/auth/login/AuthLoginOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.auth.login; 2 | 3 | import com.nrslib.usecases.account.commons.AccountInfo; 4 | import com.nrslib.usecases.core.OutputData; 5 | 6 | public class AuthLoginOutputData implements OutputData { 7 | private boolean success; 8 | private AccountInfo accountInfo; 9 | 10 | public AuthLoginOutputData(boolean success, AccountInfo accountInfo) { 11 | this.success = success; 12 | this.accountInfo = accountInfo; 13 | } 14 | 15 | private AuthLoginOutputData() {} 16 | 17 | public boolean isSuccess() { 18 | return success; 19 | } 20 | 21 | public AccountInfo getAccountInfo() { return accountInfo; } 22 | } 23 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/auth/login/AuthLoginUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.auth.login; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface AuthLoginUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/core/InputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.core; 2 | 3 | public interface InputData { 4 | } 5 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/core/OutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.core; 2 | 3 | public interface OutputData { 4 | } 5 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/core/UseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.core; 2 | 3 | public interface UseCase { 4 | TOutputData handle(TInputData inputData); 5 | } 6 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/add/UserAddInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.add; 2 | 3 | import com.nrslib.domain.model.user.UserRole; 4 | import com.nrslib.usecases.core.InputData; 5 | 6 | public class UserAddInputData implements InputData { 7 | private final String userName; 8 | private final UserRole role; 9 | 10 | public UserAddInputData(String userName, UserRole role) { 11 | this.userName = userName; 12 | this.role = role; 13 | } 14 | 15 | public String getUserName() { 16 | return userName; 17 | } 18 | 19 | public UserRole getRole() { 20 | return role; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/add/UserAddOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.add; 2 | 3 | import com.nrslib.usecases.core.OutputData; 4 | 5 | public class UserAddOutputData implements OutputData { 6 | private String userId; 7 | 8 | public UserAddOutputData(String userId) { 9 | this.userId = userId; 10 | } 11 | 12 | private UserAddOutputData() {} 13 | 14 | public String getUserId() { 15 | return userId; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/add/UserAddUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.add; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | import play.db.ebean.Transactional; 5 | 6 | @Transactional 7 | public interface UserAddUseCase extends UseCase { 8 | } 9 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/common/UserData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.common; 2 | 3 | import com.nrslib.domain.model.user.UserRole; 4 | 5 | public class UserData { 6 | private String id; 7 | private String name; 8 | private UserRole role; 9 | 10 | public UserData(String id, String name, UserRole role) { 11 | this.id = id; 12 | this.name = name; 13 | this.role = role; 14 | } 15 | 16 | private UserData(){ 17 | } 18 | 19 | public String getId() { 20 | return id; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public UserRole getRole() { return role; } 28 | } 29 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/delete/UserDeleteInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.delete; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class UserDeleteInputData implements InputData { 6 | private final String id; 7 | 8 | public UserDeleteInputData(String id) { 9 | this.id = id; 10 | } 11 | 12 | public String getId() { 13 | return id; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/delete/UserDeleteOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.delete; 2 | 3 | import com.nrslib.usecases.core.OutputData; 4 | 5 | public class UserDeleteOutputData implements OutputData { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/delete/UserDeleteUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.delete; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface UserDeleteUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getDetail/UserGetDetailInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getDetail; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class UserGetDetailInputData implements InputData { 6 | private String userId; 7 | 8 | public UserGetDetailInputData(String userId) { 9 | this.userId = userId; 10 | } 11 | 12 | public String getUserId() { 13 | return userId; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getDetail/UserGetDetailOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getDetail; 2 | 3 | import com.nrslib.usecases.core.OutputData; 4 | import com.nrslib.usecases.user.common.UserData; 5 | 6 | import java.util.Optional; 7 | 8 | public class UserGetDetailOutputData implements OutputData { 9 | private Optional userData; 10 | 11 | public UserGetDetailOutputData(Optional userData) { 12 | this.userData = userData; 13 | } 14 | 15 | private UserGetDetailOutputData() { 16 | } 17 | 18 | public Optional getUserData() { 19 | return userData; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getDetail/UserGetDetailUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getDetail; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface UserGetDetailUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getList/UserGetListInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getList; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class UserGetListInputData implements InputData { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getList/UserGetListOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getList; 2 | 3 | import com.nrslib.usecases.core.OutputData; 4 | import com.nrslib.usecases.user.common.UserData; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class UserGetListOutputData implements OutputData { 10 | private List users; 11 | 12 | public UserGetListOutputData(List users) { 13 | this.users = users; 14 | } 15 | 16 | private UserGetListOutputData() { 17 | this.users = new ArrayList<>(); 18 | } 19 | 20 | public List getUsers() { 21 | return users; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/getList/UserGetListUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.getList; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface UserGetListUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/update/UserUpdateInputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.update; 2 | 3 | import com.nrslib.usecases.core.InputData; 4 | 5 | public class UserUpdateInputData implements InputData { 6 | private final String id; 7 | private final String name; 8 | 9 | private UserUpdateInputData(String id, String name) { 10 | this.id = id; 11 | this.name = name; 12 | } 13 | 14 | public String getId() { 15 | return id; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public static class Builder { 23 | private final String id; 24 | private String name; 25 | 26 | public Builder(String id) { 27 | this.id = id; 28 | } 29 | 30 | public Builder name(String name) { 31 | this.name = name; 32 | return this; 33 | } 34 | 35 | public UserUpdateInputData build(){ 36 | return new UserUpdateInputData(id, name); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/update/UserUpdateOutputData.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.update; 2 | 3 | import com.nrslib.usecases.core.OutputData; 4 | 5 | public class UserUpdateOutputData implements OutputData { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/com/nrslib/usecases/user/update/UserUpdateUseCase.java: -------------------------------------------------------------------------------- 1 | package com.nrslib.usecases.user.update; 2 | 3 | import com.nrslib.usecases.core.UseCase; 4 | 5 | public interface UserUpdateUseCase extends UseCase { 6 | } 7 | -------------------------------------------------------------------------------- /playapp/app/config/inject/DebugDependencyConfig.java: -------------------------------------------------------------------------------- 1 | package config.inject; 2 | 3 | import com.nrslib.clArc.UseCaseBus; 4 | import com.nrslib.clArc.UseCaseBusBuilder; 5 | import com.nrslib.clArc.inject.ServiceCollection; 6 | import com.nrslib.domain.model.user.UserRepository; 7 | import com.nrslib.lib.json.objectLoader.JsonsLoader; 8 | import com.nrslib.stubs.account.StubAccountGetInfoInteractor; 9 | import com.nrslib.stubs.auth.StubAuthLoginInteractor; 10 | import com.nrslib.stubs.users.*; 11 | import com.nrslib.usecases.account.getInfo.AccountGetInfoInputData; 12 | import com.nrslib.usecases.account.getInfo.AccountGetInfoUseCase; 13 | import com.nrslib.usecases.auth.login.AuthLoginInputData; 14 | import com.nrslib.usecases.core.InputData; 15 | import com.nrslib.usecases.core.OutputData; 16 | import com.nrslib.usecases.core.UseCase; 17 | import com.nrslib.usecases.user.add.UserAddInputData; 18 | import com.nrslib.usecases.user.delete.UserDeleteInputData; 19 | import com.nrslib.usecases.user.getDetail.UserGetDetailInputData; 20 | import com.nrslib.usecases.user.getList.UserGetListInputData; 21 | import com.nrslib.usecases.user.update.UserUpdateInputData; 22 | import gateways.user.EBeanUserRepository; 23 | import lib.forClArc.PlayUseCaseInvokerFactory; 24 | 25 | import java.io.File; 26 | import java.util.HashMap; 27 | 28 | public class DebugDependencyConfig implements DependencyConfig { 29 | private HashMap, Class, ? extends OutputData>>> usecaseClazzes 30 | = new HashMap, Class, ? extends OutputData>>>() { 31 | { 32 | put(AccountGetInfoInputData.class, StubAccountGetInfoInteractor.class); 33 | 34 | put(AuthLoginInputData.class, StubAuthLoginInteractor.class); 35 | 36 | put(UserAddInputData.class, StubUserAddInteractor.class); 37 | put(UserDeleteInputData.class, StubUserDeleteInteractor.class); 38 | put(UserGetDetailInputData.class, StubUserGetDetailInteractor.class); 39 | put(UserGetListInputData.class, StubUserGetListInteractor.class); 40 | put(UserUpdateInputData.class, StubUserUpdateInteractor.class); 41 | } 42 | }; 43 | 44 | public HashMap, Class, ? extends OutputData>>> usecases() { 45 | return usecaseClazzes; 46 | } 47 | 48 | @Override 49 | public void register(ServiceCollection collection) { 50 | registerUseCase(collection); 51 | registerRepositories(collection); 52 | registerForDebug(collection); 53 | } 54 | 55 | private void registerUseCase(ServiceCollection collection) { 56 | UseCaseBusBuilder builder = new UseCaseBusBuilder(collection); 57 | usecases().forEach(builder::register); 58 | 59 | UseCaseBus bus = builder.build(new PlayUseCaseInvokerFactory()); 60 | collection.addInstance(UseCaseBus.class, bus); 61 | } 62 | 63 | private void registerRepositories(ServiceCollection collection){ 64 | collection.addTransient(UserRepository.class, EBeanUserRepository.class); 65 | } 66 | 67 | private void registerForDebug(ServiceCollection collection) { 68 | String rootPath = new File(".").getAbsoluteFile().getParent(); 69 | JsonsLoader jsonsLoader = new JsonsLoader(rootPath + "/app/com/nrslib/stubs/jsons"); 70 | collection.addInstance(JsonsLoader.class, jsonsLoader); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /playapp/app/config/inject/DependencyConfig.java: -------------------------------------------------------------------------------- 1 | package config.inject; 2 | 3 | import com.nrslib.clArc.inject.ServiceCollection; 4 | 5 | public interface DependencyConfig { 6 | void register(ServiceCollection collection); 7 | } 8 | -------------------------------------------------------------------------------- /playapp/app/config/inject/GuicyServiceProvider.java: -------------------------------------------------------------------------------- 1 | package config.inject; 2 | 3 | import com.nrslib.clArc.inject.ServiceProvider; 4 | import play.api.Play; 5 | 6 | public class GuicyServiceProvider implements ServiceProvider { 7 | @Override 8 | public T getService(Class clazz) 9 | { 10 | return Play.current().injector().instanceOf(clazz); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /playapp/app/config/inject/ProductDependencyConfig.java: -------------------------------------------------------------------------------- 1 | package config.inject; 2 | 3 | import com.nrslib.clArc.UseCaseBus; 4 | import com.nrslib.clArc.UseCaseBusBuilder; 5 | import com.nrslib.clArc.inject.ServiceCollection; 6 | import com.nrslib.domain.application.account.AccountGetInfoInteractor; 7 | import com.nrslib.domain.application.auth.AuthLoginInteractor; 8 | import com.nrslib.domain.application.user.*; 9 | import com.nrslib.domain.context.UserContext; 10 | import com.nrslib.domain.model.user.UserRepository; 11 | import com.nrslib.usecases.account.getInfo.AccountGetInfoInputData; 12 | import com.nrslib.usecases.auth.login.AuthLoginInputData; 13 | import com.nrslib.usecases.core.InputData; 14 | import com.nrslib.usecases.core.OutputData; 15 | import com.nrslib.usecases.core.UseCase; 16 | import com.nrslib.usecases.user.add.UserAddInputData; 17 | import com.nrslib.usecases.user.delete.UserDeleteInputData; 18 | import com.nrslib.usecases.user.getDetail.UserGetDetailInputData; 19 | import com.nrslib.usecases.user.getList.UserGetListInputData; 20 | import com.nrslib.usecases.user.update.UserUpdateInputData; 21 | import gateways.user.EBeanUserRepository; 22 | import lib.context.HttpSessionUserContext; 23 | import lib.forClArc.PlayUseCaseInvokerFactory; 24 | 25 | import java.util.HashMap; 26 | 27 | public class ProductDependencyConfig implements DependencyConfig { 28 | private HashMap, Class, ? extends OutputData>>> usecaseClazzes 29 | = new HashMap, Class, ? extends OutputData>>>() { 30 | { 31 | put(AccountGetInfoInputData.class, AccountGetInfoInteractor.class); 32 | 33 | put(AuthLoginInputData.class, AuthLoginInteractor.class); 34 | 35 | put(UserAddInputData.class, UserAddInteractor.class); 36 | put(UserDeleteInputData.class, UserDeleteInteractor.class); 37 | put(UserGetDetailInputData.class, UserGetDetailInteractor.class); 38 | put(UserGetListInputData.class, UserGetListInteractor.class); 39 | put(UserUpdateInputData.class, UserUpdateInteractor.class); 40 | } 41 | }; 42 | 43 | public HashMap, Class, ? extends OutputData>>> usecases() { 44 | return usecaseClazzes; 45 | } 46 | 47 | @Override 48 | public void register(ServiceCollection collection) { 49 | registerUseCase(collection); 50 | registerRepositories(collection); 51 | registerLibraries(collection); 52 | } 53 | 54 | private void registerUseCase(ServiceCollection collection) { 55 | UseCaseBusBuilder builder = new UseCaseBusBuilder(collection); 56 | usecases().forEach(builder::register); 57 | 58 | UseCaseBus bus = builder.build(new PlayUseCaseInvokerFactory()); 59 | collection.addInstance(UseCaseBus.class, bus); 60 | } 61 | 62 | private void registerRepositories(ServiceCollection collection){ 63 | collection.addTransient(UserRepository.class, EBeanUserRepository.class); 64 | } 65 | 66 | private void registerLibraries(ServiceCollection collection) { 67 | collection.addTransient(UserContext.class, HttpSessionUserContext.class); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /playapp/app/controllers/AccountController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.clArc.UseCaseBus; 5 | import com.nrslib.usecases.account.commons.AccountInfo; 6 | import com.nrslib.usecases.account.getInfo.AccountGetInfoInputData; 7 | import com.nrslib.usecases.account.getInfo.AccountGetInfoOutputData; 8 | import play.mvc.Controller; 9 | import play.mvc.Result; 10 | import viewmodels.account.AccountIndexViewModel; 11 | 12 | public class AccountController extends Controller { 13 | @Inject 14 | private UseCaseBus bus; 15 | 16 | public Result index(){ 17 | AccountGetInfoInputData inputData = new AccountGetInfoInputData(); 18 | AccountGetInfoOutputData outputData = bus.handle(inputData); 19 | 20 | AccountInfo accountInfo = outputData.getAccountInfo(); 21 | AccountIndexViewModel viewModel = new AccountIndexViewModel(accountInfo.getId(), accountInfo.getName()); 22 | 23 | return ok(views.html.account.index.render(viewModel)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /playapp/app/controllers/Application.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.clArc.UseCaseBus; 5 | import com.nrslib.usecases.user.getList.UserGetListInputData; 6 | import com.nrslib.usecases.user.getList.UserGetListOutputData; 7 | import play.mvc.*; 8 | 9 | import views.html.*; 10 | 11 | public class Application extends Controller { 12 | public Result index() 13 | { 14 | return ok(index.render("Your new application is ready.")); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /playapp/app/controllers/AuthController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.clArc.UseCaseBus; 5 | import com.nrslib.usecases.account.commons.AccountInfo; 6 | import com.nrslib.usecases.auth.login.AuthLoginInputData; 7 | import com.nrslib.usecases.auth.login.AuthLoginOutputData; 8 | import lib.auth.AppAccountInfo; 9 | import lib.auth.LoginService; 10 | import play.data.Form; 11 | import play.data.FormFactory; 12 | import play.mvc.Controller; 13 | import play.mvc.Result; 14 | import viewmodels.auth.AuthCheckViewModel; 15 | import viewmodels.auth.login.AuthLoginForm; 16 | 17 | public class AuthController extends Controller { 18 | private final Form authLoginForm; 19 | 20 | @Inject 21 | private UseCaseBus bus; 22 | 23 | @Inject 24 | private LoginService loginService; 25 | 26 | @Inject 27 | public AuthController(FormFactory formFactory){ 28 | authLoginForm = formFactory.form(AuthLoginForm.class); 29 | } 30 | 31 | public Result login() { 32 | return ok(views.html.auth.login.render(authLoginForm)); 33 | } 34 | 35 | public Result submit() { 36 | Form requestForm = authLoginForm.bindFromRequest(); 37 | if(requestForm.hasErrors()) { 38 | return badRequest(views.html.auth.login.render(requestForm)); 39 | } 40 | 41 | AuthLoginForm form = requestForm.get(); 42 | 43 | AuthLoginInputData inputData = new AuthLoginInputData(form.id, form.password); 44 | AuthLoginOutputData outputData = bus.handle(inputData); 45 | 46 | if(outputData.isSuccess()) { 47 | AccountInfo accountInfo = outputData.getAccountInfo(); 48 | AppAccountInfo appAccountInfo = new AppAccountInfo(accountInfo.getId(), accountInfo.getName()); 49 | loginService.login(accountInfo.getId(), appAccountInfo); 50 | 51 | return redirect(routes.AuthController.check()); 52 | }else{ 53 | return redirect(routes.AuthController.login()); 54 | } 55 | } 56 | 57 | public Result logout() { 58 | loginService.logout(); 59 | return redirect(routes.AuthController.check()); 60 | } 61 | 62 | public Result check() { 63 | AuthCheckViewModel viewModel = new AuthCheckViewModel(loginService.isLogin()); 64 | return ok(views.html.auth.check.render(viewModel)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /playapp/app/controllers/UserController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.clArc.UseCaseBus; 5 | import com.nrslib.usecases.user.add.UserAddInputData; 6 | import com.nrslib.usecases.user.delete.UserDeleteInputData; 7 | import com.nrslib.usecases.user.getDetail.UserGetDetailInputData; 8 | import com.nrslib.usecases.user.getDetail.UserGetDetailOutputData; 9 | import com.nrslib.usecases.user.getList.UserGetListInputData; 10 | import com.nrslib.usecases.user.getList.UserGetListOutputData; 11 | import com.nrslib.usecases.user.update.UserUpdateInputData; 12 | import lib.view.converter.user.UserRoleConverter; 13 | import play.data.Form; 14 | import play.data.FormFactory; 15 | import play.db.ebean.Transactional; 16 | import play.mvc.Controller; 17 | import play.mvc.Result; 18 | import viewmodels.user.UserDetailViewModel; 19 | import viewmodels.user.UserGetListViewModel; 20 | import viewmodels.user.add.UserAddForm; 21 | import viewmodels.user.add.UserAddInputViewModel; 22 | import viewmodels.user.common.UserViewModel; 23 | import viewmodels.user.update.UserUpdateForm; 24 | import viewmodels.user.update.UserUpdateInputViewModel; 25 | import views.html.user.detail; 26 | import views.html.user.index; 27 | 28 | import java.util.List; 29 | import java.util.stream.Collectors; 30 | 31 | public class UserController extends Controller { 32 | private final Form userAddForm; 33 | private final Form userUpdateForm; 34 | 35 | @Inject 36 | private UseCaseBus bus; 37 | 38 | @Inject 39 | private UserRoleConverter userRoleConverter; 40 | 41 | @Inject 42 | public UserController(FormFactory formFactory){ 43 | userAddForm = formFactory.form(UserAddForm.class); 44 | userUpdateForm = formFactory.form(UserUpdateForm.class); 45 | } 46 | 47 | public Result index() { 48 | UserGetListInputData inputData = new UserGetListInputData(); 49 | UserGetListOutputData outputData = bus.handle(inputData); 50 | 51 | List userViewModels = outputData.getUsers().stream() 52 | .map(user -> new UserViewModel(user.getId(), user.getName())) 53 | .collect(Collectors.toList()); 54 | 55 | UserGetListViewModel viewModel = new UserGetListViewModel(userViewModels); 56 | 57 | return ok(index.render(viewModel)); 58 | } 59 | 60 | public Result addInput () { 61 | return ok(views.html.user.add.input.render(new UserAddInputViewModel(), userAddForm)); 62 | } 63 | 64 | public Result addInputSubmit(){ 65 | Form requestForm = userAddForm.bindFromRequest(); 66 | if(requestForm.hasErrors()){ 67 | return badRequest(views.html.user.add.input.render(new UserAddInputViewModel(), requestForm)); 68 | } 69 | 70 | UserAddForm form = requestForm.get(); 71 | 72 | UserAddInputData inputData = new UserAddInputData(form.name, userRoleConverter.convert(form.roleId)); 73 | bus.handle(inputData); 74 | 75 | return redirect(routes.UserController.index()); 76 | } 77 | 78 | public Result detail(String id) { 79 | UserGetDetailInputData inputData = new UserGetDetailInputData(id); 80 | UserGetDetailOutputData outputData = bus.handle(inputData); 81 | 82 | if(!outputData.getUserData().isPresent()){ 83 | return redirect(routes.UserController.index()); 84 | } 85 | 86 | UserDetailViewModel viewModel = outputData.getUserData() 87 | .map(x -> new UserDetailViewModel(id, x.getName(), userRoleConverter.convert(x.getRole()))) 88 | .get(); 89 | 90 | return ok(detail.render(viewModel)); 91 | } 92 | 93 | public Result updateInput(String id) { 94 | UserGetDetailInputData inputData = new UserGetDetailInputData(id); 95 | UserGetDetailOutputData outputData = bus.handle(inputData); 96 | 97 | if(!outputData.getUserData().isPresent()){ 98 | return notFound(); 99 | } 100 | 101 | UserUpdateForm initialForm = new UserUpdateForm(); 102 | initialForm.name = outputData.getUserData().map(x -> x.getName()).get(); 103 | 104 | userUpdateForm.fill(initialForm); 105 | 106 | return ok(views.html.user.update.input.render(new UserUpdateInputViewModel(id), userUpdateForm)); 107 | } 108 | 109 | public Result updateInputSubmit(String id){ 110 | Form requestForm = userUpdateForm.bindFromRequest(); 111 | if(requestForm.hasErrors()){ 112 | return badRequest(views.html.user.update.input.render(new UserUpdateInputViewModel(id), requestForm)); 113 | } 114 | 115 | UserUpdateForm form = requestForm.get(); 116 | 117 | UserUpdateInputData inputData = new UserUpdateInputData.Builder(id).name(form.name).build(); 118 | bus.handle(inputData); 119 | 120 | return redirect(routes.UserController.detail(id)); 121 | } 122 | 123 | public Result deleteSubmit(String id) { 124 | UserDeleteInputData inputData = new UserDeleteInputData(id); 125 | bus.handle(inputData); 126 | 127 | return redirect(routes.UserController.index()); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /playapp/app/gateways/user/EBeanUserRepository.java: -------------------------------------------------------------------------------- 1 | package gateways.user; 2 | 3 | import com.nrslib.domain.model.user.*; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.stream.Collectors; 8 | 9 | public class EBeanUserRepository implements UserRepository { 10 | @Override 11 | public void save(User user) { 12 | UserId id = user.getId(); 13 | models.User userData = Optional 14 | .ofNullable(models.User.find.byId(id.getValue())) 15 | .orElseGet(() ->createNew(id, user.getRole())); 16 | 17 | userData.setName(user.getName().getValue()); 18 | 19 | models.User.db().save(userData); 20 | } 21 | 22 | @Override 23 | public void remove(User user) { 24 | models.User.find.byId(user.getId().getValue()).delete(); 25 | } 26 | 27 | @Override 28 | public List findAll() { 29 | List all = models.User.find.all(); 30 | 31 | List results = all.stream() 32 | .map(this::convert) 33 | .collect(Collectors.toList()); 34 | 35 | return results; 36 | } 37 | 38 | @Override 39 | public Optional find(UserId id) { 40 | String userId = id.getValue(); 41 | 42 | models.User user = models.User.find.byId(userId); 43 | 44 | if(user != null) { 45 | User userModel = convert(user); 46 | return Optional.of(userModel); 47 | }else{ 48 | return Optional.empty(); 49 | } 50 | } 51 | 52 | private models.User createNew(UserId id, UserRole role) { 53 | models.User instance = new models.User(); 54 | instance.setId(id.getValue()); 55 | instance.setRole(convert(role)); 56 | return instance; 57 | } 58 | 59 | private User convert(models.User user){ 60 | return new User( 61 | new UserId(user.getId()), 62 | new UserName(user.getName()), 63 | convertRole(user.getRole()) 64 | ); 65 | } 66 | 67 | private int convert(UserRole role) { 68 | switch (role) { 69 | case ADMIN: return 1; 70 | case MEMBER: return 2; 71 | default: throw new RuntimeException(); 72 | } 73 | } 74 | 75 | private UserRole convertRole(int roleId) { 76 | switch (roleId) { 77 | case 1 : return UserRole.ADMIN; 78 | case 2 : return UserRole.MEMBER; 79 | default: throw new RuntimeException(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /playapp/app/lib/auth/AppAccountInfo.java: -------------------------------------------------------------------------------- 1 | package lib.auth; 2 | 3 | public class AppAccountInfo { 4 | private final String id; 5 | private final String name; 6 | 7 | public AppAccountInfo(String id, String name) { 8 | this.id = id; 9 | this.name = name; 10 | } 11 | 12 | public String getId() { 13 | return id; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playapp/app/lib/auth/LoginService.java: -------------------------------------------------------------------------------- 1 | package lib.auth; 2 | 3 | import com.google.inject.Inject; 4 | import jdk.nashorn.internal.ir.ReturnNode; 5 | import play.cache.CacheApi; 6 | import play.mvc.Http; 7 | import scala.App; 8 | 9 | import java.util.UUID; 10 | 11 | public class LoginService { 12 | private final int cacheDuration = 20 * 60; 13 | private final String tokenName = "token"; 14 | 15 | @Inject 16 | private CacheApi cache; 17 | 18 | public void login(String id, AppAccountInfo accountInfo) { 19 | Http.Context context = Http.Context.current(); 20 | context.session().clear(); 21 | 22 | String cacheId = UUID.randomUUID().toString(); 23 | cache.set(cacheId, accountInfo, cacheDuration); 24 | 25 | context.session().put(tokenName, cacheId); 26 | } 27 | 28 | public void logout() { 29 | Http.Context context = Http.Context.current(); 30 | context.session().clear(); 31 | } 32 | 33 | public boolean isLogin() { 34 | Http.Context context = Http.Context.current(); 35 | String cacheId = context.session().get(tokenName); 36 | AppAccountInfo accountInfo = cache.get(cacheId); 37 | return accountInfo != null; 38 | } 39 | 40 | public AppAccountInfo getCurrent() { 41 | Http.Context context = Http.Context.current(); 42 | String cacheId = context.session().get(tokenName); 43 | AppAccountInfo accountInfo = cache.get(cacheId); 44 | return accountInfo; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /playapp/app/lib/context/HttpSessionUserContext.java: -------------------------------------------------------------------------------- 1 | package lib.context; 2 | 3 | import com.google.inject.Inject; 4 | import com.nrslib.domain.context.UserContext; 5 | import lib.auth.LoginService; 6 | 7 | public class HttpSessionUserContext implements UserContext { 8 | @Inject 9 | private LoginService loginService; 10 | 11 | @Override 12 | public String getId() { 13 | if(!loginService.isLogin()){ 14 | return null; 15 | } 16 | 17 | return loginService.getCurrent().getId(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playapp/app/lib/forClArc/PlayUseCaseInvoker.java: -------------------------------------------------------------------------------- 1 | package lib.forClArc; 2 | 3 | import com.avaje.ebean.Ebean; 4 | import com.nrslib.clArc.inject.ServiceProvider; 5 | import com.nrslib.clArc.invoke.UseCaseInvoker; 6 | import com.nrslib.usecases.core.InputData; 7 | import com.nrslib.usecases.core.OutputData; 8 | import play.db.ebean.Transactional; 9 | 10 | import java.lang.annotation.Annotation; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.lang.reflect.Method; 13 | import java.util.Arrays; 14 | import java.util.stream.Stream; 15 | 16 | public class PlayUseCaseInvoker implements UseCaseInvoker { 17 | private final Class implementClazz; 18 | private final ServiceProvider provider; 19 | private final Method handleMethod; 20 | private final boolean hasTransaction; 21 | 22 | PlayUseCaseInvoker(Class implementClazz, ServiceProvider provider) { 23 | this.implementClazz = implementClazz; 24 | this.provider = provider; 25 | Stream methods = Arrays.stream(implementClazz.getMethods()); 26 | handleMethod = methods.filter(x -> x.getName().equals("handle")).findFirst().get(); 27 | hasTransaction = this.implementClazz.getAnnotation(Transactional.class) != null; 28 | } 29 | 30 | @Override 31 | public TOutputData invoke(InputData inputData) { 32 | Object interactor = provider.getService(implementClazz); 33 | 34 | Object outputData; 35 | if(hasTransaction) { 36 | outputData = Ebean.execute(() -> invoke(interactor, inputData)); 37 | }else{ 38 | outputData = invoke(interactor, inputData); 39 | } 40 | 41 | return (TOutputData) outputData; 42 | } 43 | 44 | private TOutputData invoke(Object interactor, InputData inputData){ 45 | Object result; 46 | try { 47 | result = handleMethod.invoke(interactor, inputData); 48 | } catch (IllegalAccessException | InvocationTargetException e) { 49 | e.printStackTrace(); 50 | throw new RuntimeException(e); 51 | } 52 | return (TOutputData)result; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /playapp/app/lib/forClArc/PlayUseCaseInvokerFactory.java: -------------------------------------------------------------------------------- 1 | package lib.forClArc; 2 | 3 | import com.nrslib.clArc.inject.ServiceProvider; 4 | import com.nrslib.clArc.invoke.UseCaseInvoker; 5 | import com.nrslib.clArc.invoke.UseCaseInvokerFactory; 6 | 7 | public class PlayUseCaseInvokerFactory implements UseCaseInvokerFactory { 8 | @Override 9 | public UseCaseInvoker generate(Class implementClazz, ServiceProvider provider) { 10 | return new PlayUseCaseInvoker(implementClazz, provider); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /playapp/app/lib/view/converter/user/UserRoleConverter.java: -------------------------------------------------------------------------------- 1 | package lib.view.converter.user; 2 | 3 | import com.nrslib.domain.model.user.UserRole; 4 | 5 | public class UserRoleConverter { 6 | public UserRole convert(String roleId) { 7 | switch (roleId) { 8 | case "admin": return UserRole.ADMIN; 9 | case "member": return UserRole.MEMBER; 10 | default: throw new RuntimeException(); 11 | } 12 | } 13 | 14 | public String convert(UserRole role) { 15 | switch (role) { 16 | case ADMIN: return "admin"; 17 | case MEMBER: return "member"; 18 | default: throw new RuntimeException(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /playapp/app/models/User.java: -------------------------------------------------------------------------------- 1 | package models; 2 | 3 | import com.avaje.ebean.Model; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | 8 | @Entity 9 | public class User extends Model { 10 | @Id 11 | private String id; 12 | 13 | private String name; 14 | 15 | private int role; 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public void setId(String id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public int getRole() { return role; } 34 | 35 | public void setRole(int role) { this.role = role; } 36 | 37 | public static Find find = new Find() {}; 38 | } 39 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/account/AccountIndexViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.account; 2 | 3 | public class AccountIndexViewModel { 4 | private final String id; 5 | private final String name; 6 | 7 | public AccountIndexViewModel(String id, String name) { 8 | this.id = id; 9 | this.name = name; 10 | } 11 | 12 | public String getId() { 13 | return id; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/auth/AuthCheckViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.auth; 2 | 3 | public class AuthCheckViewModel { 4 | private final boolean login; 5 | 6 | public AuthCheckViewModel(boolean login) { 7 | this.login = login; 8 | } 9 | 10 | public boolean isLogin(){ return login; } 11 | } 12 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/auth/login/AuthLoginForm.java: -------------------------------------------------------------------------------- 1 | package viewmodels.auth.login; 2 | 3 | import play.data.validation.Constraints; 4 | 5 | public class AuthLoginForm { 6 | @Constraints.Required(message="input id") 7 | @Constraints.MinLength(3) 8 | @Constraints.MaxLength(10) 9 | public String id; 10 | 11 | @Constraints.Required(message="input password") 12 | public String password; 13 | } 14 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/UserDetailViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user; 2 | 3 | 4 | public class UserDetailViewModel { 5 | private final String id; 6 | private final String name; 7 | private final String roleId; 8 | 9 | public UserDetailViewModel(String id, String name, String roleId) { 10 | this.id = id; 11 | this.name = name; 12 | this.roleId = roleId; 13 | } 14 | 15 | public String getId() { 16 | return id; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public String getRoleId() { return roleId; } 24 | } 25 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/UserGetListViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user; 2 | 3 | import viewmodels.user.common.UserViewModel; 4 | 5 | import java.util.List; 6 | 7 | public class UserGetListViewModel { 8 | private final List users; 9 | 10 | public UserGetListViewModel(List users) { 11 | this.users = users; 12 | } 13 | 14 | public List getUsers() { 15 | return users; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/add/UserAddForm.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user.add; 2 | 3 | import play.data.validation.Constraints; 4 | 5 | public class UserAddForm { 6 | @Constraints.Required(message="type name") 7 | @Constraints.MinLength(3) 8 | @Constraints.MaxLength(10) 9 | public String name; 10 | 11 | @Constraints.Required(message="check role") 12 | public String roleId; 13 | } 14 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/add/UserAddInputViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user.add; 2 | 3 | public class UserAddInputViewModel { 4 | } 5 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/common/UserViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user.common; 2 | 3 | public class UserViewModel { 4 | private final String id; 5 | private final String name; 6 | 7 | public UserViewModel(String id, String name) { 8 | this.id = id; 9 | this.name = name; 10 | } 11 | 12 | public String getId() { 13 | return id; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/update/UserUpdateForm.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user.update; 2 | 3 | import play.data.validation.Constraints; 4 | 5 | public class UserUpdateForm { 6 | @Constraints.Required(message="type name") 7 | @Constraints.MinLength(3) 8 | @Constraints.MaxLength(10) 9 | public String name; 10 | } 11 | -------------------------------------------------------------------------------- /playapp/app/viewmodels/user/update/UserUpdateInputViewModel.java: -------------------------------------------------------------------------------- 1 | package viewmodels.user.update; 2 | 3 | public class UserUpdateInputViewModel { 4 | private final String id; 5 | 6 | public UserUpdateInputViewModel(String id) { 7 | this.id = id; 8 | } 9 | 10 | public String getId() { 11 | return id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /playapp/app/views/account/index.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.account.AccountIndexViewModel 2 | @(model: AccountIndexViewModel) 3 | 4 | @main("AccountIndex") { 5 |
6 |
7 |

Account

8 |
9 | 10 |
11 |
12 |
  • Id: @model.getId()
  • 13 |
  • Name: @model.getName()
  • 14 |
    15 |
    16 | 17 |
    18 |
    19 | Back 20 |
    21 |
    22 |
    23 | } -------------------------------------------------------------------------------- /playapp/app/views/auth/check.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.auth.AuthCheckViewModel 2 | @(model: AuthCheckViewModel) 3 | 4 | @main("AuthCheck") { 5 |
    6 |
    7 |

    Check

    8 |
    9 | 10 |
    11 |
    12 | @if(model.isLogin()){ 13 | Current State: Login 14 | }else{ 15 | Current State: Logout 16 | } 17 |
    18 |
    19 | 20 |
    21 |
    22 | @if(model.isLogin()){ 23 | Show my account 24 | } 25 | 26 | @if(model.isLogin()){ 27 | Logout 28 | }else{ 29 | Login 30 | } 31 |
    32 |
    33 | 34 |
    35 |
    36 | Back 37 |
    38 |
    39 |
    40 | } -------------------------------------------------------------------------------- /playapp/app/views/auth/login.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.auth.login.AuthLoginForm 2 | @(form: Form [AuthLoginForm]) 3 | 4 | @main("AuthLogin") { 5 |
    6 |
    7 |

    Login

    8 |
    9 | 10 |
    11 |
    12 | @helper.form(action = routes.AuthController.submit) { 13 | @helper.inputText(form("id"), '_label -> "id") 14 | @helper.inputText(form("password"), '_label -> "Password") 15 | 16 | } 17 |
    18 |
    19 | 20 |
    21 |
    22 | Back 23 |
    24 |
    25 |
    26 | } -------------------------------------------------------------------------------- /playapp/app/views/index.scala.html: -------------------------------------------------------------------------------- 1 | @(message: String) 2 | 3 | @main("Welcome to Play") { 4 |
    5 |
    6 | Try Demo 7 | Login Demo 8 |
    9 |
    10 | } 11 | -------------------------------------------------------------------------------- /playapp/app/views/main.scala.html: -------------------------------------------------------------------------------- 1 | @(title: String)(content: Html) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | @title 13 | 14 | 15 | 16 | 17 | 18 | @content 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /playapp/app/views/user/add/input.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.user.add.UserAddInputViewModel 2 | @import viewmodels.user.add.UserAddForm 3 | @import views.html.helper.options 4 | @(model: UserAddInputViewModel, form: Form[UserAddForm]) 5 | 6 | @main("UserAddInput"){ 7 |
    8 |
    9 |
    10 | @helper.form(action = routes.UserController.addInputSubmit) { 11 | @helper.inputText(form("name"), '_label -> "UserName") 12 | @helper.inputRadioGroup(field = form("roleId"), options("admin"->"管理者","member"->"一般")) 13 | 14 | } 15 |
    16 |
    17 |
    18 |
    19 | Back 20 |
    21 |
    22 |
    23 | } -------------------------------------------------------------------------------- /playapp/app/views/user/detail.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.user.UserDetailViewModel 2 | @(model: UserDetailViewModel) 3 | 4 | @main("UserIndex") { 5 |
    6 |
    7 |

    User List

    8 |
    9 | 10 |
    11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
    Name@model.getName()
    Role@model.getRoleId()
    21 |
    22 | 23 |
    24 |
    25 | Modify 26 |
    27 |
    28 | @helper.form(action = routes.UserController.deleteSubmit(model.getId())) { 29 | 30 | } 31 |
    32 |
    33 |
    34 |
    35 | Back 36 |
    37 |
    38 |
    39 | } -------------------------------------------------------------------------------- /playapp/app/views/user/index.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.user.UserGetListViewModel 2 | 3 | @(model: UserGetListViewModel) 4 | 5 | @main("UserIndex") { 6 |
    7 |
    8 |

    User List

    9 |
    10 | 11 |
    12 | 13 | 14 | 15 | @model.getUsers().map { user => 16 | 17 | 20 | 23 | 24 | } 25 |
    User Name
    18 | @user.getName() 19 | 21 | Detail 22 |
    26 |
    27 | 28 |
    29 |
    30 | Add User 31 |
    32 |
    33 |
    34 | } -------------------------------------------------------------------------------- /playapp/app/views/user/update/input.scala.html: -------------------------------------------------------------------------------- 1 | @import viewmodels.user.update.UserUpdateForm 2 | @import viewmodels.user.update.UserUpdateInputViewModel 3 | @import views.html.helper.options 4 | @(model: UserUpdateInputViewModel, form: Form[UserUpdateForm]) 5 | 6 | @main("UserAddInput"){ 7 |
    8 |
    9 |
    10 | @helper.form(action = routes.UserController.updateInputSubmit(model.getId())) { 11 | @helper.inputText(form("name"), '_label -> "UserName") 12 | 13 | } 14 |
    15 |
    16 |
    17 |
    18 | Back 19 |
    20 |
    21 |
    22 | } -------------------------------------------------------------------------------- /playapp/build.sbt: -------------------------------------------------------------------------------- 1 | name := "playclean" 2 | 3 | version := "1.0" 4 | 5 | lazy val `playclean` = (project in file(".")).enablePlugins(PlayJava, PlayEbean, PlayEnhancer) 6 | 7 | resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases" 8 | 9 | scalaVersion := "2.11.12" 10 | 11 | libraryDependencies ++= Seq( javaJdbc , cache , javaWs ) 12 | 13 | unmanagedResourceDirectories in Test <+= baseDirectory ( _ /"target/web/public/test" ) 14 | 15 | playEbeanModels in Compile := Seq("models.*") 16 | playEbeanDebugLevel := 4 17 | -------------------------------------------------------------------------------- /playapp/conf/application.conf: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for the application. 2 | # ~~~~~ 3 | 4 | # Secret key 5 | # ~~~~~ 6 | # The secret key is used to secure cryptographics functions. 7 | # If you deploy your application to several instances be sure to use the same key! 8 | application.secret="%APPLICATION_SECRET%" 9 | 10 | # The application languages 11 | # ~~~~~ 12 | application.langs="en" 13 | 14 | # Global object class 15 | # ~~~~~ 16 | # Define the Global object class for this application. 17 | # Default to Global in the root package. 18 | # application.global=Global 19 | 20 | # Router 21 | # ~~~~~ 22 | # Define the Router object to use for this application. 23 | # This router will be looked up first when the application is starting up, 24 | # so make sure this is the entry point. 25 | # Furthermore, it's assumed your route file is named properly. 26 | # So for an application router like `my.application.Router`, 27 | # you may need to define a router file `conf/my.application.routes`. 28 | # Default to Routes in the root package (and conf/routes) 29 | # application.router=my.application.Routes 30 | 31 | # Database configuration 32 | # ~~~~~ 33 | # You can declare as many datasources as you want. 34 | # By convention, the default datasource is named `default` 35 | # 36 | db.default.driver=org.h2.Driver 37 | db.default.url="jdbc:h2:mem:play" 38 | db.default.user=sa 39 | db.default.password="" 40 | 41 | # Evolutions 42 | # ~~~~~ 43 | # You can disable evolutions if needed 44 | # evolutionplugin=disabled 45 | 46 | # Logger 47 | # ~~~~~ 48 | # You can also configure logback (http://logback.qos.ch/), 49 | # by providing an application-logger.xml file in the conf directory. 50 | 51 | # Root logger: 52 | logger.root=ERROR 53 | 54 | # Logger used by the framework: 55 | logger.play=INFO 56 | 57 | # Logger provided to your application: 58 | logger.application=DEBUG 59 | 60 | play.module.enabled="Module" 61 | 62 | # Ebean 63 | ebean.default = ["models.*"] 64 | 65 | # My project config: 66 | # project.di = "product" 67 | project.di = "debug" -------------------------------------------------------------------------------- /playapp/conf/evolutions/default/1.sql: -------------------------------------------------------------------------------- 1 | # --- Created by Ebean DDL 2 | # To stop Ebean DDL generation, remove this comment and start using Evolutions 3 | 4 | # --- !Ups 5 | 6 | create table user ( 7 | id varchar(255) not null, 8 | name varchar(255), 9 | role integer, 10 | constraint pk_user primary key (id) 11 | ); 12 | 13 | 14 | # --- !Downs 15 | 16 | drop table if exists user; 17 | 18 | -------------------------------------------------------------------------------- /playapp/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # Home page 6 | GET / controllers.Application.index 7 | 8 | GET /account controllers.AccountController.index 9 | 10 | GET /auth/check controllers.AuthController.check 11 | POST /auth/submit controllers.AuthController.submit 12 | GET /login controllers.AuthController.login 13 | GET /logout controllers.AuthController.logout 14 | 15 | GET /user controllers.UserController.index 16 | GET /user/add/input controllers.UserController.addInput() 17 | POST /user/add/input/submit controllers.UserController.addInputSubmit() 18 | POST /user/delete/:id controllers.UserController.deleteSubmit(id) 19 | GET /user/detail/:id controllers.UserController.detail(id) 20 | GET /user/update/input/:id controllers.UserController.updateInput(id) 21 | POST /user/update/input/submit/:id controllers.UserController.updateInputSubmit(id) 22 | 23 | # Map static resources from the /public folder to the /assets URL path 24 | GET /assets/*file controllers.Assets.at(path="/public", file) -------------------------------------------------------------------------------- /playapp/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.17 -------------------------------------------------------------------------------- /playapp/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn 2 | 3 | resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" 4 | 5 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.9") 6 | addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.0") 7 | addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") -------------------------------------------------------------------------------- /playapp/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrslib/play-clean-java/1ed916fd49d1905ae65c6b9069e7c13562a07746/playapp/public/images/favicon.png -------------------------------------------------------------------------------- /playapp/public/javascripts/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;nthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
    ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),le({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=fe({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=fe({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!me),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=fe({},E,e.attributes),e.styles=fe({},m,e.styles),e.arrowStyles=fe({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ue}); 5 | //# sourceMappingURL=popper.min.js.map 6 | -------------------------------------------------------------------------------- /playapp/public/stylesheets/main.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrslib/play-clean-java/1ed916fd49d1905ae65c6b9069e7c13562a07746/playapp/public/stylesheets/main.css -------------------------------------------------------------------------------- /playapp/test/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import com.fasterxml.jackson.databind.JsonNode; 7 | import org.junit.*; 8 | 9 | import play.mvc.*; 10 | import play.test.*; 11 | import play.data.DynamicForm; 12 | import play.data.validation.ValidationError; 13 | import play.data.validation.Constraints.RequiredValidator; 14 | import play.i18n.Lang; 15 | import play.libs.F; 16 | import play.libs.F.*; 17 | 18 | import static play.test.Helpers.*; 19 | import static org.fest.assertions.Assertions.*; 20 | 21 | 22 | /** 23 | * 24 | * Simple (JUnit) tests that can call all parts of a play app. 25 | * If you are interested in mocking a whole application, see the wiki for more details. 26 | * 27 | */ 28 | public class ApplicationTest { 29 | 30 | @Test 31 | public void simpleCheck() { 32 | int a = 1 + 1; 33 | assertThat(a).isEqualTo(2); 34 | } 35 | 36 | @Test 37 | public void renderTemplate() { 38 | Content html = views.html.index.render("Your new application is ready."); 39 | assertThat(contentType(html)).isEqualTo("text/html"); 40 | assertThat(contentAsString(html)).contains("Your new application is ready."); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /playapp/test/IntegrationTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.*; 2 | 3 | import play.mvc.*; 4 | import play.test.*; 5 | import play.libs.F.*; 6 | 7 | import static play.test.Helpers.*; 8 | import static org.fest.assertions.Assertions.*; 9 | 10 | import static org.fluentlenium.core.filter.FilterConstructor.*; 11 | 12 | public class IntegrationTest { 13 | 14 | /** 15 | * add your integration test here 16 | * in this example we just check if the welcome page is being shown 17 | */ 18 | @Test 19 | public void test() { 20 | running(testServer(3333, fakeApplication(inMemoryDatabase())), HTMLUNIT, new Callback() { 21 | public void invoke(TestBrowser browser) { 22 | browser.goTo("http://localhost:3333"); 23 | assertThat(browser.pageSource()).contains("Your new application is ready."); 24 | } 25 | }); 26 | } 27 | 28 | } 29 | --------------------------------------------------------------------------------