/** * Add a type to the slice at a given position, possibly changing the endpoints of some descendant * intervals. * * @param type the type to add to the slice * @param position a type already in the slice before which the new type will be placed, <code> * null</code> if the type should be placed at the end of the slice * @param ancestors the new type's ancestors * @return the event for the endpoint changes, though there might be none */ protected EndpointsChangedEvent add(Constant type, Constant position, Set<Constant> ancestors) { EndpointsChangedEvent event = new EndpointsChangedEvent(this, type); order.add(type, position); int typeLambda = lambdas.get(position), positionLambda = typeLambda; Set<Constant> reducedAncestors = new HashSet<Constant>(ancestors); for (Map.Entry<Constant, Interval<Constant>> entry : descendentIntervals.entrySet()) { Interval<Constant> value = entry.getValue(); if (reducedAncestors.remove(entry.getKey())) { if (value.getMin() == position) { ++positionLambda; value.setMin(type); event.addMinChange(entry.getKey()); } if (value.getMax() == position) { ++typeLambda; } } else if (value.getMax() == position) { value.setMax(type); event.addMaxChange(entry.getKey()); } } descendentIntervals.put(type, new Interval<Constant>(order, type, position)); for (Constant ancestor : reducedAncestors) { descendentIntervals.put(ancestor, new Interval<Constant>(order, type, position)); } lambdas.put(type, typeLambda); lambdas.put(position, positionLambda); return event; }
/** * Attempt to add a type to the slice, possibly changing the endpoints of some descendant * intervals. * * @param type the type to add to the slice * @param ancestors the new type's ancestors * @return if the addition was successful, the event for the endpoint changes, though there might * be none; if the addition failed, <code>null</code> */ public EndpointsChangedEvent add(Constant type, Set<Constant> ancestors) { Interval<Constant> common = asInterval(); for (Constant ancestor : ancestors) { Interval<Constant> mask = descendentIntervals.get(ancestor); if (mask != null) { common.intersect(mask); } } // empty is okay, as long as we still have location if (order.compare(common.getMin(), common.getMax()) > 0) { return null; } int surroundMin = 0, surroundMax = 0; for (Constant ancestor : ancestors) { Interval<Constant> range = descendentIntervals.get(ancestor); if (range != null) { if (order.compare(range.getMin(), common.getMin()) < 0 && order.compare(range.getMax(), common.getMin()) > 0) { ++surroundMin; } if (order.compare(range.getMin(), common.getMax()) < 0 && order.compare(range.getMax(), common.getMax()) > 0) { ++surroundMax; } } } if (lambdas.get(common.getMin()) == surroundMin) { return add(type, common.getMin(), ancestors); } if (lambdas.get(common.getMax()) == surroundMax) { return add(type, common.getMax(), ancestors); } //// fast slicing: don't check between min and max return null; }