public ArrayList<Change> collectChanges(CourseModel courseModel,
			int tooOldInDays) {
		// Build a date before which we do not remove offerings
		Date tooOld = new Date(new Date().getTime() - 24 * 3600000l
				* tooOldInDays);
		System.out.println("Will keep all offerings older than " + tooOldInDays
				+ " days: " + tooOld);

		ArrayList<Change> changes = new ArrayList<Change>();
		collectUniversityChanges(courseModel, changes);
		collectCategoryChanges(courseModel, changes);

		// Short codes are used as keys. We hope they don't collide across
		// universities, but who knows what EdX uses inside.
		for (String code : courses.keySet()) {
			CourseRec oldRec = courseModel.getClassById(code, Source.EDX);
			if (oldRec == null)
				oldRec = courseModel.getClassByShortName(code, Source.EDX);
			ArrayList<HashMap<String, Object>> course = courses.get(code);
			if (oldRec != null) {
				diffCourse(course, oldRec, changes, courseModel, tooOld);
			} else {
				HashMap<String, Object> map = course.get(0);
				// Id and short name are both code.
				String name = getLongName(map);
				String dsc = null; // Comes from a separate file. Not using for
									// now.
				String instructor = null; // TODO
				String language = "en"; // TODO in a separate file.
				String link = null; // Will use per offering urls.
				CourseRec record = new CourseRec(Source.EDX, code, code, name,
						dsc, instructor, link, language, getSelfStudy(map));
				for (HashMap<String, Object> m : course) {
					record.addOffering(makeOffering(
							courseModel.makeNewOfferingId(Source.EDX), m));
				}
				ArrayList<String> categories = getCategoryCodes(map);
				ArrayList<String> universities = getUniversityCodes(map);
				changes.add(CourseChange.add(record, categories, universities));
			}
		}

		// TODO deleted courses.
		return changes;
	}