public class Container {
   private double capacity;
   private Set contents; // beczki

   public boolean hasSpaceFor(Drum aDrum) {
      return remainingSpace() >= aDrum.getSize();
   }

   public double remainingSpace() {
      double totalContentSize = 0.0;
      Iterator it = contents.iterator();
      while (it.hasNext()) {
         Drum aDrum = (Drum) it.next();
         totalContentSize = totalContentSize + aDrum.getSize();
      }
      return capacity – totalContentSize;
   }

   public boolean canAccommodate(Drum aDrum) {
      return hasSpaceFor(aDrum) &&
      aDrum.getContainerSpecification().isSatisfiedBy(this);
   }
}

public class PrototypePacker implements WarehousePacker {
   public void pack(Collection containers, Collection drums)
         throws NoAnswerFoundException {
      /* Ta metoda, jak napisano, spełnia ASERCJĘ. Jednakże
      w sytuacji zwrócenia wyjątku zawartość obiektu 
      klasy Container może się zmienić
      W takim razie odtwarzanie musi być zapewnione 
      na wyższym poziomie */
      Iterator it = drums.iterator();
      while (it.hasNext()) {
         Drum drum = (Drum) it.next();
         Container container =
            findContainerFor(containers, drum);
         container.add(drum);
      }
   }

   public Container findContainerFor(
               Collection containers, Drum drum)
               throws NoAnswerFoundException {
      Iterator it = containers.iterator();
      while (it.hasNext()) {
         Container container = (Container) it.next();
         if (container.canAccommodate(drum))
            return container;
      }
      throw new NoAnswerFoundException();
   }

}
