@Override
  public void load(
      final ProjectProperties properties, final boolean usedConcurrently, final Runnable onDone) {
    checkCallingThread();

    // We must listen for changes, so that we do not overwrite properties
    // modified later.

    final List<PropertySetter<?>> setters = new LinkedList<PropertySetter<?>>();

    // Just add a new element to the list when a new property needs to be
    // saved.
    setters.add(
        newPropertySetter(
            properties.getPlatform(),
            new PropertyGetter<JavaPlatform>() {
              @Override
              public PropertySource<JavaPlatform> get(PropertiesSnapshot snapshot) {
                return snapshot.getPlatform();
              }
            }));
    setters.add(
        newPropertySetter(
            properties.getSourceEncoding(),
            new PropertyGetter<Charset>() {
              @Override
              public PropertySource<Charset> get(PropertiesSnapshot snapshot) {
                return snapshot.getSourceEncoding();
              }
            }));
    setters.add(
        newPropertySetter(
            properties.getSourceLevel(),
            new PropertyGetter<String>() {
              @Override
              public PropertySource<String> get(PropertiesSnapshot snapshot) {
                return snapshot.getSourceLevel();
              }
            }));
    setters.add(
        newPropertySetter(
            properties.getCommonTasks(),
            new PropertyGetter<List<PredefinedTask>>() {
              @Override
              public PropertySource<List<PredefinedTask>> get(PropertiesSnapshot snapshot) {
                return snapshot.getCommonTasks();
              }
            }));
    setters.add(
        newPropertySetter(
            properties.getScriptPlatform(),
            new PropertyGetter<JavaPlatform>() {
              @Override
              public PropertySource<JavaPlatform> get(PropertiesSnapshot snapshot) {
                return snapshot.getScriptPlatform();
              }
            }));
    setters.add(
        newPropertySetter(
            properties.getGradleLocation(),
            new PropertyGetter<GradleLocation>() {
              @Override
              public PropertySource<GradleLocation> get(PropertiesSnapshot snapshot) {
                return snapshot.getGradleHome();
              }
            }));
    for (final String command : AbstractProjectProperties.getCustomizableCommands()) {
      MutableProperty<PredefinedTask> taskProperty = properties.tryGetBuiltInTask(command);
      if (taskProperty == null) {
        LOGGER.log(Level.WARNING, "tryGetBuiltInTask returned null for command: {0}", command);
        continue;
      }
      setters.add(
          newPropertySetter(
              taskProperty,
              new PropertyGetter<PredefinedTask>() {
                @Override
                public PropertySource<PredefinedTask> get(PropertiesSnapshot snapshot) {
                  return snapshot.tryGetBuiltInTask(command);
                }
              }));
    }

    for (PropertySetter<?> setter : setters) {
      setter.start();
    }

    final Executor setterExecutor =
        usedConcurrently ? SwingExecutor.INSTANCE : RecursiveExecutor.INSTANCE;

    NbGradleProject.PROJECT_PROCESSOR.execute(
        new Runnable() {
          @Override
          public void run() {
            try {
              final PropertiesSnapshot snapshot = XmlPropertyFormat.readFromXml(propertiesFile);

              setterExecutor.execute(
                  new Runnable() {
                    @Override
                    public void run() {
                      for (PropertySetter<?> setter : setters) {
                        setter.set(snapshot);
                      }

                      if (onDone != null) {
                        onDone.run();
                      }
                    }
                  });
            } finally {
              // required, so that the listeners will not
              // be removed before setting the properties.
              setterExecutor.execute(
                  new Runnable() {
                    @Override
                    public void run() {
                      for (PropertySetter<?> setter : setters) {
                        setter.done();
                      }
                    }
                  });
            }
          }
        });
  }
 /**
  * Set's all properties from the {@link List}.
  *
  * @param generatedObject target {@link Object}.
  */
 public void setProperties(Object generatedObject) {
   // Step 1. Call set methods for collections
   for (PropertySetter<?> propertySetter : propertySetters) {
     propertySetter.setValue(generatedObject);
   }
 }