001/* 002 * Copyright 2022-2025 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet.core; 018 019import javax.annotation.Nonnull; 020import javax.annotation.Nullable; 021import javax.annotation.concurrent.ThreadSafe; 022import java.lang.reflect.Method; 023import java.util.Objects; 024 025import static java.lang.String.format; 026import static java.util.Objects.requireNonNull; 027 028/** 029 * Represents a <em>Resource Method</em>, which is a Java {@link Method} invoked by Soklet to handle an HTTP request. 030 * <p> 031 * See <a href="https://www.soklet.com/docs/request-handling">https://www.soklet.com/docs/request-handling</a> for details. 032 * 033 * @author <a href="https://www.revetkn.com">Mark Allen</a> 034 */ 035@ThreadSafe 036public class ResourceMethod { 037 @Nonnull 038 private final HttpMethod httpMethod; 039 @Nonnull 040 private final ResourcePathDeclaration resourcePathDeclaration; 041 @Nonnull 042 private final Method method; 043 @Nonnull 044 private final Boolean serverSentEventSource; 045 046 /** 047 * Vends a <em>Resource Method</em> given its unique components. 048 * 049 * @param httpMethod an HTTP method 050 * @param resourcePathDeclaration an HTTP path which might contain placeholders, e.g. {@code /example/{exampleId}} 051 * @param method a Java method to invoke for the combination of HTTP method and resource path 052 * @param serverSentEventSource is this <em>Resource Method</em> configured as a server-sent event source? 053 * @return a <em>Resource Method</em> for the supplied components 054 */ 055 @Nonnull 056 public static ResourceMethod withComponents(@Nonnull HttpMethod httpMethod, 057 @Nonnull ResourcePathDeclaration resourcePathDeclaration, 058 @Nonnull Method method, 059 @Nonnull Boolean serverSentEventSource) { 060 requireNonNull(httpMethod); 061 requireNonNull(resourcePathDeclaration); 062 requireNonNull(method); 063 requireNonNull(serverSentEventSource); 064 065 return new ResourceMethod(httpMethod, resourcePathDeclaration, method, serverSentEventSource); 066 } 067 068 protected ResourceMethod(@Nonnull HttpMethod httpMethod, 069 @Nonnull ResourcePathDeclaration resourcePathDeclaration, 070 @Nonnull Method method, 071 @Nonnull Boolean serverSentEventSource) { 072 requireNonNull(httpMethod); 073 requireNonNull(resourcePathDeclaration); 074 requireNonNull(method); 075 requireNonNull(serverSentEventSource); 076 077 this.httpMethod = httpMethod; 078 this.resourcePathDeclaration = resourcePathDeclaration; 079 this.method = method; 080 this.serverSentEventSource = serverSentEventSource; 081 } 082 083 @Override 084 public String toString() { 085 return format("%s{httpMethod=%s, resourcePathDeclaration=%s, method=%s, serverSentEventSource=%s}", getClass().getSimpleName(), 086 getHttpMethod(), getResourcePath(), getMethod(), isServerSentEventSource()); 087 } 088 089 @Override 090 public boolean equals(@Nullable Object object) { 091 if (this == object) 092 return true; 093 094 if (!(object instanceof ResourceMethod resourceMethod)) 095 return false; 096 097 return Objects.equals(getHttpMethod(), resourceMethod.getHttpMethod()) 098 && Objects.equals(getResourcePath(), resourceMethod.getResourcePath()) 099 && Objects.equals(getMethod(), resourceMethod.getMethod()) 100 && Objects.equals(isServerSentEventSource(), resourceMethod.isServerSentEventSource()); 101 } 102 103 @Override 104 public int hashCode() { 105 return Objects.hash(getHttpMethod(), getResourcePath(), getMethod(), isServerSentEventSource()); 106 } 107 108 /** 109 * Returns the HTTP method for this <em>Resource Method</em>. 110 * 111 * @return the HTTP method 112 */ 113 @Nonnull 114 public HttpMethod getHttpMethod() { 115 return this.httpMethod; 116 } 117 118 /** 119 * Returns the HTTP path for this <em>Resource Method</em>, which might contain placeholders - for example, {@code /example/{exampleId}}. 120 * 121 * @return the HTTP path 122 */ 123 @Nonnull 124 public ResourcePathDeclaration getResourcePath() { 125 return this.resourcePathDeclaration; 126 } 127 128 /** 129 * Returns the Java method to invoke for the combination of HTTP method and resource path. 130 * 131 * @return the Java method to invoke 132 */ 133 @Nonnull 134 public Method getMethod() { 135 return this.method; 136 } 137 138 /** 139 * Returns whether or not this <em>Resource Method</em> functions as a Server-Sent Event Source. 140 * 141 * @return {@code true} if this <em>Resource Method</em> functions as a Server-Sent Event Source, {@code false} otherwise 142 */ 143 @Nonnull 144 public Boolean isServerSentEventSource() { 145 return this.serverSentEventSource; 146 } 147}