com.threecrickets.jygments.style.Style.java Source code

Java tutorial

Introduction

Here is the source code for com.threecrickets.jygments.style.Style.java

Source

/**
 * Copyright 2010-2016 Three Crickets LLC.
 * <p>
 * The contents of this file are subject to the terms of a BSD license. See
 * attached license.txt.
 * <p>
 * Alternatively, you can obtain a royalty free commercial license with less
 * limitations, transferable or non-transferable, directly from Three Crickets
 * at http://threecrickets.com/
 */

package com.threecrickets.jygments.style;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.threecrickets.jygments.Jygments;
import com.threecrickets.jygments.NestedDef;
import com.threecrickets.jygments.ResolutionException;
import com.threecrickets.jygments.grammar.TokenType;
import com.threecrickets.jygments.style.def.StyleElementDef;

/**
 * @author Tal Liron
 */
public class Style extends NestedDef<Style> {
    //
    // Static operations
    //

    public static Style getByName(String name) throws ResolutionException {
        if (Character.isLowerCase(name.charAt(0)))
            name = Character.toUpperCase(name.charAt(0)) + name.substring(1) + "Style";

        Style style = getByFullName(name);
        if (style != null)
            return style;
        else {
            // Try contrib package
            String pack = Jygments.class.getPackage().getName() + ".contrib";
            name = pack + "." + name;
            style = getByFullName(name);
            if (style == null)
                throw new ResolutionException("Could not load style: " + name);
            return style;
        }
    }

    @SuppressWarnings("unchecked")
    public static Style getByFullName(String fullName) throws ResolutionException {
        // Try cache
        Style style = styles.get(fullName);
        if (style != null)
            return style;

        try {
            return (Style) Jygments.class.getClassLoader().loadClass(fullName).newInstance();
        } catch (InstantiationException x) {
        } catch (IllegalAccessException x) {
        } catch (ClassNotFoundException x) {
        }

        InputStream stream = Jygments.class.getClassLoader()
                .getResourceAsStream(fullName.replace('.', '/') + ".json");
        if (stream != null) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.getFactory().configure(JsonParser.Feature.ALLOW_COMMENTS, true);
            try {
                Map<String, Object> json = objectMapper.readValue(stream, HashMap.class);
                style = new Style();
                style.addJson(json);
                style.resolve();

                // Cache it
                Style existing = styles.putIfAbsent(fullName, style);
                if (existing != null)
                    style = existing;

                return style;
            } catch (JsonParseException x) {
                throw new ResolutionException(x);
            } catch (JsonMappingException x) {
                throw new ResolutionException(x);
            } catch (IOException x) {
                throw new ResolutionException(x);
            }
        }

        return null;
    }

    //
    // Attributes
    //

    public Map<TokenType, List<StyleElement>> getStyleElements() {
        return styleElements;
    }

    //
    // Operations
    //

    public void addStyleElement(TokenType tokenType, StyleElement styleElement) {
        List<StyleElement> styleElementsForTokenType = styleElements.get(tokenType);
        if (styleElementsForTokenType == null) {
            styleElementsForTokenType = new ArrayList<StyleElement>();
            styleElements.put(tokenType, styleElementsForTokenType);
        }
        styleElementsForTokenType.add(styleElement);
    }

    public void resolve() throws ResolutionException {
        resolve(this);
    }

    //
    // Def
    //

    @Override
    public boolean resolve(Style style) throws ResolutionException {
        if (super.resolve(style)) {
            boolean done = false;
            while (!done) {
                done = true;
                for (TokenType tokenType : TokenType.getTokenTypes()) {
                    if (tokenType != TokenType.Token) {
                        if (!styleElements.containsKey(tokenType)) {
                            boolean doneOne = false;
                            TokenType parent = tokenType.getParent();
                            while (parent != null) {
                                if (parent == TokenType.Token) {
                                    doneOne = true;
                                    break;
                                }

                                List<StyleElement> parentElements = styleElements.get(parent);
                                if (parentElements != null) {
                                    styleElements.put(tokenType, parentElements);
                                    doneOne = true;
                                    break;
                                }

                                parent = parent.getParent();
                            }

                            if (!doneOne)
                                done = false;
                        }
                    }
                }
            }

            return true;
        } else
            return false;
    }

    // //////////////////////////////////////////////////////////////////////////
    // Protected

    protected void add(String tokenTypeName, String... styleElementNames) {
        ArrayList<String> list = new ArrayList<String>(styleElementNames.length);
        for (String styleElementName : styleElementNames)
            list.add(styleElementName);
        addDef(new StyleElementDef(tokenTypeName, list));
    }

    @SuppressWarnings("unchecked")
    protected void addJson(Map<String, Object> json) throws ResolutionException {
        for (Map.Entry<String, Object> entry : json.entrySet()) {
            String tokenTypeName = entry.getKey();
            if (entry.getValue() instanceof Iterable<?>) {
                for (String styleElementName : (Iterable<String>) entry.getValue())
                    add(tokenTypeName, styleElementName);
            } else if (entry.getValue() instanceof String)
                add(tokenTypeName, (String) entry.getValue());
            else
                throw new ResolutionException("Unexpected value in style definition: " + entry.getValue());
        }
    }

    // //////////////////////////////////////////////////////////////////////////
    // Private

    private static final ConcurrentMap<String, Style> styles = new ConcurrentHashMap<String, Style>();

    private final Map<TokenType, List<StyleElement>> styleElements = new HashMap<TokenType, List<StyleElement>>();
}