All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.imca_cat.pollingwatchservice.PollingWatchKey Maven / Gradle / Ivy

/*
 * Copyright (c) 2013-2018 Cinchapi Inc.
 *
 * 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.imca_cat.pollingwatchservice;

import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.Watchable;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * A {@code WatchKey} implementation for {@link PollingWatchService}.
 */
class PollingWatchKey implements WatchKey {
    private final PollingWatchService service;
    private final Path path;
    private final List> kinds;
    private final List modifiers;
    private Map entries;
    private final List> events;
    private final List> eventsPending;
    private PollingWatchKeyState state;

    public PollingWatchKey(PollingWatchService service, Path path) {
        this(service, path, new WatchEvent.Kind[0],
                new WatchEvent.Modifier[0]);
    }

    public PollingWatchKey(PollingWatchService service, Path path,
            WatchEvent.Kind[] kinds, WatchEvent.Modifier[] modifiers) {
        this(service, path, kinds, modifiers, null);
    }

    public PollingWatchKey(PollingWatchService service, Path path,
            WatchEvent.Kind[] kinds, WatchEvent.Modifier[] modifiers,
            Map entries) {
        super();
        this.service = service;
        this.path = path;
        this.kinds = new ArrayList<>(Arrays.asList(kinds));
        this.modifiers = new ArrayList<>(Arrays.asList(modifiers));
        this.entries = entries;
        events = new ArrayList<>();
        eventsPending = new ArrayList<>();
        state = PollingWatchKeyState.READY;
    }

    public synchronized boolean hasKindAndModifier(WatchEvent.Kind k,
            WatchEvent.Modifier m) {
        return hasKind(k) && hasModifier(m);
    }

    public synchronized void kindsAndModifiers(WatchEvent.Kind[] kinds,
            WatchEvent.Modifier[] modifiers) {
        this.kinds.clear();
        this.kinds.addAll(Arrays.asList(kinds));
        this.modifiers.clear();
        this.modifiers.addAll(Arrays.asList(modifiers));
    }

    public synchronized boolean hasKind(WatchEvent.Kind k) {
        return kinds.contains(k);
    }

    public synchronized boolean hasModifier(WatchEvent.Modifier m) {
        return modifiers.contains(m);
    }

    /**
     * Returns a read-only map of entries.
     */
    public synchronized Map entries() {
        return Collections.unmodifiableMap(entries);
    }

    /**
     * Sets entries. The entries map must not be modified externally after being
     * set.
     */
    public synchronized void entries(Map entries) {
        this.entries = entries;
    }

    public synchronized boolean isReady() {
        return state.equals(PollingWatchKeyState.READY);
    }

    public synchronized boolean isSignaled() {
        return state.equals(PollingWatchKeyState.SIGNALED);
    }

    public synchronized boolean isInvalid() {
        return state.equals(PollingWatchKeyState.INVALID);
    }

    @Override
    public synchronized boolean isValid() {
        return !isInvalid();
    }

    @Override
    public synchronized List> pollEvents() {
        List> result = new ArrayList>(events);
        events.clear();
        return result;
    }

    public synchronized void signal() {
        if(isInvalid())
            return;
        if(isSignaled())
            return;
        state = PollingWatchKeyState.SIGNALED;
    }

    public synchronized void enqueue() {
        if(isSignaled())
            return;
        if(isReady())
            signal();
        service.enqueue(this);
    }

    public synchronized void enqueueIfReadyAndHasEvents() {
        if(!isReady())
            return;
        if(events.isEmpty())
            return;
        signal();
        service.enqueue(this);
    }

    @Override
    public synchronized boolean reset() {
        if(isInvalid())
            return false;
        if(isReady())
            return true;
        events.addAll(eventsPending);
        eventsPending.clear();
        state = PollingWatchKeyState.READY;
        if(!events.isEmpty())
            enqueue();
        return true;
    }

    @Override
    public synchronized void cancel() {
        if(isInvalid())
            return;
        state = PollingWatchKeyState.INVALID;
    }

    @Override
    public Watchable watchable() {
        return path;
    }

    public Path watchablePath() {
        return path;
    }

    public synchronized void addEvent(PollingWatchEvent e) {
        List> l = isReady() ? events : eventsPending;
        if(!l.isEmpty() && (e.isModify() || e.isOverflow())) {
            PollingWatchEvent last = l.get(l.size() - 1);
            if(last.kind().equals(e.kind())) {
                last.incrementCount();
            }
            else {
                l.add(e);
            }
        }
        else {
            l.add(e);
        }
    }

    @Override
    public boolean equals(Object o) {
        if(this == o)
            return true;
        if(!(o instanceof PollingWatchKey))
            return false;
        return path.equals(((PollingWatchKey) o).path);
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + path.hashCode();
        return result;
    }

    @Override
    public synchronized String toString() {
        return String.format("%s (state=%s, kinds=%s, modifiers=%s, entries)",
                path, state, kinds, modifiers, entries);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy