/*
 * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

// -- This file was mechanically generated: Do not edit! -- //

package sun.nio.cs;

import java.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class StandardCharsets extends CharsetProvider {

    _INCLUDE_ALIASES_TABLES_
    _INCLUDE_ALIASES_MAP_
    _INCLUDE_CLASSES_MAP_
    _INCLUDE_CACHE_MAP_

    // Maps canonical names to class names
    private Map<String,String> classMap;
    // Maps alias names to canonical names
    private Map<String,String> aliasMap;
    // Maps canonical names to cached instances
    private Map<String,Charset> cache;

    private String packagePrefix = "sun.nio.cs";

    public StandardCharsets() {
        this.aliasMap = new Aliases();
        this.classMap = new Classes();
        this.cache = new Cache();
    }

    private String canonicalize(String csn) {
        String acn = aliasMap.get(csn);
        return (acn != null) ? acn : csn;
    }

    // Private ASCII-only version, optimized for interpretation during startup
    //
    private static String toLower(String s) {
        int n = s.length();
        boolean allLower = true;
        for (int i = 0; i < n; i++) {
            int c = s.charAt(i);
            if (((c - 'A') | ('Z' - c)) >= 0) {
                allLower = false;
                break;
            }
        }
        if (allLower)
            return s;
        char[] ca = new char[n];
        for (int i = 0; i < n; i++) {
            int c = s.charAt(i);
            if (((c - 'A') | ('Z' - c)) >= 0)
                ca[i] = (char)(c + 0x20);
            else
                ca[i] = (char)c;
        }
        return new String(ca);
    }

    private Charset lookup(String charsetName) {
        init();
        String csn = canonicalize(toLower(charsetName));

        // Check cache first
        Charset cs = cache.get(csn);
        if (cs != null)
            return cs;

        // Do we even support this charset?
        String cln = classMap.get(csn);
        if (cln == null)
            return null;

        if (cln.equals("US_ASCII")) {
            cs = new US_ASCII();
            cache.put(csn, cs);
            return cs;
        }

        // Instantiate the charset and cache it
        try {
            Class<?> c = Class.forName(packagePrefix + "." + cln,
                                    true,
                                    this.getClass().getClassLoader());
            cs = (Charset)c.newInstance();
            cache.put(csn, cs);
            return cs;
        } catch (ClassNotFoundException |
                 IllegalAccessException |
                 InstantiationException x) {
            return null;
        }
    }

    public final Charset charsetForName(String charsetName) {
        synchronized (this) {
            return lookup(canonicalize(charsetName));
        }
    }

    public final Iterator<Charset> charsets() {
        synchronized (this) {
            init();
        }
        return new Iterator<Charset>() {

                Iterator<String> i = classMap.keySet().iterator();

                public boolean hasNext() {
                    return i.hasNext();
                }

                public Charset next() {
                    String csn = i.next();
                    return lookup(csn);
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }

            };
    }

    private boolean initialized = false;

    /*   provider the sun.nio.cs.map property fir sjis/ms932 mapping hack
     */
    private void init() {
        if (initialized)
            return;
        if (!jdk.internal.misc.VM.isBooted())
            return;
        initialized = true;

        String map = getProperty("sun.nio.cs.map");
        if (map != null) {
            String[] maps = map.split(",");
            for (int i = 0; i < maps.length; i++) {
                if (maps[i].equalsIgnoreCase("Windows-31J/Shift_JIS")) {
                    // if we dont have both sjis and ms932, do nothing
                    if (classMap.get("shift_jis") == null ||
                        classMap.get("windows-31j") == null) {
                        break;
                    }
                    aliases_MS932 = new String[] {
                        "MS932",        // JDK historical
                        "windows-932",
                        "csWindows31J",
                        "shift-jis",
                        "ms_kanji",
                        "x-sjis",
                        "csShiftJIS",
                        // This alias takes precedence over the actual
                        // Shift_JIS charset itself since aliases are always
                        // resolved first, before looking up canonical names.
                        "shift_jis"
                    };
                    aliases_SJIS = new String[] { "sjis" };

                    for (String alias : aliases_MS932) {
                        aliasMap.put(toLower(alias), "windows-31j");
                    }
                    cache.put("shift_jis", null);
                    break;
                }
            }
        }
    }

    private static String getProperty(String key) {
        // this method may be called during initialization of
        // system class loader and thus not using lambda
        return AccessController.doPrivileged(
            new PrivilegedAction<String>() {
                @Override
                public String run() {
                    return System.getProperty(key);
                }
            });
    }


}
