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  /** Maps main encoding options to the given stream builder. */
076  public static <T extends AbstractFFmpegStreamBuilder<?>> void map(
077      MainEncodingOptions opts, T dest) {
078    mapper.map(opts, dest);
079  }
080
081  /** Maps audio encoding options to the given stream builder. */
082  public static <T extends AbstractFFmpegStreamBuilder<?>> void map(
083      AudioEncodingOptions opts, T dest) {
084    mapper.map(new AudioWrapper(opts), dest);
085  }
086
087  /** Maps video encoding options to the given stream builder. */
088  public static <T extends AbstractFFmpegStreamBuilder<?>> void map(
089      VideoEncodingOptions opts, T dest) {
090    mapper.map(new VideoWrapper(opts), dest);
091  }
092
093  /** Maps all encoding options to the given stream builder. */
094  public static <T extends AbstractFFmpegStreamBuilder<?>> void map(EncodingOptions opts, T dest) {
095    map(opts.getMain(), dest);
096
097    if (opts.getAudio().isEnabled()) {
098      map(opts.getAudio(), dest);
099    }
100    if (opts.getVideo().isEnabled()) {
101      map(opts.getVideo(), dest);
102    }
103  }
104}