/*******************************************************************************
* Copyright 2014 Virginia Polytechnic Institute and State University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package edu.vt.vbi.patric.common;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@SuppressWarnings("unchecked")
/**
*
*/
public class Workspace {
public final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
public JSONArray tracks;
public JSONArray tags;
public JSONArray mapping;
public long timestamp;
/**
* Construct Workspace Object
*/
public Workspace() {
tracks = new JSONArray();
tags = new JSONArray();
mapping = new JSONArray();
setTimestamp();
}
/**
* Construct Workspace with parameters
*
* @param tracks
* @param tags
* @param mapping
*/
public Workspace(JSONArray tracks, JSONArray tags, JSONArray mapping) {
this.tracks = tracks;
this.tags = tags;
this.mapping = mapping;
setTimestamp();
}
/**
* Construct Workspace with given Workspace Object
*
* @param ws JSONObject
*/
public Workspace(JSONObject ws) {
this.tracks = (JSONArray) ws.get("tracks");
this.tags = (JSONArray) ws.get("tags");
this.mapping = (JSONArray) ws.get("mapping");
if (ws.get("timestamp") != null) {
this.timestamp = Long.parseLong(ws.get("timestamp").toString());
}
else {
setTimestamp();
}
}
/**
* Generate JSON object to feed Library (StationsList) View
*
* @return JSONArray
*/
public JSONArray getLibraryByDataType() {
int cntFeature = 0, cntGenome = 0, cntExpression = 0;
if (tracks != null && tracks.size() > 0) {
for (Object track : tracks) {
JSONObject jsonTrack = (JSONObject) track;
if (jsonTrack.get("trackType").toString().equals("Feature")) {
cntFeature++;
}
else if (jsonTrack.get("trackType").toString().equals("Genome")) {
cntGenome++;
}
else if (jsonTrack.get("trackType").toString().equals("ExpressionExperiment")) {
cntExpression++;
}
}
}
JSONArray rtn = new JSONArray();
JSONObject rtnGenome = new JSONObject();
JSONObject rtnFeature = new JSONObject();
JSONObject rtnExperiment = new JSONObject();
rtnFeature.put("name", "Features (" + cntFeature + ")");
rtnFeature.put("type", "Feature");
rtnFeature.put("leaf", true);
rtnFeature.put("id", 2);
rtnGenome.put("name", "Genomes (" + cntGenome + ")");
rtnGenome.put("type", "Genome");
rtnGenome.put("leaf", true);
rtnGenome.put("id", 3);
rtnExperiment.put("name", "Experiments (" + cntExpression + ")");
rtnExperiment.put("type", "ExpressionExperiment");
rtnExperiment.put("leaf", true);
rtnExperiment.put("id", 4);
rtn.add(rtnGenome);
rtn.add(rtnFeature);
rtn.add(rtnExperiment);
return rtn;
}
/**
* Get maximum Track ID
*
* @return int Track ID
*/
public int getMaxTrackId() {
int id = 0;
int tmp = 0;
for (Object track : tracks) {
JSONObject jTrack = (JSONObject) track;
tmp = Integer.parseInt(jTrack.get("trackId").toString());
if (tmp > id) {
id = tmp;
}
}
return id;
}
/**
* Get maximum Tag ID
*
* @return int Tag ID
*/
public int getMaxTagId() {
int id = 0;
int tmp = 0;
for (Object tag : tags) {
JSONObject jTrack = (JSONObject) tag;
tmp = Integer.parseInt(jTrack.get("tagId").toString());
if (tmp > id) {
id = tmp;
}
}
return id;
}
/**
* Create a Track
*
* @param trackId
* @param type
* @param internalId
* @return JSONObject track
*/
public JSONObject createTrack(int trackId, String trackType, Object internalId) {
JSONObject track = new JSONObject();
track.put("trackId", trackId);
track.put("trackType", trackType);
track.put("internalId", internalId);
return track;
}
/**
* Create a Tag. Group type.
* @param tagId
* @param name
* @param type
* @param desc
* @param count
* @param cdate
* @return
*/
public JSONObject createGroupTag(int tagId, String name, String type, String desc, int count, String cdate) {
JSONObject tag = new JSONObject();
String timestamp = sdf.format(Calendar.getInstance().getTime());
tag.put("tagId", tagId);
tag.put("tagType", "Group");
tag.put("name", name);
tag.put("type", type);
tag.put("desc", desc);
tag.put("members", count);
if (cdate == null) {
tag.put("cdate", timestamp);
tag.put("mdate", timestamp);
}
else {
tag.put("cdate", cdate);
tag.put("mdate", cdate);
}
return tag;
}
/**
* Create a Tag. String type.
* @param tagId
* @param name
* @return
*/
public JSONObject createStringTag(int tagId, String name) {
JSONObject tag = new JSONObject();
tag.put("tagId", tagId);
tag.put("tagType", "String");
tag.put("name", name);
return tag;
}
/**
* Create a Map.
* @param tagId
* @param trackId
* @return
*/
public JSONObject createMapping(int tagId, int trackId) {
JSONObject m = new JSONObject();
m.put("tagId", tagId);
m.put("trackId", trackId);
return m;
}
/**
* Add a Track
* @param type
* @param internalId
* @return
*/
public int addTrack(String type, Object internalId) {
int trackId = findTrack(type, internalId);
if (trackId > 0) {
return trackId;
}
else {
trackId = getMaxTrackId() + 1;
JSONObject track = createTrack(trackId, type, internalId);
this.tracks.add(track);
return trackId;
}
}
public HashSet<Integer> addTracks(String type, HashSet<?> internalIds) {
HashSet<Integer> trackIds = new HashSet<Integer>();
int maxId = getMaxTrackId();
int trackId = -1;
for (Object internalId : internalIds) {
trackId = findTrack(type, internalId);
if (trackId > 0) {
trackIds.add(trackId);
}
else {
trackId = maxId + 1;
maxId++;
JSONObject track = createTrack(trackId, type, internalId);
this.tracks.add(track);
trackIds.add(trackId);
}
}
return trackIds;
}
public HashSet<Integer> addTracks(String type, String internalIds) {
HashSet<Object> hsInternalIds = new HashSet<Object>();
for (String internalId : internalIds.split(",")) {
try {
hsInternalIds.add(Long.parseLong(internalId));
}
catch (NumberFormatException nfe) {
hsInternalIds.add(internalId);
}
}
return addTracks(type, hsInternalIds);
}
/**
* Find a Track matches a given type and internal ID. Return -1 if no track matches.
* @param type
* @param internalId
* @return
*/
public int findTrack(String type, Object internalId) {
for (Iterator<JSONObject> iter = tracks.iterator(); iter.hasNext();) {
JSONObject track = iter.next();
// System.out.println("tracking type of internalID::"+track.get("internalId").getClass().getName());
if (track.get("trackType").equals(type) && track.get("internalId").equals(internalId)) {
return Integer.parseInt(track.get("trackId").toString());
}
}
return -1;
}
/**
* Find Tracks matches a given type and a set of internal ID.
* @param type group
* @param internalIds either String or Long
* @return
*/
public HashSet<Integer> findTracks(String type, HashSet<?> internalIds) {
HashSet<Integer> trackIds = new HashSet<Integer>();
for (Object track : tracks) {
JSONObject tr = (JSONObject) track;
if (tr.get("trackType").equals(type) && internalIds.contains(tr.get("internalId"))) {
trackIds.add(Integer.parseInt(tr.get("trackId").toString()));
}
}
return trackIds;
}
public int findTag(String type, String name) {
for (Iterator<JSONObject> iter = tags.iterator(); iter.hasNext();) {
JSONObject tag = iter.next();
if (tag.get("tagType").toString().equals(type) && tag.get("name").toString().equals(name)) {
return Integer.parseInt(tag.get("tagId").toString());
}
}
return -1;
}
public int findTag(String type, String name, String contentType) {
for (Iterator<JSONObject> iter = tags.iterator(); iter.hasNext();) {
JSONObject tag = iter.next();
if (tag.get("tagType").toString().equals(type) && tag.get("name").toString().equals(name)
&& tag.get("type").toString().equals(contentType)) {
return Integer.parseInt(tag.get("tagId").toString());
}
}
return -1;
}
public JSONObject findTagByTagId(int tagId) {
for (Iterator<JSONObject> iter = tags.iterator(); iter.hasNext();) {
JSONObject tag = iter.next();
if (Integer.parseInt(tag.get("tagId").toString()) == tagId) {
return tag;
}
}
return null;
}
public int findIndexByTagId(int tagId) {
for (int i = 0; i < tags.size(); i++) {
JSONObject tag = (JSONObject) tags.get(i);
if (Integer.parseInt(tag.get("tagId").toString()) == tagId) {
return i;
}
}
return -1;
}
public ArrayList<JSONObject> findMappingByTrackId(int trackId) {
ArrayList<JSONObject> result = new ArrayList<JSONObject>();
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject m = iter.next();
if (Integer.parseInt(m.get("trackId").toString()) == trackId) {
result.add(m);
}
}
return result;
}
public ArrayList<JSONObject> findMappingByTagId(int tagId) {
ArrayList<JSONObject> result = new ArrayList<JSONObject>();
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject m = iter.next();
if (Integer.parseInt(m.get("tagId").toString()) == tagId) {
result.add(m);
}
}
return result;
}
public boolean isMappingExist(int tagId, int trackId) {
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject m = iter.next();
if (Integer.parseInt(m.get("tagId").toString()) == tagId && Integer.parseInt(m.get("trackId").toString()) == trackId) {
return true;
}
}
return false;
}
public int addGroup(String name, String type, String desc, int count, String date) {
int tagId = getMaxTagId() + 1;
JSONObject tag = createGroupTag(tagId, name, type, desc, count, date);
this.tags.add(tag);
return tagId;
}
public void addTagging(String tags, HashSet<Integer> trackId) {
int tagId = -1;
if (tags.contains(",")) {
for (String tag : tags.split(",")) {
tag = tag.trim();
tagId = findTag("String", tag);
if (tagId > 0) {
for (int tId : trackId) {
if (isMappingExist(tagId, tId) == false) {
addMapping(tagId, tId);
}
}
}
else {
// create
tagId = getMaxTagId() + 1;
JSONObject t = createStringTag(tagId, tag);
this.tags.add(t);
addMapping(tagId, trackId);
}
}
}
else if (!tags.equals("")) {
tags = tags.trim();
tagId = findTag("String", tags);
if (tagId > 0) {
for (int tId : trackId) {
if (isMappingExist(tagId, tId) == false) {
addMapping(tagId, tId);
}
}
}
else {
// create
tagId = getMaxTagId() + 1;
JSONObject t = createStringTag(tagId, tags);
this.tags.add(t);
addMapping(tagId, trackId);
}
}
}
public void addMapping(int tagId, int trackId) {
JSONObject m = createMapping(tagId, trackId);
this.mapping.add(m);
}
public void addMapping(int tagId, HashSet<Integer> trackIds) {
ArrayList<JSONObject> list = new ArrayList<JSONObject>();
for (Integer trackId : trackIds) {
JSONObject m = createMapping(tagId, trackId);
list.add(m);
}
this.mapping.addAll(list);
}
public void updateGroupTag(int tagId, String name, String desc) {
int new_count = countAssociation(tagId);
int idx = findIndexByTagId(tagId);
if (idx > -1) {
JSONObject group = (JSONObject) tags.get(idx);
if (name != null) {
group.put("name", name);
}
if (desc != null) {
group.put("desc", desc);
}
group.put("members", new_count);
group.put("mdate", sdf.format(Calendar.getInstance().getTime()));
}
}
public void removeTracks(HashSet<Integer> trackIds) {
for (Iterator<JSONObject> iter = tracks.iterator(); iter.hasNext();) {
JSONObject jsonTrack = iter.next();
if (trackIds.contains(Integer.parseInt(jsonTrack.get("trackId").toString()))) {
iter.remove();
}
}
}
public void removeTags(HashSet<Integer> tagIds) {
for (Iterator<JSONObject> iter = tags.iterator(); iter.hasNext();) {
JSONObject jsonTag = iter.next();
if (tagIds.contains(Integer.parseInt(jsonTag.get("tagId").toString()))) {
iter.remove();
}
}
}
public void removeTag(int tagId) {
for (Iterator<JSONObject> iter = tags.iterator(); iter.hasNext();) {
JSONObject jsonTag = iter.next();
if (Integer.parseInt(jsonTag.get("tagId").toString()) == tagId) {
iter.remove();
}
}
}
public void removeMapping(HashSet<Integer> tagIds, HashSet<Integer> trackIds) {
if (tagIds != null && trackIds != null) {
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject jsonM = iter.next();
if (trackIds.contains(Integer.parseInt(jsonM.get("trackId").toString()))
&& tagIds.contains(Integer.parseInt(jsonM.get("tagId").toString()))) {
iter.remove();
}
}
}
else if (tagIds == null && trackIds != null) {
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject jsonM = iter.next();
if (trackIds.contains(Integer.parseInt(jsonM.get("trackId").toString()))) {
iter.remove();
}
}
}
else if (tagIds != null && trackIds == null) {
for (Iterator<JSONObject> iter = mapping.iterator(); iter.hasNext();) {
JSONObject jsonM = iter.next();
if (tagIds.contains(Integer.parseInt(jsonM.get("tagId").toString()))) {
iter.remove();
}
}
}
}
public JSONArray getTracks(HashSet<Integer> trackIds) {
JSONArray rtn = new JSONArray();
for (Object track : tracks) {
JSONObject jsonTrack = (JSONObject) track;
if (trackIds.contains(Integer.parseInt(jsonTrack.get("trackId").toString()))) {
rtn.add(jsonTrack);
}
}
return rtn;
}
public JSONArray getTracks(JSONObject filters) {
JSONArray rtn = new JSONArray();
String k = "", v = "";
if (tracks != null && tracks.size() > 0) {
if (filters.containsKey("key") && filters.containsKey("value")) {
k = filters.get("key").toString();
v = filters.get("value").toString();
HashSet<String> hash = new HashSet<String>();
hash.addAll(Arrays.asList(v.split(",")));
for (Object track : tracks) {
JSONObject jsonTrack = (JSONObject) track;
if (jsonTrack.containsKey(k) && hash.contains(jsonTrack.get(k).toString())) { // pass
// filters
rtn.add(jsonTrack);
}
}
}
}
return rtn;
}
public JSONArray getGroups(JSONObject filters) {
JSONArray rtn = new JSONArray();
String k = "", v = "";
if (tags != null && tags.size() > 0) {
if (filters.containsKey("key") && filters.containsKey("value")) {
k = filters.get("key").toString();
v = filters.get("value").toString();
HashSet<String> hash = new HashSet<String>();
hash.addAll(Arrays.asList(v.split(",")));
for (Object tag : tags) {
JSONObject jsonTag = (JSONObject) tag;
if (jsonTag.get("tagType").equals("Group") && hash.contains(jsonTag.get(k).toString())) {
rtn.add(jsonTag);
}
}
}
}
return rtn;
}
public JSONArray getTags(JSONObject filters) {
JSONArray rtn = new JSONArray();
String k = "", v = "";
if (tags != null && tags.size() > 0) {
if (filters.containsKey("key") && filters.containsKey("value")) {
k = filters.get("key").toString();
v = filters.get("value").toString();
HashSet<String> hash = new HashSet<String>();
hash.addAll(Arrays.asList(v.split(",")));
for (Object tag : tags) {
JSONObject jsonTag = (JSONObject) tag;
if (jsonTag.containsKey(k) && hash.contains(jsonTag.get(k).toString())) {
rtn.add(jsonTag);
}
}
}
}
return rtn;
}
public int countAssociation(int tagId) {
int count = 0;
if (mapping != null && mapping.size() > 0) {
for (Object map : mapping) {
JSONObject jsonMap = (JSONObject) map;
if (Integer.parseInt(jsonMap.get("tagId").toString()) == tagId) {
count++;
}
}
}
return count;
}
public boolean hasAssociation(String type, int trackId) {
boolean test = false;
ArrayList<JSONObject> associations = this.findMappingByTrackId(trackId);
for (JSONObject m : associations) {
JSONObject tag = findTagByTagId(Integer.parseInt(m.get("tagId").toString()));
if (tag != null && tag.get("tagType").toString().equals(type)) {
test = true;
}
}
return test;
}
public JSONObject getWorkspace() {
JSONObject ws = new JSONObject();
ws.put("tracks", tracks);
ws.put("tags", tags);
ws.put("mapping", mapping);
return ws;
}
public JSONArray getTracks() {
return tracks;
}
public int getTrackCount() {
if (this.tracks != null) {
return tracks.size();
}
return -1;
}
public int getGroupCount() {
if (this.tags != null) {
return getGroups().size();
}
return -1;
}
public void setTracks(JSONArray tracks) {
this.tracks = tracks;
}
public JSONArray getTags() {
return tags;
}
public JSONArray getGroups() {
JSONArray rtn = new JSONArray();
for (Object tag : tags) {
JSONObject jsonTag = (JSONObject) tag;
if (jsonTag.get("tagType").equals("Group")) {
rtn.add(jsonTag);
}
}
return rtn;
}
public void setTags(JSONArray tags) {
this.tags = tags;
}
public JSONArray getMapping() {
return mapping;
}
public void setMapping(JSONArray mapping) {
this.mapping = mapping;
}
public void setTimestamp() {
this.timestamp = Calendar.getInstance().getTimeInMillis();
}
public long getTimestamp() {
return this.timestamp;
}
}