001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
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 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.common.utils;
020
021import java.util.HashMap;
022import java.util.Map;
023
024/**
025 * Yet Another variable resolver.
026 *
027 * @see TextTemplate
028 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
029 */
030public class Vars {
031
032    public static interface Resolver {
033        String get(String key);
034    }
035
036    public static Map<String, String> expand(final Map<String, String> vars) {
037        return expand(vars, null);
038    }
039
040    public static Map<String, String> expand(final Map<String, String> vars, final Resolver resolver) {
041        final Map<String, String> result = new HashMap<String, String>(vars.size());
042        Resolver resolver2 = new Resolver() {
043            @Override
044            public String get(String key) {
045                String v = result.get(key);
046                if (v == null) {
047                    v = vars.get(key);
048                    if (v == null && resolver != null) {
049                        return resolver.get(key);
050                    }
051                }
052                return v;
053            }
054        };
055        for (Map.Entry<?, ?> entry : vars.entrySet()) {
056            String key = (String) entry.getKey();
057            String v = (String) entry.getValue();
058            if (v == null) {
059                result.put(key, null);
060            } else {
061                String rv = expand(v, resolver2);
062                while (!rv.equals(v)) {
063                    v = rv;
064                    rv = expand(v, resolver2);
065                }
066                result.put(key, rv);
067            }
068        }
069        return result;
070    }
071
072    public static String expand(String expression, final Map<?, ?> vars) {
073        int s = expression.indexOf("${", 0);
074        if (s == -1) {
075            return expression;
076        }
077        int e = expression.indexOf('}', s + 2);
078        if (e == -1) {
079            return expression;
080        }
081        return expand(expression, 0, s, e, new Resolver() {
082            @Override
083            public String get(String key) {
084                Object v = vars.get(key);
085                return v != null ? v.toString() : null;
086            }
087        });
088    }
089
090    public static String expand(String expression, Resolver resolver) {
091        int s = expression.indexOf("${", 0);
092        if (s == -1) {
093            return expression;
094        }
095        int e = expression.indexOf('}', s + 2);
096        if (e == -1) {
097            return expression;
098        }
099        return expand(expression, 0, s, e, resolver);
100    }
101
102    private static String expand(String expression, int offset, int s, int e, Resolver resolver) {
103        StringBuilder buf = new StringBuilder();
104
105        do {
106            if (s > offset) {
107                buf.append(expression.substring(offset, s));
108            }
109            String v = resolveVar(expression.substring(s + 2, e), resolver);
110            if (v == null) {
111                buf.append(expression.substring(s, e + 1));
112            } else {
113                buf.append(v);
114            }
115            offset = e + 1;
116            s = expression.indexOf("${", offset);
117            if (s == -1) {
118                break;
119            }
120            e = expression.indexOf('}', s + 2);
121            if (e == -1) {
122                break;
123            }
124        } while (true);
125
126        if (offset < expression.length()) {
127            buf.append(expression.substring(offset));
128        }
129
130        return buf.toString();
131    }
132
133    private final static String resolveVar(String var, Resolver resolver) {
134        String key = var;
135        int i = var.indexOf('?');
136        if (i > -1) {
137            key = key.substring(0, i);
138            Object v = resolver.get(key);
139            if (v != null) {
140                return v.toString();
141            } else {
142                return var.substring(i + 1);
143            }
144        }
145        Object v = resolver.get(key);
146        return v != null ? v.toString() : null;
147    }
148
149}