Skip to content

Commit dbbe953

Browse files
committed
NIFI-15386 - Upgrade Box SDK to Version 10
1 parent 21fa19a commit dbbe953

File tree

51 files changed

+2764
-2233
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2764
-2233
lines changed

nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/BoxEventJsonArrayWriter.java

Lines changed: 175 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,86 +16,215 @@
1616
*/
1717
package org.apache.nifi.processors.box;
1818

19-
import com.box.sdk.BoxEvent;
20-
import com.eclipsesource.json.Json;
21-
import com.eclipsesource.json.JsonObject;
19+
import com.box.sdkgen.schemas.event.Event;
20+
import com.box.sdkgen.schemas.eventsource.EventSource;
21+
import com.box.sdkgen.schemas.eventsourceresource.EventSourceResource;
22+
import com.box.sdkgen.schemas.file.File;
23+
import com.box.sdkgen.schemas.folder.Folder;
24+
import com.box.sdkgen.schemas.foldermini.FolderMini;
25+
import com.box.sdkgen.schemas.user.User;
26+
import com.fasterxml.jackson.core.JsonFactory;
27+
import com.fasterxml.jackson.core.JsonGenerator;
28+
import com.fasterxml.jackson.databind.ObjectMapper;
2229

2330
import java.io.Closeable;
2431
import java.io.IOException;
2532
import java.io.OutputStream;
26-
import java.io.OutputStreamWriter;
27-
import java.io.Writer;
28-
import java.util.Objects;
29-
30-
import static java.nio.charset.StandardCharsets.UTF_8;
33+
import java.util.Map;
3134

3235
/**
33-
* A class responsible for writing {@link BoxEvent} objects into a JSON array.
36+
* A class responsible for writing {@link Event} objects into a JSON array.
3437
* Not thread-safe.
3538
*/
3639
final class BoxEventJsonArrayWriter implements Closeable {
3740

38-
private final Writer writer;
41+
private static final JsonFactory JSON_FACTORY = new JsonFactory();
42+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
43+
private final JsonGenerator generator;
3944
private boolean hasBegun;
40-
private boolean hasEntries;
4145
private boolean closed;
4246

43-
private BoxEventJsonArrayWriter(final Writer writer) {
44-
this.writer = writer;
47+
private BoxEventJsonArrayWriter(final JsonGenerator generator) {
48+
this.generator = generator;
4549
this.hasBegun = false;
46-
this.hasEntries = false;
4750
this.closed = false;
4851
}
4952

5053
static BoxEventJsonArrayWriter create(final OutputStream outputStream) throws IOException {
51-
final Writer writer = new OutputStreamWriter(outputStream, UTF_8);
52-
return new BoxEventJsonArrayWriter(writer);
54+
final JsonGenerator generator = JSON_FACTORY.createGenerator(outputStream);
55+
return new BoxEventJsonArrayWriter(generator);
5356
}
5457

55-
void write(final BoxEvent event) throws IOException {
58+
void write(final Event event) throws IOException {
5659
if (closed) {
5760
throw new IOException("The Writer is closed");
5861
}
5962

6063
if (!hasBegun) {
61-
beginArray();
64+
generator.writeStartArray();
6265
hasBegun = true;
6366
}
6467

65-
if (hasEntries) {
66-
writer.write(',');
68+
writeEvent(event);
69+
}
70+
71+
private void writeEvent(final Event event) throws IOException {
72+
generator.writeStartObject();
73+
74+
// Map Event fields to JSON using camelCase to match the original NiFi Box processor format
75+
writeStringField("createdAt", event.getCreatedAt() != null ? event.getCreatedAt().toString() : null);
76+
writeStringField("recordedAt", event.getRecordedAt() != null ? event.getRecordedAt().toString() : null);
77+
writeStringField("eventType", event.getEventType() != null ? event.getEventType().getValue() : null);
78+
writeStringField("id", event.getEventId());
79+
writeStringField("sessionID", event.getSessionId());
80+
writeStringField("type", event.getType());
81+
82+
// Handle createdBy if present (camelCase for field name, but inner fields match Box API)
83+
if (event.getCreatedBy() != null) {
84+
generator.writeObjectFieldStart("createdBy");
85+
writeStringField("id", event.getCreatedBy().getId());
86+
writeStringField("type", event.getCreatedBy().getType() != null ? event.getCreatedBy().getType().getValue() : null);
87+
writeStringField("name", event.getCreatedBy().getName());
88+
writeStringField("login", event.getCreatedBy().getLogin());
89+
generator.writeEndObject();
90+
} else {
91+
generator.writeNullField("createdBy");
6792
}
6893

69-
final JsonObject json = toRecord(event);
70-
json.writeTo(writer);
94+
// Handle source if present - use snake_case for inner fields to match Box API format
95+
writeSource(event.getSource());
96+
97+
// Handle additionalDetails if present - serialize as proper JSON object
98+
writeAdditionalDetails(event.getAdditionalDetails());
7199

72-
hasEntries = true;
100+
generator.writeEndObject();
73101
}
74102

75-
private JsonObject toRecord(final BoxEvent event) {
76-
final JsonObject json = Json.object();
77-
78-
json.add("accessibleBy", event.getAccessibleBy() == null ? Json.NULL : Json.parse(event.getAccessibleBy().getJson()));
79-
json.add("actionBy", event.getActionBy() == null ? Json.NULL : Json.parse(event.getActionBy().getJson()));
80-
json.add("additionalDetails", Objects.requireNonNullElse(event.getAdditionalDetails(), Json.NULL));
81-
json.add("createdAt", event.getCreatedAt() == null ? Json.NULL : Json.value(event.getCreatedAt().toString()));
82-
json.add("createdBy", event.getCreatedBy() == null ? Json.NULL : Json.parse(event.getCreatedBy().getJson()));
83-
json.add("eventType", event.getEventType() == null ? Json.NULL : Json.value(event.getEventType().name()));
84-
json.add("id", Objects.requireNonNullElse(Json.value(event.getID()), Json.NULL));
85-
json.add("ipAddress", Objects.requireNonNullElse(Json.value(event.getIPAddress()), Json.NULL));
86-
json.add("sessionID", Objects.requireNonNullElse(Json.value(event.getSessionID()), Json.NULL));
87-
json.add("source", Objects.requireNonNullElse(event.getSourceJSON(), Json.NULL));
88-
json.add("typeName", Objects.requireNonNullElse(Json.value(event.getTypeName()), Json.NULL));
89-
90-
return json;
103+
private void writeSource(final EventSourceResource source) throws IOException {
104+
if (source == null) {
105+
generator.writeNullField("source");
106+
return;
107+
}
108+
109+
generator.writeObjectFieldStart("source");
110+
try {
111+
// EventSourceResource is a union type (OneOfSix) - check what kind of source we have
112+
if (source.isFile()) {
113+
// File source - contains file_id, file_name, and parent folder info
114+
File file = source.getFile();
115+
writeStringField("item_type", "file");
116+
writeStringField("item_id", file.getId());
117+
writeStringField("item_name", file.getName());
118+
// Add file-specific fields for collaboration events
119+
writeStringField("file_id", file.getId());
120+
writeStringField("file_name", file.getName());
121+
// Add parent folder info if available
122+
FolderMini parent = file.getParent();
123+
if (parent != null) {
124+
writeStringField("folder_id", parent.getId());
125+
writeStringField("folder_name", parent.getName());
126+
}
127+
} else if (source.isFolder()) {
128+
// Folder source - contains folder_id, folder_name
129+
Folder folder = source.getFolder();
130+
writeStringField("item_type", "folder");
131+
writeStringField("item_id", folder.getId());
132+
writeStringField("item_name", folder.getName());
133+
// Add folder-specific fields for collaboration events
134+
writeStringField("folder_id", folder.getId());
135+
writeStringField("folder_name", folder.getName());
136+
} else if (source.isEventSource()) {
137+
// Generic EventSource - has item_type, item_id, item_name
138+
EventSource eventSource = source.getEventSource();
139+
String itemType = eventSource.getItemType() != null ? eventSource.getItemType().getValue() : null;
140+
writeStringField("item_type", itemType);
141+
writeStringField("item_id", eventSource.getItemId());
142+
writeStringField("item_name", eventSource.getItemName());
143+
// For EventSource, also populate file/folder specific fields based on item_type
144+
if ("file".equals(itemType)) {
145+
writeStringField("file_id", eventSource.getItemId());
146+
writeStringField("file_name", eventSource.getItemName());
147+
} else if ("folder".equals(itemType)) {
148+
writeStringField("folder_id", eventSource.getItemId());
149+
writeStringField("folder_name", eventSource.getItemName());
150+
}
151+
// Add parent folder info if available
152+
FolderMini parent = eventSource.getParent();
153+
if (parent != null) {
154+
writeStringField("parent_id", parent.getId());
155+
writeStringField("parent_name", parent.getName());
156+
}
157+
} else if (source.isUser()) {
158+
// User source
159+
User user = source.getUser();
160+
writeStringField("item_type", "user");
161+
writeStringField("id", user.getId());
162+
writeStringField("name", user.getName());
163+
writeStringField("login", user.getLogin());
164+
} else if (source.isMap()) {
165+
// Generic map - write all entries
166+
Map<String, Object> map = source.getMap();
167+
for (Map.Entry<String, Object> entry : map.entrySet()) {
168+
Object value = entry.getValue();
169+
if (value != null) {
170+
generator.writeFieldName(entry.getKey());
171+
generator.writeObject(value);
172+
}
173+
}
174+
} else if (source.isAppItemEventSource()) {
175+
// AppItemEventSource
176+
writeStringField("item_type", "app_item");
177+
} else {
178+
writeStringField("item_type", "unknown");
179+
}
180+
} catch (Exception e) {
181+
writeStringField("error", "Could not serialize source: " + e.getMessage());
182+
}
183+
generator.writeEndObject();
91184
}
92185

93-
private void beginArray() throws IOException {
94-
writer.write('[');
186+
private void writeAdditionalDetails(final Map<String, Object> additionalDetails) throws IOException {
187+
if (additionalDetails == null) {
188+
generator.writeNullField("additionalDetails");
189+
return;
190+
}
191+
192+
try {
193+
// Write additionalDetails as a proper JSON object, not a string
194+
generator.writeFieldName("additionalDetails");
195+
generator.writeStartObject();
196+
for (Map.Entry<String, Object> entry : additionalDetails.entrySet()) {
197+
String key = entry.getKey();
198+
Object value = entry.getValue();
199+
if (value == null) {
200+
generator.writeNullField(key);
201+
} else if (value instanceof String) {
202+
generator.writeStringField(key, (String) value);
203+
} else if (value instanceof Number) {
204+
generator.writeNumberField(key, ((Number) value).doubleValue());
205+
} else if (value instanceof Boolean) {
206+
generator.writeBooleanField(key, (Boolean) value);
207+
} else if (value instanceof Map) {
208+
// Nested map - use ObjectMapper to serialize
209+
generator.writeFieldName(key);
210+
generator.writeRawValue(OBJECT_MAPPER.writeValueAsString(value));
211+
} else {
212+
// For other types, convert to string
213+
generator.writeStringField(key, value.toString());
214+
}
215+
}
216+
generator.writeEndObject();
217+
} catch (Exception e) {
218+
generator.writeNullField("additionalDetails");
219+
}
95220
}
96221

97-
private void endArray() throws IOException {
98-
writer.write(']');
222+
private void writeStringField(final String fieldName, final String value) throws IOException {
223+
if (value != null) {
224+
generator.writeStringField(fieldName, value);
225+
} else {
226+
generator.writeNullField(fieldName);
227+
}
99228
}
100229

101230
@Override
@@ -107,10 +236,10 @@ public void close() throws IOException {
107236
closed = true;
108237

109238
if (!hasBegun) {
110-
beginArray();
239+
generator.writeStartArray();
111240
}
112-
endArray();
241+
generator.writeEndArray();
113242

114-
writer.close();
243+
generator.close();
115244
}
116245
}

nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/BoxFileUtils.java

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,46 +16,75 @@
1616
*/
1717
package org.apache.nifi.processors.box;
1818

19-
import com.box.sdk.BoxFile;
20-
import com.box.sdk.BoxFolder;
21-
import com.box.sdk.BoxItem;
19+
import com.box.sdkgen.schemas.file.File;
20+
import com.box.sdkgen.schemas.folder.Folder;
21+
import com.box.sdkgen.schemas.foldermini.FolderMini;
2222
import org.apache.nifi.flowfile.attributes.CoreAttributes;
2323

2424
import java.util.LinkedHashMap;
25+
import java.util.List;
2526
import java.util.Map;
27+
import java.util.stream.Collectors;
2628

2729
import static java.lang.String.valueOf;
28-
import static java.util.stream.Collectors.joining;
2930

3031
public final class BoxFileUtils {
3132

3233
public static final String BOX_URL = "https://app.box.com/file/";
3334

34-
public static String getParentIds(final BoxItem.Info info) {
35-
return info.getPathCollection().stream()
36-
.map(BoxItem.Info::getID)
37-
.collect(joining(","));
35+
public static String getParentIds(final File fileInfo) {
36+
if (fileInfo.getPathCollection() == null || fileInfo.getPathCollection().getEntries() == null) {
37+
return "";
38+
}
39+
return fileInfo.getPathCollection().getEntries().stream()
40+
.map(FolderMini::getId)
41+
.collect(Collectors.joining(","));
3842
}
39-
public static String getParentPath(BoxItem.Info info) {
40-
return "/" + info.getPathCollection().stream()
41-
.filter(pathItemInfo -> !pathItemInfo.getID().equals("0"))
42-
.map(BoxItem.Info::getName)
43-
.collect(joining("/"));
43+
44+
public static String getParentPath(final File fileInfo) {
45+
if (fileInfo.getPathCollection() == null || fileInfo.getPathCollection().getEntries() == null) {
46+
return "/";
47+
}
48+
return "/" + fileInfo.getPathCollection().getEntries().stream()
49+
.filter(pathItem -> !pathItem.getId().equals("0"))
50+
.map(FolderMini::getName)
51+
.collect(Collectors.joining("/"));
52+
}
53+
54+
public static String getParentPath(final List<FolderMini> pathCollection) {
55+
if (pathCollection == null) {
56+
return "/";
57+
}
58+
return "/" + pathCollection.stream()
59+
.filter(pathItem -> !pathItem.getId().equals("0"))
60+
.map(FolderMini::getName)
61+
.collect(Collectors.joining("/"));
4462
}
4563

46-
public static String getFolderPath(BoxFolder.Info folderInfo) {
47-
final String parentFolderPath = getParentPath(folderInfo);
64+
public static String getFolderPath(final Folder folderInfo) {
65+
final String parentFolderPath = getParentPathForFolder(folderInfo);
4866
return "/".equals(parentFolderPath) ? parentFolderPath + folderInfo.getName() : parentFolderPath + "/" + folderInfo.getName();
4967
}
5068

51-
public static Map<String, String> createAttributeMap(BoxFile.Info fileInfo) {
69+
private static String getParentPathForFolder(final Folder folderInfo) {
70+
if (folderInfo.getPathCollection() == null || folderInfo.getPathCollection().getEntries() == null) {
71+
return "/";
72+
}
73+
return "/" + folderInfo.getPathCollection().getEntries().stream()
74+
.filter(pathItem -> !pathItem.getId().equals("0"))
75+
.map(FolderMini::getName)
76+
.collect(Collectors.joining("/"));
77+
}
78+
79+
public static Map<String, String> createAttributeMap(final File fileInfo) {
5280
final Map<String, String> attributes = new LinkedHashMap<>();
53-
attributes.put(BoxFileAttributes.ID, fileInfo.getID());
81+
attributes.put(BoxFileAttributes.ID, fileInfo.getId());
5482
attributes.put(CoreAttributes.FILENAME.key(), fileInfo.getName());
5583
attributes.put(CoreAttributes.PATH.key(), getParentPath(fileInfo));
56-
attributes.put(BoxFileAttributes.TIMESTAMP, valueOf(fileInfo.getModifiedAt()));
84+
if (fileInfo.getModifiedAt() != null) {
85+
attributes.put(BoxFileAttributes.TIMESTAMP, valueOf(fileInfo.getModifiedAt()));
86+
}
5787
attributes.put(BoxFileAttributes.SIZE, valueOf(fileInfo.getSize()));
5888
return attributes;
5989
}
60-
6190
}

0 commit comments

Comments
 (0)