org.jboss.weld.vertx.examples.translator.DataCache.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.weld.vertx.examples.translator.DataCache.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2016, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.weld.vertx.examples.translator;

import static org.jboss.weld.vertx.examples.translator.Addresses.CLEAR_CACHE;
import static org.jboss.weld.vertx.examples.translator.Addresses.REQUEST_DATA;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

import org.jboss.weld.vertx.VertxConsumer;
import org.jboss.weld.vertx.VertxEvent;

import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;

/**
 *
 * @author Martin Kouba
 */
@ApplicationScoped
public class DataCache {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataCache.class.getName());

    private final Vertx vertx;

    private final ConcurrentMap<String, List<String>> cache;

    @Inject
    public DataCache(Vertx vertx) {
        this.cache = new ConcurrentHashMap<>();
        this.vertx = vertx;
    }

    void clear(@Observes @VertxConsumer(CLEAR_CACHE) VertxEvent event) {
        LOGGER.info("Clear dictionary cache");
        cache.clear();
    }

    /**
     *
     * @param word
     * @return a list of matching translations or <code>null</code> if no data available yet
     */
    List<String> getTranslations(String word) {
        List<String> translations = cache.get(word.toLowerCase());
        if (translations == null) {
            // No translations available - send request
            // We use synchronizer to block for 2 seconds
            final BlockingQueue<List<String>> synchronizer = new LinkedBlockingQueue<>();
            vertx.eventBus().send(REQUEST_DATA, word, (r) -> {
                if (r.succeeded()) {
                    synchronizer.add(putIfAbsent(r.result().body()));
                }
            });
            try {
                translations = synchronizer.poll(2, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                LOGGER.warn("No translation data available for {0} right now...", word);
            }
        }
        return translations;
    }

    private List<String> putIfAbsent(Object data) {
        if (data instanceof JsonObject) {
            JsonObject dataObject = (JsonObject) data;
            String word = dataObject.getString("word");
            if (word != null) {
                List<String> translations;
                JsonArray translationsArray = dataObject.getJsonArray("translations");
                if (translationsArray != null) {
                    translations = new ArrayList<>();
                    for (Object element : translationsArray) {
                        translations.add(element.toString());
                    }
                    translations = Collections.unmodifiableList(translations);
                } else {
                    translations = Collections.emptyList();
                }
                putIfAbsent(word, translations);
                return translations;
            }
        }
        return null;
    }

    void putIfAbsent(String word, List<String> matches) {
        if (cache.putIfAbsent(word.toLowerCase(), matches) == null) {
            LOGGER.info("Caching data for: {0}", word);
        }
    }

}