com.comphenix.protocol.events.PacketMetadata.java Source code

Java tutorial

Introduction

Here is the source code for com.comphenix.protocol.events.PacketMetadata.java

Source

/**
 *  ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
 *  Copyright (C) 2017 dmulloy2
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU General Public License as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with this program;
 *  if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 */
package com.comphenix.protocol.events;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import org.apache.commons.lang3.Validate;

/**
 * Stores and retrieves metadata for applicable packet objects.
 * @author dmulloy2
 */
class PacketMetadata {

    private static class MetaObject<T> {
        private final String key;
        private final T value;

        private MetaObject(String key, T value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public int hashCode() {
            return Objects.hash(key, value);
        }

        @Override
        public boolean equals(Object o) {
            if (o == this)
                return true;

            if (o instanceof MetaObject) {
                MetaObject that = (MetaObject) o;
                return that.key.equals(this.key) && that.value.equals(this.value);
            }

            return false;
        }

        @Override
        public String toString() {
            return "MetaObject[" + key + "=" + value + "]";
        }
    }

    // Packet meta cache
    private static Cache<Object, List<MetaObject>> META_CACHE;

    public static <T> Optional<T> get(Object packet, String key) {
        Validate.notNull(key, "Null keys are not permitted!");

        if (META_CACHE == null) {
            return Optional.empty();
        }

        List<MetaObject> meta = META_CACHE.getIfPresent(packet);
        if (meta == null) {
            return Optional.empty();
        }

        for (MetaObject object : meta) {
            if (object.key.equals(key)) {
                return Optional.of((T) object.value);
            }
        }

        return Optional.empty();
    }

    private static void createCache() {
        META_CACHE = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
    }

    public static <T> void set(Object packet, String key, T value) {
        Validate.notNull(key, "Null keys are not permitted!");

        if (META_CACHE == null) {
            createCache();
        }

        List<MetaObject> packetMeta;

        try {
            packetMeta = META_CACHE.get(packet, ArrayList::new);
        } catch (ExecutionException ex) {
            // Not possible, but let's humor the array list constructor having an issue
            packetMeta = new ArrayList<>();
        }

        packetMeta.removeIf(meta -> meta.key.equals(key));
        packetMeta.add(new MetaObject<>(key, value));
        META_CACHE.put(packet, packetMeta);
    }

    public static <T> Optional<T> remove(Object packet, String key) {
        Validate.notNull(key, "Null keys are not permitted!");

        if (META_CACHE == null) {
            return Optional.empty();
        }

        List<MetaObject> packetMeta = META_CACHE.getIfPresent(packet);
        if (packetMeta == null) {
            return Optional.empty();
        }

        Optional<T> value = Optional.empty();
        Iterator<MetaObject> iter = packetMeta.iterator();
        while (iter.hasNext()) {
            MetaObject meta = iter.next();
            if (meta.key.equals(key)) {
                value = Optional.of((T) meta.value);
                iter.remove();
            }
        }

        return value;
    }
}