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

org.databene.commons.depend.Node Maven / Gradle / Ivy

Go to download

'databene commons' is an open source Java library by Volker Bergmann. It provides extensions to the Java core library by utility classes, abstract concepts and concrete implementations.

The newest version!
/*
 * Copyright (C) 2004-2015 Volker Bergmann ([email protected]).
 * All rights reserved.
 *
 * 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.databene.commons.depend;

import java.util.ArrayList;
import java.util.List;

import static org.databene.commons.depend.NodeState.*;

/**
 * Helper class for calculating dependencies.
 * @author Volker Bergmann
 * @since 0.3.04
 * @param 
 */
class Node> {
    
    private NodeState state;
    
    private E subject;
    private List> providers;
    private List providerRequired;
    private List> clients;
    
    public Node(E subject) {
        super();
        this.subject = subject;
        this.providers = new ArrayList>();
        this.providerRequired = new ArrayList();
        this.clients = new ArrayList>();
        this.state = INITIALIZABLE; // As long as no providers are added, the node is initializable
    }
    
    // properties ------------------------------------------------------------------------------------------------------

    /**
     * @return the subject
     */
    public E getSubject() {
        return subject;
    }
    
    /**
     * @return the state
     */
    public NodeState getState() {
        return state;
    }

    public boolean requires(Node provider) {
        return providerRequired.get(providers.indexOf(provider));
    }
    
    public List> getProviders() {
        return providers;
    }
    
    public Node addProvider(Node provider, boolean required) {
    	if (!hasForeignProviders() && provider != this) // A provider is about to be added. If this was a standalone node so far,...
    		this.state = INACTIVE;                      // ...I need to reconsider
        if (this.providers.contains(provider)) {
            if (required && !required(provider)) {
                providerRequired.set(providers.indexOf(provider), Boolean.TRUE);
                providersChanged();
            }
        } else {
            this.providers.add(provider);
            this.providerRequired.add(required);
            provider.addClient(this);
            providersChanged();
        }
        return this;
    }
    
    public boolean hasForeignProviders() {
        if (providers.size() == 0)
        	return false;
        for (Node provider : providers)
        	if (provider != this)
        		return true;
        return false;
    }
    
    public boolean required(Node provider) {
        return providerRequired.get(providers.indexOf(provider));
    }
    
    public List> getClients() {
        return clients;
    }

    public void addClient(Node client) {
        if (!this.clients.contains(client))
            this.clients.add(client);
    }
    
    public boolean hasForeignClients() {
    	if (clients.size() == 0)
    		return false;
    	for (Node client : clients)
    		if (client != this)
    			return true;
    	return false;
    }
    
    // interface -------------------------------------------------------------------------------------------------------

    void providersChanged() {
        if (state == INITIALIZABLE || state == INITIALIZED)
            return;
        // check initializability
        boolean initializable = true;
        boolean partiallyInitializable = true;
        for (Node provider : providers)
            if (provider != this && !allowsClientInitialization(provider.getState())) {
                initializable = false;
                if (required(provider))
                    partiallyInitializable = false;
            }
        if (initializable) {
            this.state = INITIALIZABLE;
            return;
        }
        if (state == PARTIALLY_INITIALIZED)
            return;
        if (partiallyInitializable) {
            this.state = PARTIALLY_INITIALIZABLE;
            return;
        }
        if (state != INACTIVE)
            return;
        if (!hasForeignProviders())
            this.state = FORCEABLE;
        for (Node provider : providers)
            if (provider != this && provider.getState() == INITIALIZED) {
                this.state = FORCEABLE;
                return;
            }
    }

    private static boolean allowsClientInitialization(NodeState providerState) {
        return providerState == INITIALIZED || providerState == FORCED || providerState == PARTIALLY_INITIALIZED;
    }
/*
    private boolean allProvidersInState(NodeState state) {
        for (Node provider : providers)
            if (provider.getState() != state)
                return false;
        return true;
    }
*/
    public void initialize() {
        if (state != INITIALIZABLE)
            throw new IllegalStateException("Node not initializable: " + this);
        setState(INITIALIZED);
    }

    private void setState(NodeState state) {
        this.state = state;
        for (Node client : clients)
            client.providersChanged();
    }
    
    public void initializePartially() {
        if (state != PARTIALLY_INITIALIZABLE)
            throw new IllegalStateException("Node not partially initializable: " + this);
        setState(PARTIALLY_INITIALIZED);
    }
    
    public void force() {
        setState(FORCED);
    }
    
    void assertState(NodeState state) {
        if (this.state != state)
            throw new IllegalStateException("Expected to be in state '" + state + "', " 
                    + "found: '" + this.state + "'");
    }
    
    // java.lang.Object ------------------------------------------------------------------------------------------------
    
    @Override
    public int hashCode() {
        return subject.hashCode();
    }

    @SuppressWarnings("rawtypes")
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null || getClass() != obj.getClass())
            return false;
        final Node that = (Node) obj;
        return (this.subject != null ? this.subject.equals(that.subject) : that.subject == null);
    }
    
    @Override
    public String toString() {
        return subject.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy