private Map fetchMapInner()

in freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/CJSONInterpreter.java [596:769]


    private Map<String, Object> fetchMapInner(
            Map<String, Object> map, char terminator, boolean forceStringValues)
            throws EvaluationException {
        int p2;
        
        int mapP = p - 1;
        skipWS();
        if (terminator == 0x20) {
            mapP = p;
        }
        
        // Key lookup
        while (true) {
            char c;
            
            if (p < ln) {
                c = tx.charAt(p);
                if (c == terminator) {
                    return map;
                }
                if (c == ',') {
                    throw newSyntaxError(
                            "Key-value pair is missing before the comma.");
                }
            } else {
                if (terminator == 0x20) {
                    return map;
                } else {
                    throw newSyntaxError("Reached the end of the text, "
                            + "but the map was not closed with "
                            + TextUtil.jQuoteOrName(terminator) + ".",
                            mapP);
                }
            }
            
            int keyP = p;
            Object o1 = fetchExpression(false, true);
            FunctionCall keyFunc;
            if (o1 instanceof FunctionCall) {
                keyFunc = (FunctionCall) o1;
                try {
                    o1 = ee.evalFunctionCall(keyFunc, this);
                } catch (Throwable e) {
                    throw newError("Failed to evaluate function "
                            + TextUtil.jQuote(keyFunc.getName()) + ".",
                            keyP, e);
                }
            } else {
                keyFunc = null;
            }
            
            c = skipSeparator(terminator, null, null);
            if (c == ':') {
                if (!(o1 instanceof String)) {
                    if (keyFunc != o1) {
                        throw newError(
                                "The key must be a String, but it is a(n) "
                                + cjsonTypeNameOfValue(o1) + ".", keyP);
                    } else {
                        throw newError(
                                "You can't use the function here, "
                                + "because it can't be evaluated "
                                + "in this context.",
                                keyP);
                    }
                }
                
                if (p == ln) {
                    throw newSyntaxError(
                            "The key must be followed by a value because "
                            + "colon was used.", keyP);
                }
                
                Object o2;
                boolean done = false;
                try {
                    Object nr;
                    try {
                        nr = ee.notify(
                                EvaluationEvent.ENTER_MAP_KEY,
                                this, (String) o1, null);
                        done = true;
                    } catch (Throwable e) {
                        throw newWrappedError(e, keyP);
                    }
                    if (nr == null) {
                        o2 = fetchExpression(forceStringValues, false);
                        map.put((String) o1, o2);
                    } else {
                        p2 = p;
                        skipExpression();
                        if (nr == EvaluationEnvironment.RETURN_FRAGMENT) {
                            map.put((String) o1,
                                    new Fragment(tx, p2, p, fileName));
                        }
                    }
                } finally {
                    if (done) {
                        try {
                            ee.notify(
                                    EvaluationEvent.LEAVE_MAP_KEY,
                                    this, (String) o1, null);
                        } catch (Throwable e) {
                            throw newWrappedError(e);
                        }
                    }
                }
                
                c = skipSeparator(terminator, null,
                        "Colon is for separating the key from the value, "
                        + "and the value was alredy given previously.");
            } else if (c == ',' || c == terminator || c == 0x20) {
                if (keyFunc == null) {
                    if (o1 instanceof String) {
                        boolean done = false;
                        try {
                            Object nr;
                            try {
                                nr = ee.notify(
                                        EvaluationEvent.ENTER_MAP_KEY,
                                        this, (String) o1, null);
                                done = true;
                            } catch (Throwable e) {
                                throw newWrappedError(e, keyP);
                            }
                            if (nr == null
                                    || nr == EvaluationEnvironment
                                            .RETURN_FRAGMENT) {
                                map.put((String) o1, Boolean.TRUE);
                            }
                        } finally {
                            if (done) {
                                try {
                                    ee.notify(
                                            EvaluationEvent.LEAVE_MAP_KEY,
                                            this, (String) o1, null);
                                } catch (Throwable e) {
                                    throw newWrappedError(e);
                                }
                            }
                        }
                    } else if (o1 instanceof Map) {
                        map.putAll((Map<String, Object>) o1);
                    } else {
                        throw newError(
                                "This expression should be either a string "
                                + "or a map, but it is a(n) "
                                + cjsonTypeNameOfValue(o1) + ".", keyP);
                    }
                } else {
                    if (o1 instanceof Map) {
                        map.putAll((Map<String, Object>) o1);
                    } else {
                        if (keyFunc == o1) {
                            throw newError(
                                    "You can't use the function here, "
                                    + "because it can't be evaluated "
                                    + "in this context.",
                                    keyP);
                        } else {
                            throw newError(
                                    "Function doesn't evalute to a map, but "
                                    + "to " + cjsonTypeNameOfValue(o1)
                                    + ", so it can't be merged into the map.",
                                    keyP);
                        }
                    }
                }
            }
            if (c == terminator) {
                return map;
            }
        }
    }