2
0

theme-test.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. package com.example.theme;
  2. import java.util.*;
  3. import java.util.concurrent.*;
  4. import java.util.function.*;
  5. import java.util.stream.*;
  6. import java.time.*;
  7. import java.time.format.*;
  8. import java.net.*;
  9. import java.io.*;
  10. import java.nio.file.*;
  11. import java.sql.*;
  12. import java.lang.annotation.*;
  13. import java.math.BigDecimal;
  14. import java.math.BigInteger;
  15. // Enum definition
  16. public enum LogLevel {
  17. DEBUG(0, "Debug"),
  18. INFO(1, "Info"),
  19. WARN(2, "Warning"),
  20. ERROR(3, "Error");
  21. private final int level;
  22. private final String description;
  23. LogLevel(int level, String description) {
  24. this.level = level;
  25. this.description = description;
  26. }
  27. public int getLevel() { return level; }
  28. public String getDescription() { return description; }
  29. }
  30. // Interface with generics
  31. public interface Repository<T extends Entity> {
  32. Optional<T> findById(Long id);
  33. List<T> findAll();
  34. T save(T entity);
  35. void delete(Long id);
  36. Stream<T> stream();
  37. @FunctionalInterface
  38. interface Predicate<T> {
  39. boolean test(T t);
  40. }
  41. }
  42. // Abstract class
  43. public abstract class AbstractService<T extends Entity> implements Repository<T> {
  44. protected final Map<Long, T> cache = new ConcurrentHashMap<>();
  45. protected volatile boolean initialized = false;
  46. @Override
  47. public Optional<T> findById(Long id) {
  48. return Optional.ofNullable(cache.get(id));
  49. }
  50. @Override
  51. public List<T> findAll() {
  52. return new ArrayList<>(cache.values());
  53. }
  54. @Override
  55. public Stream<T> stream() {
  56. return cache.values().stream();
  57. }
  58. protected abstract void validate(T entity) throws ValidationException;
  59. }
  60. // Annotation definition
  61. @Retention(RetentionPolicy.RUNTIME)
  62. @Target({ElementType.TYPE, ElementType.METHOD})
  63. public @interface Service {
  64. String value() default "";
  65. boolean transactional() default true;
  66. Class<?>[] exceptions() = {};
  67. }
  68. // Record class (Java 14+)
  69. public record User(
  70. Long id,
  71. String username,
  72. String email,
  73. @Deprecated String fullName,
  74. LocalDateTime createdAt,
  75. boolean active
  76. ) implements Entity {
  77. public User {
  78. Objects.requireNonNull(username, "Username cannot be null");
  79. Objects.requireNonNull(email, "Email cannot be null");
  80. Objects.requireNonNull(createdAt, "Created date cannot be null");
  81. }
  82. public static User of(String username, String email) {
  83. return new User(null, username, email, null, LocalDateTime.now(), true);
  84. }
  85. public User withId(Long id) {
  86. return new User(id, username, email, fullName, createdAt, active);
  87. }
  88. }
  89. // Exception classes
  90. public class ValidationException extends RuntimeException {
  91. private final List<String> errors;
  92. public ValidationException(String message) {
  93. super(message);
  94. this.errors = List.of(message);
  95. }
  96. public ValidationException(List<String> errors) {
  97. super(String.join(", ", errors));
  98. this.errors = Collections.unmodifiableList(errors);
  99. }
  100. public List<String> getErrors() { return errors; }
  101. }
  102. public class ResourceNotFoundException extends RuntimeException {
  103. public ResourceNotFoundException(String resource, Long id) {
  104. super(String.format("%s with id %d not found", resource, id));
  105. }
  106. }
  107. // Service implementation
  108. @Service(value = "userService", transactional = true)
  109. public class UserService extends AbstractService<User> {
  110. private static final Logger logger = LoggerFactory.getLogger(UserService.class);
  111. private static final int MAX_RETRY_ATTEMPTS = 3;
  112. private static final Duration TIMEOUT = Duration.ofSeconds(30);
  113. private final EmailService emailService;
  114. private final UserRepository userRepository;
  115. private final PasswordEncoder passwordEncoder;
  116. @Inject
  117. public UserService(EmailService emailService,
  118. UserRepository userRepository,
  119. PasswordEncoder passwordEncoder) {
  120. this.emailService = emailService;
  121. this.userRepository = userRepository;
  122. this.passwordEncoder = passwordEncoder;
  123. }
  124. @Override
  125. protected void validate(User user) throws ValidationException {
  126. List<String> errors = new ArrayList<>();
  127. if (user.username() == null || user.username().trim().isEmpty()) {
  128. errors.add("Username is required");
  129. } else if (!user.username().matches("^[a-zA-Z0-9_]{3,20}$")) {
  130. errors.add("Username must be 3-20 characters, alphanumeric and underscore only");
  131. }
  132. if (user.email() == null || !user.email().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
  133. errors.add("Valid email is required");
  134. }
  135. if (!errors.isEmpty()) {
  136. throw new ValidationException(errors);
  137. }
  138. }
  139. @Transactional
  140. public User createUser(CreateUserRequest request) throws ValidationException {
  141. logger.info("Creating new user: {}", request.username());
  142. // Check if user already exists
  143. if (userRepository.findByUsername(request.username()).isPresent()) {
  144. throw new ValidationException("Username already exists");
  145. }
  146. if (userRepository.findByEmail(request.email()).isPresent()) {
  147. throw new ValidationException("Email already exists");
  148. }
  149. // Create new user
  150. User user = User.of(request.username(), request.email())
  151. .withId(generateId());
  152. validate(user);
  153. try {
  154. User savedUser = userRepository.save(user);
  155. cache.put(savedUser.id(), savedUser);
  156. // Send welcome email asynchronously
  157. CompletableFuture.runAsync(() ->
  158. emailService.sendWelcomeEmail(savedUser)
  159. ).exceptionally(throwable -> {
  160. logger.error("Failed to send welcome email to user {}", savedUser.id(), throwable);
  161. return null;
  162. });
  163. logger.info("Successfully created user with ID: {}", savedUser.id());
  164. return savedUser;
  165. } catch (DataAccessException e) {
  166. logger.error("Database error while creating user", e);
  167. throw new ServiceException("Failed to create user", e);
  168. }
  169. }
  170. public Optional<User> findByUsername(String username) {
  171. return cache.values().stream()
  172. .filter(user -> user.username().equals(username))
  173. .findFirst();
  174. }
  175. public List<User> findActiveUsers() {
  176. return cache.values().stream()
  177. .filter(User::active)
  178. .sorted(Comparator.comparing(User::createdAt).reversed())
  179. .collect(Collectors.toList());
  180. }
  181. @Retry(maxAttempts = MAX_RETRY_ATTEMPTS, backoff = @Backoff(delay = 1000))
  182. public User updateUser(Long id, UpdateUserRequest request) {
  183. User existingUser = findById(id)
  184. .orElseThrow(() -> new ResourceNotFoundException("User", id));
  185. User updatedUser = new User(
  186. id,
  187. request.username() != null ? request.username() : existingUser.username(),
  188. request.email() != null ? request.email() : existingUser.email(),
  189. existingUser.fullName(),
  190. existingUser.createdAt(),
  191. request.active() != null ? request.active() : existingUser.active()
  192. );
  193. validate(updatedUser);
  194. try {
  195. User savedUser = userRepository.save(updatedUser);
  196. cache.put(id, savedUser);
  197. return savedUser;
  198. } catch (DataAccessException e) {
  199. logger.error("Failed to update user with ID: {}", id, e);
  200. throw new ServiceException("Failed to update user", e);
  201. }
  202. }
  203. @Async
  204. public CompletableFuture<Void> deleteUser(Long id) {
  205. return CompletableFuture.runAsync(() -> {
  206. try {
  207. userRepository.deleteById(id);
  208. cache.remove(id);
  209. logger.info("Successfully deleted user with ID: {}", id);
  210. } catch (DataAccessException e) {
  211. logger.error("Failed to delete user with ID: {}", id, e);
  212. throw new ServiceException("Failed to delete user", e);
  213. }
  214. });
  215. }
  216. private Long generateId() {
  217. return System.currentTimeMillis() + (long)(Math.random() * 1000);
  218. }
  219. }
  220. // Utility class
  221. public final class DateUtils {
  222. private DateUtils() {
  223. // Utility class - prevent instantiation
  224. }
  225. private static final DateTimeFormatter ISO_FORMATTER =
  226. DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
  227. public static String formatIsoDateTime(LocalDateTime dateTime) {
  228. return dateTime.atZone(ZoneId.systemDefault()).format(ISO_FORMATTER);
  229. }
  230. public static LocalDateTime parseIsoDateTime(String isoString) {
  231. return LocalDateTime.parse(isoString, ISO_FORMATTER);
  232. }
  233. public static boolean isWithinLastDays(LocalDateTime dateTime, int days) {
  234. return dateTime.isAfter(LocalDateTime.now().minusDays(days));
  235. }
  236. }
  237. // Builder pattern
  238. public class UserQueryBuilder {
  239. private String username;
  240. private String email;
  241. private Boolean active;
  242. private LocalDateTime createdAfter;
  243. private LocalDateTime createdBefore;
  244. private SortOrder sortOrder = SortOrder.ASC;
  245. private String sortBy = "createdAt";
  246. private int limit = 100;
  247. private int offset = 0;
  248. public UserQueryBuilder withUsername(String username) {
  249. this.username = username;
  250. return this;
  251. }
  252. public UserQueryBuilder withEmail(String email) {
  253. this.email = email;
  254. return this;
  255. }
  256. public UserQueryBuilder activeOnly(boolean active) {
  257. this.active = active;
  258. return this;
  259. }
  260. public UserQueryBuilder createdAfter(LocalDateTime date) {
  261. this.createdAfter = date;
  262. return this;
  263. }
  264. public UserQueryBuilder createdBefore(LocalDateTime date) {
  265. this.createdBefore = date;
  266. return this;
  267. }
  268. public UserQueryBuilder sortBy(String field, SortOrder order) {
  269. this.sortBy = field;
  270. this.sortOrder = order;
  271. return this;
  272. }
  273. public UserQueryBuilder limit(int limit) {
  274. this.limit = Math.max(1, Math.min(limit, 1000));
  275. return this;
  276. }
  277. public UserQueryBuilder offset(int offset) {
  278. this.offset = Math.max(0, offset);
  279. return this;
  280. }
  281. public UserQuery build() {
  282. return new UserQuery(username, email, active, createdAfter, createdBefore,
  283. sortBy, sortOrder, limit, offset);
  284. }
  285. }
  286. // Lambda expressions and streams
  287. public class StreamProcessor {
  288. private static final Map<String, Function<String, Object>> TYPE_CONVERTERS = Map.of(
  289. "string", s -> s,
  290. "int", Integer::parseInt,
  291. "double", Double::parseDouble,
  292. "boolean", Boolean::parseBoolean,
  293. "bigdecimal", BigDecimal::new,
  294. "bigint", BigInteger::new
  295. );
  296. public Map<String, Object> processConfig(Properties properties) {
  297. return properties.entrySet().stream()
  298. .filter(entry -> entry.getKey() instanceof String)
  299. .filter(entry -> entry.getValue() != null)
  300. .collect(Collectors.toMap(
  301. entry -> (String) entry.getKey(),
  302. entry -> convertValue((String) entry.getKey(), (String) entry.getValue())
  303. ));
  304. }
  305. private Object convertValue(String key, String value) {
  306. String type = determineType(key, value);
  307. return TYPE_CONVERTERS.getOrDefault(type, Function.identity()).apply(value);
  308. }
  309. private String determineType(String key, String value) {
  310. if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
  311. return "boolean";
  312. } else if (value.matches("-?\\d+")) {
  313. return "int";
  314. } else if (value.matches("-?\\d*\\.\\d+")) {
  315. return "double";
  316. } else if (key.toLowerCase().contains("amount") || key.toLowerCase().contains("price")) {
  317. return "bigdecimal";
  318. }
  319. return "string";
  320. }
  321. public List<String> validateEmails(List<String> emails) {
  322. return emails.stream()
  323. .filter(Objects::nonNull)
  324. .map(String::trim)
  325. .filter(email -> !email.isEmpty())
  326. .filter(email -> email.matches("^[A-Za-z0-9+_.-]+@(.+)$"))
  327. .distinct()
  328. .collect(Collectors.toList());
  329. }
  330. public CompletableFuture<List<User>> processUsersAsync(List<User> users) {
  331. return CompletableFuture.supplyAsync(() ->
  332. users.parallelStream()
  333. .filter(User::active)
  334. .filter(user -> user.createdAt().isAfter(LocalDateTime.now().minusYears(1)))
  335. .sorted(Comparator.comparing(User::username))
  336. .collect(Collectors.toList())
  337. );
  338. }
  339. }
  340. // Main class for testing
  341. public class Main {
  342. private static final Logger logger = LoggerFactory.getLogger(Main.class);
  343. public static void main(String[] args) {
  344. try {
  345. // Initialize application context
  346. ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  347. // Get service bean
  348. UserService userService = context.getBean(UserService.class);
  349. // Create test users
  350. List<User> users = Arrays.asList(
  351. User.of("john_doe", "[email protected]"),
  352. User.of("jane_smith", "[email protected]"),
  353. User.of("bob_wilson", "[email protected]")
  354. );
  355. // Process users
  356. List<CompletableFuture<User>> futures = users.stream()
  357. .map(user -> {
  358. try {
  359. return CompletableFuture.completedFuture(userService.createUser(
  360. new CreateUserRequest(user.username(), user.email())
  361. ));
  362. } catch (ValidationException e) {
  363. logger.error("Failed to create user: {}", user.username(), e);
  364. return CompletableFuture.<User>failedFuture(e);
  365. }
  366. })
  367. .collect(Collectors.toList());
  368. // Wait for all to complete
  369. CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
  370. .thenRun(() -> {
  371. logger.info("All users created successfully");
  372. System.out.println("Application started successfully!");
  373. })
  374. .exceptionally(throwable -> {
  375. logger.error("Failed to initialize users", throwable);
  376. System.err.println("Application startup failed!");
  377. return null;
  378. });
  379. } catch (Exception e) {
  380. logger.error("Application startup failed", e);
  381. System.exit(1);
  382. }
  383. }
  384. }