imToken v2.14.1版本的 MD5 值为:83050b2c91219b46832c8336279e7878

以下内容为反编译后的 ProcessAllImagesInFolderUtility.java 源代码,内容仅作参考


package com.drew.tools;

import com.adobe.internal.xmp.XMPException;
import com.adobe.internal.xmp.XMPIterator;
import com.adobe.internal.xmp.options.IteratorOptions;
import com.adobe.internal.xmp.properties.XMPPropertyInfo;
import com.drew.imaging.FileTypeDetector;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.lang.StringUtil;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifDirectoryBase;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.ExifThumbnailDirectory;
import com.drew.metadata.file.FileSystemDirectory;
import com.drew.metadata.xmp.XmpDirectory;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ProcessAllImagesInFolderUtility {

    public interface FileHandler {
        void onBeforeExtraction(File file, PrintStream printStream, String str);

        void onExtractionError(File file, Throwable th, PrintStream printStream);

        void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream);

        void onScanCompleted(PrintStream printStream);

        void onStartingDirectory(File file);

        boolean shouldProcess(File file);
    }

    public static void main(String[] strArr) throws IOException, JpegProcessingException {
        ArrayList<String> arrayList = new ArrayList();
        PrintStream printStream = System.out;
        FileHandler fileHandler = null;
        int i2 = 0;
        while (i2 < strArr.length) {
            String str = strArr[i2];
            if (str.equalsIgnoreCase("--text")) {
                fileHandler = new TextFileOutputHandler();
            } else if (str.equalsIgnoreCase("--markdown")) {
                fileHandler = new MarkdownTableOutputHandler();
            } else if (str.equalsIgnoreCase("--unknown")) {
                fileHandler = new UnknownTagHandler();
            } else if (str.equalsIgnoreCase("--log-file")) {
                if (i2 == strArr.length - 1) {
                    printUsage();
                    System.exit(1);
                }
                i2++;
                printStream = new PrintStream((OutputStream) new FileOutputStream(strArr[i2], false), true);
            } else {
                arrayList.add(str);
            }
            i2++;
        }
        if (arrayList.isEmpty()) {
            System.err.println("Expects one or more directories as arguments.");
            printUsage();
            System.exit(1);
        }
        if (fileHandler == null) {
            fileHandler = new BasicFileHandler();
        }
        long nanoTime = System.nanoTime();
        for (String str2 : arrayList) {
            processDirectory(new File(str2), fileHandler, "", printStream);
        }
        fileHandler.onScanCompleted(printStream);
        System.out.println(String.format("Completed in %d ms", Long.valueOf((System.nanoTime() - nanoTime) / 1000000)));
        if (printStream != System.out) {
            printStream.close();
        }
    }

    private static void printUsage() {
        System.out.println("Usage:");
        System.out.println();
        System.out.println("  java com.drew.tools.ProcessAllImagesInFolderUtility [--text|--markdown|--unknown] [--log-file <file-name>]");
    }

    private static void processDirectory(File file, FileHandler fileHandler, String str, PrintStream printStream) {
        fileHandler.onStartingDirectory(file);
        String[] list = file.list();
        if (list == null) {
            return;
        }
        Arrays.sort(list);
        for (String str2 : list) {
            File file2 = new File(file, str2);
            if (file2.isDirectory()) {
                if (str.length() != 0) {
                    str2 = str + "/" + str2;
                }
                processDirectory(file2, fileHandler, str2, printStream);
            } else if (fileHandler.shouldProcess(file2)) {
                fileHandler.onBeforeExtraction(file2, printStream, str);
                try {
                    fileHandler.onExtractionSuccess(file2, ImageMetadataReader.readMetadata(file2), str, printStream);
                } catch (Throwable th) {
                    fileHandler.onExtractionError(file2, th, printStream);
                }
            }
        }
    }

    static abstract class FileHandlerBase implements FileHandler {
        private final Set<String> _supportedExtensions = new HashSet(Arrays.asList("jpg", "jpeg", "png", "gif", "bmp", "ico", "webp", "pcx", "ai", "eps", "nef", "crw", "cr2", "orf", "arw", "raf", "srw", "x3f", "rw2", "rwl", "tif", "tiff", "psd", "dng", "3g2", "3gp", "m4v", "mov", "mp4", "pbm", "pnm", "pgm"));
        private int _processedFileCount = 0;
        private int _exceptionCount = 0;
        private int _errorCount = 0;
        private long _processedByteCount = 0;

        @Override
        public void onStartingDirectory(File file) {
        }

        FileHandlerBase() {
        }

        @Override
        public boolean shouldProcess(File file) {
            String extension = getExtension(file);
            return extension != null && this._supportedExtensions.contains(extension.toLowerCase());
        }

        @Override
        public void onBeforeExtraction(File file, PrintStream printStream, String str) {
            this._processedFileCount++;
            this._processedByteCount += file.length();
        }

        @Override
        public void onExtractionError(File file, Throwable th, PrintStream printStream) {
            this._exceptionCount++;
            printStream.printf("\t[%s] %s\n", th.getClass().getName(), th.getMessage());
        }

        @Override
        public void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream) {
            if (metadata.hasErrors()) {
                printStream.print(file);
                printStream.print('\n');
                for (Directory directory : metadata.getDirectories()) {
                    if (directory.hasErrors()) {
                        Iterator<String> it = directory.getErrors().iterator();
                        while (it.hasNext()) {
                            printStream.printf("\t[%s] %s\n", directory.getName(), it.next());
                            this._errorCount++;
                        }
                    }
                }
            }
        }

        @Override
        public void onScanCompleted(PrintStream printStream) {
            int i2 = this._processedFileCount;
            if (i2 > 0) {
                printStream.print(String.format("Processed %,d files (%,d bytes) with %,d exceptions and %,d file errors\n", Integer.valueOf(i2), Long.valueOf(this._processedByteCount), Integer.valueOf(this._exceptionCount), Integer.valueOf(this._errorCount)));
            }
        }

        protected String getExtension(File file) {
            String name = file.getName();
            int lastIndexOf = name.lastIndexOf(46);
            if (lastIndexOf == -1 || lastIndexOf == name.length() - 1) {
                return null;
            }
            return name.substring(lastIndexOf + 1);
        }
    }

    static class TextFileOutputHandler extends FileHandlerBase {
        private static final String NEW_LINE = "\n";

        TextFileOutputHandler() {
        }

        @Override
        public void onStartingDirectory(File file) {
            super.onStartingDirectory(file);
            File file2 = new File(file + "/metadata");
            if (file2.exists()) {
                deleteRecursively(file2);
            }
        }

        private static void deleteRecursively(File file) {
            String[] list;
            if (!file.isDirectory()) {
                throw new IllegalArgumentException("Must be a directory.");
            }
            if (file.exists() && (list = file.list()) != null) {
                for (String str : list) {
                    File file2 = new File(str);
                    if (file2.isDirectory()) {
                        deleteRecursively(file2);
                    } else {
                        file2.delete();
                    }
                }
            }
            file.delete();
        }

        @Override
        public void onBeforeExtraction(File file, PrintStream printStream, String str) {
            super.onBeforeExtraction(file, printStream, str);
            printStream.print(file.getAbsoluteFile());
            printStream.print("\n");
        }

        @Override
        public void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream) {
            PrintWriter printWriter;
            PrintWriter openWriter;
            int i2;
            boolean z2;
            String str2;
            super.onExtractionSuccess(file, metadata, str, printStream);
            try {
                try {
                    openWriter = openWriter(file);
                } catch (Throwable th) {
                    th = th;
                    printWriter = null;
                }
                try {
                    int i3 = 3;
                    if (metadata.hasErrors()) {
                        for (Directory directory : metadata.getDirectories()) {
                            if (directory.hasErrors()) {
                                Iterator<String> it = directory.getErrors().iterator();
                                while (it.hasNext()) {
                                    openWriter.format("[ERROR: %s] %s%s", directory.getName(), it.next(), "\n");
                                }
                            }
                        }
                        openWriter.write("\n");
                    }
                    for (Directory directory2 : metadata.getDirectories()) {
                        String name = directory2.getName();
                        Iterator<Tag> it2 = directory2.getTags().iterator();
                        while (true) {
                            String str3 = "";
                            if (!it2.hasNext()) {
                                break;
                            }
                            Tag next = it2.next();
                            String tagName = next.getTagName();
                            try {
                                str2 = next.getDescription();
                            } catch (Exception e2) {
                                str2 = "ERROR: " + e2.getMessage();
                            }
                            if (str2 != null) {
                                str3 = str2;
                            }
                            if ((directory2 instanceof FileSystemDirectory) && next.getTagType() == i3) {
                                str3 = "<omitted for regression testing as checkout dependent>";
                            }
                            Object[] objArr = new Object[5];
                            objArr[0] = name;
                            objArr[1] = next.getTagTypeHex();
                            objArr[2] = tagName;
                            objArr[i3] = str3;
                            objArr[4] = "\n";
                            openWriter.format("[%s - %s] %s = %s%s", objArr);
                        }
                        if (directory2.getTagCount() != 0) {
                            openWriter.write("\n");
                        }
                        if (directory2 instanceof XmpDirectory) {
                            try {
                                XMPIterator it3 = ((XmpDirectory) directory2).getXMPMeta().iterator(new IteratorOptions().setJustLeafnodes(true));
                                z2 = false;
                                while (it3.hasNext()) {
                                    try {
                                        XMPPropertyInfo xMPPropertyInfo = (XMPPropertyInfo) it3.next();
                                        String namespace = xMPPropertyInfo.getNamespace();
                                        String path = xMPPropertyInfo.getPath();
                                        String value = xMPPropertyInfo.getValue();
                                        if (path != null) {
                                            if (namespace == null) {
                                                namespace = "";
                                            }
                                            if (value == null) {
                                                value = "";
                                            } else if (value.length() > 512) {
                                                try {
                                                    value = String.format("%s <truncated from %d characters>", value.substring(0, 512), Integer.valueOf(value.length()));
                                                } catch (XMPException e3) {
                                                    e = e3;
                                                    i2 = 3;
                                                    e.printStackTrace();
                                                    if (z2) {
                                                    }
                                                    i3 = i2;
                                                }
                                            }
                                            Object[] objArr2 = new Object[4];
                                            objArr2[0] = namespace;
                                            objArr2[1] = path;
                                            objArr2[2] = value;
                                            i2 = 3;
                                            try {
                                                objArr2[3] = "\n";
                                                openWriter.format("[XMPMeta - %s] %s = %s%s", objArr2);
                                                z2 = true;
                                                i3 = 3;
                                            } catch (XMPException e4) {
                                                e = e4;
                                                e.printStackTrace();
                                                if (z2) {
                                                }
                                                i3 = i2;
                                            }
                                        }
                                    } catch (XMPException e5) {
                                        e = e5;
                                        i2 = i3;
                                    }
                                }
                                i2 = i3;
                            } catch (XMPException e6) {
                                e = e6;
                                i2 = i3;
                                z2 = false;
                            }
                            if (z2) {
                                openWriter.write("\n");
                            }
                        } else {
                            i2 = i3;
                        }
                        i3 = i2;
                    }
                    writeHierarchyLevel(metadata, openWriter, null, 0);
                    openWriter.write("\n");
                    closeWriter(openWriter);
                } catch (Throwable th2) {
                    th = th2;
                    printWriter = openWriter;
                    closeWriter(printWriter);
                    throw th;
                }
            } catch (IOException e7) {
                e7.printStackTrace();
            }
        }

        private static void writeHierarchyLevel(Metadata metadata, PrintWriter printWriter, Directory directory, int i2) {
            int i3;
            for (Directory directory2 : metadata.getDirectories()) {
                if (directory == null) {
                    if (directory2.getParent() == null) {
                        for (i3 = 0; i3 < i2 * 4; i3++) {
                            printWriter.write(32);
                        }
                        printWriter.write("- ");
                        printWriter.write(directory2.getName());
                        printWriter.write("\n");
                        writeHierarchyLevel(metadata, printWriter, directory2, i2 + 1);
                    }
                } else if (directory.equals(directory2.getParent())) {
                    while (i3 < i2 * 4) {
                    }
                    printWriter.write("- ");
                    printWriter.write(directory2.getName());
                    printWriter.write("\n");
                    writeHierarchyLevel(metadata, printWriter, directory2, i2 + 1);
                }
            }
        }

        @Override
        public void onExtractionError(File file, Throwable th, PrintStream printStream) {
            PrintWriter printWriter;
            super.onExtractionError(file, th, printStream);
            try {
                try {
                    printWriter = openWriter(file);
                    try {
                        printWriter.write("EXCEPTION: " + th.getMessage() + "\n");
                        printWriter.write("\n");
                        closeWriter(printWriter);
                    } catch (Throwable th2) {
                        th = th2;
                        closeWriter(printWriter);
                        throw th;
                    }
                } catch (IOException e2) {
                    printStream.printf("IO exception writing metadata file: %s%s", e2.getMessage(), "\n");
                }
            } catch (Throwable th3) {
                th = th3;
                printWriter = null;
            }
        }

        private static PrintWriter openWriter(File file) throws IOException {
            File file2 = new File(String.format("%s/metadata", file.getParent()));
            if (!file2.exists()) {
                file2.mkdir();
            }
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(String.format("%s/metadata/%s.txt", file.getParent(), file.getName())), "UTF-8");
            outputStreamWriter.write("FILE: " + file.getName() + "\n");
            BufferedInputStream bufferedInputStream = null;
            try {
                BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new FileInputStream(file));
                try {
                    outputStreamWriter.write(String.format("TYPE: %s\n", FileTypeDetector.detectFileType(bufferedInputStream2).toString().toUpperCase()));
                    outputStreamWriter.write("\n");
                    bufferedInputStream2.close();
                    return new PrintWriter(outputStreamWriter);
                } catch (Throwable th) {
                    th = th;
                    bufferedInputStream = bufferedInputStream2;
                    if (bufferedInputStream != null) {
                        bufferedInputStream.close();
                    }
                    throw th;
                }
            } catch (Throwable th2) {
                th = th2;
            }
        }

        private static void closeWriter(Writer writer) throws IOException {
            if (writer != null) {
                writer.write("Generated using metadata-extractor\n");
                writer.write("https://drewnoakes.com/code/exif/\n");
                writer.flush();
                writer.close();
            }
        }
    }

    static class MarkdownTableOutputHandler extends FileHandlerBase {
        private final Map<String, String> _extensionEquivalence;
        private final Map<String, List<Row>> _rowListByExtension;

        public static class Row {
            private String exifVersion;
            final File file;
            private String makernote;
            private String manufacturer;
            final Metadata metadata;
            private String model;
            final String relativePath;
            private String thumbnail;

            Row(File file, Metadata metadata, String str) {
                boolean z2;
                this.file = file;
                this.metadata = metadata;
                this.relativePath = str;
                ExifIFD0Directory exifIFD0Directory = (ExifIFD0Directory) metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                ExifSubIFDDirectory exifSubIFDDirectory = (ExifSubIFDDirectory) metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
                ExifThumbnailDirectory exifThumbnailDirectory = (ExifThumbnailDirectory) metadata.getFirstDirectoryOfType(ExifThumbnailDirectory.class);
                if (exifIFD0Directory != null) {
                    this.manufacturer = exifIFD0Directory.getDescription(271);
                    this.model = exifIFD0Directory.getDescription(272);
                }
                if (exifSubIFDDirectory != null) {
                    this.exifVersion = exifSubIFDDirectory.getDescription(ExifDirectoryBase.TAG_EXIF_VERSION);
                    z2 = exifSubIFDDirectory.containsTag(ExifDirectoryBase.TAG_MAKERNOTE);
                } else {
                    z2 = false;
                }
                if (exifThumbnailDirectory != null) {
                    Integer integer = exifThumbnailDirectory.getInteger(256);
                    Integer integer2 = exifThumbnailDirectory.getInteger(257);
                    this.thumbnail = (integer == null || integer2 == null) ? "Yes" : String.format("Yes (%s x %s)", integer, integer2);
                }
                Iterator<Directory> it = metadata.getDirectories().iterator();
                while (true) {
                    if (!it.hasNext()) {
                        break;
                    }
                    Directory next = it.next();
                    if (next.getClass().getName().contains("Makernote")) {
                        this.makernote = next.getName().replace("Makernote", "").trim();
                        break;
                    }
                }
                if (this.makernote == null) {
                    this.makernote = z2 ? "(Unknown)" : "N/A";
                }
            }
        }

        public MarkdownTableOutputHandler() {
            HashMap hashMap = new HashMap();
            this._extensionEquivalence = hashMap;
            this._rowListByExtension = new HashMap();
            hashMap.put("jpeg", "jpg");
        }

        @Override
        public void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream) {
            super.onExtractionSuccess(file, metadata, str, printStream);
            String extension = getExtension(file);
            if (extension == null) {
                return;
            }
            String lowerCase = extension.toLowerCase();
            if (this._extensionEquivalence.containsKey(lowerCase)) {
                lowerCase = this._extensionEquivalence.get(lowerCase);
            }
            List<Row> list = this._rowListByExtension.get(lowerCase);
            if (list == null) {
                list = new ArrayList<>();
                this._rowListByExtension.put(lowerCase, list);
            }
            list.add(new Row(file, metadata, str));
        }

        @Override
        public void onScanCompleted(PrintStream printStream) {
            PrintStream printStream2;
            Throwable th;
            FileOutputStream fileOutputStream;
            IOException e2;
            super.onScanCompleted(printStream);
            try {
                try {
                    try {
                        fileOutputStream = new FileOutputStream("../wiki/ImageDatabaseSummary.md", false);
                    } catch (Throwable th2) {
                        th = th2;
                    }
                    try {
                        printStream2 = new PrintStream((OutputStream) fileOutputStream, false);
                        try {
                            writeOutput(printStream2);
                            printStream2.flush();
                            printStream2.close();
                            fileOutputStream.close();
                        } catch (IOException e3) {
                            e2 = e3;
                            e2.printStackTrace();
                            if (printStream2 != null) {
                                printStream2.close();
                            }
                            if (fileOutputStream != null) {
                                fileOutputStream.close();
                            }
                        }
                    } catch (IOException e4) {
                        printStream2 = null;
                        e2 = e4;
                    } catch (Throwable th3) {
                        printStream2 = null;
                        th = th3;
                        if (printStream2 != null) {
                            printStream2.close();
                        }
                        if (fileOutputStream != null) {
                            try {
                                fileOutputStream.close();
                            } catch (IOException e5) {
                                e5.printStackTrace();
                            }
                        }
                        throw th;
                    }
                } catch (IOException e6) {
                    printStream2 = null;
                    e2 = e6;
                    fileOutputStream = null;
                } catch (Throwable th4) {
                    printStream2 = null;
                    th = th4;
                    fileOutputStream = null;
                }
            } catch (IOException e7) {
                e7.printStackTrace();
            }
        }

        private void writeOutput(PrintStream printStream) throws IOException {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(printStream);
            outputStreamWriter.write("# Image Database Summary\n\n");
            for (Map.Entry<String, List<Row>> entry : this._rowListByExtension.entrySet()) {
                outputStreamWriter.write("## " + entry.getKey().toUpperCase() + " Files\n\n");
                outputStreamWriter.write("File|Manufacturer|Model|Dir Count|Exif?|Makernote|Thumbnail|All Data\n");
                outputStreamWriter.write("----|------------|-----|---------|-----|---------|---------|--------\n");
                List<Row> value = entry.getValue();
                Collections.sort(value, new Comparator<Row>() {
                    @Override
                    public int compare(Row row, Row row2) {
                        int compare = StringUtil.compare(row.manufacturer, row2.manufacturer);
                        return compare != 0 ? compare : StringUtil.compare(row.model, row2.model);
                    }
                });
                for (Row row : value) {
                    Object[] objArr = new Object[11];
                    objArr[0] = row.file.getName();
                    objArr[1] = row.relativePath;
                    objArr[2] = StringUtil.urlEncode(row.file.getName());
                    String str = "";
                    objArr[3] = row.manufacturer == null ? "" : row.manufacturer;
                    objArr[4] = row.model == null ? "" : row.model;
                    objArr[5] = Integer.valueOf(row.metadata.getDirectoryCount());
                    objArr[6] = row.exifVersion == null ? "" : row.exifVersion;
                    objArr[7] = row.makernote == null ? "" : row.makernote;
                    if (row.thumbnail != null) {
                        str = row.thumbnail;
                    }
                    objArr[8] = str;
                    objArr[9] = row.relativePath;
                    objArr[10] = StringUtil.urlEncode(row.file.getName()).toLowerCase();
                    outputStreamWriter.write(String.format("[%s](https://raw.githubusercontent.com/drewnoakes/metadata-extractor-images/master/%s/%s)|%s|%s|%d|%s|%s|%s|[metadata](https://raw.githubusercontent.com/drewnoakes/metadata-extractor-images/master/%s/metadata/%s.txt)\n", objArr));
                }
                outputStreamWriter.write(10);
            }
            outputStreamWriter.flush();
        }
    }

    static class UnknownTagHandler extends FileHandlerBase {
        private HashMap<String, HashMap<Integer, Integer>> _occurrenceCountByTagByDirectory = new HashMap<>();

        UnknownTagHandler() {
        }

        @Override
        public void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream) {
            super.onExtractionSuccess(file, metadata, str, printStream);
            for (Directory directory : metadata.getDirectories()) {
                for (Tag tag : directory.getTags()) {
                    if (!tag.hasTagName()) {
                        HashMap<Integer, Integer> hashMap = this._occurrenceCountByTagByDirectory.get(directory.getName());
                        if (hashMap == null) {
                            hashMap = new HashMap<>();
                            this._occurrenceCountByTagByDirectory.put(directory.getName(), hashMap);
                        }
                        Integer num = hashMap.get(Integer.valueOf(tag.getTagType()));
                        if (num == null) {
                            hashMap.put(Integer.valueOf(tag.getTagType()), 0);
                            num = 0;
                        }
                        hashMap.put(Integer.valueOf(tag.getTagType()), Integer.valueOf(num.intValue() + 1));
                    }
                }
            }
        }

        @Override
        public void onScanCompleted(PrintStream printStream) {
            super.onScanCompleted(printStream);
            for (Map.Entry<String, HashMap<Integer, Integer>> entry : this._occurrenceCountByTagByDirectory.entrySet()) {
                String key = entry.getKey();
                ArrayList<Map.Entry> arrayList = new ArrayList(entry.getValue().entrySet());
                Collections.sort(arrayList, new Comparator<Map.Entry<Integer, Integer>>() {
                    @Override
                    public int compare(Map.Entry<Integer, Integer> entry2, Map.Entry<Integer, Integer> entry3) {
                        return entry3.getValue().compareTo(entry2.getValue());
                    }
                });
                for (Map.Entry entry2 : arrayList) {
                    printStream.format("%s, 0x%04X, %d\n", key, (Integer) entry2.getKey(), (Integer) entry2.getValue());
                }
            }
        }
    }

    static class BasicFileHandler extends FileHandlerBase {
        BasicFileHandler() {
        }

        @Override
        public void onExtractionSuccess(File file, Metadata metadata, String str, PrintStream printStream) {
            super.onExtractionSuccess(file, metadata, str, printStream);
            for (Directory directory : metadata.getDirectories()) {
                directory.getName();
                for (Tag tag : directory.getTags()) {
                    tag.getTagName();
                    tag.getDescription();
                }
            }
        }
    }
}