class ConfigMerge {

    private static final String NAME = "ConfigMerge";

    private ConfigMerge() {
    }

    /**
     * Merge base and new configuration.
     * @param cfgBase base configuration
     * @param cfgNew new configuration, will receive properties from the base configuration
     * @throws Exception exception
     */
    public static void merge(Configuration cfgBase, Configuration cfgNew) throws Exception {
        Configuration cfgDefault = new Configuration();

        // Basic strategy: take all non-static/transient fields that have a setter
        // from cfgBase that are not of default value and set them to cfgNew.
        var fields = Arrays.stream(cfgBase.getClass().getDeclaredFields())
                .filter(ConfigMerge::isCopyable)
                .collect(Collectors.toList());

        for (Field field : fields) {
            String fieldName = field.getName();
            PropertyDescriptor desc;
            try {
                desc = new PropertyDescriptor(fieldName, Configuration.class);
            } catch (IntrospectionException ex) {
                throw new Exception("cannot get property descriptor for '" + fieldName + "'");
            }

            Method setter = desc.getWriteMethod();
            if (setter == null) {
                throw new Exception("no setter for '" + fieldName + "'");
            }

            Method getter = desc.getReadMethod();
            if (getter == null) {
                throw new Exception("no getter for '" + fieldName + "'");
            }

            try {
                Object obj = getter.invoke(cfgBase);
                if (Objects.equals(obj, getter.invoke(cfgDefault))) {
                        continue;
                }
            } catch (Exception ex) {
                throw new Exception("failed to invoke getter for " + fieldName + ": " + ex);
            }

            try {
                setter.invoke(cfgNew, getter.invoke(cfgBase));
            } catch (Exception ex) {
                throw new Exception("failed to invoke setter for '" + fieldName + "'");
            }
        }
    }

    private static boolean isCopyable(Field field) {

        int modifiers = field.getModifiers();
        return !Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers) &&
                !Modifier.isFinal(modifiers);
    }

    public static void main(String[] argv) {<FILL_FUNCTION_BODY>}

    private static void aUsage(PrintStream out) {
        out.println("Usage:");
        out.println(NAME + " [-h] <config_file_base> <config_file_new> <output_file>");
        out.println();
        out.println("OPTIONS:");
        out.println("Help");
        out.println("-?                   print this help message");
        out.println("-h                   print this help message");
        out.println();
    }

    private static void bUsage(PrintStream out) {
        out.println("Maybe try to run " + NAME + " -h");
    }
}


        Getopt getopt = new Getopt(argv, "h?");

        try {
            getopt.parse();
        } catch (ParseException ex) {
            System.err.println(NAME + ": " + ex.getMessage());
            bUsage(System.err);
            System.exit(1);
        }

        int cmd;
        getopt.reset();
        while ((cmd = getopt.getOpt()) != -1) {
            switch (cmd) {
                case '?':
                case 'h':
                    aUsage(System.out);
                    System.exit(0);
                    break;
                default:
                    System.err.println("Internal Error - Not implemented option: " + (char) cmd);
                    bUsage(System.err);
                    System.exit(1);
                    break;
            }
        }

        int optind = getopt.getOptind();
        if (optind < 0 || argv.length - optind != 3) {
            aUsage(System.err);
            System.exit(1);
        }

        Configuration cfgBase = null;
        try {
            cfgBase = Configuration.read(new File(argv[optind]));
        } catch (IOException ex) {
            System.err.println("cannot read base file " + argv[optind] + ":" + ex);
            System.exit(1);
        }

        Configuration cfgNew = null;
        try {
            cfgNew = Configuration.read(new File(argv[optind + 1]));
        } catch (IOException ex) {
            System.err.println("cannot read file " + argv[optind + 1] + ":" + ex);
            System.exit(1);
        }

        try {
            merge(cfgBase, cfgNew);
        } catch (Exception ex) {
            System.err.print(ex);
            System.exit(1);
        }

        // Write the resulting XML representation to the output file.
        try (OutputStream os = new FileOutputStream(argv[optind + 2])) {
            cfgNew.encodeObject(os);
        } catch (IOException ex) {
            System.err.print(ex);
            System.exit(1);
        }
    
<no_super_class>