public void add(Bitemporal newValue) {
		sanityCheck();
		
		Collection<Bitemporal> toEnd = new HashSet<Bitemporal>();
		Collection<Bitemporal> toAdd = new LinkedList<Bitemporal>();

		for (Bitemporal possibleOverlap : getHistory(TimeUtils.now())) {
			if (newValue.getValidityInterval().overlaps(possibleOverlap.getValidityInterval())) {
				toEnd.add(possibleOverlap);
			}
		}

		DateTime validityStartOfNewValue = newValue.getValidityInterval().getStart();
		for (Bitemporal validOnStartOfNewValue : get(validityStartOfNewValue, TimeUtils.now())) {
			if (validityStartOfNewValue.compareTo(validOnStartOfNewValue.getValidityInterval().getStart()) > 0) {
				Interval validityInterval = TimeUtils.interval(validOnStartOfNewValue.getValidityInterval().getStart(),
						validityStartOfNewValue);
				toAdd.add(validOnStartOfNewValue.copyWith(validityInterval));
			}
		}

		if (!(newValue.getValidityInterval().getEnd().getMillis() == Long.MAX_VALUE)) {
			DateTime validityEndOfNewValue = newValue.getValidityInterval().getEnd();
			for (Bitemporal validOnEndOfNewValue : get(validityEndOfNewValue, TimeUtils.now())) {
				if (validityEndOfNewValue.compareTo(validOnEndOfNewValue.getValidityInterval().getStart()) > 0) {
					Interval validityInterval = TimeUtils.interval(validityEndOfNewValue, validOnEndOfNewValue
							.getValidityInterval().getEnd());
					toAdd.add(validOnEndOfNewValue.copyWith(validityInterval));
				}
			}
		}

		for (Bitemporal needsToEnd : toEnd) {
			needsToEnd.end();
		}
		for (Bitemporal toBeAdded : toAdd) {
			data.add(toBeAdded);
		}
		data.add(newValue.copyWith(newValue.getValidityInterval()));
	}