All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jmms.testing.fake.FakeExpr Maven / Gradle / Ivy

/*
 * Copyright 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package jmms.testing.fake;

import leap.lang.Randoms;
import leap.lang.Strings;
import leap.lang.json.JSON;
import leap.lang.reflect.Reflection;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class FakeExpr {

    public static boolean isExpr(String s) {
        return null != s && s.length() > 0 && s.indexOf("{{") >= 0 && s.indexOf("}}") >= 0;
    }

    private final DefaultFaker faker;
    private final List   nodes = new ArrayList<>();

    public FakeExpr(DefaultFaker faker) {
        this.faker = faker;
    }

    FakeExpr parse(String s) {
        try {
            int end = s.length() - 1;

            StringBuilder t = new StringBuilder();

            boolean lastNode = false;

            for (int pos = 0; pos < s.length(); pos++) {
                char c = s.charAt(pos);

                if (c == '{' && pos < end && s.charAt(pos + 1) == '{') {
                    int close = s.indexOf("}}", pos + 1);
                    if (close > 0) {
                        if (t.length() > 0) {
                            nodes.add(new Text(t.toString()));
                            t.delete(0, t.length());
                        }

                        String expr = s.substring(pos + 2, close);
                        parseExpr(expr);
                        pos = close + 1;
                        lastNode = true;
                        continue;
                    }
                } else if (c == '[' && pos < end && s.charAt(pos + 1) == '[') {
                    int close = s.indexOf("]]", pos + 1);
                    if (close > 0) {
                        if (t.length() > 0) {
                            nodes.add(new Text(t.toString()));
                            t.delete(0, t.length());
                        }

                        String expr = s.substring(pos + 2, close);
                        nodes.add(new Group(new FakeExpr(faker).parse(expr)));
                        pos = close + 1;
                        lastNode = true;
                        continue;
                    }
                }

                if (lastNode && t.length() == 0) {
                    if (c == '(' && pos < end && s.charAt(pos + 1) == '{') {
                        int close = s.indexOf("})", pos + 1);
                        if (close > 0) {
                            String expr = s.substring(pos + 1, close + 1);
                            nodes.get(nodes.size() - 1).withOptions(JSON.decode(expr, FakeOptions.class));
                            pos = close + 1;
                            lastNode = false;
                            continue;
                        }
                    }
                }

                lastNode = false;
                t.append(c);
            }

            if (t.length() > 0) {
                nodes.add(new Text(t.toString()));
            }
        }catch (RuntimeException e) {
            throw new IllegalStateException("<- " + s + " -> , " + e.getMessage(), e);
        }

        return this;
    }

    void eval(Object sample, StringBuilder s) {
        for(Node node : nodes) {
            node.eval(sample, s);
        }
    }

    private void parseExpr(String expr) {
        //regex
        if(expr.startsWith("^") && expr.endsWith("$")) {
            nodes.add(new Regex(expr));
            return;
        }

        //sample
        if(expr.equalsIgnoreCase("sample")) {
            nodes.add(new Sample());
            return;
        }

        //samples
        if(expr.startsWith("[") && expr.endsWith("]")) {
            List list = JSON.decode(expr);
            nodes.add(new Samples(list));
            return;
        }

        //chars
        if(expr.indexOf('#') >= 0 || expr.indexOf('?') >= 0 || expr.indexOf('*') >= 0) {
            parseChars(expr);
            return;
        }

        //fake
        String key = expr;
        String locale = null;
        FakeOptions opts = null;

        String[] parts = Strings.split(expr, "::");
        if(parts.length == 2) {
            key = parts[0];
            locale = parts[1];
        }
        int left = key.indexOf('(');
        if(left > 0) {
            String json = key.substring(left+1,key.length()-1).trim();
            key = key.substring(0, left);

            if(Strings.isDigits(json)) {
                FakeMethods.FakeMethod fm = faker.methods.get(key);
                Class type = FakeOptions.class;
                if(null != fm) {
                    type = fm.getOptionsType();
                }
                opts = (FakeOptions)Reflection.newInstance(type);
                opts.setLen(Integer.parseInt(json));
            }else {
                String[] nums = Strings.split(json, ',');
                if(nums.length == 2 && Strings.isDigits(nums[0]) && Strings.isDigits(nums[1])) {
                    FakeMethods.FakeMethod fm = faker.methods.get(key);
                    Class type = FakeOptions.class;
                    if(null != fm) {
                        type = fm.getOptionsType();
                    }
                    opts = (FakeOptions)Reflection.newInstance(type);
                    opts.setMinLen(Integer.parseInt(nums[0]));
                    opts.setMaxLen(Integer.parseInt(nums[1]));
                }else {
                    if(!json.startsWith("{")) {
                        json = "{" + json + "}";
                    }
                    FakeMethods.FakeMethod fm = faker.methods.get(key);
                    Class type = FakeOptions.class;
                    if(null != fm) {
                        type = fm.getOptionsType();
                    }
                    opts = (FakeOptions)JSON.decode(json, type);
                }
            }
        }
        if(null != opts) {
            opts.setLocale(locale);
        }
        nodes.add(new Fake(key, locale, opts));
    }

    private void parseChars(String chars) {
        for(int i=0;i 0) {
                        s.append(join);
                    }
                    expr.eval(sample, s);
                }
            }
        }
    }

    private static class Text extends Node {
        private final String str;

        public Text(String str) {
            this.str = str;
        }

        @Override
        void eval(Object sample, StringBuilder s) {
            s.append(str);
        }
    }

    private static class Sample extends Node {
        @Override
        void eval(Object sample, StringBuilder s) {
            if(null != sample) {
                s.append(sample.toString());
            }
        }
    }

    private static class Samples extends Node {
        private final List   list;
        private final Random random = new Random();

        public Samples(List list) {
            this.list = list;
        }

        @Override
        void eval(Object sample, StringBuilder s) {
            if(list.isEmpty()) {
                return;
            }

            Object item = list.get(random.nextInt(list.size()));
            if(null != item) {
                s.append(item.toString());
            }
        }
    }

    private class Fake extends Node {
        private final String      key;
        private final String      locale;
        private final FakeOptions opts;

        public Fake(String key, String locale, FakeOptions opts) {
            this.key = key;
            this.locale = locale;
            this.opts = null == opts ? FakeOptions.locale(locale) : opts;
        }

        @Override
        void eval(Object sample, StringBuilder s) {
            Object v = faker.tryFake(key, opts);
            if(null != v) {
                s.append(v.toString());
            }else {
                s.append("{{").append(key);
                if(null != locale) {
                    s.append("::").append(locale);
                }
                s.append("}}");
            }
        }
    }

    private static class FixedChar extends Node {
        private final char c;

        public FixedChar(char c) {
            this.c = c;
        }

        @Override
        void eval(Object sample, StringBuilder s) {
            s.append(c);
        }
    }

    private static abstract class Chars extends Node {
        protected int minLen = 1;
        protected int maxLen = 1;

        @Override
        void eval(Object sample, StringBuilder s) {
            int len = minLen == maxLen ? minLen : Randoms.nextInt(minLen, maxLen);

            for(int i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy