Skip to content

Commit abdeebf

Browse files
authored
Merge pull request #1014 from WildMeOrg/912_mediaasset_in_opensearch
Index MediaAssets in OpenSearch
2 parents c58ab39 + 18d703b commit abdeebf

21 files changed

+253
-38
lines changed

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,20 @@
382382
<scope>test</scope>
383383
</dependency>
384384

385+
<dependency>
386+
<groupId>org.mockito</groupId>
387+
<artifactId>mockito-inline</artifactId>
388+
<version>3.12.4</version>
389+
<scope>test</scope>
390+
</dependency>
391+
392+
<dependency>
393+
<groupId>org.mockito</groupId>
394+
<artifactId>mockito-core</artifactId>
395+
<version>3.12.4</version>
396+
<scope>test</scope>
397+
</dependency>
398+
385399
<dependency>
386400
<groupId>org.geotools</groupId>
387401
<artifactId>gt-shapefile</artifactId>

src/main/java/org/ecocean/Annotation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public void opensearchDocumentSerializer(JsonGenerator jgen, Shepherd myShepherd
168168
jgen.writeBooleanField("matchAgainst", this.getMatchAgainst());
169169
MediaAsset ma = this.getMediaAsset();
170170
if (ma != null) {
171-
jgen.writeNumberField("mediaAssetId", ma.getId());
171+
jgen.writeNumberField("mediaAssetId", ma.getIdInt());
172172
}
173173
Encounter enc = this.findEncounter(myShepherd);
174174
if (enc != null) {

src/main/java/org/ecocean/Encounter.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ private MediaAsset addMediaIfNeeded(Shepherd myShepherd, File mpath, String key,
13531353
MediaAsset ma = astore.find(sp, myShepherd);
13541354
if (ma != null) {
13551355
ma.addLabel(label);
1356-
if (parentMA != null) ma.setParentId(parentMA.getId());
1356+
if (parentMA != null) ma.setParentId(parentMA.getIdInt());
13571357
return ma;
13581358
}
13591359
System.out.println("creating new MediaAsset for key=" + key);
@@ -1365,7 +1365,7 @@ private MediaAsset addMediaIfNeeded(Shepherd myShepherd, File mpath, String key,
13651365
return null;
13661366
}
13671367
if (parentMA != null) {
1368-
ma.setParentId(parentMA.getId());
1368+
ma.setParentId(parentMA.getIdInt());
13691369
ma.updateMinimalMetadata(); // for children (ostensibly derived?) MediaAssets, really only need minimal metadata or so i claim
13701370
} else {
13711371
try {
@@ -1417,7 +1417,7 @@ public MediaAsset spotImageAsMediaAsset(MediaAsset parent, String baseDir,
14171417
System.out.println("spotImageAsMediaAsset threw IOException " + ex.toString());
14181418
}
14191419
}
1420-
ma.setParentId(parent.getId());
1420+
ma.setParentId(parent.getIdInt());
14211421
return ma;
14221422
}
14231423

@@ -2897,7 +2897,7 @@ public int indexOfMediaAsset(int id) {
28972897
for (int i = 0; i < annotations.size(); i++) {
28982898
MediaAsset ma = annotations.get(i).getMediaAsset();
28992899
if (ma == null) continue;
2900-
if (ma.getId() == id) return i;
2900+
if (ma.getIdInt() == id) return i;
29012901
}
29022902
return -1;
29032903
}
@@ -2928,7 +2928,7 @@ public void replaceAnnotation(Annotation oldAnn, Annotation newAnn) {
29282928
}
29292929

29302930
public void removeMediaAsset(MediaAsset ma) {
2931-
removeAnnotation(indexOfMediaAsset(ma.getId()));
2931+
removeAnnotation(indexOfMediaAsset(ma.getIdInt()));
29322932
}
29332933

29342934
// this is a kinda hacky way to find media ... really used by encounter.jsp now but likely should go away?
@@ -3370,7 +3370,7 @@ public boolean restAccess(HttpServletRequest request, org.json.JSONObject jsonob
33703370
return true;
33713371
}
33723372

3373-
///////// these are bunk now - dont use Features TODO: fix these - perhaps by crawlng thru ma.getAnnotations() ?
3373+
///////// this is bunk now: see fix for findAllByMediaAsset() if you need this
33743374
public static Encounter findByMediaAsset(MediaAsset ma, Shepherd myShepherd) {
33753375
String queryString =
33763376
"SELECT FROM org.ecocean.Encounter WHERE annotations.contains(ann) && ann.mediaAsset.id =="
@@ -3391,8 +3391,8 @@ public static List<Encounter> findAllByMediaAsset(MediaAsset ma, Shepherd myShep
33913391

33923392
try {
33933393
String queryString =
3394-
"SELECT FROM org.ecocean.Encounter WHERE annotations.contains(ann) && ann.mediaAsset.id =="
3395-
+ ma.getId();
3394+
"SELECT FROM org.ecocean.Encounter WHERE annotations.contains(ann) && ann.features.contains(feat) && mediaAsset.features.contains(feat) && mediaAsset.id =="
3395+
+ ma.getId() + " VARIABLES org.ecocean.media.MediaAsset mediaAsset; org.ecocean.Annotation ann; org.ecocean.media.Feature feat";
33963396
Query query = myShepherd.getPM().newQuery(queryString);
33973397
Collection results = (Collection)query.execute();
33983398
returnEncs = new ArrayList<Encounter>(results);
@@ -4069,7 +4069,7 @@ public void opensearchDocumentSerializer(JsonGenerator jgen, Shepherd myShepherd
40694069
jgen.writeArrayFieldStart("mediaAssets");
40704070
for (MediaAsset ma : mas) {
40714071
jgen.writeStartObject();
4072-
jgen.writeNumberField("id", ma.getId());
4072+
jgen.writeNumberField("id", ma.getIdInt());
40734073
jgen.writeStringField("uuid", ma.getUUID());
40744074
try {
40754075
// historic data might throw IllegalArgumentException: Path not under given root

src/main/java/org/ecocean/OpenSearch.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import javax.jdo.Query;
1515
import javax.net.ssl.SSLContext;
1616
import javax.net.ssl.SSLEngine;
17+
import org.ecocean.media.MediaAsset;
1718
import org.ecocean.SystemValue;
1819
import org.json.JSONArray;
1920
import org.json.JSONObject;
@@ -62,7 +63,7 @@ public class OpenSearch {
6263
public static String SEARCH_PIT_TIME = (String)getConfigurationValue("searchPitTime", "10m");
6364
public static String INDEX_TIMESTAMP_PREFIX = "OpenSearch_index_timestamp_";
6465
public static String[] VALID_INDICES = {
65-
"encounter", "individual", "occurrence", "annotation"
66+
"encounter", "individual", "occurrence", "annotation", "media_asset"
6667
};
6768
public static int BACKGROUND_DELAY_MINUTES = (Integer)getConfigurationValue(
6869
"backgroundDelayMinutes", 20);
@@ -159,6 +160,8 @@ public void run() {
159160
BACKGROUND_SLICE_SIZE);
160161
Base.opensearchSyncIndex(myShepherd, MarkedIndividual.class,
161162
BACKGROUND_SLICE_SIZE);
163+
Base.opensearchSyncIndex(myShepherd, MediaAsset.class,
164+
BACKGROUND_SLICE_SIZE);
162165
System.out.println("OpenSearch background indexing finished.");
163166
myShepherd.rollbackAndClose();
164167
} catch (Exception ex) {

src/main/java/org/ecocean/Shepherd.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,26 @@ public Iterator getAllMediaAssets() {
21462146
}
21472147
}
21482148

2149+
// note: where clause can also contain " ORDER BY xxx"
2150+
public Iterator getMediaAssetsFilter(String jdoWhereClause) {
2151+
Query query = null;
2152+
2153+
try {
2154+
query = pm.newQuery("SELECT FROM org.ecocean.media.MediaAsset WHERE " + jdoWhereClause);
2155+
Collection c = (Collection)(query.execute());
2156+
List list = new ArrayList(c);
2157+
Iterator it = list.iterator();
2158+
query.closeAll();
2159+
return it;
2160+
} catch (Exception npe) {
2161+
System.out.println(
2162+
"Error encountered when trying to execute getAllAnnotationsFilter. Returning a null iterator.");
2163+
npe.printStackTrace();
2164+
if (query != null) query.closeAll();
2165+
return null;
2166+
}
2167+
}
2168+
21492169
public ArrayList<MediaAsset> getAllMediaAssetsAsArray() {
21502170
try {
21512171
Extent maClass = pm.getExtent(MediaAsset.class, true);

src/main/java/org/ecocean/api/BaseObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected JSONObject processPost(HttpServletRequest request, String[] args, JSON
145145
maj.put("uuid", ma.getUUID());
146146
maj.put("url", ma.webURL());
147147
assetsArr.put(maj);
148-
maIds.add(ma.getId());
148+
maIds.add(ma.getIdInt());
149149
}
150150
rtn.put("assets", assetsArr);
151151
enc.setAnnotations(anns);

src/main/java/org/ecocean/identity/IBEISIA.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ private static boolean needToSend(MediaAsset ma) {
11191119
}
11201120

11211121
private static void markSent(MediaAsset ma) {
1122-
alreadySentMA.put(ma.getId(), true);
1122+
alreadySentMA.put(ma.getIdInt(), true);
11231123
}
11241124

11251125
private static boolean needToSend(Annotation ann) {
@@ -1600,8 +1600,8 @@ private static JSONObject processCallbackDetect(String taskID,
16001600
MediaAsset asset = null;
16011601
for (MediaAsset ma : mas) {
16021602
if (ma.getAcmId() == null) continue; // was likely an asset rejected (e.g. video)
1603-
if (ma.getAcmId().equals(iuuid) && !alreadyDetected.contains(ma.getId())) {
1604-
alreadyDetected.add(ma.getId());
1603+
if (ma.getAcmId().equals(iuuid) && !alreadyDetected.contains(ma.getIdInt())) {
1604+
alreadyDetected.add(ma.getIdInt());
16051605
asset = ma;
16061606
break;
16071607
}
@@ -1674,7 +1674,7 @@ private static JSONObject processCallbackDetect(String taskID,
16741674
if (newAnns.length() > 0) {
16751675
List<Encounter> assignedEncs = asset.assignEncounters(myShepherd); // here is where we make some encounter(s) if we need to
16761676
rtn.put("_assignedEncsSize", assignedEncs.size());
1677-
amap.put(Integer.toString(asset.getId()), newAnns);
1677+
amap.put(Integer.toString(asset.getIdInt()), newAnns);
16781678
// now we have to collect them under an Occurrence and/or ImportTask as applicable
16791679
// we basically pick the first of these we find (in case there is more than one?)
16801680
// and only assign it where there is none.

src/main/java/org/ecocean/media/AssetStore.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public MediaAsset findOrCreate(JSONObject params, Shepherd myShepherd) {
215215
3) restricting to store is kinda silly cuz id is primary key so would never have duplicate id across more than one store anyway
216216
*/
217217
public ArrayList<MediaAsset> findAllChildren(MediaAsset parent, Shepherd myShepherd) {
218-
if ((parent == null) || (parent.getId() < 1)) return null;
218+
if ((parent == null) || (parent.getIdInt() < 1)) return null;
219219
ArrayList<MediaAsset> all = new ArrayList<MediaAsset>();
220220
Extent mac = myShepherd.getPM().getExtent(MediaAsset.class, true);
221221
Query matches = myShepherd.getPM().newQuery(mac, "parentId == " + parent.getId());
@@ -294,7 +294,7 @@ public MediaAsset updateChild(MediaAsset parent, String type, HashMap<String, Ob
294294
MediaAsset ma = this.copyIn(targetFile, sp);
295295
if (ma == null) return null; // not sure how this would happen *without* an exception, but meh.
296296
ma.addLabel("_" + type);
297-
ma.setParentId(parent.getId());
297+
ma.setParentId(parent.getIdInt());
298298
if ((opts != null) && (opts.get("feature") != null)) {
299299
Feature ft = (Feature)opts.get("feature");
300300
ma.addDerivationMethod("feature", ft.getId());

src/main/java/org/ecocean/media/MediaAsset.java

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.ecocean.media;
22

3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
35
import java.io.File;
46
import java.io.FileOutputStream;
57
import java.io.IOException;
@@ -21,6 +23,7 @@
2123
import org.apache.commons.lang3.builder.ToStringBuilder;
2224
import org.ecocean.AccessControl;
2325
import org.ecocean.Annotation;
26+
import org.ecocean.Base;
2427
import org.ecocean.CommonConfiguration;
2528
import org.ecocean.Encounter;
2629
import org.ecocean.ia.Task;
@@ -42,8 +45,9 @@
4245
/**
4346
* MediaAsset describes a photo or video that can be displayed or used for processing and analysis.
4447
*/
45-
public class MediaAsset implements java.io.Serializable {
48+
public class MediaAsset extends Base implements java.io.Serializable {
4649
static final long serialVersionUID = 8844223450447974780L;
50+
@Override public String opensearchIndexName() { return "media_asset"; }
4751
protected int id = MediaAssetFactory.NOT_SAVED;
4852

4953
protected String uuid = null;
@@ -93,6 +97,10 @@ public class MediaAsset implements java.io.Serializable {
9397
* To be called by AssetStore factory method.
9498
*/
9599

100+
public MediaAsset() {
101+
this(MediaAssetFactory.NOT_SAVED, null, null);
102+
}
103+
96104
public MediaAsset(final AssetStore store, final JSONObject params) {
97105
// this(store, params, null);
98106
this(MediaAssetFactory.NOT_SAVED, store, params);
@@ -146,10 +154,18 @@ private String getUrlString(final URL url) {
146154
return url.toExternalForm();
147155
}
148156

149-
public int getId() {
157+
public int getIdInt() {
150158
return id;
151159
}
152160

161+
public String getId() {
162+
return String.valueOf(id);
163+
}
164+
165+
public void setId(String s) {
166+
id = Integer.parseInt(s);
167+
}
168+
153169
public void setId(int i) {
154170
id = i;
155171
}
@@ -346,6 +362,10 @@ public void setDerivationMethodAsString(String d) {
346362
}
347363
}
348364

365+
public long getVersion() {
366+
return this.revision;
367+
}
368+
349369
public long setRevision() {
350370
this.revision = System.currentTimeMillis();
351371
return this.revision;
@@ -1143,7 +1163,7 @@ public static void updateStandardChildrenBackground(final String context, int id
11431163
}
11441164

11451165
public void updateStandardChildrenBackground(String context) { // convenience
1146-
updateStandardChildrenBackground(context, this.getId());
1166+
updateStandardChildrenBackground(context, this.getIdInt());
11471167
}
11481168

11491169
public void setKeywords(ArrayList<Keyword> kws) {
@@ -1363,7 +1383,7 @@ public MediaAssetMetadata setMinimalMetadata(int width, int height, String conte
13631383
}
13641384

13651385
public void refreshIAStatus(Shepherd myShepherd) {
1366-
String s = IBEISIA.parseDetectionStatus(Integer.toString(this.getId()), myShepherd);
1386+
String s = IBEISIA.parseDetectionStatus(Integer.toString(this.getIdInt()), myShepherd);
13671387

13681388
if (s != null) this.setDetectionStatus(s);
13691389
String cumulative = null;
@@ -1614,4 +1634,69 @@ public int hashCode() {
16141634
public void setIsValidImageForIA(Boolean value) {
16151635
if (value == null) { validImageForIA = null; } else { validImageForIA = value; }
16161636
}
1637+
1638+
public JSONObject opensearchMapping() {
1639+
JSONObject map = super.opensearchMapping();
1640+
JSONObject keywordType = new JSONObject("{\"type\": \"keyword\"}");
1641+
1642+
// "id" is done in Base
1643+
map.put("acmId", keywordType);
1644+
map.put("uuid", keywordType);
1645+
map.put("detectionStatus", keywordType);
1646+
1647+
map.put("encounters", new org.json.JSONObject("{\"type\": \"nested\"}"));
1648+
map.put("annotations", new org.json.JSONObject("{\"type\": \"nested\"}"));
1649+
1650+
return map;
1651+
}
1652+
1653+
public void opensearchDocumentSerializer(JsonGenerator jgen, Shepherd myShepherd)
1654+
throws IOException, JsonProcessingException {
1655+
super.opensearchDocumentSerializer(jgen, myShepherd);
1656+
1657+
jgen.writeStringField("acmId", this.getAcmId());
1658+
jgen.writeStringField("uuid", this.getUUID());
1659+
jgen.writeStringField("filename", this.getFilename());
1660+
jgen.writeStringField("userFilename", this.getUserFilename());
1661+
jgen.writeStringField("detectionStatus", this.getDetectionStatus());
1662+
URL url = this.safeURL();
1663+
jgen.writeStringField("url", (url == null) ? null : url.toString());
1664+
jgen.writeArrayFieldStart("encounters");
1665+
for (Encounter enc : Encounter.findAllByMediaAsset(this, myShepherd)) {
1666+
jgen.writeStartObject();
1667+
jgen.writeStringField("id", enc.getId());
1668+
jgen.writeStringField("taxonomy", enc.getTaxonomyString());
1669+
jgen.writeEndObject();
1670+
}
1671+
jgen.writeEndArray();
1672+
jgen.writeArrayFieldStart("annotations");
1673+
for (Annotation ann : this.getAnnotations()) {
1674+
jgen.writeStartObject();
1675+
jgen.writeStringField("id", ann.getId());
1676+
jgen.writeStringField("acmId", ann.getAcmId());
1677+
jgen.writeStringField("iaClass", ann.getIAClass());
1678+
jgen.writeStringField("viewpoint", ann.getViewpoint());
1679+
jgen.writeEndObject();
1680+
}
1681+
jgen.writeEndArray();
1682+
}
1683+
1684+
@Override public String getAllVersionsSql() {
1685+
return "SELECT CAST(\"ID\" AS text), \"REVISION\" AS version FROM \"MEDIAASSET\" WHERE \"PARENTID\" IS NULL ORDER BY version";
1686+
}
1687+
1688+
@Override public Base getById(Shepherd myShepherd, String id) {
1689+
return myShepherd.getMediaAsset(id);
1690+
}
1691+
1692+
// comment cruft only needed for Base class
1693+
@Override public String getComments() {
1694+
return null;
1695+
}
1696+
1697+
@Override public void setComments(final String comments) {
1698+
}
1699+
1700+
@Override public void addComments(final String newComments) {
1701+
}
16171702
}

src/main/java/org/ecocean/media/TwitterAssetStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public static List<MediaAsset> entitiesAsMediaAssets(MediaAsset ma) {
161161
kid.addLabel("_entity");
162162
setEntityMetadata(kid);
163163
kid.getMetadata().getDataAsString();
164-
kid.setParentId(ma.getId());
164+
kid.setParentId(ma.getIdInt());
165165
// derivationMethods? metadata? (of image) etc.... ??
166166
mas.add(kid);
167167
}

0 commit comments

Comments
 (0)