@SuppressWarnings("unchecked")
 private static synchronized Map<Class<? extends Substance>, Method> getSubstanceGetters(
     Composed composed) {
   Map<Class<? extends Substance>, Method> getters = substanceGettersMap.get(composed.getClass());
   if (getters == null) {
     Method[] methods = composed.getClass().getMethods();
     getters = new LinkedHashMap<>();
     for (Method m : methods) {
       if (m.getName().startsWith("get")
           && Substance.class.isAssignableFrom(m.getReturnType())
           && m.getParameterTypes().length == 0) {
         getters.put((Class<Substance>) m.getReturnType(), m);
       }
     }
     substanceGettersMap.put(composed.getClass(), getters);
   }
   return getters;
 }
  public static void transfer(final Composed source, final Composed target, double amount) {

    double total = 0;
    int pom = 1;

    for (Substance s : source) {

      try {
        total += s.getAmount();
      } catch (Exception e) {
        // TODO Auto-generated catch block
        // System.out.println(e.getMessage());
        // e.printStackTrace();
        break;
      }
    }

    if (total == 0.0) return;

    double ratio = amount / total;

    if (ratio > 1) ratio = 1.0;

    for (Substance s1 : source) {
      try {
        Substance s2 = target.substance(s1.getClass());
        if (s2 == null) {
          throw new IllegalArgumentException(
              String.format("substance '%s' not found in target", s1.getSubstanceName()));
        }
        double a = ratio * s1.getAmount();

        if (s1.getAmount() < 0) {
          System.out.println("teraz: " + s1.getAmount() + "  " + a);
          pom = 0;
        }

        if (s1 instanceof Composed) {
          transfer((Composed) s1, (Composed) s2, a);

        } else {

          s1.inc(-a);
          s2.inc(a);
        }
      } catch (Exception e) {
        // TODO Auto-generated catch block
        // e.printStackTrace();
        break;
      }

      if (pom == 0) System.out.println("to ta");
    }
  }
 public static void copy(Composed source, Composed target) {
   for (Substance s1 : target) {
     Substance s2 = source.substance(s1.getClass());
     if (s2 != null) {
       if (s1 instanceof Composed) {
         copy((Composed) s2, (Composed) s1);
       } else {
         s1.setAmount(s2.getAmount());
       }
     }
   }
 }