• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

temporalio / sdk-java / #169

pending completion
#169

push

github-actions

web-flow
Remove use of deprecated API (#1758)

4 of 4 new or added lines in 1 file covered. (100.0%)

17345 of 21558 relevant lines covered (80.46%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.59
/temporal-sdk/src/main/java/io/temporal/common/metadata/POJOWorkflowImplMetadata.java
1
/*
2
 * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
3
 *
4
 * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
 *
6
 * Modifications copyright (C) 2017 Uber Technologies, Inc.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this material except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *   http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
package io.temporal.common.metadata;
22

23
import com.google.common.collect.ImmutableList;
24
import io.temporal.common.Experimental;
25
import java.util.*;
26

27
/**
28
 * Rules:
29
 *
30
 * <ul>
31
 *   <li>A workflow implementation must implement at least one non empty interface annotated with
32
 *       WorkflowInterface
33
 *   <li>An interface annotated with WorkflowInterface can extend zero or more interfaces.
34
 *   <li>An interface annotated with WorkflowInterface defines workflow methods for all methods it
35
 *       inherited from interfaces which are not annotated with WorkflowInterface.
36
 *   <li>Each method name can be defined only once across all interfaces annotated with
37
 *       WorkflowInterface. So if annotated interface A has method foo() and an annotated interface
38
 *       B extends A it cannot also declare foo() even with a different signature.
39
 * </ul>
40
 */
41
public final class POJOWorkflowImplMetadata {
42

43
  private static class EqualsByNameType {
44
    private final String name;
45
    private final WorkflowMethodType type;
46

47
    EqualsByNameType(String name, WorkflowMethodType type) {
1✔
48
      this.name = name;
1✔
49
      this.type = type;
1✔
50
    }
1✔
51

52
    @Override
53
    public boolean equals(Object o) {
54
      if (this == o) return true;
1✔
55
      if (o == null || getClass() != o.getClass()) return false;
1✔
56
      EqualsByNameType that = (EqualsByNameType) o;
1✔
57
      return com.google.common.base.Objects.equal(name, that.name) && type == that.type;
1✔
58
    }
59

60
    @Override
61
    public int hashCode() {
62
      return com.google.common.base.Objects.hashCode(name, type);
1✔
63
    }
64
  }
65

66
  private final List<POJOWorkflowInterfaceMetadata> workflowInterfaces;
67
  private final List<POJOWorkflowMethodMetadata> workflowMethods;
68
  private final List<POJOWorkflowMethodMetadata> signalMethods;
69
  private final List<POJOWorkflowMethodMetadata> queryMethods;
70
  private final List<POJOWorkflowMethodMetadata> updateMethods;
71
  private final List<POJOWorkflowMethodMetadata> updateValidatorMethods;
72

73
  /**
74
   * Create POJOWorkflowImplMetadata for a workflow implementation class. The object must implement
75
   * at least one workflow method.
76
   */
77
  public static POJOWorkflowImplMetadata newInstance(Class<?> implClass) {
78
    return new POJOWorkflowImplMetadata(implClass, false);
1✔
79
  }
80

81
  /**
82
   * Create POJOWorkflowImplMetadata for a workflow implementation class. The class may not
83
   * implement any workflow method. This is to be used for classes that implement only query and
84
   * signal methods.
85
   */
86
  public static POJOWorkflowImplMetadata newListenerInstance(Class<?> implClass) {
87
    return new POJOWorkflowImplMetadata(implClass, true);
1✔
88
  }
89

90
  private POJOWorkflowImplMetadata(Class<?> implClass, boolean listener) {
1✔
91
    if (implClass.isInterface()
1✔
92
        || implClass.isPrimitive()
1✔
93
        || implClass.isAnnotation()
1✔
94
        || implClass.isArray()
1✔
95
        || implClass.isEnum()) {
1✔
96
      throw new IllegalArgumentException("concrete class expected: " + implClass);
×
97
    }
98

99
    List<POJOWorkflowInterfaceMetadata> workflowInterfaces = new ArrayList<>();
1✔
100
    Map<String, POJOWorkflowMethodMetadata> workflowMethods = new HashMap<>();
1✔
101
    Map<String, POJOWorkflowMethodMetadata> queryMethods = new HashMap<>();
1✔
102
    Map<String, POJOWorkflowMethodMetadata> signalMethods = new HashMap<>();
1✔
103
    Map<String, POJOWorkflowMethodMetadata> updateMethods = new HashMap<>();
1✔
104
    Map<String, POJOWorkflowMethodMetadata> updateValidatorMethods = new HashMap<>();
1✔
105
    Map<EqualsByNameType, POJOWorkflowMethodMetadata> byNameType = new HashMap<>();
1✔
106

107
    // Getting all the top level interfaces instead of the direct ones that Class.getInterfaces()
108
    // returns
109
    Set<Class<?>> interfaces = POJOReflectionUtils.getTopLevelInterfaces(implClass);
1✔
110
    for (Class<?> anInterface : interfaces) {
1✔
111
      POJOWorkflowInterfaceMetadata interfaceMetadata =
1✔
112
          POJOWorkflowInterfaceMetadata.newImplementationInstance(anInterface, listener);
1✔
113
      List<POJOWorkflowMethodMetadata> methods = interfaceMetadata.getMethodsMetadata();
1✔
114
      if (!methods.isEmpty()) {
1✔
115
        workflowInterfaces.add(interfaceMetadata);
1✔
116
      }
117
      for (POJOWorkflowMethodMetadata methodMetadata : methods) {
1✔
118
        EqualsByNameType key =
1✔
119
            new EqualsByNameType(methodMetadata.getName(), methodMetadata.getType());
1✔
120
        POJOWorkflowMethodMetadata registeredMM = byNameType.put(key, methodMetadata);
1✔
121
        if (registeredMM != null
1✔
122
            && !registeredMM.getWorkflowMethod().equals(methodMetadata.getWorkflowMethod())) {
1✔
123
          throw new IllegalArgumentException(
1✔
124
              "Duplicated name of "
125
                  + methodMetadata.getType()
1✔
126
                  + ": \""
127
                  + methodMetadata.getName()
1✔
128
                  + "\" declared at \""
129
                  + registeredMM.getWorkflowMethod()
1✔
130
                  + "\" and \""
131
                  + methodMetadata.getWorkflowMethod()
1✔
132
                  + "\"");
133
        }
134
        switch (methodMetadata.getType()) {
1✔
135
          case WORKFLOW:
136
            workflowMethods.put(methodMetadata.getName(), methodMetadata);
1✔
137
            break;
1✔
138
          case SIGNAL:
139
            signalMethods.put(methodMetadata.getName(), methodMetadata);
1✔
140
            break;
1✔
141
          case QUERY:
142
            queryMethods.put(methodMetadata.getName(), methodMetadata);
1✔
143
            break;
1✔
144
          case UPDATE:
145
            updateMethods.put(methodMetadata.getName(), methodMetadata);
1✔
146
            break;
1✔
147
          case UPDATE_VALIDATOR:
148
            updateValidatorMethods.put(methodMetadata.getName(), methodMetadata);
1✔
149
            break;
150
        }
151
      }
1✔
152
    }
1✔
153
    if (byNameType.isEmpty() && !listener) {
1✔
154
      throw new IllegalArgumentException(
1✔
155
          "Class doesn't implement any non empty public interface annotated with @WorkflowInterface: "
156
              + implClass.getName());
1✔
157
    }
158
    this.workflowInterfaces = ImmutableList.copyOf(workflowInterfaces);
1✔
159
    this.workflowMethods = ImmutableList.copyOf(workflowMethods.values());
1✔
160
    this.signalMethods = ImmutableList.copyOf(signalMethods.values());
1✔
161
    this.queryMethods = ImmutableList.copyOf(queryMethods.values());
1✔
162
    this.updateMethods = ImmutableList.copyOf(updateMethods.values());
1✔
163
    this.updateValidatorMethods = ImmutableList.copyOf(updateValidatorMethods.values());
1✔
164
  }
1✔
165

166
  /** List of workflow interfaces an object implements. */
167
  public List<POJOWorkflowInterfaceMetadata> getWorkflowInterfaces() {
168
    return workflowInterfaces;
1✔
169
  }
170

171
  /** List of workflow methods an object implements across all the workflow interfaces. */
172
  public List<POJOWorkflowMethodMetadata> getWorkflowMethods() {
173
    return workflowMethods;
1✔
174
  }
175

176
  /** List of signal methods an object implements across all the workflow interfaces. */
177
  public List<POJOWorkflowMethodMetadata> getSignalMethods() {
178
    return signalMethods;
1✔
179
  }
180

181
  /** List of query methods an object implements across all the workflow interfaces. */
182
  public List<POJOWorkflowMethodMetadata> getQueryMethods() {
183
    return queryMethods;
1✔
184
  }
185

186
  /** List of update methods an object implements across all the workflow interfaces. */
187
  @Experimental
188
  public List<POJOWorkflowMethodMetadata> getUpdateMethods() {
189
    return updateMethods;
1✔
190
  }
191

192
  /** List of update validator methods an object implements across all the workflow interfaces. */
193
  @Experimental
194
  public List<POJOWorkflowMethodMetadata> getUpdateValidatorMethods() {
195
    return updateValidatorMethods;
1✔
196
  }
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc