Package org.eclipse.sapphire.services

Source Code of org.eclipse.sapphire.services.DataService

/******************************************************************************
* Copyright (c) 2014 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    Konstantin Komissarchik - initial implementation and ongoing maintenance
******************************************************************************/

package org.eclipse.sapphire.services;

import static org.eclipse.sapphire.modeling.util.MiscUtil.equal;

import org.eclipse.sapphire.ElementType;
import org.eclipse.sapphire.LocalizableText;
import org.eclipse.sapphire.PropertyDef;
import org.eclipse.sapphire.Text;

/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
*/

public abstract class DataService<T> extends Service
{
    private static final Object INITIAL_DATA = new Object();
   
    @Text( "Reentrant call detected during refresh in {0}" )
    private static LocalizableText reentrantRefreshMessage;
   
    @Text( "{0} data accessed prior to service initialization" )
    private static LocalizableText dataAccessedPriorToInitMessage;

    @Text( "{0}: {1}.compute() has failed" )
    private static LocalizableText computeFailedMessage;

    static
    {
        LocalizableText.init( DataService.class );
    }

    @SuppressWarnings( "unchecked" )
    private T data = (T) INITIAL_DATA;
   
    private boolean initialized;
    private boolean refreshing;
   
    @Override
    protected final void init()
    {
        synchronized( context().lock() )
        {
            initDataService();
           
            this.initialized = true;
        }
    }

    protected void initDataService()
    {
    }
   
    public final T data()
    {
        synchronized( context().lock() )
        {
            if( ! this.initialized )
            {
                throw new IllegalStateException( dataAccessedPriorToInitMessage.format( getClass().getSimpleName() ) );
            }
           
            if( this.data == INITIAL_DATA )
            {
                refresh();
            }
           
            return this.data;
        }
    }
   
    protected abstract T compute();
   
    protected final void refresh()
    {
        boolean broadcast = false;
       
        synchronized( context().lock() )
        {
            if( this.refreshing )
            {
                throw new IllegalStateException( reentrantRefreshMessage.format( getClass().getSimpleName() ) );
            }
           
            this.refreshing = true;
           
            try
            {
                final T newData;
               
                try
                {
                    newData = compute();
                }
                catch( Exception e )
                {
                    final ServiceContext context = context();
                    final String contextLabel;
                   
                    final PropertyDef property = context.find( PropertyDef.class );
   
                    if( property != null )
                    {
                        contextLabel = property.getModelElementType().getSimpleName() + "." + property.name();
                    }
                    else
                    {
                        final ElementType type = context.find( ElementType.class );
                       
                        if( type != null )
                        {
                            contextLabel = type.getSimpleName();
                        }
                        else
                        {
                            contextLabel = context.getClass().getSimpleName();
                        }
                    }
                   
                    throw new RuntimeException( computeFailedMessage.format( contextLabel, getClass().getSimpleName() ), e );
                }
               
                if( this.data == INITIAL_DATA )
                {
                    this.data = newData;
                }
                else if( ! equal( this.data, newData ) )
                {
                    this.data = newData;
                   
                    broadcast = true;
                }
            }
            finally
            {
                this.refreshing = false;
            }
        }
       
        if( broadcast )
        {
            broadcast();
        }
    }

}
TOP

Related Classes of org.eclipse.sapphire.services.DataService

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.