class GeneratorScalable extends AbstractInjectionScalable {

    @Override
    public double scale(Network n, double asked, ScalingConvention scalingConvention) {
        Objects.requireNonNull(n);
        Objects.requireNonNull(scalingConvention);

        Generator g = n.getGenerator(id);
        double done = 0;
        if (g == null) {
            LOGGER.warn("Generator {} not found", id);
            return done;
        }

        Terminal t = g.getTerminal();
        if (!t.isConnected()) {
            GeneratorUtil.connectGenerator(g);
            LOGGER.info("Connecting {}", g.getId());
        }

        double oldTargetP = g.getTargetP();
        if (oldTargetP < this.minimumValue(n) || oldTargetP > this.maximumValue(n)) {
            throw new PowsyblException("Error scaling GeneratorScalable " + id +
                    " : Initial P is not in the range [Pmin, Pmax]");
        }

        // We use natural generator convention to compute the limits.
        // The actual convention is taken into account afterwards.
        double availableUp = maximumValue(n, GENERATOR) - oldTargetP;
        double availableDown = oldTargetP - minimumValue(n, GENERATOR);

        if (scalingConvention == GENERATOR) {
            done = asked > 0 ? Math.min(asked, availableUp) : -Math.min(-asked, availableDown);
            g.setTargetP(oldTargetP + done);
        } else {
            done = asked > 0 ? Math.min(asked, availableDown) : -Math.min(-asked, availableUp);
            g.setTargetP(oldTargetP - done);
        }

        LOGGER.info("Change active power setpoint of {} from {} to {} (pmax={})",
                    g.getId(), oldTargetP, g.getTargetP(), g.getMaxP());

        return done;
    }

      GeneratorScalable(String id);
      GeneratorScalable(String id, double minValue, double maxValue);

}