Search in sources :

Example 1 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class JsonSerializer method parseMapKey.

private Object parseMapKey(String key, PDescriptor keyType) throws SerializerException {
    try {
        switch(keyType.getType()) {
            case BOOL:
                if (key.equalsIgnoreCase("true")) {
                    return Boolean.TRUE;
                } else if (key.equalsIgnoreCase("false")) {
                    return Boolean.FALSE;
                }
                throw new SerializerException("Invalid boolean value: \"" + Strings.escape(key) + "\"");
            case BYTE:
                return Byte.parseByte(key);
            case I16:
                return Short.parseShort(key);
            case I32:
                return Integer.parseInt(key);
            case I64:
                return Long.parseLong(key);
            case DOUBLE:
                try {
                    JsonTokenizer tokenizer = new JsonTokenizer(new ByteArrayInputStream(key.getBytes(StandardCharsets.US_ASCII)));
                    JsonToken token = tokenizer.next();
                    if (!token.isNumber()) {
                        throw new SerializerException("Unable to parse double from key \"" + key + "\"");
                    } else if (tokenizer.hasNext()) {
                        throw new SerializerException("Garbage after double: \"" + key + "\"");
                    }
                    return token.doubleValue();
                } catch (SerializerException e) {
                    throw e;
                } catch (JsonException | IOException e) {
                    throw new SerializerException(e, "Unable to parse double from key \"" + key + "\"");
                }
            case STRING:
                return key;
            case BINARY:
                try {
                    return Binary.fromBase64(key);
                } catch (IllegalArgumentException e) {
                    throw new SerializerException(e, "Unable to parse Base64 data");
                }
            case ENUM:
                PEnumBuilder<?> eb = ((PEnumDescriptor<?>) keyType).builder();
                if (Strings.isInteger(key)) {
                    eb.setById(Integer.parseInt(key));
                } else {
                    eb.setByName(key);
                }
                if (readStrict && !eb.valid()) {
                    throw new SerializerException("\"%s\" is not a known enum value for %s", Strings.escape(key), keyType.getQualifiedName());
                }
                return eb.build();
            case MESSAGE:
                PMessageDescriptor<?, ?> st = (PMessageDescriptor<?, ?>) keyType;
                if (!st.isSimple()) {
                    throw new SerializerException("Only simple structs can be used as map key. %s is not.", st.getQualifiedName());
                }
                ByteArrayInputStream input = new ByteArrayInputStream(key.getBytes(StandardCharsets.UTF_8));
                try {
                    JsonTokenizer tokenizer = new JsonTokenizer(input);
                    if (JsonToken.kMapStart == tokenizer.expectSymbol("message start", JsonToken.kMapStart, JsonToken.kListStart)) {
                        return parseMessage(tokenizer, st);
                    } else {
                        return parseCompactMessage(tokenizer, st);
                    }
                } catch (JsonException | IOException e) {
                    throw new SerializerException(e, "Error parsing message key: " + e.getMessage());
                }
            default:
                throw new SerializerException("Illegal key type: %s", keyType.getType());
        }
    } catch (NumberFormatException nfe) {
        throw new SerializerException(nfe, "Unable to parse numeric value %s", key);
    }
}
Also used : JsonException(net.morimekta.util.json.JsonException) IOException(java.io.IOException) PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor) ByteArrayInputStream(java.io.ByteArrayInputStream) JsonToken(net.morimekta.util.json.JsonToken) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) JsonTokenizer(net.morimekta.util.json.JsonTokenizer)

Example 2 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProgramConverter method convert.

/**
 * Convert document model to declared document.
 *
 * @param path The program file path.
 * @param path Path of the program file to convert.
 * @param program Program model to convert.
 * @return The declared thrift document.
 */
public CProgram convert(String path, ProgramType program) {
    ImmutableList.Builder<PDeclaredDescriptor<?>> declaredTypes = ImmutableList.builder();
    ImmutableList.Builder<CConst> constants = ImmutableList.builder();
    ImmutableMap.Builder<String, String> typedefs = ImmutableMap.builder();
    ImmutableList.Builder<CService> services = ImmutableList.builder();
    RecursiveTypeRegistry registry = programRegistry.registryForPath(path);
    File dir = new File(path).getParentFile();
    if (program.hasIncludes()) {
        for (String include : program.getIncludes()) {
            String includePath = new File(dir, include).getPath();
            registry.registerInclude(ReflectionUtils.programNameFromPath(include), programRegistry.registryForPath(includePath));
        }
    }
    for (Declaration decl : program.getDecl()) {
        switch(decl.unionField()) {
            case DECL_ENUM:
                {
                    EnumType enumType = decl.getDeclEnum();
                    int nextValue = PEnumDescriptor.DEFAULT_FIRST_VALUE;
                    CEnumDescriptor type = new CEnumDescriptor(enumType.getDocumentation(), program.getProgramName(), enumType.getName(), enumType.getAnnotations());
                    List<CEnumValue> values = new ArrayList<>();
                    for (EnumValue value : enumType.getValues()) {
                        int v = value.hasId() ? value.getId() : nextValue;
                        nextValue = v + 1;
                        values.add(new CEnumValue(value.getDocumentation(), value.getId(), value.getName(), type, value.getAnnotations()));
                    }
                    type.setValues(values);
                    declaredTypes.add(type);
                    registry.register(type);
                    break;
                }
            case DECL_STRUCT:
                {
                    MessageType messageType = decl.getDeclStruct();
                    List<CField> fields = new ArrayList<>();
                    if (messageType.hasFields()) {
                        fields.addAll(messageType.getFields().stream().map(field -> makeField(registry, program.getProgramName(), field, messageType.getVariant())).collect(Collectors.toList()));
                    }
                    PMessageDescriptor<?, ?> type;
                    switch(messageType.getVariant()) {
                        case STRUCT:
                            type = new CStructDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        case UNION:
                            type = new CUnionDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        case EXCEPTION:
                            type = new CExceptionDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        default:
                            throw new UnsupportedOperationException("Unhandled message variant " + messageType.getVariant());
                    }
                    declaredTypes.add(type);
                    registry.register(type);
                    break;
                }
            case DECL_CONST:
                {
                    ConstType constant = decl.getDeclConst();
                    constants.add(makeConst(registry, program.getProgramName(), constant));
                    break;
                }
            case DECL_TYPEDEF:
                {
                    typedefs.put(decl.getDeclTypedef().getName(), decl.getDeclTypedef().getType());
                    registry.registerTypedef(decl.getDeclTypedef().getName(), program.getProgramName(), decl.getDeclTypedef().getType());
                    break;
                }
            case DECL_SERVICE:
                {
                    ServiceType serviceType = decl.getDeclService();
                    ImmutableList.Builder<CServiceMethod> methodBuilder = ImmutableList.builder();
                    if (serviceType.hasMethods()) {
                        for (FunctionType sm : serviceType.getMethods()) {
                            List<CField> rqFields = new ArrayList<>();
                            if (sm.numParams() > 0) {
                                for (FieldType field : sm.getParams()) {
                                    rqFields.add(makeField(registry, program.getProgramName(), field, MessageVariant.STRUCT));
                                }
                            }
                            CStructDescriptor request = new CStructDescriptor(null, program.getProgramName(), serviceType.getName() + '.' + sm.getName() + ".request", rqFields, null);
                            CUnionDescriptor response = null;
                            if (!sm.isOneWay()) {
                                List<CField> rsFields = new ArrayList<>();
                                CField success;
                                if (sm.getReturnType() != null) {
                                    PDescriptorProvider type = registry.getProvider(sm.getReturnType(), program.getProgramName(), sm.getAnnotations());
                                    success = new CField(null, 0, PRequirement.OPTIONAL, "success", type, null, null);
                                } else {
                                    success = new CField(null, 0, PRequirement.OPTIONAL, "success", PPrimitive.VOID.provider(), null, null);
                                }
                                rsFields.add(success);
                                if (sm.numExceptions() > 0) {
                                    for (FieldType field : sm.getExceptions()) {
                                        rsFields.add(makeField(registry, program.getProgramName(), field, MessageVariant.UNION));
                                    }
                                }
                                response = new CUnionDescriptor(null, program.getProgramName(), serviceType.getName() + '.' + sm.getName() + ".response", rsFields, null);
                            }
                            CServiceMethod method = new CServiceMethod(sm.getDocumentation(), sm.getName(), sm.isOneWay(), request, response, sm.getAnnotations());
                            methodBuilder.add(method);
                        }
                    // for each method
                    }
                    // if has methods
                    PServiceProvider extendsProvider = null;
                    if (serviceType.hasExtend()) {
                        extendsProvider = registry.getServiceProvider(serviceType.getExtend(), program.getProgramName());
                    }
                    CService service = new CService(serviceType.getDocumentation(), program.getProgramName(), serviceType.getName(), extendsProvider, methodBuilder.build(), serviceType.getAnnotations());
                    services.add(service);
                    registry.registerRecursively(service);
                }
        }
    }
    return new CProgram(path, program.getDocumentation(), program.getProgramName(), program.getNamespaces(), getIncludedProgramNames(program), program.getIncludes(), typedefs.build(), declaredTypes.build(), services.build(), constants.build());
}
Also used : PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor) PPrimitive(net.morimekta.providence.descriptor.PPrimitive) PDeclaredDescriptor(net.morimekta.providence.descriptor.PDeclaredDescriptor) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) EnumValue(net.morimekta.providence.model.EnumValue) ReflectionUtils.programNameFromPath(net.morimekta.providence.reflect.util.ReflectionUtils.programNameFromPath) CExceptionDescriptor(net.morimekta.providence.reflect.contained.CExceptionDescriptor) TypeRegistry(net.morimekta.providence.util.TypeRegistry) EnumType(net.morimekta.providence.model.EnumType) CService(net.morimekta.providence.reflect.contained.CService) PServiceProvider(net.morimekta.providence.descriptor.PServiceProvider) CConst(net.morimekta.providence.reflect.contained.CConst) ImmutableMap(com.google.common.collect.ImmutableMap) CProgram(net.morimekta.providence.reflect.contained.CProgram) Declaration(net.morimekta.providence.model.Declaration) Set(java.util.Set) ConstType(net.morimekta.providence.model.ConstType) Collectors(java.util.stream.Collectors) File(java.io.File) PDescriptorProvider(net.morimekta.providence.descriptor.PDescriptorProvider) CUnionDescriptor(net.morimekta.providence.reflect.contained.CUnionDescriptor) MessageVariant(net.morimekta.providence.model.MessageVariant) List(java.util.List) MessageType(net.morimekta.providence.model.MessageType) CEnumDescriptor(net.morimekta.providence.reflect.contained.CEnumDescriptor) CField(net.morimekta.providence.reflect.contained.CField) FunctionType(net.morimekta.providence.model.FunctionType) CStructDescriptor(net.morimekta.providence.reflect.contained.CStructDescriptor) PRequirement(net.morimekta.providence.descriptor.PRequirement) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) ServiceType(net.morimekta.providence.model.ServiceType) FieldType(net.morimekta.providence.model.FieldType) ProgramType(net.morimekta.providence.model.ProgramType) CServiceMethod(net.morimekta.providence.reflect.contained.CServiceMethod) ImmutableList(com.google.common.collect.ImmutableList) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) EnumValue(net.morimekta.providence.model.EnumValue) CServiceMethod(net.morimekta.providence.reflect.contained.CServiceMethod) CUnionDescriptor(net.morimekta.providence.reflect.contained.CUnionDescriptor) EnumType(net.morimekta.providence.model.EnumType) ServiceType(net.morimekta.providence.model.ServiceType) CField(net.morimekta.providence.reflect.contained.CField) CConst(net.morimekta.providence.reflect.contained.CConst) CService(net.morimekta.providence.reflect.contained.CService) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Declaration(net.morimekta.providence.model.Declaration) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) CStructDescriptor(net.morimekta.providence.reflect.contained.CStructDescriptor) ConstType(net.morimekta.providence.model.ConstType) MessageType(net.morimekta.providence.model.MessageType) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) FunctionType(net.morimekta.providence.model.FunctionType) ImmutableMap(com.google.common.collect.ImmutableMap) FieldType(net.morimekta.providence.model.FieldType) PServiceProvider(net.morimekta.providence.descriptor.PServiceProvider) CProgram(net.morimekta.providence.reflect.contained.CProgram) PDeclaredDescriptor(net.morimekta.providence.descriptor.PDeclaredDescriptor) CEnumDescriptor(net.morimekta.providence.reflect.contained.CEnumDescriptor) File(java.io.File) PDescriptorProvider(net.morimekta.providence.descriptor.PDescriptorProvider) CExceptionDescriptor(net.morimekta.providence.reflect.contained.CExceptionDescriptor)

Example 3 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProvidenceConfigParser method parseConfigRecursively.

@SuppressWarnings("unchecked")
<M extends PMessage<M, F>, F extends PField> Pair<M, Set<String>> parseConfigRecursively(@Nonnull Path file, M parent, String[] stack) throws IOException {
    Tokenizer tokenizer;
    try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file.toFile()))) {
        // Non-enclosed content, meaning we should read the whole file immediately.
        tokenizer = new Tokenizer(new Utf8StreamReader(in), Tokenizer.DEFAULT_BUFFER_SIZE, true);
    }
    ProvidenceConfigContext context = new ProvidenceConfigContext();
    Set<String> includedFilePaths = new TreeSet<>();
    includedFilePaths.add(canonicalFileLocation(file).toString());
    Stage lastStage = Stage.INCLUDES;
    M result = null;
    Token token = tokenizer.peek();
    while (token != null) {
        tokenizer.next();
        if (lastStage == Stage.MESSAGE) {
            throw new TokenizerException(token, "Unexpected token '" + token.asString() + "', expected end of file.").setLine(tokenizer.getLine());
        } else if (INCLUDE.equals(token.asString())) {
            // if include && stage == INCLUDES --> INCLUDES
            if (lastStage != Stage.INCLUDES) {
                throw new TokenizerException(token, "Include added after defines or message. Only one def block allowed.").setLine(tokenizer.getLine());
            }
            token = tokenizer.expectLiteral("file to be included");
            String includedFilePath = token.decodeLiteral(strict);
            PMessage included;
            Path includedFile;
            try {
                includedFile = resolveFile(file, includedFilePath);
                Pair<PMessage, Set<String>> tmp = checkAndParseInternal(includedFile, null, stack);
                if (tmp != null) {
                    includedFilePaths.add(includedFile.toString());
                    includedFilePaths.addAll(tmp.second);
                    included = tmp.first;
                } else {
                    included = null;
                }
            } catch (FileNotFoundException e) {
                throw new TokenizerException(token, "Included file \"%s\" not found.", includedFilePath).setLine(tokenizer.getLine());
            }
            token = tokenizer.expectIdentifier("the token 'as'");
            if (!AS.equals(token.asString())) {
                throw new TokenizerException(token, "Expected token 'as' after included file \"%s\".", includedFilePath).setLine(tokenizer.getLine());
            }
            token = tokenizer.expectIdentifier("Include alias");
            String alias = token.asString();
            if (RESERVED_WORDS.contains(alias)) {
                throw new TokenizerException(token, "Alias \"%s\" is a reserved word.", alias).setLine(tokenizer.getLine());
            }
            if (context.containsReference(alias)) {
                throw new TokenizerException(token, "Alias \"%s\" is already used.", alias).setLine(tokenizer.getLine());
            }
            context.setInclude(alias, included);
        } else if (DEF.equals(token.asString())) {
            // if params && stage == DEF --> DEF
            lastStage = Stage.DEFINES;
            parseDefinitions(context, tokenizer);
        } else if (token.isQualifiedIdentifier()) {
            // if a.b (type identifier) --> MESSAGE
            lastStage = Stage.MESSAGE;
            PMessageDescriptor<M, F> descriptor;
            try {
                descriptor = (PMessageDescriptor) registry.getDeclaredType(token.asString());
            } catch (IllegalArgumentException e) {
                // even in non-strict mode.
                if (strict || stack.length == 1) {
                    throw new TokenizerException(token, "Unknown declared type: %s", token.asString()).setLine(tokenizer.getLine());
                }
                return null;
            }
            result = parseConfigMessage(tokenizer, context, descriptor.builder(), parent, file);
        } else {
            throw new TokenizerException(token, "Unexpected token '" + token.asString() + "'. Expected include, defines or message type").setLine(tokenizer.getLine());
        }
        token = tokenizer.peek();
    }
    if (result == null) {
        throw new TokenizerException("No message in config: " + file.getFileName().toString());
    }
    return Pair.create(result, includedFilePaths);
}
Also used : Path(java.nio.file.Path) ProvidenceConfigUtil.readCanonicalPath(net.morimekta.providence.config.impl.ProvidenceConfigUtil.readCanonicalPath) Utf8StreamReader(net.morimekta.util.io.Utf8StreamReader) FileNotFoundException(java.io.FileNotFoundException) Token(net.morimekta.providence.serializer.pretty.Token) TokenizerException(net.morimekta.providence.serializer.pretty.TokenizerException) FileInputStream(java.io.FileInputStream) BufferedInputStream(java.io.BufferedInputStream) TreeSet(java.util.TreeSet) PMessage(net.morimekta.providence.PMessage) Stage(net.morimekta.providence.config.impl.ProvidenceConfigUtil.Stage) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) Tokenizer(net.morimekta.providence.serializer.pretty.Tokenizer) Pair(net.morimekta.util.Pair)

Example 4 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProvidenceConfigParser method parseFieldValue.

@SuppressWarnings("unchecked")
Object parseFieldValue(Token next, Tokenizer tokenizer, ProvidenceConfigContext context, PDescriptor descriptor, boolean requireEnumValue) throws IOException {
    try {
        switch(descriptor.getType()) {
            case BOOL:
                if (TRUE.equals(next.asString())) {
                    return true;
                } else if (FALSE.equals(next.asString())) {
                    return false;
                } else if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                }
                break;
            case BYTE:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isInteger()) {
                    return (byte) next.parseInteger();
                }
                break;
            case I16:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isInteger()) {
                    return (short) next.parseInteger();
                }
                break;
            case I32:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isInteger()) {
                    return (int) next.parseInteger();
                }
                break;
            case I64:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isInteger()) {
                    return next.parseInteger();
                }
                break;
            case DOUBLE:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isInteger() || next.isReal()) {
                    return next.parseDouble();
                }
                break;
            case STRING:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isStringLiteral()) {
                    return next.decodeLiteral(strict);
                }
                break;
            case BINARY:
                if (Token.B64.equals(next.asString())) {
                    tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
                    return Binary.fromBase64(tokenizer.readBinary(Token.kParamsEnd));
                } else if (Token.HEX.equals(next.asString())) {
                    tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
                    return Binary.fromHexString(tokenizer.readBinary(Token.kParamsEnd));
                } else if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                }
                break;
            case ENUM:
                {
                    PEnumDescriptor ed = (PEnumDescriptor) descriptor;
                    PEnumValue value;
                    String name = next.asString();
                    if (next.isInteger()) {
                        value = ed.findById((int) next.parseInteger());
                    } else if (next.isIdentifier()) {
                        value = ed.findByName(name);
                        if (value == null && context.containsReference(name)) {
                            value = resolve(context, next, tokenizer, ed);
                        }
                    } else if (next.isReferenceIdentifier()) {
                        value = resolve(context, next, tokenizer, descriptor);
                    } else {
                        break;
                    }
                    if (value == null && (strict || requireEnumValue)) {
                        PEnumValue option = null;
                        if (next.isIdentifier()) {
                            for (PEnumValue o : ed.getValues()) {
                                if (o.getName().equalsIgnoreCase(name)) {
                                    option = o;
                                    break;
                                }
                            }
                        }
                        if (option != null) {
                            throw new TokenizerException(next, "No such enum value '%s' for %s, did you mean '%s'?", name, ed.getQualifiedName(), option.getName()).setLine(tokenizer.getLine());
                        }
                        throw new TokenizerException(next, "No such enum value '%s' for %s.", name, ed.getQualifiedName()).setLine(tokenizer.getLine());
                    }
                    return value;
                }
            case MESSAGE:
                if (next.isReferenceIdentifier()) {
                    return resolve(context, next, tokenizer, descriptor);
                } else if (next.isSymbol(Token.kMessageStart)) {
                    return parseMessage(tokenizer, context, ((PMessageDescriptor) descriptor).builder());
                }
                break;
            case MAP:
                {
                    if (next.isReferenceIdentifier()) {
                        Map resolved;
                        try {
                            // Make sure the reference is to a map.
                            resolved = resolve(context, next, tokenizer, descriptor);
                        } catch (ClassCastException e) {
                            throw new TokenizerException(next, "Reference %s is not a map field ", next.asString()).setLine(tokenizer.getLine());
                        }
                        return resolved;
                    } else if (next.isSymbol(Token.kMessageStart)) {
                        return parseMapValue(tokenizer, context, (PMap) descriptor, new LinkedHashMap());
                    }
                    break;
                }
            case SET:
                {
                    if (next.isReferenceIdentifier()) {
                        return resolve(context, next, tokenizer, descriptor);
                    } else if (next.isSymbol(Token.kListStart)) {
                        @SuppressWarnings("unchecked") PSet<Object> ct = (PSet) descriptor;
                        Set<Object> value = new LinkedHashSet<>();
                        next = tokenizer.expect("set value or end");
                        while (!next.isSymbol(Token.kListEnd)) {
                            Object item = parseFieldValue(next, tokenizer, context, ct.itemDescriptor(), strict);
                            if (item != null) {
                                value.add(item);
                            }
                            // sets require separator, and allows separator after last.
                            if (tokenizer.expectSymbol("set separator or end", Token.kLineSep1, Token.kListEnd) == Token.kListEnd) {
                                break;
                            }
                            next = tokenizer.expect("set value or end");
                        }
                        return ct.builder().addAll(value).build();
                    }
                    break;
                }
            case LIST:
                {
                    if (next.isReferenceIdentifier()) {
                        return resolve(context, next, tokenizer, descriptor);
                    } else if (next.isSymbol(Token.kListStart)) {
                        @SuppressWarnings("unchecked") PList<Object> ct = (PList) descriptor;
                        PList.Builder<Object> builder = ct.builder();
                        next = tokenizer.expect("list value or end");
                        while (!next.isSymbol(Token.kListEnd)) {
                            Object item = parseFieldValue(next, tokenizer, context, ct.itemDescriptor(), strict);
                            if (item != null) {
                                builder.add(item);
                            }
                            // lists require separator, and allows separator after last.
                            if (tokenizer.expectSymbol("list separator or end", Token.kLineSep1, Token.kListEnd) == Token.kListEnd) {
                                break;
                            }
                            next = tokenizer.expect("list value or end");
                        }
                        return builder.build();
                    }
                    break;
                }
            default:
                {
                    throw new TokenizerException(next, descriptor.getType() + " not supported!").setLine(tokenizer.getLine());
                }
        }
    } catch (ProvidenceConfigException e) {
        throw new TokenizerException(next, e.getMessage()).setLine(tokenizer.getLine());
    }
    throw new TokenizerException(next, "Unhandled value \"%s\" for type %s", next.asString(), descriptor.getType()).setLine(tokenizer.getLine());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PList(net.morimekta.providence.descriptor.PList) PEnumValue(net.morimekta.providence.PEnumValue) TokenizerException(net.morimekta.providence.serializer.pretty.TokenizerException) PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor) ProvidenceConfigException(net.morimekta.providence.config.ProvidenceConfigException) LinkedHashMap(java.util.LinkedHashMap) PSet(net.morimekta.providence.descriptor.PSet) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) PMap(net.morimekta.providence.descriptor.PMap)

Example 5 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class OverrideConfigSupplier method builderForField.

private static PMessageBuilder builderForField(boolean strict, PMessageBuilder builder, String... path) throws ProvidenceConfigException {
    for (int i = 0; i < (path.length - 1); ++i) {
        PMessageDescriptor descriptor = builder.descriptor();
        String fieldName = path[i];
        PField field = descriptor.findFieldByName(fieldName);
        if (field == null) {
            if (strict) {
                throw new ProvidenceConfigException("No such field %s in %s [%s]", fieldName, descriptor.getQualifiedName(), String.join(".", path));
            }
            return null;
        }
        if (field.getType() != PType.MESSAGE) {
            throw new ProvidenceConfigException("'%s' is not a message field in %s [%s]", fieldName, descriptor.getQualifiedName(), String.join(".", path));
        }
        builder = builder.mutator(field.getId());
    }
    return builder;
}
Also used : PField(net.morimekta.providence.descriptor.PField) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor)

Aggregations

PMessageDescriptor (net.morimekta.providence.descriptor.PMessageDescriptor)14 PEnumDescriptor (net.morimekta.providence.descriptor.PEnumDescriptor)7 PMessage (net.morimekta.providence.PMessage)5 IOException (java.io.IOException)4 PField (net.morimekta.providence.descriptor.PField)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 StringReader (java.io.StringReader)2 UncheckedIOException (java.io.UncheckedIOException)2 Blob (java.sql.Blob)2 Clob (java.sql.Clob)2 Timestamp (java.sql.Timestamp)2 TreeSet (java.util.TreeSet)2 Nonnull (javax.annotation.Nonnull)2 PEnumValue (net.morimekta.providence.PEnumValue)2 PMessageBuilder (net.morimekta.providence.PMessageBuilder)2 ProvidenceConfigException (net.morimekta.providence.config.ProvidenceConfigException)2 PDeclaredDescriptor (net.morimekta.providence.descriptor.PDeclaredDescriptor)2 PDescriptor (net.morimekta.providence.descriptor.PDescriptor)2 PList (net.morimekta.providence.descriptor.PList)2 PMap (net.morimekta.providence.descriptor.PMap)2