/**
   * Builds a layer by cloning a prototype neuron and adding to it weights such that it is fully
   * connected to the feeding layer.
   *
   * @param layerConfiguration
   * @param previousLayerAbsoluteSize
   * @return the built layer.
   */
  @Override
  public Layer buildLayer(LayerConfiguration layerConfiguration, int previousLayerAbsoluteSize) {
    prototypeNeuron.setActivationFunction(layerConfiguration.getActivationFunction());
    int layerSize = layerConfiguration.getSize();
    boolean bias = layerConfiguration.isBias();

    // determine correct domain registry
    DomainRegistry domainRegistry = domainProvider.generateDomain(previousLayerAbsoluteSize);

    // set domain for prototype neuron
    prototypeNeuron.setDomain(domainRegistry.getDomainString());

    // get prototype weight vector
    Vector prototypeWeightVector = null;
    try {
      prototypeWeightVector = (Vector) domainRegistry.getBuiltRepresentation();
    } catch (ClassCastException exception) {
      throw new UnsupportedOperationException(
          "The domain string of the neural network weights has to be real valued");
    }

    // add neurons to layer
    Layer layer = new Layer();
    for (int i = 0; i < layerSize; i++) {
      Neuron newNeuron = prototypeNeuron.getClone();

      Vector weights = prototypeWeightVector.getClone();
      // TODO: initialisation should be done by training algorithm
      this.getWeightInitialisationStrategy().initialise(weights);
      newNeuron.setWeights(weights);
      layer.add(newNeuron);
    }
    if (bias) {
      layer.add(new BiasNeuron());
      layer.setBias(true);
    }
    return layer;
  }