package comeon.core.mediareaders;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.TagDescriptor;
import com.drew.metadata.exif.ExifThumbnailDirectory;
import comeon.core.MediaUploadBatch;
import comeon.model.Media;
import comeon.model.User;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.LazyDynaBean;
import org.apache.commons.beanutils.LazyDynaClass;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public final class PictureReader extends AbstractMediaReader {
private static final String NON_WORD_CHARS = "[^\\w]";
public PictureReader(final File file, final User user) {
super(file, user);
}
protected final Media buildMedia(final MediaUploadBatch context) throws MediaReaderException, IOException {
final String fileName = getFile().getAbsolutePath();
try {
final Metadata rawMetadata = ImageMetadataReader.readMetadata(getFile());
final ExifThumbnailDirectory thumbnailDirectory = rawMetadata.getDirectory(ExifThumbnailDirectory.class);
final byte[] thumbnail;
if (thumbnailDirectory != null && thumbnailDirectory.hasThumbnailData()) {
thumbnail = thumbnailDirectory.getThumbnailData();
} else {
thumbnail = new byte[0];
}
final Map<String, Object> metadata = new HashMap<>(rawMetadata.getDirectoryCount());
for (final Directory directory : rawMetadata.getDirectories()) {
copy(directory, metadata);
preProcess(context, directory, metadata);
}
return new Media(getFile(), fileName, context.getTemplate(), metadata, thumbnail);
} catch (final ImageProcessingException e) {
throw new MediaReaderException(e);
}
}
private void copy(final Directory directory, final Map<String, Object> metadata) {
final TagDescriptor<?> descriptor = MetadataHelper.getDescriptor(directory);
final LazyDynaClass directoryClass = new LazyDynaClass(directory.getName(), null, directory.getTags()
.parallelStream()
.map(t -> new DynaProperty(t.getTagName().replaceAll(NON_WORD_CHARS, ""), String.class))
.toArray(DynaProperty[]::new));
directoryClass.setReturnNull(true);
final DynaBean directoryMetadata = new LazyDynaBean(directoryClass);
directory.getTags().stream().forEach(t -> directoryMetadata.set(
t.getTagName().replaceAll(NON_WORD_CHARS, ""),
descriptor.getDescription(t.getTagType())
));
metadata.put(directory.getName().replaceAll(NON_WORD_CHARS, ""), directoryMetadata);
}
private void preProcess(final MediaUploadBatch context, final Directory directory, final Map<String, Object> metadata) {
context.getPreProcessors().stream()
.filter(p -> directory.getClass().isAssignableFrom(p.getSupportedClass()))
.forEach(p -> p.process(directory, metadata));
}
}