public static List<BinaryTemporalConstraint> convertChainToBinaryTemporalConstraints(
     TemporalChain chain) {
   List<BinaryTemporalConstraint> constraints = new ArrayList<BinaryTemporalConstraint>();
   List<EPlanElement> chainedElements = chain.getElements();
   for (int i = 1; i < chainedElements.size(); i++) {
     EPlanElement a = chainedElements.get(i - 1);
     EPlanElement b = chainedElements.get(i);
     BinaryTemporalConstraint constraint =
         createConstraint(
             a, Timepoint.END, b, Timepoint.START, AmountUtils.exactZero(SI.SECOND), null, "");
     constraints.add(constraint);
   }
   return constraints;
 }
 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;
 }