Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

NPE in JsonDiff #12

Closed
DrLansing opened this Issue · 19 comments

4 participants

@DrLansing

Under certain conditions findCorrespondingNode(toArrs, fromNode) returns null, which causes NPE in fixHalfDeletedArrs().
I suspect that the correct behavior might be to return fromNode instead of null, but I don't know enough to be sure.

Test data (sorry so ugly) follows.

#### from:
{
  "name" : "Daily Ops Update",
  "dateTime" : {
    "path" : "/p:Plan/p:timeFrame"
  },
  "subplanList" : [ {
    "name" : "Ships Schedules",
    "dateTime" : {
      "path" : "/p:Plan/p:timeFrame"
    },
    "subplanList" : [ {
      "name" : "SAPPHIRE PRINCESS",
      "dateTime" : {
        "path" : "/p:Plan/p:timeFrame"
      },
      "actionList" : [ {
        "name" : "stockdale task 3d",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2011-08-02T00:00:00.000Z",
            "finish" : "2011-09-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "stockdale task 2d",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2011-08-01T20:00:00.000Z",
            "finish" : "2011-09-11T08:00:00.000Z"
          }
        }
      }, {
        "name" : "stockdale task 2d",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2011-08-01T20:00:00.000Z",
            "finish" : "2011-09-11T08:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-06T00:00:00.000Z",
            "finish" : "2010-07-06T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-07T00:00:00.000Z",
            "finish" : "2010-07-09T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-10T00:00:00.000Z",
            "finish" : "2010-07-10T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-11T00:00:00.000Z",
            "finish" : "2010-07-11T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-12T00:00:00.000Z",
            "finish" : "2010-07-12T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-13T00:00:00.000Z",
            "finish" : "2010-07-13T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-14T00:00:00.000Z",
            "finish" : "2010-07-14T00:00:00.000Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-15T00:00:00.000Z",
            "finish" : "2010-07-15T00:00:00.000Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2010-07-16T00:00:00.000Z",
            "finish" : "2010-07-16T00:00:00.000Z"
          }
        }
      } ]
    } ]
  } ]
}
##### to:
{
  "name" : "Daily Ops Update",
  "type" : "Undefined",
  "subplanList" : [ {
    "name" : "Ships Schedules",
    "type" : "LineOfOperation",
    "subplanList" : [ {
      "name" : "SAPPHIRE PRINCESS",
      "type" : "Undefined",
      "actionList" : [ {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-16T00:00:00.000Z",
            "finish" : "2012-08-16T23:59:59.999Z"
          }
        }
      }, {
        "name" : "U/W Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-17T00:00:00.000Z",
            "finish" : "2012-08-19T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Acapulco, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-20T00:00:00.000Z",
            "finish" : "2012-08-20T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Ixtapa, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-21T00:00:00.000Z",
            "finish" : "2012-08-21T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Puerto Vallarta, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-22T00:00:00.000Z",
            "finish" : "2012-08-22T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Mazatlan, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-23T00:00:00.000Z",
            "finish" : "2012-08-23T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Cabo San Lucas, Mexico",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-24T00:00:00.000Z",
            "finish" : "2012-08-24T23:59:59.999Z"
          }
        }
      }, {
        "name" : "U/W Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-25T00:00:00.000Z",
            "finish" : "2012-08-25T23:59:59.999Z"
          }
        }
      }, {
        "name" : "IPT Los Angeles, California",
        "dateTime" : {
          "path" : "/p:Action/p:plannedTime",
          "timePeriod" : {
            "start" : "2012-08-26T00:00:00.000Z",
            "finish" : "2012-09-02T23:59:59.999Z"
          }
        }
      } ],
      "dateTime" : {
        "path" : "/p:Plan/p:timeFrame"
      }
    } ],
    "dateTime" : {
      "path" : "/p:Plan/p:timeFrame"
    }
  } ],
  "dateTime" : {
    "path" : "/p:Plan/p:timeFrame"
  }
}
@algesten
Owner

Exciting! I'll have a look.

@DrLansing

Looking back at issue #7, there is a chance that this issue is related.

For my current testing (recall that I use Eclipse on Windows 7) I repeat the following test by running a new JVM each time:

@Test
public void test() {
    try {
        Class jd = foodev.jsondiff.JsonDiff.class;
        Class[] clss = jd.getDeclaredClasses();
        for(Class cls : clss) {
            String name = cls.getSimpleName();
            if(name.length() == 7)
                System.out.println(name + " " + cls.hashCode());
        }
        String diff = foodev.jsondiff.JsonDiff.diff(from,  to);
        System.out.println(String.format("%d %d %d", from.length(),to.length(),diff.length()));
    } catch(NullPointerException e) {
        System.err.println("NPE at " + e.getStackTrace()[0]);
    } catch(Exception e) {
        System.err.println(e);
    }
}

For the input (from and to) submitted above, this test always gives:
NPE at foodev.jsondiff.JsonDiff.fixHalfDeletedArrs(JsonDiff.java:468)

For some more complicated input, the behavior becomes non-deterministic, and on repeating the test with that same input I get things like:
ArrNode 631912203
ObjNode 1241761406
50567 27316 16902

ArrNode 956291993
ObjNode 631912203
NPE at foodev.jsondiff.JsonDiff.findCorrespondingNode(JsonDiff.java:677)

ArrNode 1241761406
ObjNode 1037869096
50567 27316 16882

My current theory is that the hashing that you are using is based on 2 problematic assumptions:
1) the algorithm does not create collisions
2) the values of ArrNode.class.hashCode() and ObjNode.class.hashCode() are constant.

What do you think?

@DrLansing

Using https://raw.github.com/yonik/java_util/master/src/util/hash/MurmurHash3.java as hasher

with these methods:

    public int hash(int i, String s) {
        byte[] b = s.getBytes(charset);
        byte[] c = ByteBuffer.allocate(4 + b.length).putInt(i).array();
        System.arraycopy(b, 0, c, 4, b.length);
        return hasher.hash(c, c.length, 0);
    }

    public int hash(int i, int j) {
        byte[] b = ByteBuffer.allocate(8).putInt(i).array();
        byte[] c = ByteBuffer.allocate(4).putInt(j).array();
        System.arraycopy(c, 0, b, 4, 4);
        return hasher.hash(b, b.length, 0);
    }

and making changes like this:

    @Override
    public int hashCode() {
        int i = parent.hashCode();
        if (val.isJsonArray()) {
            // for arr and obj we must hash in a type qualifier
            // since otherwise changes between these kinds of
            // nodes will be considered equal 
            i = hash(i, "ARRAY");//i * 31 + ArrNode.class.hashCode();
        } else if (val.isJsonObject()) {
            i = hash(i, "OBJECT");//i * 31 + ObjNode.class.hashCode();
        } else {

// i = i * 31 + (val.isJsonPrimitive() || val.isJsonNull() ? val.hashCode() : 0);
i = hash(i, (val.isJsonPrimitive() || val.isJsonNull() ? val.hashCode() : 0));
}
return i;
}

I obtain:
1) a result that is deterministic and that makes sense
2) no NPEs
3) performance about double on large input (goes from ~200 msec to ~400 msec.)

@DrLansing

I should say "performance cost about double"

@DrLansing

Still seeing findCorrespondingNode(toArrs, fromNode) returning null sometimes.

@nvrs

I second that, i am getting NPE on findCorrespondingNode as well on rare occasions, ND as well which makes it hard to debug.

@algesten
Owner

So the different hasher, does that solve the problem or not?

@nvrs

Hmm sorry, didnt read through the whole tread properly, going to test with new hasher now.

@nvrs

I am still getting the NPE with the different hasher, a lot less however (1/10th i d say of the top of my head). When i have some spare time i ll try to prepare a test to demonstrate it.

@nachogmd
Collaborator

This issue seems to happen when an existing array "dissapears". It is not possible to findCorrespondingNode when this is missing... So the fix is pretty simple:

 // investigation of half deleted nodes that must be converted to full SET operations.
private static void fixHalfDeletedArrs(HashMap<Integer, ArrNode> fromArrs, HashMap<Integer, ArrNode> toArrs,
        LinkedHashMap<Integer, Leaf> mutations, LinkedList<ArrNode> lastDeletedArrNode) {

    ArrNode makeSet = null;

    for (int i = 0; i < lastDeletedArrNode.size(); i++) {

        ArrNode test = lastDeletedArrNode.get(i);

        // if we have arrays in arrays that are half deleted, the first
        // could be the parent of the following
        if (makeSet != null && test.hasParent(makeSet)) {
            continue;
        }

        // make synthetic node to use for getting real value from fromArrs.
        makeSet = test.cloneToNewIndex(test.index - 1);
        makeSet = fromArrs.get(makeSet.doHash(true));

        ArrNode fromNode = makeSet;

        if (fromNode != null) {
              // find corresponding node in fromNode. 
            ArrNode toNode = findCorrespondingNode(toArrs, fromNode);

            // remove any mutation that has this node as parent.
            Iterator<Leaf> iter = mutations.values().iterator();
            while (iter.hasNext()) {
                Leaf l = iter.next();
                if (l.parent == toNode || l.parent.hasParent(toNode) ||
                        l.parent == fromNode || l.parent.hasParent(fromNode)) {
                    iter.remove();
                }
            }

            // create new SET mutation for entire value.
            toNode.leaf.oper = Oper.SET;
            mutations.put(toNode.doHash(true), toNode.leaf);
        }

    }
}
@algesten
Owner

I lifted in your code, and no tests were tripped, so I'll commit it, but do we have a test case that can provoke this NPE?

@nachogmd
Collaborator

This is a possible test:

public void testArrayChangeToNull() {
    String from = "{a:[{b:1}],b:1}";
    String to = "{\"b\":1}";
    String diff = "{\"-a\":0}";

    String d = JsonDiff.diff(from, to);
    Assert.assertEquals(diff, d);

    String p = JsonPatch.apply(from, diff);
    Assert.assertEquals(to, p);
}
@algesten algesten referenced this issue from a commit
@algesten possible test for #12 306c7df
@algesten
Owner

Not quite feeling this. I checked in this test and tried to revert the previous checked in fix. I expected this to result in a test error – but it doesn't. Ideas?

@nachogmd
Collaborator

Its quite strange actually... It does seem to have somehow an indeterministic behaviour... Investigating!

I can't even reproduce any longer the original issue that brought me here...

@nachogmd
Collaborator

Ok, it took some time but I found a test case.... The thing is that this error depends on the entry names. The second diff produces a NPE. My guess for this indetermination is the compareTo method. What do you think?

@Test
public void testArrayChangeToNull() {
    String from,to;
    from = "{\"externalIds\":[{\"id\":\"4066-b329\"}],\"relation\":[{\"rules\":{\"keys\":[{\"shareHolders\":[{\"percentage\":0.0}]}]}}]}";
    to =   "{\"externalIds\":[{\"id\":\"4066-b329\"}]}";

    JsonDiff.diff(from, to);
    from = "{\"externalIds\":[{\"id\":\"4066-b329\"}],\"catalogueRelationList\":[{\"rules\":{\"keys\":[{\"shareHolders\":[{\"percentage\":0.0}]}]}}]}";
    to =   "{\"externalIds\":[{\"id\":\"4066-b329\"}]}";
    JsonDiff.diff(from, to);

    String diff = "{\"-catalogueRelationList\":0}";

    String d = JsonDiff.diff(from, to);
    Assert.assertEquals(diff, d);

    String p = JsonPatch.apply(from, diff);
    Assert.assertEquals(to, p);
}
@nachogmd
Collaborator

If you try the preceding test with the current code base - reverted code - you get a NPE on the second diff... Please try it yourself. No more indetermination in this case :)

@nachogmd
Collaborator

Hi again, after struggling for a bit with the reasons behind this NPE I started to see some light ;)

The second case, when we order the field list we start with catalogueRelationList and in a second inspection when trying to fixHalfDeletedArrs we are testing against a negative index and thus the NPE. So,

 makeSet = test.cloneToNewIndex(test.index - 1);

but test.index == 0 and test is cloned against a negative index

If before that we check that test.index > 0 it goes fine because it should not try fixing negative indexes. The resulting patch would be:

diff --git a/src/main/java/foodev/jsondiff/JsonDiff.java b/src/main/java/foodev/jsondiff/JsonDiff.java
index 1dfef71..c0ab96e 100644
--- a/src/main/java/foodev/jsondiff/JsonDiff.java
+++ b/src/main/java/foodev/jsondiff/JsonDiff.java
@@ -440,8 +440,8 @@
             ArrNode test = lastDeletedArrNode.get(i);

             // if we have arrays in arrays that are half deleted, the first
-            // could be the parent of the following
-            if (makeSet != null && test.hasParent(makeSet)) {
+            // could be the parent of the following or we could be at the beginning of the array
+            if (makeSet != null && test.hasParent(makeSet) || test.index == 0) {
                 continue;
             }


@algesten
Owner

Hey! Sorry for not being in contact. Just got a bit snowed under with work. Will check your stuff tonight. Thanks!

@algesten algesten closed this in e0d5452
@algesten
Owner

Thanks a ton @nachogmd for your help! Super bug fixing! And @DrLansing if you're still here, would be very interesting to hear whether this fixes your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.