Skip to content

Commit

Permalink
Start implementing update functionality. Also, validate ISO date rang…
Browse files Browse the repository at this point in the history
…es better
  • Loading branch information
GenieTim committed Jan 3, 2024
1 parent 714dcdd commit 5d98575
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ public boolean verify(JComponent comp) {
if (!content.matches(ImageCaptureApp.REGEX_DATE)) {
returnValue = false;
}
// check that, for date ranges, the range is valid/increasing
if (content.contains("-")) {
String[] split = content.split("-");
if (split[1].compareTo(split[0]) < 0) {
returnValue = false;
}
}
}
return returnValue;
}
Expand Down
118 changes: 111 additions & 7 deletions src/main/java/edu/harvard/mcz/imagecapture/data/NahimaManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected static Integer resolveId(JSONObject objWithId, String objectType) {
return id;
}

protected static Integer resolveId(JSONObject objWithId) {
public static Integer resolveId(JSONObject objWithId) {
if (objWithId == null) {
return null;
}
Expand Down Expand Up @@ -133,14 +133,42 @@ protected void login() throws IOException, InterruptedException, RuntimeExceptio
* @param specimen the specimen whose images to upload
* @return the created mediassets
*/
public ArrayList<JSONObject> uploadImagesForSpecimen(Specimen specimen) throws IOException, InterruptedException, RuntimeException {
public ArrayList<JSONObject> uploadImagesForSpecimen(Specimen specimen, JSONObject existingExport) throws IOException, InterruptedException, RuntimeException {
// docs:
// https://docs.easydb.de/en/technical/api/eas/
// https://docs.easydb.de/en/sysadmin/eas/api/put/
String baseQueryUrl = this.url + "eas/put?token=" + this.token;
ArrayList<JSONObject> results = new ArrayList<>();

for (ICImage image : specimen.getICImages()) {
// first, filter whether this particular image is already online, part of this specimen
boolean foundExisting = false;
if (existingExport != null) {
// check if the image has already been uploaded
JSONArray mediaassets = existingExport.getJSONObject("entomologie").getJSONArray("_reverse_nested:entomologie_mediaassetpublic:entomologie");
for (int i = 0; i < mediaassets.length(); ++i) {
JSONObject std = mediaassets.getJSONObject(i).getJSONObject("mediaassetpublic").getJSONObject("_standard").getJSONObject("eas");
Iterator<String> keys = std.keys();

while (keys.hasNext()) {
String key = keys.next();
String filename = std.getJSONArray(key).getJSONObject(0).getString("original_filename");
if (Objects.equals(filename, image.getFilename())) {
// file has been uploaded already
results.add(
mediaassets.getJSONObject(i)
);
foundExisting = true;
break;
}
}
}
}
if (foundExisting) {
continue;
}

// if not existing, continue with uploading
String queryUrl = baseQueryUrl + "&original_filename=" + image.getFilename() + "&instance=image";
log.debug("Running image upload to URL " + queryUrl);

Expand Down Expand Up @@ -225,6 +253,60 @@ public JSONObject findObjectByUuid(String uuid) throws IOException {
return new JSONObject(returnValue);
}

/**
* Load an object from Nahima by its global object identifier
*
* @param globalObjectId the global object identifier
* @return the object
* @throws IOException
* @throws InterruptedException
*/
public JSONObject findObjectByGlobalObjectId(String globalObjectId) throws IOException, InterruptedException {
if (globalObjectId == null || globalObjectId.equals("")) {
return null;
}

String queryURL = this.url + "search";
JSONObject query = new JSONObject() {{
put("best_mask_filter", true);
put("generate_rights", false);
put("search", new JSONArray() {{
put(new JSONObject() {{
put("type", "in");
put("fields", new JSONArray() {{
put("_global_object_id");
}});
put("in", new JSONArray() {{
put(globalObjectId);
}});
}});
}});
}};

JSONObject result = this.postRequest(queryURL, query);
if (result.has("code") && result.getString("code").startsWith("error")) {
throw new RuntimeException("Failed to fetch object by global object id '" + globalObjectId + "': Error code: " + result.get("code"));
}
if (result.has("objects") && result.getJSONArray("objects").length() == 0) {
return null;
}
if (result.has("objects")) {
// TODO: we can expect that for what we use it currently, there will never be more than one.
// however, that's not a general case
return result.getJSONArray("objects").getJSONObject(0);
}
return result;
}

/**
* Small utility method to speed some things up,
* by loading from this local cache (keyword: memoization)
*
* @param id the cache identifier
* @param objectType the type of object to retrieve
* @return the cached object
* @see NahimaManager::storeInCache
*/
protected JSONObject loadFromCache(String id, String objectType) {
Map<String, JSONObject> typeCache = resolveCache.get(objectType);
if (typeCache != null) {
Expand All @@ -233,6 +315,15 @@ protected JSONObject loadFromCache(String id, String objectType) {
return null;
}

/**
* Small utility method to speed some things up,
* by storing to this local cache (keyword: memoization)
*
* @param id the cache identifier
* @param objectType the type of object to retrieve
* @param result the object to cache/memoize
* @see NahimaManager::loadFromCache
*/
protected void storeInCache(String id, String objectType, JSONObject result) {
Map<String, JSONObject> typeCache = resolveCache.computeIfAbsent(objectType, k -> new HashMap<>());
typeCache.put(id, result);
Expand Down Expand Up @@ -1215,8 +1306,9 @@ public JSONObject reduceAssociateForAssociation(JSONObject associate, String obj
* @param mask the mask specifying the fields to use
* @return the wrapped object, ready to be created
*/
private JSONObject wrapForCreation(JSONObject inner, String objectType, String mask, boolean omitPool) {
inner = this.addDefaultValuesForCreation(inner, omitPool);

public JSONObject wrapForCreation(JSONObject inner, JSONObject existing, String objectType, String mask, boolean omitPool) {
inner = this.addDefaultValuesForCreation(inner, omitPool, existing);
JSONObject result = new JSONObject(new HashMap<>() {{
put("_mask", mask);
put("_objecttype", objectType);
Expand All @@ -1226,6 +1318,10 @@ private JSONObject wrapForCreation(JSONObject inner, String objectType, String m
return result;
}

public JSONObject wrapForCreation(JSONObject inner, String objectType, String mask, boolean omitPool) {
return wrapForCreation(inner, null, objectType, mask, omitPool);
}

public JSONObject wrapForCreation(JSONObject inner, String objectType, String mask) {
return wrapForCreation(inner, objectType, mask, false);
}
Expand All @@ -1244,19 +1340,27 @@ public JSONObject addDefaultValuesForCreation(JSONObject inner) {
return addDefaultValuesForCreation(inner, false);
}

public JSONObject addDefaultValuesForCreation(JSONObject inner, JSONObject existing) {
return addDefaultValuesForCreation(inner, false, existing);
}

public JSONObject addDefaultValuesForCreation(JSONObject inner, boolean omitPool) {
return addDefaultValuesForCreation(inner, omitPool, null);
}

/**
* Add default values, such as _id and _version, for creation
*
* @param inner the object to add the
* @param omitPool whether to *not* add the property _pool
* @return the object with the new values
*/
public JSONObject addDefaultValuesForCreation(JSONObject inner, boolean omitPool) {
public JSONObject addDefaultValuesForCreation(JSONObject inner, boolean omitPool, JSONObject existing) {
if (!omitPool) {
inner.put("_pool", defaultPool);
}
inner.put("_id", JSONObject.NULL);
inner.put("_version", 1);
inner.put("_id", existing == null ? JSONObject.NULL : resolveId(existing));
inner.put("_version", existing == null ? 1 : existing.getInt("_version"));
return inner;
}

Expand Down
Loading

0 comments on commit 5d98575

Please sign in to comment.