001/*
002 * Copyright 2012-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.ansi;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.EnumSet;
022import java.util.List;
023import java.util.Set;
024
025import org.springframework.core.env.PropertyResolver;
026import org.springframework.core.env.PropertySource;
027import org.springframework.util.StringUtils;
028
029/**
030 * {@link PropertyResolver} for {@link AnsiStyle}, {@link AnsiColor} and
031 * {@link AnsiBackground} elements. Supports properties of the form
032 * {@code AnsiStyle.BOLD}, {@code AnsiColor.RED} or {@code AnsiBackground.GREEN}. Also
033 * supports a prefix of {@code Ansi.} which is an aggregation of everything (with
034 * background colors prefixed {@code BG_}).
035 *
036 * @author Phillip Webb
037 * @since 1.3.0
038 */
039public class AnsiPropertySource extends PropertySource<AnsiElement> {
040
041        private static final Iterable<MappedEnum<?>> MAPPED_ENUMS;
042
043        static {
044                List<MappedEnum<?>> enums = new ArrayList<>();
045                enums.add(new MappedEnum<>("AnsiStyle.", AnsiStyle.class));
046                enums.add(new MappedEnum<>("AnsiColor.", AnsiColor.class));
047                enums.add(new MappedEnum<>("AnsiBackground.", AnsiBackground.class));
048                enums.add(new MappedEnum<>("Ansi.", AnsiStyle.class));
049                enums.add(new MappedEnum<>("Ansi.", AnsiColor.class));
050                enums.add(new MappedEnum<>("Ansi.BG_", AnsiBackground.class));
051                MAPPED_ENUMS = Collections.unmodifiableList(enums);
052        }
053
054        private final boolean encode;
055
056        /**
057         * Create a new {@link AnsiPropertySource} instance.
058         * @param name the name of the property source
059         * @param encode if the output should be encoded
060         */
061        public AnsiPropertySource(String name, boolean encode) {
062                super(name);
063                this.encode = encode;
064        }
065
066        @Override
067        public Object getProperty(String name) {
068                if (StringUtils.hasLength(name)) {
069                        for (MappedEnum<?> mappedEnum : MAPPED_ENUMS) {
070                                if (name.startsWith(mappedEnum.getPrefix())) {
071                                        String enumName = name.substring(mappedEnum.getPrefix().length());
072                                        for (Enum<?> ansiEnum : mappedEnum.getEnums()) {
073                                                if (ansiEnum.name().equals(enumName)) {
074                                                        if (this.encode) {
075                                                                return AnsiOutput.encode((AnsiElement) ansiEnum);
076                                                        }
077                                                        return ansiEnum;
078                                                }
079                                        }
080                                }
081                        }
082                }
083                return null;
084        }
085
086        /**
087         * Mapping between an enum and the pseudo property source.
088         */
089        private static class MappedEnum<E extends Enum<E>> {
090
091                private final String prefix;
092
093                private final Set<E> enums;
094
095                MappedEnum(String prefix, Class<E> enumType) {
096                        this.prefix = prefix;
097                        this.enums = EnumSet.allOf(enumType);
098
099                }
100
101                public String getPrefix() {
102                        return this.prefix;
103                }
104
105                public Set<E> getEnums() {
106                        return this.enums;
107                }
108
109        }
110
111}