/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 Lachlan Dowding
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package permafrost.tundra.data.transform;

import com.wm.data.IData;
import com.wm.data.IDataCursor;
import com.wm.data.IDataFactory;
import permafrost.tundra.data.IDataHelper;

/**
 * Translates an input value to an output value using a translation table.
 */
public class Translator extends Transformer<String, Object> {
    /**
     * The translations used when translating values.
     */
    private final IData translations;
    /**
     * The default value used when translating a value with no translation, and the value used when translating a null
     * value.
     */
    private final Object defaultValue, nullValue;

    /**
     * Creates a new Translator object.
     *
     * @param translations  The translation table used to translate values.
     * @param reverse       If true, the translation table is flipped so keys become values and vice versa.
     */
    public Translator(IData translations, boolean reverse) {
        super(String.class, Object.class, TransformerMode.VALUES, true, true, true, true);
        if (translations == null) {
            this.translations = IDataFactory.create();
        } else if (reverse) {
            this.translations = IDataHelper.flip(translations);
        } else {
            this.translations = translations;
        }

        defaultValue = IDataHelper.get(translations, "$default");
        nullValue = IDataHelper.get(translations, "$null");
    }

    /**
     * Transforms the given value.
     *
     * @param key   The key associated with the value being transformed.
     * @param value The value to be transformed.
     * @return      The transformed value.
     */
    @Override
    protected Object transformValue(String key, String value) {
        IDataCursor cursor = translations.getCursor();
        try {
            Object defaultValue = this.defaultValue == null ? value : this.defaultValue;
            return IDataHelper.getOrDefault(cursor, value, Object.class, defaultValue);
        } finally {
            cursor.destroy();
        }
    }

    /**
     * Translates a null value.
     *
     * @param key   The key associated with the null value being transformed.
     * @return      The transformed null value.
     */
    @Override
    protected Object transformNull(String key) {
        return nullValue;
    }
}

@@ -2275,92 +2275,61 @@
     
-%7D else if (reverse) %7B%0A            this.translations = IDataHelper.flip(translations)
+    defaultValue = null;%0A            nullValue = null
 ;%0A  
@@ -2347,37 +2347,32 @@
 e %7B%0A            
-this.
 translations = t
@@ -2374,33 +2374,55 @@
 s = 
-translations;%0A        %7D%0A%0A
+IDataHelper.duplicate(translations, true);%0A    
     
@@ -2444,35 +2444,38 @@
 e = IDataHelper.
-get
+remove
 (translations, %22
@@ -2486,32 +2486,36 @@
 ault%22);%0A        
+    
 nullValue = IDat
@@ -2522,19 +2522,22 @@
 aHelper.
-get
+remove
 (transla
@@ -2552,16 +2552,207 @@
 $null%22);
+%0A%0A            if (reverse) %7B%0A                this.translations = IDataHelper.flip(translations);%0A            %7D else %7B%0A                this.translations = translations;%0A            %7D%0A        %7D
 %0A    %7D%0A%0A

Fix Translator $default and $null support to work when reverse is true