Null pointer exception with arraylists and hashmaps (processing 1.5, Jer Thorpe based code)

Hi,

I am working on a project that uses different methods of data visualisation as multimodal information design.

I do not know how to use the processing 2.x XML object so my code has been written using the processing 1.5 standard.

Full commentary of how things work has not been written yet, but every thing is really basic.

There are a few files in the project. The dataset and images used in the sketch can be found at http://fts.rca.ac.uk/?k=X6UnrEPinSbe1409098476. The zip file also contains the processing code posted below.

The null pointer exception error points to two lines of code in the file "RecordObject.pde". The lines are currently commented out but can be found at the bottom of the file.

The problem I am facing occurs while trying to create an arc diagram of the dataset.

/BPMA_v_.09.pde/

import processing.opengl.*;

ArrayList<RecordObject> recordObjectList = new ArrayList();
HashMap<String, RecordYear> recordYearHash = new HashMap();
HashMap<String, RecordFindNo> recordFindNoHash = new HashMap();
HashMap<String, RecordArtist> recordArtistHash = new HashMap();
ArrayList<RecordYear> uniqueRecordYears = new ArrayList();
ArrayList<RecordFindNo> uniqueRecordFindNumbs = new ArrayList();
ArrayList<RecordArtist> uniqueRecordArtists = new ArrayList();

String file = "rm_arch.xml"; //XML File with poster record information
String mode = new String();
PImage logo = new PImage();
int wiOffset;  //content horizontal margin
int hiOffset;  //content vertical margin

void setup()
{
  size(screen.width, (screen.height-77), OPENGL);  //sets the sketches width and height to the width and height of the monitor and renders using the openGL renderer
  smooth();  //edge smoothing
  frameRate(120);  //sets the sketch's frame rate to 120 fps

  logo = loadImage("logo_inv.png");  //lood the BPMA logo
  wiOffset = logo.width + 50;  //sets the the horizontal margin to the width of the logo + 50 pixels
  hiOffset = logo.height+50;  //sets the vertical margin to the height of the logo + 50 pixels

  //Open the record file stream
  getRecords(file);  //call the method to open the records with 

  //Check for records and display message if file is missing or inaccessible or there are no records in the file
  if (recordObjectList.size() == 0 || recordObjectList == null || recordObjectList.size() <= 1)
  {
    println("0 Records found. Can't open archive file or archive is empty.");
  }

  //Display the number of records found
  else
  {
    println(recordObjectList.size() + " records found.");
  }
}//end setup

void draw()
{
  background(0);  //sets the sketch background to black

  //draw the BPMA Logo
  image(logo, 20, 20);  //draws the BPMA logo with a 20 pixel top and left margin

  //display the trigger legend
  text("A - Display 'Artist' view mode", 20, hiOffset);
  float leading = 1.75*textAscent();
  text("G - Display 'Grid' view mode", 20, leading+hiOffset);
  text("T - Display 'Timeline' view", 20, (2*leading)+hiOffset);
  text("R - Reset view", 20, (3*leading)+hiOffset);

  for (RecordObject ro:recordObjectList)
  {
    ro.update();
    ro.render();

    //trigger actions
    if (mode == "tl")
    {
      fill(255);
      text(ro.yr, ro.tpos.x, height-30);
    }

    //not working yet
    if(mode == "artist")
    {
      ro.mode = "artist";
    }
  }
}//end draw method

void getRecords(String fileName)
{
  //get XML data
  XMLElement xml = new XMLElement(this, fileName);

  //get the total naumber of records in the data set
  int tot = xml.getChildCount();  //record count

  for (int i = 0; i < tot; ++i)
  {
    XMLElement progeny = xml.getChild(i);

    //For each record on the list, create a record object
    RecordObject ro = new RecordObject();

    //store the record data
    ro.title = progeny.getStringAttribute("title");

    if (progeny.getStringAttribute("findNo").length() < 1)
    {
      ro.findNo = "0000";
    }

    else
    {
      ro.findNo = progeny.getStringAttribute("findNo");
    }

    ro.findNo = progeny.getStringAttribute("findNo");
    ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
    ro.desc = progeny.getStringAttribute("desc");
    ro.yr = progeny.getStringAttribute("year");
    ro.girth = progeny.getIntAttribute("w");
    ro.tallness = progeny.getIntAttribute("h");
    ro.artist = progeny.getStringAttribute("artist");

    //set the initial position of the objects
    ro.pos.x = width/2;
    ro.pos.y = height/2;

    //set the target position
    ro.tpos.x = random(width/2)+wiOffset;
    ro.tpos.y = (random((height-100)-random(ro.recImage.height)))+20;

    //Are there already records of items from this year?
    if (ro.yr != null)
    {
      recordObjectList.add(ro);

      //does the year already exist in the list?
      if (recordYearHash.containsKey(ro.yr))
      {
        /** IT DOES EXIST
         * Get the year from the hash and find number from the record and add it to the hash
         */
        RecordYear ry = recordYearHash.get(ro.yr);
        ++ry.count;
        ry.recImg = ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
        ry.yrs.add(ro);
      }

      else
      {
        /** NEITHER THE YEAR OR FIND NUMBER EXIST
         * Happy New Year! It's a Jpeg!
         */
        RecordYear ry = new RecordYear(); //Create a year object for the record
        ry.theYear = ro.yr;
        ry.count = 1;
        ry.recImg = ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
        ry.yrs.add(ro);

        //Add the new year to the hash
        recordYearHash.put(ro.yr, ry);
        uniqueRecordYears.add(ry);

        //Add the new Find Number to the hash
        RecordFindNo rfn = new RecordFindNo();
        rfn.theFindNo = ro.findNo;
        rfn.count = 1;
        rfn.findNumbs.add(ro);
        recordFindNoHash.put(ro.findNo, rfn);
        uniqueRecordFindNumbs.add(rfn);

        //Add the new Artist to the hash
        RecordArtist ra = new RecordArtist();
        ra.theArtist = ro.artist;
        ra.count = 1;
        ra.recArts.add(ro);
        recordArtistHash.put(ro.artist, ra);
        uniqueRecordArtists.add(ra);
      }
    }
  }

  println(tot + " records processed.");
  println("There should be " + recordObjectList.size()/5 + " rows.");
}

/** Pre-Condition:
 */
void artistView()
{
  int cols = recordObjectList.size();

  for (int i=0; i < recordObjectList.size(); ++i)
  {
    RecordObject rO = recordObjectList.get(i);
    rO.scaleFact = .25;
    rO.tpos.y = height/2;

    int x = i%cols;
    rO.tpos.x = (.75*(x*rO.scaleFact*rO.recImage.width)+wiOffset);
  }
  /** Arcs for posters with like artists needed*/
}//end artistView
/** Post-Condition:
 */

/** Pre-Condition:
 */
void gridView()
{
  text("Yes", 50, 50);
  int numCol = 10;

  for (int i = 0; i < recordObjectList.size(); ++i)
  {
    int x = i%numCol;
    int y = i/numCol;

    RecordObject rec = recordObjectList.get(i);
    rec.scaleFact = .375;
    rec.tpos.x = (.75*(x*rec.scaleFact*rec.recImage.width)+wiOffset);
    rec.tpos.y = (1.2*(y*rec.scaleFact*rec.tallness)+20);
  }
}//end gridView
/** Post-Condition:
 */

/** Pre-Condition:
 */
void resetView()
{
  for (int i = 0; i < recordObjectList.size(); ++i)
  {
    RecordObject ro = recordObjectList.get(i);
    ro.scaleFact = .20;

    //burst on the scene
    ro.tpos.x = random(width/2)+wiOffset;
    ro.tpos.y = (random((height-100)-random(ro.recImage.height)))+20;
  }
}//end resetView
/** Post-Condition:
 */

/** Pre-Condition:
 */
void timeLine()
{
  for (int i = 0; i < uniqueRecordYears.size(); ++i)
  {
    RecordYear ry = uniqueRecordYears.get(i);

    for (int j = 0; j < ry.yrs.size(); ++j)
    {
      RecordObject record = ry.yrs.get(j);
      record.scaleFact = .125;
      record.tpos.x = ((i*record.scaleFact*record.recImage.width) + (record.scaleFact * (record.recImage.width)*(1+record.scaleFact)))+wiOffset;
      record.tpos.y = (height - 150)-(record.scaleFact*(20 - record.tallness)) + (record.stackPosition*j*50);
    }
  }
}//end timeLine
/** Post-Condition:
 */

void keyPressed()
{
  if (key == 'a')
  {
    mode = "artist";
    artistView();
  }

  if (key == 'g')
  {
    mode = "grid";
    gridView();
  }

  if (key == 'r')
  {
    mode = null;
    resetView();
  }

  if (key == 't')
  {
    mode = "tl";
    timeLine();
  }
}

/RecordArtist.pde/

class RecordArtist
{
  String theArtist;
  int count = 0;

  ArrayList<RecordObject> recArts = new ArrayList();

  RecordArtist()
  {
  }
}

/RecordFindNo.pde/

class RecordFindNo
{
  String theFindNo;
  int count = 0;

  PImage recImg = new PImage();

  ArrayList<RecordObject> findNumbs = new ArrayList();

  RecordFindNo()
  {
  }
}

/RecordObject.pde/<---Exception error points to this file

class RecordObject
{
  //
  PVector pos = new PVector(); //current position
  PVector tpos = new PVector(); //target position
  int dir = 1; //Direction, not used yet
  double xSpeed = .04; //Horizontal speed
  double ySpeed = .04; //Vertical speed

  float alph = 0;  //start opacity
  float interalph;
  float talph = 255;  //target opacity

  PImage recImage = new PImage(); //Item image
  String title; //Item name
  String desc; //Item description
  String yr; //Item creation year
  String findNo; //Item find number (used for images)
  String artist; //Item designer
  String mode;  //trigger mode
  int girth; //Item image width
  int tallness; //Item image height 

  float scaleFact = .20;

  int stackPosition = -1;  //for stacking images vertically in 'timeline' mode

  RecordObject()
  {
  }

  //Update the position of the record's image

  /** PREcondition:
   */
  void update()
  {
    //easeing
    pos.x+=(tpos.x - pos.x)*xSpeed;
    pos.y+=(tpos.y - pos.y)*ySpeed;
  }
  /** POSTcondition:
   */

  void render()
  {
    pushMatrix();
    translate(pos.x, pos.y);

    noStroke();
    fill(255);
    rect(-(scaleFact*6), -(scaleFact*6), scaleFact*(girth+12), scaleFact*(tallness+12));
    image(recImage, 0, 0, (scaleFact*girth), (scaleFact*tallness));

    if (mouseX > pos.x-(scaleFact*6) && mouseX < pos.x + (scaleFact*girth)+(scaleFact*6) && mouseY > pos.y-(scaleFact*6) && mouseY < pos.y + (scaleFact*tallness)+(scaleFact*6))
    {
      fill(200, 200, 60);
      rect(-(scaleFact*6), -(scaleFact*6), scaleFact*(girth+12), scaleFact*(tallness+12));
      image(recImage, 0, 0, (scaleFact*girth), (scaleFact*tallness));
    }

    popMatrix();

    if (mouseX > pos.x-(scaleFact*6) && mouseX < pos.x + (scaleFact*girth)+(scaleFact*6) && mouseY > pos.y-(scaleFact*6) && mouseY < pos.y + (scaleFact*tallness)+(scaleFact*6))
    {
      image(recImage, width-(girth+20), 20, girth, tallness);
      fill(255);
      text(title, width-(girth+20), tallness+(5*textAscent()));

      if (this.artist.length() < 1)
      {
        text("Artist: Unknown", width-(girth+20), tallness+(7*textAscent()));
      }

      if (this.artist != null)
      {
        text("Artist: " + artist + '\n', width-(girth+20), tallness+(7*textAscent()));
      }

      text("Year: " + yr + '\n', width-(girth+20), tallness+(9*textAscent()));
      text("Find Number: " + findNo +'\n', width-(girth+20), tallness+(11*textAscent()));
    }

    if (this.mode == "artist")
    {
      //debug attempt
      //RecordArtist Artist = recordArtistHash.get(artist);
      //println(Artist.recArts);

      //This does not work
      /**
      RecordArtist Artist = recordArtistHash.get(artist);
       ArrayList<RecordObject> relatedObjects = Artist.recArts;
       //Draw an arc from this record to all other records with the same artist
       for(RecordObject rOb:relatedObjects)
       {
       text(rOb.artist,rOb.tpos.x,rOb.tpos.y+50);
       //DRAW ARCS HERE
       }
      */

      //Neither does this
      /**
      ArrayList relatedObjects = recordArtistHash.get(artist).recArts;

       for(int i = 0; i < relatedObjects.size(); ++i)
       {
       text(this.artist,this.tpos.x,this.tpos.y+50);
       //DRAW ARCS HERE
       }
       */
    }
  }
}

/RecordYear.pde/

class RecordYear
{
  String theYear;
  int count = 0;

  PImage recImg = new PImage();

  ArrayList<RecordObject> yrs = new ArrayList();

  RecordYear()
  {
  }
}

Answers

  • in your debug

    RecordArtist Artist = recordArtistHash.get(artist);
    

    print out artist and Artist (on separate lines)

    i think the problem is that artist is not in the hash so Artist is null. which is fine until you try and dereference it by, say, printing Artist.recArts.

    (terrible naming btw, don't have variables that only differ by capitalisation)

Sign In or Register to comment.