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

Invoiced / invoiced-java / #255

02 Feb 2024 11:00PM CUT coverage: 81.958%. Remained the same
#255

push

github

jaredtking
Add publish action

695 of 848 relevant lines covered (81.96%)

0.82 hits per line

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

74.43
/src/main/java/com/invoiced/entity/AbstractEntity.java
1
package com.invoiced.entity;
2

3
import com.fasterxml.jackson.databind.JavaType;
4
import com.fasterxml.jackson.databind.SerializationFeature;
5
import com.invoiced.exception.EntityException;
6
import com.invoiced.util.ListResponse;
7
import com.invoiced.util.Util;
8

9
import java.lang.reflect.Field;
10
import java.lang.reflect.Modifier;
11
import java.util.HashMap;
12

13
public abstract class AbstractEntity<T extends AbstractEntity> {
14

15
  protected Class<T> tClass;
16
  protected String entityName;
17
  private Connection conn;
18
  private boolean entityCreated;
19
  private String endpointBase = "";
1✔
20

21
  public AbstractEntity(Connection conn, Class<T> tClass) {
1✔
22
    this.conn = conn;
1✔
23
    this.tClass = tClass;
1✔
24
    this.entityCreated = false;
1✔
25
  }
1✔
26

27
  public AbstractEntity(Class<T> tClass) {
1✔
28
    this.tClass = tClass;
1✔
29
    this.entityCreated = false;
1✔
30
  }
1✔
31

32
  protected static void setFields(Object from, Object to) throws EntityException {
33
    Field[] fields = from.getClass().getFields();
1✔
34

35
    for (Field field : fields) {
1✔
36
      try {
37
        Field fieldFrom = from.getClass().getField(field.getName());
1✔
38

39
        if (Modifier.isPrivate(field.getModifiers())) {
1✔
40
          continue;
×
41
        }
42

43
        if (Modifier.isPrivate(fieldFrom.getModifiers())) {
1✔
44
          continue;
×
45
        }
46

47
        if (Modifier.isFinal(field.getModifiers())) {
1✔
48
          continue;
×
49
        }
50

51
        if (Modifier.isFinal(fieldFrom.getModifiers())) {
1✔
52
          continue;
×
53
        }
54

55
        Object value = fieldFrom.get(from);
1✔
56
        to.getClass().getField(field.getName()).set(to, value);
1✔
57

58
      } catch (Throwable c) {
×
59
        throw new EntityException(c);
×
60
      }
1✔
61
    }
62
  }
1✔
63

64
  protected String getEndpoint(boolean includeId) {
65
    String url = this.getEndpointBase() + this.entityName;
1✔
66

67
    if (this.getEntityId() != null && includeId) {
1✔
68
      url += "/" + this.getEntityId();
1✔
69
    }
70

71
    return url;
1✔
72
  }
73

74
  protected Connection getConnection() {
75
    return this.conn;
1✔
76
  }
77

78
  protected void setConnection(Connection conn) {
79
    this.conn = conn;
1✔
80
  }
1✔
81

82
  protected void setClass(Class<T> tClass) {
83
    this.tClass = tClass;
1✔
84
  }
1✔
85

86
  protected String getEndpointBase() {
87
    return this.endpointBase;
1✔
88
  }
89

90
  protected void setEndpointBase(String base) {
91
    this.endpointBase = base;
1✔
92
  }
1✔
93

94
  public void create() throws EntityException {
95

96
    if (this.entityCreated) {
1✔
97
      throw new EntityException(new Throwable("Object has already been created."));
×
98
    }
99

100
    if (!this.hasCRUD()) {
1✔
101
      throw new EntityException(new Throwable("Create operation not available on object."));
1✔
102
    }
103

104
    String url = this.getEndpoint(false);
1✔
105

106
    try {
107
      String jsonRequest = this.toJsonString("create");
1✔
108
      String response = this.conn.post(url, null, jsonRequest);
1✔
109

110
      T object = Util.getMapper().readValue(response, this.tClass);
1✔
111
      object.setConnection(this.conn);
1✔
112
      object.setClass(this.tClass);
1✔
113

114
      setFields(object, this);
1✔
115
    } catch (Throwable c) {
×
116
      throw new EntityException(c);
×
117
    }
1✔
118

119
    this.entityCreated = true;
1✔
120
  }
1✔
121

122
  @Override
123
  public String toString() {
124

125
    String s1 = super.toString();
1✔
126

127
    try {
128

129
      String jsonString = this.toJsonString();
1✔
130
      s1 = s1 + " JSON: " + jsonString;
1✔
131

132
    } catch (Throwable c) {
×
133
      throw new RuntimeException(c);
×
134
    }
1✔
135

136
    return s1;
1✔
137
  }
138

139
  public String toJsonString() throws EntityException {
140
    try {
141
      return Util.getMapper().enable(SerializationFeature.INDENT_OUTPUT).writeValueAsString(this);
1✔
142
    } catch (Throwable c) {
×
143
      throw new EntityException(c);
×
144
    }
145
  }
146

147
  private String toJsonString(String operation) throws EntityException {
148

149
    String[] exclusions = null;
1✔
150

151
    try {
152

153
      if (operation == "create") exclusions = this.getCreateExclusions();
1✔
154
      else if (operation == "update") exclusions = this.getSaveExclusions();
1✔
155

156
      return Util.getFilteredMapper(exclusions)
1✔
157
              .writeValueAsString(this);
1✔
158

159
    } catch (Throwable c) {
×
160
      throw new EntityException(c);
×
161
    }
162
  }
163

164
  public void save() throws EntityException {
165
    if (!this.hasCRUD()) {
1✔
166
      throw new EntityException(new Throwable("Save operation not available on object."));
×
167
    }
168

169
    String url = this.getEndpoint(true);
1✔
170

171
    try {
172
      String jsonRequest = this.toJsonString("update");
1✔
173
      String response = this.conn.patch(url, jsonRequest);
1✔
174

175
      T object = Util.getMapper().readValue(response, this.tClass);
1✔
176
      setFields(object, this);
1✔
177
    } catch (Throwable c) {
×
178
      throw new EntityException(c);
×
179
    }
1✔
180
  }
1✔
181

182
  public T retrieve() throws EntityException {
183
    return this.retrieve("", null);
1✔
184
  }
185

186
  public T retrieve(long id) throws EntityException {
187
    return this.retrieve(String.valueOf(id), null);
1✔
188
  }
189

190
  public T retrieve(String id) throws EntityException {
191
    return this.retrieve(id, null);
1✔
192
  }
193

194
  public T retrieve(long id, HashMap<String, Object> queryParams) throws EntityException {
195
    return this.retrieve(String.valueOf(id), queryParams);
×
196
  }
197

198
  public T retrieve(String id, HashMap<String, Object> queryParams) throws EntityException {
199
    String url = this.getEndpoint(false);
1✔
200
    if (id.length() > 0) url += "/" + id;
1✔
201

202
    try {
203
      String response = this.conn.get(url, queryParams);
1✔
204

205
      T object = Util.getMapper().readValue(response, this.tClass);
1✔
206
      object.setConnection(this.conn);
1✔
207
      object.setClass(this.tClass);
1✔
208
      object.setEndpointBase(this.endpointBase);
1✔
209

210
      return object;
1✔
211
    } catch (Throwable c) {
1✔
212

213
      throw new EntityException(c);
1✔
214
    }
215
  }
216

217
  public void delete() throws EntityException {
218

219
    if (!this.hasCRUD()) {
1✔
220
      throw new EntityException(new Throwable("Delete operation not available on object."));
×
221
    }
222

223
    String url = this.getEndpoint(true);
1✔
224

225
    try {
226

227
      this.conn.delete(url);
1✔
228

229
    } catch (Throwable c) {
×
230

231
      throw new EntityException(c);
×
232
    }
1✔
233
  }
1✔
234

235
  public void delete(boolean includeId) throws EntityException {
236

237
    if (!this.hasCRUD()) {
1✔
238
      throw new EntityException(new Throwable("Delete operation not available on object."));
×
239
    }
240

241
    String url = this.getEndpoint(includeId);
1✔
242

243
    try {
244

245
      this.conn.delete(url);
1✔
246

247
    } catch (Throwable c) {
×
248

249
      throw new EntityException(c);
×
250
    }
1✔
251
  }
1✔
252

253
  public void deleteWithResponse() throws EntityException {
254
    if (!this.hasCRUD()) {
1✔
255
      throw new EntityException(new Throwable("Delete operation not available on object."));
×
256
    }
257

258
    String url = this.getEndpoint(true);
1✔
259

260
    try {
261
      String response = this.conn.deleteWithResponse(url);
1✔
262

263
      T object = Util.getMapper().readValue(response, this.tClass);
1✔
264
      object.setConnection(this.conn);
1✔
265
      object.setClass(this.tClass);
1✔
266
      object.setEndpointBase(this.endpointBase);
1✔
267

268
      setFields(object, this);
1✔
269
    } catch (Throwable c) {
×
270
      throw new EntityException(c);
×
271
    }
1✔
272
  }
1✔
273

274
  public EntityList<T> list(String nextURL) throws EntityException {
275

276
    EntityList<T> entities = null;
×
277

278
    try {
279

280
      entities = this.list(nextURL, null);
×
281

282
    } catch (EntityException e) {
×
283
      throw e;
×
284
    }
×
285

286
    return entities;
×
287
  }
288

289
  public EntityList<T> listAll() throws EntityException {
290
    EntityList<T> entities = null;
1✔
291

292
    try {
293

294
      entities = this.listAll(null);
1✔
295

296
    } catch (EntityException e) {
×
297
      throw e;
×
298
    }
1✔
299

300
    return entities;
1✔
301
  }
302

303
  public EntityList<T> list(String nextURL, HashMap<String, Object> queryParams)
304
      throws EntityException {
305

306
    if (!this.hasList()) {
1✔
307
      throw new EntityException(new Throwable("List operation not available on object."));
×
308
    }
309

310
    String url = nextURL != null && nextURL.length() > 0 ? nextURL : this.conn.baseUrl() + this.getEndpoint(false);
1✔
311

312
    EntityList<T> entities = null;
1✔
313

314
    try {
315

316
      ListResponse response = this.conn.getList(url, queryParams);
1✔
317

318
      JavaType collectionType =
319
          Util.getMapper().getTypeFactory().constructCollectionType(EntityList.class, this.tClass);
1✔
320

321
      entities = Util.getMapper().readValue(response.getResult(), collectionType);
1✔
322

323
      entities.setLinkURLs(response.getLinks());
1✔
324
      entities.setTotalCount(response.getTotalCount());
1✔
325

326
      for (T entity : entities) {
1✔
327

328
        entity.setConnection(this.conn);
1✔
329
        entity.setClass(this.tClass);
1✔
330
      }
1✔
331

332
    } catch (Throwable c) {
×
333
      throw new EntityException(c);
×
334
    }
1✔
335

336
    return entities;
1✔
337
  }
338

339
  public EntityList<T> listAll(HashMap<String, Object> queryParams) throws EntityException {
340
    EntityList<T> entities = null;
1✔
341
    EntityList<T> tmp = null;
1✔
342

343
    if (!this.hasList()) {
1✔
344
      throw new EntityException(new Throwable("List operation not available on object."));
×
345
    }
346

347
    String url = null;
1✔
348

349
    try {
350

351
      do {
352

353
        tmp = this.list(url, queryParams);
1✔
354
        if (entities == null) {
1✔
355
          entities = tmp;
1✔
356
        } else {
357
          entities.addAll(tmp);
×
358
        }
359

360
        url = tmp.getLinkURLs().get("next");
1✔
361

362
      } while (tmp.getLinkURLs().get("next") != null
1✔
363
          && !tmp.getLinkURLs().get("self").equals(tmp.getLinkURLs().get("last")));
1✔
364

365
      entities.setLinkURLs(tmp.getLinkURLs());
1✔
366

367
    } catch (EntityException e) {
×
368
      throw e;
×
369
    } catch (Throwable c) {
×
370
      throw new EntityException(c);
×
371
    }
1✔
372

373
    return entities;
1✔
374
  }
375

376
  protected boolean hasCRUD() {
377
    return true;
1✔
378
  }
379

380
  protected boolean hasList() {
381
    return true;
1✔
382
  }
383

384
  abstract String getEntityId();
385

386
  abstract String[] getCreateExclusions();
387

388
  abstract String[] getSaveExclusions();
389
}
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

© 2025 Coveralls, Inc