Search in sources :

Example 1 with Pair

use of net.morimekta.util.Pair 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 2 with Pair

use of net.morimekta.util.Pair in project providence by morimekta.

the class ProvidenceConfigSupplierTest method testWatchedSupplier.

@Test
public void testWatchedSupplier() throws IOException {
    Database first = Database.builder().setDriver("com.mysql.Driver").build();
    Database second = Database.builder().setDriver("org.h2.Driver").build();
    File file = tmp.newFile().getAbsoluteFile().getCanonicalFile();
    when((Pair) parser.parseConfig(file.toPath(), null)).thenReturn(Pair.create(first, ImmutableSet.of(file.toString())));
    ArgumentCaptor<FileWatcher.Watcher> watcherCapture = ArgumentCaptor.forClass(FileWatcher.Watcher.class);
    doNothing().when(watcher).weakAddWatcher(watcherCapture.capture());
    ProvidenceConfigSupplier<Database, Database._Field> supplier = new ProvidenceConfigSupplier<>(file, null, watcher, parser, clock);
    assertThat(supplier.get(), is(sameInstance(first)));
    assertThat(supplier.get(), is(sameInstance(first)));
    assertThat(supplier.get(), is(sameInstance(first)));
    verify(parser).parseConfig(file.toPath(), null);
    verify(watcher).weakAddWatcher(any(FileWatcher.Watcher.class));
    verify(watcher, atMost(4)).startWatching(file);
    verifyNoMoreInteractions(watcher, parser);
    reset(parser, watcher);
    when((Pair) parser.parseConfig(file.toPath(), null)).thenReturn(Pair.create(second, ImmutableSet.of(file.toString())));
    doNothing().when(watcher).weakAddWatcher(watcherCapture.capture());
    watcherCapture.getValue().onFileUpdate(file);
    assertThat(supplier.get(), is(sameInstance(second)));
    assertThat(supplier.get(), is(sameInstance(second)));
    assertThat(supplier.get(), is(sameInstance(second)));
    verify(parser).parseConfig(file.toPath(), null);
    verifyNoMoreInteractions(parser, watcher);
}
Also used : FileWatcher(net.morimekta.util.FileWatcher) Database(net.morimekta.test.providence.config.Database) FileWatcher(net.morimekta.util.FileWatcher) File(java.io.File) Pair(net.morimekta.util.Pair) Test(org.junit.Test)

Example 3 with Pair

use of net.morimekta.util.Pair in project providence by morimekta.

the class ProvidenceConfigSupplierTest method testSupplier.

@Test
public void testSupplier() throws IOException {
    Database first = Database.builder().setDriver("com.mysql.Driver").build();
    Database second = Database.builder().setDriver("org.h2.Driver").build();
    File file = tmp.newFile().getAbsoluteFile().getCanonicalFile();
    when((Pair) parser.parseConfig(file.toPath(), null)).thenReturn(Pair.create(first, ImmutableSet.of(file.toString())));
    ArgumentCaptor<FileWatcher.Watcher> watcherCapture = ArgumentCaptor.forClass(FileWatcher.Watcher.class);
    doNothing().when(watcher).weakAddWatcher(watcherCapture.capture());
    ProvidenceConfigSupplier<Database, Database._Field> supplier = new ProvidenceConfigSupplier<>(file, null, watcher, parser, clock);
    assertThat(supplier.get(), is(sameInstance(first)));
    assertThat(supplier.get(), is(sameInstance(first)));
    assertThat(supplier.get(), is(sameInstance(first)));
    verify(parser).parseConfig(file.toPath(), null);
    verify(watcher).weakAddWatcher(any(FileWatcher.Watcher.class));
    verify(watcher, atLeast(1)).startWatching(any(File.class));
    verifyNoMoreInteractions(watcher, parser);
    reset(parser, watcher);
    when((Pair) parser.parseConfig(file.toPath(), null)).thenReturn(Pair.create(second, ImmutableSet.of(file.toString())));
    doNothing().when(watcher).weakAddWatcher(watcherCapture.capture());
    watcherCapture.getValue().onFileUpdate(file);
    assertThat(supplier.get(), is(sameInstance(second)));
    assertThat(supplier.get(), is(sameInstance(second)));
    assertThat(supplier.get(), is(sameInstance(second)));
    verify(parser).parseConfig(file.toPath(), null);
    verifyNoMoreInteractions(parser, watcher);
}
Also used : FileWatcher(net.morimekta.util.FileWatcher) Database(net.morimekta.test.providence.config.Database) FileWatcher(net.morimekta.util.FileWatcher) File(java.io.File) Pair(net.morimekta.util.Pair) Test(org.junit.Test)

Example 4 with Pair

use of net.morimekta.util.Pair in project providence by morimekta.

the class ProvidenceConfigSupplierTest method testSupplierKeepInstanceOnFailedReload.

@Test
public void testSupplierKeepInstanceOnFailedReload() throws IOException {
    Database first = Database.builder().build();
    File file = tmp.newFile().getAbsoluteFile().getCanonicalFile();
    when((Pair) parser.parseConfig(file.toPath(), null)).thenReturn(Pair.create(first, ImmutableSet.of(file.toString())));
    ArgumentCaptor<FileWatcher.Watcher> watcherCapture = ArgumentCaptor.forClass(FileWatcher.Watcher.class);
    doNothing().when(watcher).weakAddWatcher(watcherCapture.capture());
    ProvidenceConfigSupplier<Database, Database._Field> supplier = new ProvidenceConfigSupplier<>(file, null, watcher, parser, clock);
    assertThat(supplier.get(), is(first));
    verify(watcher).weakAddWatcher(any(FileWatcher.Watcher.class));
    reset(parser, watcher);
    when(parser.parseConfig(file.toPath(), null)).thenThrow(new ProvidenceConfigException("test"));
    watcherCapture.getValue().onFileUpdate(file);
    verify(parser).parseConfig(file.toPath(), null);
    verifyNoMoreInteractions(parser);
    assertThat(supplier.get(), is(first));
}
Also used : FileWatcher(net.morimekta.util.FileWatcher) Database(net.morimekta.test.providence.config.Database) FileWatcher(net.morimekta.util.FileWatcher) File(java.io.File) ProvidenceConfigException(net.morimekta.providence.config.ProvidenceConfigException) Pair(net.morimekta.util.Pair) Test(org.junit.Test)

Aggregations

Pair (net.morimekta.util.Pair)4 File (java.io.File)3 Database (net.morimekta.test.providence.config.Database)3 FileWatcher (net.morimekta.util.FileWatcher)3 Test (org.junit.Test)3 BufferedInputStream (java.io.BufferedInputStream)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 Path (java.nio.file.Path)1 TreeSet (java.util.TreeSet)1 PMessage (net.morimekta.providence.PMessage)1 ProvidenceConfigException (net.morimekta.providence.config.ProvidenceConfigException)1 Stage (net.morimekta.providence.config.impl.ProvidenceConfigUtil.Stage)1 ProvidenceConfigUtil.readCanonicalPath (net.morimekta.providence.config.impl.ProvidenceConfigUtil.readCanonicalPath)1 PMessageDescriptor (net.morimekta.providence.descriptor.PMessageDescriptor)1 Token (net.morimekta.providence.serializer.pretty.Token)1 Tokenizer (net.morimekta.providence.serializer.pretty.Tokenizer)1 TokenizerException (net.morimekta.providence.serializer.pretty.TokenizerException)1 Utf8StreamReader (net.morimekta.util.io.Utf8StreamReader)1