private SuggestedStartTime getSimpleBounds(EPlanElement element) {
   Date latestEarliestStart = null;
   Date earliestLatestStart = null;
   Date latestEarliestEnd = null;
   Date earliestLatestEnd = null;
   for (PeriodicTemporalConstraint timepointConstraint :
       ConstraintUtils.getPeriodicConstraints(element, false)) {
     if (timepointConstraint.getWaiverRationale() != null) {
       continue; // skip this one because it is waived
     }
     Date earliest = ConstraintUtils.getPeriodicConstraintEarliestDate(timepointConstraint);
     Date latest = ConstraintUtils.getPeriodicConstraintLatestDate(timepointConstraint);
     switch (timepointConstraint.getPoint().getEndpoint()) {
       case START:
         latestEarliestStart = pickLater(latestEarliestStart, earliest);
         earliestLatestStart = pickEarlier(earliestLatestStart, latest);
         break;
       case END:
         latestEarliestEnd = pickLater(latestEarliestEnd, earliest);
         earliestLatestEnd = pickEarlier(earliestLatestEnd, latest);
         break;
       default:
         Logger.getLogger(SpifePlanConstraintInfo.class)
             .warn("unexpected timepoint: " + timepointConstraint.getPoint().getEndpoint());
     }
   }
   TemporalExtent extent = element.getMember(TemporalMember.class).getExtent();
   if (extent != null) {
     if (latestEarliestEnd != null) {
       Date earliest = DateUtils.subtract(latestEarliestEnd, extent.getDurationMillis());
       latestEarliestStart = pickLater(latestEarliestStart, earliest);
     }
     if (earliestLatestEnd != null) {
       Date latest = DateUtils.subtract(earliestLatestEnd, extent.getDurationMillis());
       earliestLatestStart = pickEarlier(earliestLatestStart, latest);
     }
   }
   if ((latestEarliestStart == null) || (earliestLatestStart == null)) {
     return null;
   }
   return new SuggestedStartTime(
       element, latestEarliestStart, latestEarliestStart, earliestLatestStart);
 }
 private List<Violation> findViolations(Collection<EPlanElement> elements) {
   if (!ConstraintsPreferences.isFindTemporalViolations()) {
     return Collections.emptyList();
   }
   // collect things that could be violated
   Set<BinaryTemporalConstraint> relations = new LinkedHashSet<BinaryTemporalConstraint>();
   List<PeriodicTemporalConstraint> bounds = new ArrayList<PeriodicTemporalConstraint>();
   LinkedHashSet<TemporalChain> chains = TemporalChainUtils.getChains(elements, false);
   for (EPlanElement element : elements) {
     relations.addAll(ConstraintUtils.getBinaryConstraints(element, false));
     bounds.addAll(ConstraintUtils.getPeriodicConstraints(element, false));
   }
   // find the violations
   List<Violation> violations = new ArrayList<Violation>();
   for (BinaryTemporalConstraint relation : relations) {
     if (relation.isViolated()) {
       violations.add(new TemporalDistanceViolation(this, this, relation));
     }
   }
   for (PeriodicTemporalConstraint bound : bounds) {
     if (bound.isViolated()) {
       violations.add(new TemporalEndpointViolation(this, this, bound));
     }
   }
   for (TemporalChain chain : chains) {
     EPlanElement lastPlanElement = null;
     TemporalExtent lastExtent = null;
     for (EPlanElement planElement : chain.getElements()) {
       if (planElement == null) {
         continue;
       }
       if (SpifePlanUtils.getScheduled(planElement) == TriState.FALSE) {
         continue;
       }
       TemporalExtent extent = planElement.getMember(TemporalMember.class).getExtent();
       if (extent == null) {
         continue;
       }
       if (lastExtent != null) {
         if (TemporalChainLinkViolation.isViolated(lastExtent.getEnd(), extent.getStart())) {
           violations.add(
               new TemporalChainLinkViolation(
                   this, this, lastPlanElement, lastExtent, planElement, extent));
         }
       }
       lastPlanElement = planElement;
       lastExtent = extent;
     }
   }
   TemporalNetworkMember<?> networkMember = TemporalNetworkMember.get(plan);
   if (networkMember.isConsistent()) {
     this.nogoodParts = Collections.emptySet();
   } else {
     Set<INogoodPart> parts = networkMember.getNogoodParts();
     for (INogoodPart part : parts) {
       violations.add(new NogoodViolation(this, part));
     }
     this.nogoodParts = parts;
   }
   return violations;
 }
 private Set<EPlanElement> getAffectedElements(List<Notification> notifications) {
   final Set<EPlanElement> affectedElements = new LinkedHashSet<EPlanElement>();
   class RemovalVisitor extends PlanVisitor {
     @Override
     protected void visit(EPlanElement element) {
       affectedElements.remove(element);
     }
   }
   class AdditionVisitor extends PlanVisitor {
     @Override
     protected void visit(EPlanElement element) {
       affectedElements.add(element);
     }
   }
   PlanVisitor removalVisitor = new RemovalVisitor();
   PlanVisitor additionVisitor = new AdditionVisitor();
   for (Notification notification : notifications) {
     Object feature = notification.getFeature();
     Object notifier = notification.getNotifier();
     if ((feature == PlanPackage.Literals.EPLAN_PARENT__CHILDREN)
         || (feature == PlanPackage.Literals.EACTIVITY__CHILDREN)) {
       removalVisitor.visitAll(EPlanUtils.getElementsRemoved(notification));
       additionVisitor.visitAll(EPlanUtils.getElementsAdded(notification));
     } else if ((feature == TemporalPackage.Literals.TEMPORAL_MEMBER__START_TIME)
         || (feature == TemporalPackage.Literals.TEMPORAL_MEMBER__DURATION)
         || (feature == TemporalPackage.Literals.TEMPORAL_MEMBER__END_TIME)
         || (feature == TemporalPackage.Literals.TEMPORAL_MEMBER__SCHEDULED)) {
       EMember member = (EMember) notifier;
       affectedElements.add(member.getPlanElement());
     } else if ((feature == ConstraintsPackage.Literals.CONSTRAINTS_MEMBER__CHAIN)
         || (feature
             == ConstraintsPackage.Literals.CONSTRAINTS_MEMBER__PERIODIC_TEMPORAL_CONSTRAINTS)
         || (feature
             == ConstraintsPackage.Literals.CONSTRAINTS_MEMBER__BINARY_TEMPORAL_CONSTRAINTS)) {
       EMember member = (EMember) notifier;
       affectedElements.add(member.getPlanElement());
     } else if (feature == AdvisorPackage.Literals.IWAIVABLE__WAIVER_RATIONALE) {
       if (notifier instanceof BinaryTemporalConstraint) {
         BinaryTemporalConstraint binary = (BinaryTemporalConstraint) notifier;
         affectedElements.add(binary.getPointA().getElement());
         affectedElements.add(binary.getPointB().getElement());
       } else if (notifier instanceof PeriodicTemporalConstraint) {
         PeriodicTemporalConstraint periodic = (PeriodicTemporalConstraint) notifier;
         affectedElements.add(periodic.getPoint().getElement());
       }
     } else if (ConstraintUtils.areAnchorsAllowed()
         && ADParameterUtils.isActivityAttributeOrParameter(notifier)) {
       EPlanElement planElement = ADParameterUtils.getActivityAttributeOrParameter(notifier);
       List<TemporalConstraint> constraints = new ArrayList<TemporalConstraint>();
       constraints.addAll(ConstraintUtils.getBinaryConstraints(planElement, false));
       constraints.addAll(ConstraintUtils.getPeriodicConstraints(planElement, false));
       for (TemporalConstraint constraint : constraints) {
         if (constraint instanceof BinaryTemporalConstraint) {
           BinaryTemporalConstraint btc = (BinaryTemporalConstraint) constraint;
           if (ConstraintUtils.isAnchorPointForElement(
                   btc.getPointA(), planElement, (EStructuralFeature) feature)
               || ConstraintUtils.isAnchorPointForElement(
                   btc.getPointB(), planElement, (EStructuralFeature) feature)) {
             affectedElements.add(planElement);
             break;
           }
         } else if (constraint instanceof PeriodicTemporalConstraint) {
           PeriodicTemporalConstraint ptc = (PeriodicTemporalConstraint) constraint;
           if (ConstraintUtils.isAnchorPointForElement(
               ptc.getPoint(), planElement, (EStructuralFeature) feature)) {
             affectedElements.add(planElement);
             break;
           }
         }
       }
     }
   }
   return affectedElements;
 }