JSON parse for TFL Open Data - java

Hello everyone I'm trying to parse a JSON file from this LINK.
The returned JSON is as follows-
I need to loop through all the instances of journeys first, then I have to loop through legs for each journeys to get the detailed instruction. As you can see each legs consists of instruction in parts which returns a string, my ultimate goal is to combine these string for each journeys and display them as a TextView. So for the above JSON the end goal is to display -
Jubilee line towards Stratford, or North Greenwich
Northern line towards Edgware, or High Barnet
Till now I've been trying to navigate through this JSON without any luck.
Here is the code I've been working on-
try {
//object is the JSON file.
JSONArray Journey = object.getJSONArray("journeys");
if (Journey != null) {
//Retrieving number of possible routes.
for (int i=0;i<Journey.length();i++){
Routes.add(Journey.getJSONObject(i));
}
//Retrieving number of possible legs for each route.
if (!Routes.isEmpty()){
for (int j = 0; j< Routes.size(); j++){
Legs.add(j, Routes.get(j).getJSONArray("legs"));
}
//Trying to retrieve the detailed instruction here and failing.
for(int k=0;k<Routes.get(k).getJSONArray("legs").length();k++){
instructionDetail.add(k,Legs.get(k).getJSONObject(k).getJSONObject("instruction"));
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
I believe my approach is wrong and I didn't get the loop right.. Suggestions to parse and navigate and any other approach will be highly appreciated!
Thanks!
UPDATE:

JSONArray journeys = new JSONObject("");
for(int i = 0 ; i < journeys.length() ; i++) { // Traverse journeys
JSONObject journey = journeys.getJSONObject(i); // get journeys(i) -> journey
if(journey.has("legs")) { // if journey has "legs" key
JSONArray legs = journey.getJSONArray("legs"); // get the legs array from journey object
for(int j = 0 ; j < legs.length() ; j++) { // Traverse legs
JSONObject leg = legs.getJSONObject(j); // get legs(j) -> leg
if(leg.has("instruction")) { // if leg has "instruction" key in it
JSONObject instruction = leg.getJSONObject("instruction"); // get instruction jsonObject
String detailed = instruction.optString("detailed", "Fallback detailed"); // get detailed string in instruction object
}
}
}
}
Update:
private static class Detail {
String journeyType;
String legType;
String instructionType;
String detail;
public Detail(String journeyType, String legType, String instructionType, String detail) {
this.journeyType = journeyType;
this.legType = legType;
this.instructionType = instructionType;
this.detail = detail;
}
}
...
...
List<Detail> detailList = new ArrayList<>();
JSONArray journeys = new JSONObject("");
for(int i = 0 ; i < journeys.length() ; i++) { // Traverse journeys
JSONObject journey = journeys.getJSONObject(i); // get journeys(i) -> journey
if(journey.has("legs")) { // if journey has "legs" key
JSONArray legs = journey.getJSONArray("legs"); // get the legs array from journey object
for(int j = 0 ; j < legs.length() ; j++) { // Traverse legs
JSONObject leg = legs.getJSONObject(j); // get legs(j) -> leg
if(leg.has("instruction")) { // if leg has "instruction" key in it
JSONObject instruction = leg.getJSONObject("instruction"); // get instruction jsonObject
String journeyType = journey.getString("$type");
String legType = leg.getString("$type");
String instructionType = instruction.getString("$type");
String detailed = instruction.getString("detailed"); // get detailed string in instruction object
detailList.add(new Detail(journeyType, legType, instructionType, detailed));
}
}
}
}
for(Detail detail : detailList) {
TextView textView = new TextView([yourContext]);
textView.setText(detail.detail);
yourContentViewGroup.addView(textView);
// or you can use View.inflate(context, layoutRes, yourContentViewGroup) and design a layout to show other detail instance values
}

Related

Is it possible to get distinct values from JSONObject in java

I have a json file that contains 500k Objects and this is its format:
"WORKORDER": [
{
"Attributes": {
"SITEID": {
"content": "BEDFORD"
},
"WONUM": {
"content": "1000"
},
"WOPRIORITY": {
"content": 2
},
"WORKTYPE": {
"content": "CM"
}
}
},
{
"Attributes": {
"SITEID": {
"content": "BEDFORD"
},
"WONUM": {
"content": "1000-10"
},
"WORKTYPE": {
"content": "CM"
}
}
}
Im geting the distinct values like this :
for (int i = 0; i < WORKORDER.length(); i++) {
JSONObject obj = WORKORDER.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if( att.has(col)){ // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if(!(list.contains(colval))) {
out.println( colval);
list.add(colval);
}
But it takes long time for only 5000 objects !
Is there any way to get the distinct values of any column without parsing the whole Json file, otherwise parsing only the column needed.
You are iterating on a JSON with 500k elements. For each element you check if it was previously added in a List. That means your logic will iterate the list 500k times.
Instead, you should use a HashSet, first, the Set prevent duplicated value. So you just need to set.add(value) but the most interesting is the fact that the instance have a constant complexity value. Since it used buckets to organize the value, it doesn't have to iterate the Set fully.
You can read more about that in amit answer's about How can a HashSet offer constant time add operation?
Note that HashSet gives amortized and average time performance of O(1), not worst case. This means, we can suffer an O(n) operation from time to time.
So, when the bins are too packed up, we just create a new, bigger array, and copy the elements to it.
Note that to use any Hash#### implementation, you need to make sure the instance you store implements hashCode and equals correctly. You can find out more about this in the community post about What issues should be considered when overriding equals and hashCode in Java?.
Now for the solution :
Set<Object> sets = new HashSet<>();
for (int i = 0; i < WORKORDER.length(); i++) {
// ...
Object colval = column.get("content");
if(sets.add(colval)){ //`add` return true if it wasn't present already.
out.println( colval);
}
}
I kept the Object type but this should be correctly typed, at least to be sure that those instance are implementing those methods as needed.
colval being an Object, it is possible it doesn't implements correctly the methods needed so I suggest you parse it correctly. You should use column.getString("content) instead or check the instance type.
To validate this, I have used a method to create a fake JSON:
public static JSONObject createDummyJson(int items) {
JSONObject json = new JSONObject();
JSONArray orders = new JSONArray();
json.put("order", orders);
JSONObject attributes;
JSONObject item;
JSONObject order;
Random rand = new Random();
String[] columns = {"columnA", "columnB", "columnC", "columnD"};
for(int i = 0; i < items; ++i) {
order = new JSONObject();
attributes = new JSONObject();
order.put("Attributes", attributes);
orders.put(order);
for(int j = 0; j < rand.nextInt(1000) % columns.length; ++j) {
item= new JSONObject();
long rValue = rand.nextLong();
item.put("content", j%3 == 0 ? ("" + rValue ) : rValue );
attributes.put(columns[j], item);
}
}
return json;
}
Then ran a basic benchmark for both method and had the following results :
public static void main(String[] args) throws Exception {
final int jsonLength = 500_000;
JSONObject json = createDummyJson(jsonLength);
long start = System.currentTimeMillis();
List<Object> list = parseJson(json);
long end = System.currentTimeMillis();
System.out.format("List - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, list.size());
start = System.currentTimeMillis();
Set<Object> set = parseJsonSet(json);
end = System.currentTimeMillis();
System.out.format("Set - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, set.size());
}
public static List<Object> parseJson(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
List<Object> list = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (!(list.contains(colval))) {
//System.out.println(colval);
list.add(colval);
}
}
}
return list;
}
public static Set<Object> parseJsonSet(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
Set<Object> set = new HashSet<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (set.add(colval)) {
//System.out.println(colval);
}
}
}
return set;
}
List - Run in 5993 ms for 500000 items and output 46971 lines
Set - Run in 62 ms for 500000 items and output 46971 lines
I even went to a JSON with 5M row (removed the List that would never end)
Set - Run in 6436 ms for 5000000 items and output 468895 lines
Important, remove the line that print in console every new insertion, it will reduce the execution time a bit.

Java: How to dynamically reload data parser class and bot for companion robot?

I’m developing a companion bot for dementia suffers able to record, store and integrate memories into conversation. The bot calls an xml. file for conversations which can detect contexts passing an argument via baseContext.xml to call a topic.class and dynamically reload new xml data parser and bot while Main.class continues other tasks.
However, I can’t decide if trying to reload the parser/bot into JVM is feasible or whether pausing the class threads and calling a new class/es would be the best solution, or another solution is available. Ideally I’d like to pass the new xml data into the JVM while the other classes persist.
Any help much appreciated.
Main Class (calls the bot, camera, scheduler, text history etc)
public class Main extends javax.swing.JFrame {
private static Bot bot;
public BlockingQueue<String> queue;
public Main() {
initComponents();
//get the parser going
DataParser dp = new DataParser();
//make new bot with level 0 as default and given data parser
bot = new Bot("0", dp);
//dispaly the default message
txtHistory.setText("Bot: " + bot.getMessage());
}
public Main(BlockingQueue<String>queue) {
this.queue = queue;
}
// display bot response in the text area
private static final String VOICENAME="kevin16";
private static void addBotText(String message) {
txtHistory.setText(txtHistory.getText() + "\nBot: " + message);
//turn the bot response to sound
Voice voice;
VoiceManager vm= VoiceManager.getInstance();
voice=vm.getVoice(VOICENAME);
voice.allocate();
try{
voice.speak(bot.getMessage());
}catch(Exception e){
}
voice.deallocate();
}
public static void listen (String speech) {
txtHistory.setText(txtHistory.getText() + "\nYou: " + speech + "\n");
//send the input to the bot and get bot response
The Data parser class deals with the xml loading into DOM
package bot;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class DataParser {
private Document dom;
private HashMap<String, State> states = new HashMap<String, State>();
private ArrayList<String> invalidMessages = new ArrayList();
private int invalidMessageIndex = 0;
public int stateCounter = 1000;
public String fileSource;
// default constructor
public DataParser() {
// Load the XML file and parse it
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//get the filepath of source
String fileSource = Context.getSource();
DocumentBuilder db = dbf.newDocumentBuilder();
//parse using builder to get DOM representation of the XML file
dom = db.parse(fileSource);
// Load configuration and states from the XML file
loadConfiguration();
loadStates();
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (SAXException se) {
se.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
// Load states from XML file
private void loadStates() {
// get document element object
Element docEle = dom.getDocumentElement();
// get all State node names
NodeList nl = docEle.getElementsByTagName("State");
// if node is not null and has children
if (nl != null && nl.getLength() > 0) {
// loop through all children
for (int i = 0; i < nl.getLength(); i++) {
// get state element
Element el = (Element) nl.item(i);
// get state id
String id = el.getAttribute("id");
// get all state messages
ArrayList messages = new ArrayList();
NodeList messagesNodeList = el.getElementsByTagName("message");
// if messages node is not null and has children
if (messagesNodeList != null && messagesNodeList.getLength() > 0) {
// loop through all children
for (int j = 0; j < messagesNodeList.getLength(); j++) {
// get current message element
Element elmsg = (Element) messagesNodeList.item(j);
// append message node value to the messages list
messages.add(elmsg.getFirstChild().getNodeValue());
}
}
// get keywords in the current state
ArrayList keywords = getKeywords(el);
// construct a new State object
State state = new State(id, messages, keywords);
stateCounter ++;
// add the state to the states hashmap
states.put(id, state);
}
}
}
// get state object by id
public State getState(String id) {
return states.get(id);
}
// create a new state
public void addState(State state){
states.put(state.getId(), state);
stateCounter++;
}
// get all keywords in an State tag
public ArrayList getKeywords(Element ele) {
// construct keywords arraylist
ArrayList keywords = new ArrayList();
// get all nodes by keyword tag name
NodeList nl = ele.getElementsByTagName("keyword");
// if the tag is not null and has children
if (nl != null && nl.getLength() > 0) {
// loop through all the children
for (int i = 0; i < nl.getLength(); i++) {
//get the keyword element
Element el = (Element) nl.item(i);
// find the keyword target, classname and argument attributes
String wordTag = el.getFirstChild().getNodeValue();
String target = el.getAttribute("target");
String className = el.getAttribute("className");
String arg = el.getAttribute("arg");
String variable = el.getAttribute("variable");
int points = 0;
try{
points = Integer.valueOf(el.getAttribute("points"));
}catch (Exception e){
}
String learn = el.getAttribute("learn");
// split keyword by comma
String[] words = wordTag.split(",");
// loop through all words
for (String word : words) {
// trim the word to remove spaces
word = word.trim();
// construct a new keyword
Keyword keyword = new Keyword(word, target, className, arg, variable, points, learn );
// add the keyword to keywords array list
keywords.add(keyword);
}
}
}
// return all the keywords in the given node
return keywords;
}
// returns one of the invalid messages and move the index to the next message
public String getInvalidAnswer() {
// get current answer
String answer = invalidMessages.get(invalidMessageIndex);
// increase the index, if it is end of messages, reset the index to 0
invalidMessageIndex++;
if (invalidMessageIndex >= invalidMessages.size()) {
invalidMessageIndex = 0;
}
return answer;
}
// load cofig tags from data xml file
private void loadConfiguration() {
// get document element
Element docEle = dom.getDocumentElement();
// get all node names for invalid messages
NodeList node = docEle.getElementsByTagName("InvalidMessages");
// get all message nodes inside invalid messages node
NodeList nl = ((Element) node.item(0)).getElementsByTagName("message");
// if node is not null and has children
if (nl != null && nl.getLength() > 0) {
// loop through all children
for (int i = 0; i < nl.getLength(); i++) {
// get message node
Element el = (Element) nl.item(i);
// get message and add it to invalid messages array
String message = el.getFirstChild().getNodeValue();
invalidMessages.add(message);
}
}
}
}
The bot class manages conversation and calls specialised classes.
package bot;
import smallTalk.Morning;
import smallTalk.Afternoon;
import smallTalk.Evening;
import smallTalk.Night;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Bot {
// Store all regular expression matches
private HashMap<String,String> dictionary;
// Default state to start the bot
String level = "0";
DataParser parser;
// default constructor
public Bot(String level, DataParser parser) {
dictionary = new HashMap<String,String>();
this.level = level;
this.parser = parser;
}
// get current state message
public String getMessage() {
State state = parser.getState(level);
return replaceMatches(state.getMessage()).trim();
}
// send user message to the bot and get the response
public String send(String message) {
String response = "";
State state = parser.getState(level);
// end of the tree
if (state.getKeywords().isEmpty()) {
this.level = "0";
}
// match the keyword with given message
Keyword match = parse(message, state.getKeywords());
// if no keyword is matched, display one of the invalid answers
if (match == null) {
response = parser.getInvalidAnswer();
} else {
// if match classname is provided, check to get the dynamic response
if (match.className.length() > 0) {
// check for Weather dynamic response
if (match.className.equals("Weather")) {
Weather weather = new Weather();
response = weather.getResponse(match.arg);
this.level = "0";
}
// check for News dynamic response
else if (match.className.equals("News")) {
News news = new News();
response = news.getResponse(match.arg);
this.level = "0";
}
else if (match.className.equals("Morning")) {
Morning morning = new Morning();
morning.wakeup();
}
else if (match.className.equals("Afternoon")) {
Afternoon afternoon = new Afternoon();
afternoon.midday();
}
else if (match.className.equals("Evening")) {
Evening evening = new Evening();
evening.dinner();
}
else if (match.className.equals("Night")) {
Night night = new Night();
night.late();
}
// check for Topic dynamic response
else if (match.className.equals("Topic")) {
Topic topic = new Topic();
topic.getTopic(match.arg);
}
} else {
// get the new state and return the new message
if (response.length() == 0) {
this.level = match.target;
state = parser.getState(level);
// if it is end of the tree
if (state.getKeywords().isEmpty()) {
response = this.getMessage();
this.level = "0";
}
}
}
}
return response;
}
// parse the given text to find best match in the keywords
private Keyword parse(String text, ArrayList<Keyword> keylist) {
// set the default match to none
int bestMatch = -1;
Keyword match = null;
// loop through keywords
for (int i = 0; i < keylist.size(); i++) {
// get number of matches of the keyword with given text
int matches = getMatches(text, keylist.get(i));
// if match is better than best match, replace it
if (matches > -1 && matches > bestMatch) {
match = keylist.get(i);
bestMatch = matches;
}
}
// add best answers regex variable value into the dictionary for future reference
if (match != null){
if(match.learn.length() > 0 ){
// get training data keyword and description
String subject = dictionary.get(match.learn);
String result = match.variableValue;
// create a new state for new trained data
ArrayList<String> messages = new ArrayList<String>();
messages.add(result);
State myState = new State(String.valueOf(parser.stateCounter),messages,new ArrayList());
parser.addState(myState);
// add the new trained keyword
Keyword keyword = new Keyword(subject, myState.getId(), "", "", "", 1, "" );
State state = parser.getState("1");
ArrayList<Keyword> keywords = state.getKeywords();
keywords.add(keyword);
}else{
if (match.variableValue.length() > 0){
dictionary.put(match.variable, match.variableValue);
}
}
}
return match;
}
// get number of matches of the given keywords in the given list
private int getMatches(String text, Keyword keyword) {
// no match by default
int result = -1;
// return 0 match when keyword is *
if(keyword.keyword.equals("*")){
return keyword.points;
}
// if regex is expected
if(keyword.variable.length() > 0){
String match = Regex.match(keyword.keyword, text);
if(match.length() > 0){
keyword.variableValue = match;
return keyword.points;
}
}
String[] words = keyword.keyword.split(" ");
// loop through list of the keywords
for (String word : words) {
// if current keyword is in the text, add points
if (text.toLowerCase().indexOf(word.toLowerCase()) >= 0) {
result = result + keyword.points + 1;
} else {
// return null if one of the keywords does not exists
return -1;
}
}
return result;
}
// replace given text with variables in the dictionary
public String replaceMatches(String text){
// replace variables within dictionary in the text
for (Map.Entry<String, String> entry : dictionary.entrySet()) {
text = text.replaceAll("\\["+entry.getKey() + "\\]", entry.getValue());
}
// remove empty variables tags
return Regex.clear(text);
}
}
The Context class passes the xml file source to data parser.
package bot;
public class Context {
public static String source = "newcontext.xml";
//method to get value of source called in dataParser
public static String getSource(){
return source;
}
//get the new topic from Topic Class and prepare to reload DataParser/Bot
public static void newSource(String currentTopic){
source = currentTopic;
}
}

How to get random objects from a JSON array

This JSONAray:
"cows": [
{
"age": 972,
"name": "Betty"
"status": "publish",
"sticky": "pregnant"
},
{
"age": 977,
"name"; "Kate"
"status": "publish",
"sticky": "heat"
},
{
"age": 959,
"name": "Julie"
"site_age": 63178480,
"sticky": "Nursing"
},
...
}
that contains 20 objects. What I wanted is this: get 3 random objects out of the 20. And the ages of any of the three won't be a certain number say 961.
Currently this what I am doing:
private void parseCowsReq(JSONObject array) {
try {
for (int i = 0; i < 3; i++) {
int randumNum = getRandomCow(array);
JSONObject jsonObject = array.getJSONObject(randumNum);
String cowName = jsonObject.getString("name");
String cowStatus = jsonObject.getString("status");
Log.d(TAG, "Cow name is " + cowName + "cow Status is " + cowStatus);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private int getRandomCow(JSONArray jsonArray) {
int length = jsonArray.length();
int[] array;
array = new int[length-1];
int rnd = new Random().nextInt(array.length);
return array[rnd];
}
There are of issues with this code.
I don't know how to ensure that the object gotten in line
JSONObject jsonObject = array.getJSONObject(randumNum); won't have an
age of 961
The random number gotten is always 0
Please do you have any idea how this can be done?
you can do it with this:
public ArrayList<Integer> getRandomObject(JSONArray jsonArray, int indexesWeeNeed){
Random rn = new Random();
Set<Integer> generated = new LinkedHashSet<>();
while(generated.size() < indexesWeeNeed){
int index = rn.nextInt(10);
JSONObject jsonObject = (JSONObject) jsonArray.get(index);
int age = jsonObject.getInt("age");
if(age<961) {
generated.add(index);
}
}
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.addAll(generated);
return arrayList;
}
One part that's messed up is when you call
Random().nextInt(array.length);
array.length is the new array you just created. You need to perform the function on the existing array:
Random().nextInt(jsonArray)
to get a random number other than zero.
As for ensuring you don't get a certain age, I'd suggest breaking up the code to not call the getRandomCow(array) function inside of the for loop. When you retrieve a cow, check the name doesn't match, check the age, and if it works, keep it. If not get another cow.
Well firstly, load the objects:
JSONArray array = /* your array */;
Next, we need a method to retrieve 3 unique objects from the JSONArray (which is actually a List). Let's shuffle the indexes of the json array, so that we don't end up having to repeatedly generate duplicates:
public Stream<JSONObject> randomObjects(JSONArray array, int amount) {
if (amount > array.size()) {
//error out, null, return array, whatever you desire
return array;
}
List<Integer> indexes = IntStream.range(0, array.size()).collect(Collectors.toList());
//random, but less time generating them and keeping track of duplicates
Collections.shuffle(indexes);
Set<Integer> back = new HashSet<>();
Iterator<Integer> itr = indexes.iterator();
while (back.size() < amount && itr.hasNext()) {
int val = itr.next();
if (array.get(val).getInt("age") != 961) { //or any other predicates
back.add(val);
}
}
return back.stream().map(array::get);
}
Using this, we can select the three objects from the list and utilize them how we wish:
randomObjects(array, 3).map(o -> o.getInt("age")).forEach(System.out::println);
//972
//977
//952
When I said "or any other predicates, you can pass those as well via the method:
public Stream<JSONObject> randomObjects(..., Predicate<Integer> validObject) {
//...
int val = itr.next();
if (validObject.test(val)) {
back.add(val);
}
//...
}
Which would mean you could change the blacklisting per method call:
Stream<JSONObject> random = randomObjects(array, 3, val -> array.get(val).getInt("age") != 961);

Simple weighted Graph: Loops not allowed exception

I'm attempting to create a programme which tracks the emails of people. I am using a string for the vertex in my graph (The string is their email) and a DefaultWeightedEdge from Jgrapht. If these people send one email between each other then the weight of the edge connecting that node is set to 1. If they send another email after already having sent one I increment the edge weight by 1.
I think I have the main bulk of the code correct, however I am getting this exception.
Exception in thread "main" java.lang.IllegalArgumentException: loops
not allowed at
org.jgrapht.graph.AbstractBaseGraph.addEdge(AbstractBaseGraph.java:203)
at groupProject.Analysis.StoreEmails(Analysis.java:58) at
groupProject.AnalyserRun.main(AnalyserRun.java:7)
Here is my code:
public class Analysis {
SimpleWeightedGraph<String, DefaultWeightedEdge> graph = new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
jsonParser jP = new jsonParser("/Users/Kieran/test/test2.json");
int numEmails = jP.getNumEmails();
ArrayList<String> senders = new ArrayList<String>();
ArrayList<String> recipients = new ArrayList<String>();
ArrayList<String> all = senders;
ArrayList<DefaultWeightedEdge> edges = new ArrayList<DefaultWeightedEdge>();
public void StoreEmails(){
//Creates vertex's for every sender
for(int i = 0; i < numEmails; i++){
Email email = jP.parseJSON(i);
if(!senders.contains(email.getSender())){
graph.addVertex(email.getSender());
senders.add(email.getSender());
}
}
//creates vertex's for every recipient
for(int i = 0; i < numEmails; i++){
Email email = jP.parseJSON(i);
if(email.getRecipients().length != 0){
for(int j = 0; j < email.getRecipients().length; j++){
if(!recipients.contains(email.getRecipients()[j])){
graph.addVertex(email.getRecipients()[j]);
recipients.add(email.getRecipients()[j]);
}
}
}
}
all.removeAll(recipients);
all.addAll(recipients);
/*
* Adds all of the edges from senders to recipients and if the edge already exists then it will increase the weight by one
* however is is a directed graph so you need to check both pairs.
*/
for(int j = 0; j < numEmails; j++){
Email email = jP.parseJSON(j);
for(int k = 0; k < email.getRecipients().length; k++){
if(graph.containsEdge(email.getSender(), email.getRecipients()[k])){
int current_weight = (int) graph.getEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]));
graph.setEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]), current_weight+1);
}else{
DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
graph.setEdgeWeight(e, 1);
}
}
}
builder();
}
public int calcConnectedness(String s1,String s2){
int connectedness = 0;
int weightS1S2 = 0;
int weightS2S1 = 0;
if(graph.containsEdge(s1, s2)){
weightS1S2 = (int) graph.getEdgeWeight(graph.getEdge(s1, s2));
connectedness += weightS1S2;
}
/*if(graph.containsEdge(s2, s1)){
weightS2S1 = (int) graph.getEdgeWeight(graph.getEdge(s2, s1));
connectedness += weightS2S1;
}*/
return connectedness;
}
public void builder(){
for(int i = 0; i < all.size(); i++){
for(int j = i+1; j < all.size(); j++){
if(graph.containsEdge(all.get(i), all.get(j)))
make(all.get(i), all.get(j), calcConnectedness(all.get(i), all.get(j)));
}
}
}
public void make(String user1, String user2, int connectedness){
System.out.println(user1 + " " + user2 + " Are connected by a factor of: "+connectedness);
}
}
After some research the only information I was able to find which may be causing the problem is the fact that in Java, strings are immutable. However, I was still not able to resolve my issues.
The answer was in this section of code:
}else{
DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
graph.setEdgeWeight(e, 1);
}
It turns out that email.getSender() was in email.getRecipients() so the source and destination of the edge was the same i.e a loop. I solved the issue by doing a simple check beforehand with an if statement to only add an edge if it was not the same as the source.

Jfreechart: how to get the individual items in a BoxAndWhiskerChart

I am generating a box and whisker chart with one item per category.I also want to generate a report with the mean, median and all the values per item in the BoxPlot. So, after i create the dataset, defaultboxandwhiskercategorydataset based on the categoryType, I call the method convertReportData to fetch each item in the defaultboxandwhiskercategorydataset and save the mean, median etc into another data object later for report generation. But it just prints only one category. Could anyone please help me to figure out what is wrong?
My boxplot
Code:
public static BoxAndWhiskerCategoryDataset createDataset() {
startTime = inputData.getItimeFrom();
endTime = inputData.getItimeTo();
List<String> categorylist = new ArrayList<>();
categorylist.add("Distance 0-20");
categorylist.add("Distance 20-40");
categorylist.add("Distance 40-60");
categorylist.add("Distance 60-80");
categorylist.add("Distance 80-100");
categorylist.add("Distance >100");
Map<String, List<Double>> map = new HashMap<String, List<Double>>();
map = addDistance(values_list);
DefaultBoxAndWhiskerCategoryDataset defaultboxandwhiskercategorydataset = new DefaultBoxAndWhiskerCategoryDataset();
for (String categoryType : categorylist) {
map.remove(null);
for (Map.Entry<String, List<Double>> entry : map.entrySet()) {
if (entry.getKey().equalsIgnoreCase(categoryType)) {
defaultboxandwhiskercategorydataset.add(entry.getValue(),
categoryType, " ");
}
}
}
convertReportData(defaultboxandwhiskercategorydataset, categorylist);
return defaultboxandwhiskercategorydataset;
}
private static void convertReportData(DefaultBoxAndWhiskerCategoryDataset boxandwhiskercategorydataset, List<String> latencyTypelist) {
report = new HashMap<>();
for (int i = 0; i < boxandwhiskercategorydataset.getColumnKeys().size(); i++) {
BoxAndWhiskerItem item = boxandwhiskercategorydataset.getItem(i, 0);
ReportData data = new ReportData();
data.setMean(item.getMean());
data.setMedian(item.getMedian());
data.setQ1(item.getQ1());
data.setQ3(item.getQ3());
data.setMaxOutlier(item.getMaxOutlier());
data.setMaxRegularNumber(item.getMaxRegularValue());
data.setMinOutlier(item.getMinOutlier());
data.setMinRegularNumber(item.getMinRegularValue());
data.setOutliers(item.getOutliers());
report.put(boxandwhiskercategorydataset.getRowKey(i).toString(),
data);
}
}
The problem is with
for (int i = 0; i < boxandwhiskercategorydataset.getColumnKeys().size(); i++) {
you are using getColumnKeys whereas you have only one Column. It should have been,
for (int i = 0; i < boxandwhiskercategorydataset.getRowKeys().size(); i++) {

Categories

Resources