Package org.qi4j.library.alarm

Source Code of org.qi4j.library.alarm.AlarmSystem$AlarmSystemMixin

/*
* Copyright 1996-2011 Niclas Hedhman.
*
* 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.qi4j.library.alarm;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.qi4j.api.entity.EntityBuilder;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.query.Query;
import org.qi4j.api.query.QueryBuilder;
import org.qi4j.api.query.QueryBuilderFactory;
import org.qi4j.api.service.ServiceReference;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.api.unitofwork.UnitOfWorkFactory;
import org.qi4j.api.value.ValueBuilder;
import org.qi4j.api.value.ValueBuilderFactory;

/**
* Defines the AlarmSystem interface.
*
* <p>
* The <code>AlarmSystem</code> is a central registry/handler for all
* <code>AlarmPoint</code> objects. By registering <code>AlarmListener</code>s
* to the AlarmSystem, objects are able to 'ignore' the fact that there
* are many <code>AlarmPoint</code> objects in the system.
* </p>
* <p>
* Also, new attributes registered with the AlarmSystem will propagate into
* all existing and future <code>AlarmPoint</code>s, whereas attributes at <code>
* AlarmPoint</code> level is individual to an <code>AlarmPoint</code>.
* </p>
* <p>
* Many different AlarmModels can co-exist in the same application.
* In fact, every AlarmPoint can have its own AlarmModel, and the AlarmModel
* can be changed in runtime, for unrivaled flexibility. However, typically
* the AlarmModel is set in the AlarmSystem only, and all Alarms will
* use the default model.
* </p>
* <p>The default alarm model is a service set by during assembly;
* </p>
* <pre><code>
*   public void assemble( ModuleAssembly module )
*       throws AssemblyException
*   {
*       module.addServices( AlarmSystemService.class );
*       module.addServices( StandardAlarmModelService.class );
*   }
* </code></pre>
*
* @author Niclas Hedhman
*/
@Mixins( AlarmSystemService.AlarmSystemMixin.class )
public interface AlarmSystem
{

    /**
     * Returns all the AlarmModels that has been installed.
     *
     * @return all the AlarmModels that has been installed.
     */
    List<AlarmModelDescriptor> alarmModels();

    /**
     * Returns the default AlarmModel.
     *
     * @return the default AlarmModel in this AlarmSystem.
     */
    AlarmModel defaultAlarmModel();

    /**
     * Returns a list of all Alarms registered to the service.
     * <p>
     * The returned Collection may not be modified in any way. The
     * implementation is free to return a clone, but not required to do
     * so, and may decide to terminate if the collection is modified.
     * </p>
     *
     * @return a list of all Alarms registered to the service.
     */
    Query<AlarmPoint> alarmList();

    /**
     * Creates an AlarmPoint with the default AlarmModel.
     *
     * @param name the name of the AlarmPoint to be created.
     *
     * @param category The category the created AlarmPoint should belong to.
     *
     * @return the created AlarmPoint with the given name using the default AlarmModel.
     */
    AlarmPoint createAlarm( String name, AlarmCategory category );

    /**
     * Register AlarmListener to recieve <code>AlarmEvents</code> from all
     * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
     *
     * @param listener the global listener to be added.
     */
    void addAlarmListener( AlarmListener listener );

    /**
     * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
     *
     * @param listener the global listener to be removed.
     */
    void removeAlarmListener( AlarmListener listener );

    /**
     * Returns an immmutable list of all AlarmListeners registered to the service.
     *
     * @return a list of all AlarmListeners registered to the service.
     */
    List<AlarmListener> alarmListeners();

    /**
     * AlarmSystem implementation.
     */
    class AlarmSystemMixin
        implements AlarmSystem
    {
        @Service
        private Iterable<ServiceReference<AlarmModel>> models;

        private final CopyOnWriteArrayList<AlarmListener> alarmListeners;

        @Structure
        private UnitOfWorkFactory uowf;

        @Structure
        private ValueBuilderFactory vbf;

        @Structure
        private QueryBuilderFactory qbf;

        public AlarmSystemMixin()
        {
            alarmListeners = new CopyOnWriteArrayList<AlarmListener>();
        }

        /**
         * Returns all the AlarmModels that has been installed.
         */
        @Override
        public List<AlarmModelDescriptor> alarmModels()
        {
            List<AlarmModelDescriptor> descriptors = new ArrayList<AlarmModelDescriptor>();
            for( ServiceReference<AlarmModel> model : models )
            {
                descriptors.add( model.metaInfo( AlarmModelDescriptor.class ) );
            }
            return descriptors;
        }

        /**
         * Returns the default AlarmModel.
         */
        @Override
        public AlarmModel defaultAlarmModel()
        {
            AlarmModelDescriptor defaultDefault = null;
            for( AlarmModelDescriptor descriptor : alarmModels() )
            {
                if( descriptor.isDefaultModel() )
                {
                    return alarmModel( descriptor );
                }
                defaultDefault = descriptor;
            }
            return alarmModel( defaultDefault );
        }

        private AlarmModel alarmModel( AlarmModelDescriptor descriptor )
        {
            for( ServiceReference<AlarmModel> model : models )
            {
                if( model.metaInfo( AlarmModelDescriptor.class ).equals( descriptor ) )
                {
                    return model.get();
                }
            }
            return null;
        }

        /**
         * Creates an AlarmPoint with the default AlarmModel.
         * @param name The system name of the AlarmPoint.
         * @param category The AlarmPoint Category the created alarm should belong to.
         */
        @Override
        public AlarmPoint createAlarm( String name, AlarmCategory category )
        {
            UnitOfWork uow = uowf.currentUnitOfWork();
            EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
            builder.instance().category().set( category );
            AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
            state.systemName().set( name );
            state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
            return builder.newInstance();
        }

        private AlarmStatus createStatus( String status )
        {
            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
            AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
            statePrototype.name().set( status );
            statePrototype.creationDate().set( new Date() );
            return builder.newInstance();
        }

        /**
         * Register AlarmListener to recieve <code>AlarmEvents</code> from all
         * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
         */
        @Override
        public void addAlarmListener( AlarmListener listener )
        {
            alarmListeners.add( listener );
        }

        /**
         * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
         */
        @Override
        public void removeAlarmListener( AlarmListener listener )
        {
            alarmListeners.remove( listener );
        }

        /**
         * Returns a list of all Alarms registered to the service.
         */
        @Override
        public Query<AlarmPoint> alarmList()
        {
            UnitOfWork uow = uowf.currentUnitOfWork();
            QueryBuilder<AlarmPoint> builder = qbf.newQueryBuilder( AlarmPoint.class );
            return uow.newQuery( builder );
        }

        @Override
        public List<AlarmListener> alarmListeners()
        {
            synchronized( alarmListeners )
            {
                return alarmListeners;
            }
        }

        public void alarmFired( AlarmEvent event )
        {
            Iterator list;
            //noinspection SynchronizeOnNonFinalField
            synchronized( alarmListeners )
            {
                list = alarmListeners.iterator();
            }
            while( list.hasNext() )
            {
                AlarmListener listener = (AlarmListener) list.next();
                try
                {
                    listener.alarmFired( event );
                }
                catch( Exception e )
                {
                    // TODO: Utilize a logger system instead.
                    System.err.println( "Exception in AlarmListener: " + listener );
                    e.printStackTrace();
                }
            }
        }
    }
}
TOP

Related Classes of org.qi4j.library.alarm.AlarmSystem$AlarmSystemMixin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.