001package net.bramp.ffmpeg.modelmapper;
002
003import static net.bramp.ffmpeg.modelmapper.NotDefaultCondition.notDefault;
004
005import net.bramp.ffmpeg.builder.AbstractFFmpegStreamBuilder;
006import net.bramp.ffmpeg.builder.FFmpegOutputBuilder;
007import net.bramp.ffmpeg.options.AudioEncodingOptions;
008import net.bramp.ffmpeg.options.EncodingOptions;
009import net.bramp.ffmpeg.options.MainEncodingOptions;
010import net.bramp.ffmpeg.options.VideoEncodingOptions;
011import org.modelmapper.ModelMapper;
012import org.modelmapper.TypeMap;
013import org.modelmapper.config.Configuration;
014import org.modelmapper.convention.NameTokenizers;
015
016/**
017 * Copies values from one type of object to another
018 *
019 * @author bramp
020 */
021public class Mapper {
022
023  private Mapper() {
024    throw new InstantiationError("Must not instantiate this class");
025  }
026
027  private static final ModelMapper mapper = newModelMapper();
028
029  private static <S, D> TypeMap<S, D> createTypeMap(
030      ModelMapper mapper, Class<S> sourceType, Class<D> destinationType, Configuration config) {
031
032    return mapper
033        .createTypeMap(sourceType, destinationType, config)
034        // We setPropertyCondition because ModelMapper seems to ignore this in
035        // the config
036        .setPropertyCondition(config.getPropertyCondition());
037  }
038
039  private static ModelMapper newModelMapper() {
040    final ModelMapper mapper = new ModelMapper();
041
042    Configuration config =
043        mapper
044            .getConfiguration()
045            .copy()
046            .setFieldMatchingEnabled(true)
047            .setPropertyCondition(notDefault)
048            .setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
049
050    createTypeMap(mapper, MainEncodingOptions.class, FFmpegOutputBuilder.class, config);
051    createTypeMap(mapper, AudioWrapper.class, FFmpegOutputBuilder.class, config);
052    createTypeMap(mapper, VideoWrapper.class, FFmpegOutputBuilder.class, config);
053
054    return mapper;
055  }
056
057  /** Simple wrapper object, to inject the word "audio" in the property name */
058  static class AudioWrapper {
059    public final AudioEncodingOptions audio;
060
061    AudioWrapper(AudioEncodingOptions audio) {
062      this.audio = audio;
063    }
064  }
065
066  /** Simple wrapper object, to inject the word "video" in the property name */
067  static class VideoWrapper {
068    public final VideoEncodingOptions video;
069
070    VideoWrapper(VideoEncodingOptions video) {
071      this.video = video;
072    }
073  }
074
075  public static <T extends AbstractFFmpegStreamBuilder<T>> void map(
076      MainEncodingOptions opts, AbstractFFmpegStreamBuilder<T> dest) {
077    mapper.map(opts, dest);
078  }
079
080  public static <T extends AbstractFFmpegStreamBuilder<T>> void map(
081      AudioEncodingOptions opts, AbstractFFmpegStreamBuilder<T> dest) {
082    mapper.map(new AudioWrapper(opts), dest);
083  }
084
085  public static <T extends AbstractFFmpegStreamBuilder<T>> void map(
086      VideoEncodingOptions opts, AbstractFFmpegStreamBuilder<T> dest) {
087    mapper.map(new VideoWrapper(opts), dest);
088  }
089
090  public static <T extends AbstractFFmpegStreamBuilder<T>> void map(
091      EncodingOptions opts, AbstractFFmpegStreamBuilder<T> dest) {
092    map(opts.getMain(), dest);
093
094    if (opts.getAudio().enabled) {
095      map(opts.getAudio(), dest);
096    }
097    if (opts.getVideo().enabled) {
098      map(opts.getVideo(), dest);
099    }
100  }
101}