001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2016-2026 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.core;
020
021import java.util.logging.Logger;
022import org.jgrapes.core.annotation.Handler;
023import org.jgrapes.core.annotation.HandlerDefinition.ChannelReplacements;
024import org.jgrapes.core.internal.ComponentVertex;
025
026/**
027 * This class can be used as base class for implementing a component. 
028 * <P>
029 * This class implements the {@link Manager} interface. Contrary 
030 * to classes that only implement {@link ComponentType}, derived 
031 * classes therefore don't need a manager attribute to get access to the 
032 * component management methods provided by this interface.
033 * <P>
034 * This class also implements the {@code Channel} interface in such a way
035 * that each instance of this class can be used as an independent
036 * channel. Note that events that have a component as one of their
037 * channels are always handled by the component's handlers, i.e. in 
038 * addition to the channels explicitly defined for a handler. 
039 * 
040 * @see Handler
041 * @see ComponentType
042 */
043public abstract class Component extends ComponentVertex
044        implements ComponentType, Channel {
045
046    protected final Logger logger = Logger.getLogger(getClass().getName());
047    private final Channel componentChannel;
048
049    /**
050     * Creates a new component base with its channel set to
051     * itself.
052     */
053    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
054    public Component() {
055        super(null);
056        componentChannel = this;
057        initComponentsHandlers();
058    }
059
060    /**
061     * Creates a new component base with its channel set to the given 
062     * channel. As a special case {@link Channel#SELF} can be
063     * passed to the constructor to make the component use itself
064     * as channel. The special value is necessary as you 
065     * obviously cannot pass an object to be constructed to its 
066     * constructor.
067     *
068     * @param componentChannel the channel that the component's
069     * handlers listen on by default and that 
070     * {@link Manager#fire(Event, Channel...)} sends the event to
071     */
072    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
073    public Component(Channel componentChannel) {
074        super(null);
075        if (componentChannel == SELF) {
076            this.componentChannel = this;
077        } else {
078            this.componentChannel = componentChannel;
079        }
080        initComponentsHandlers();
081    }
082
083    /**
084     * Creates a new component base like {@link #Component(Channel)}
085     * but with channel mappings for {@link Handler} annotations.
086     *
087     * @param componentChannel the channel that the component's
088     * handlers listen on by default and that 
089     * {@link Manager#fire(Event, Channel...)} sends the event to
090     * @param channelReplacements the channel replacements to apply
091     * to the `channels` elements of the {@link Handler} annotations
092     */
093    @SuppressWarnings({ "PMD.LooseCoupling",
094        "PMD.ConstructorCallsOverridableMethod" })
095    public Component(
096            Channel componentChannel, ChannelReplacements channelReplacements) {
097        super(channelReplacements);
098        if (componentChannel == SELF) {
099            this.componentChannel = this;
100        } else {
101            this.componentChannel = componentChannel;
102        }
103        initComponentsHandlers();
104    }
105
106    /*
107     * (non-Javadoc)
108     * 
109     * @see org.jgrapes.core.internal.ComponentVertex#setName(java.lang.String)
110     */
111    @Override
112    public Component setName(String name) {
113        super.setName(name);
114        return this;
115    }
116
117    /*
118     * (non-Javadoc)
119     * 
120     * @see org.jgrapes.core.internal.ComponentVertex#getComponent()
121     */
122    @Override
123    public Component component() {
124        return this;
125    }
126
127    /**
128     * Returns the channel associated with the component.
129     * 
130     * @return the channel as assigned by the constructor.
131     * 
132     * @see org.jgrapes.core.Manager#channel()
133     */
134    @Override
135    public Channel channel() {
136        return componentChannel;
137    }
138
139    /**
140     * Return the object itself as value.
141     */
142    @Override
143    public Object defaultCriterion() {
144        return this;
145    }
146
147    /**
148     * Matches the object itself (using identity comparison) or the
149     * {@link Channel} class.
150     * 
151     * @see Channel#isEligibleFor(Object)
152     */
153    @Override
154    @SuppressWarnings("PMD.CompareObjectsWithEquals")
155    public boolean isEligibleFor(Object value) {
156        return value.equals(Channel.class)
157            || value == defaultCriterion();
158    }
159
160}