⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 facadeimpl.java

📁 Rapla是一个灵活的多用户资源管理系统。它提供的一些功能有:日历GUI
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*--------------------------------------------------------------------------*
 | Copyright (C) 2006 Christopher Kohlhaas                                  |
 |                                                                          |
 | This program is free software; you can redistribute it and/or modify     |
 | it under the terms of the GNU General Public License as published by the |
 | Free Software Foundation. A copy of the license has been included with   |
 | these distribution in the COPYING file, if not go to www.fsf.org         |
 |                                                                          |
 | As a special exception, you are granted the permissions to link this     |
 | program with every library, which license fulfills the Open Source       |
 | Definition as published by the Open Source Initiative (OSI).             |
 *--------------------------------------------------------------------------*/
package org.rapla.facade.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeSet;
import java.util.Vector;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.rapla.components.util.Command;
import org.rapla.components.util.CommandQueue;
import org.rapla.components.util.DateTools;
import org.rapla.components.util.Tools;
import org.rapla.components.xmlbundle.I18nBundle;
import org.rapla.entities.Category;
import org.rapla.entities.Entity;
import org.rapla.entities.EntityNotFoundException;
import org.rapla.entities.Ownable;
import org.rapla.entities.RaplaObject;
import org.rapla.entities.RaplaType;
import org.rapla.entities.User;
import org.rapla.entities.UserComparator;
import org.rapla.entities.configuration.CalendarModelConfiguration;
import org.rapla.entities.configuration.Preferences;
import org.rapla.entities.configuration.RaplaMap;
import org.rapla.entities.configuration.internal.CalendarModelConfigurationImpl;
import org.rapla.entities.configuration.internal.RaplaMapImpl;
import org.rapla.entities.domain.Allocatable;
import org.rapla.entities.domain.Appointment;
import org.rapla.entities.domain.Period;
import org.rapla.entities.domain.Permission;
import org.rapla.entities.domain.Reservation;
import org.rapla.entities.domain.internal.AllocatableImpl;
import org.rapla.entities.domain.internal.AppointmentImpl;
import org.rapla.entities.domain.internal.PeriodImpl;
import org.rapla.entities.domain.internal.ReservationImpl;
import org.rapla.entities.dynamictype.Attribute;
import org.rapla.entities.dynamictype.AttributeType;
import org.rapla.entities.dynamictype.Classifiable;
import org.rapla.entities.dynamictype.Classification;
import org.rapla.entities.dynamictype.ClassificationFilter;
import org.rapla.entities.dynamictype.DynamicType;
import org.rapla.entities.dynamictype.DynamicTypeAnnotations;
import org.rapla.entities.dynamictype.internal.AttributeImpl;
import org.rapla.entities.dynamictype.internal.DynamicTypeImpl;
import org.rapla.entities.internal.CategoryImpl;
import org.rapla.entities.internal.UserImpl;
import org.rapla.entities.storage.Mementable;
import org.rapla.entities.storage.RefEntity;
import org.rapla.facade.AllocationChangeEvent;
import org.rapla.facade.AllocationChangeListener;
import org.rapla.facade.ClientFacade;
import org.rapla.facade.Conflict;
import org.rapla.facade.ModificationEvent;
import org.rapla.facade.ModificationListener;
import org.rapla.facade.PeriodModel;
import org.rapla.facade.UpdateErrorListener;
import org.rapla.facade.UpdateModule;
import org.rapla.framework.RaplaContext;
import org.rapla.framework.RaplaContextException;
import org.rapla.framework.RaplaException;
import org.rapla.framework.RaplaLocale;
import org.rapla.storage.CachableStorageOperator;
import org.rapla.storage.RaplaSecurityException;
import org.rapla.storage.StorageOperator;
import org.rapla.storage.StorageUpdateListener;
import org.rapla.storage.UpdateResult;
/** This is the default implementation of the necessary Client-Facade to the DB-Subsystem.
 * <p>Sample configuration 1:
  <pre>
   &lt;facade id="facade">
      &lt;store>file&lt;/store>
   &lt;/facade>
  </pre>
  </p>
  <p>Sample Configuration 2:
  <pre>
     &lt;facade id="facade" logger="facade">
        &lt;store>remote&lt;/store>
        &lt;username>homer&lt;/username>
        &lt;password>duffs&lt;/password>
     &lt;/facade>
  </pre>
 This facade automatically starts with user homer.
 *  </p>
 *  <p>The store entry contains the id of a storage-component.
 *  Storage-Components are all components that implement the
 *  {@link StorageOperator} interface.
 *  </p>
 */

public class FacadeImpl extends AbstractLogEnabled
    implements
        ClientFacade
        ,StorageUpdateListener
{
    protected CommandQueue notifyQueue;
    private Configuration operatorConfig;
    private User workingUser = null;
    private User originalUser = null;
    private StorageOperator operator;
    private Vector modificatonListenerList = new Vector();
    private Vector allocationListenerList = new Vector();
    private Vector errorListenerList = new Vector();
    private I18nBundle i18n;
    private PeriodModelImpl periodModel;
    private ConflictFinder conflictFinder;
    String username;
    String password;
    Locale locale;

    public FacadeImpl(RaplaContext context,Configuration config, Logger logger) throws RaplaException
    {
        enableLogging( logger );
        i18n = (I18nBundle) context.lookup(I18nBundle.ROLE + "/org.rapla.RaplaResources");
        locale = ((RaplaLocale)context.lookup(RaplaLocale.ROLE)).getLocale();
        operatorConfig = config.getChild("store");
        getLogger().debug("Facade configured with operator '" + operatorConfig.getValue("*") + "'");
        username = config.getChild("username").getValue(null);
        password = config.getChild("password").getValue("");
        try {
            operator = (StorageOperator) context.lookup(StorageOperator.ROLE + "/" + operatorConfig.getValue("*"));
            conflictFinder = new ConflictFinder( operator );
            operator.addStorageUpdateListener(this);
        }
        catch (RaplaContextException ex)
        {
            throw new RaplaContextException
                (
                 CachableStorageOperator.ROLE,
                 "Store at " + operatorConfig.getLocation()
                 + " is not found (or could not be initialized)"
                 ,ex
                 );
        }
        notifyQueue = org.rapla.components.util.CommandQueue.createCommandQueue();
        if (username!=null)
            if (!login(username,password.toCharArray()))
                throw new RaplaException(i18n.getString("error.login"));
        initRefresh();
    }

    //Implementation of StorageUpdateListener.
    /** This method is called by the storage-operator, when stored objects
        have changed.

        <strong>Caution:</strong> You must not lock the storage operator during processing
        of this call, because it could have been locked by the store method, causing deadlocks
     */
    public void objectsUpdated(UpdateResult evt) {
        if (getLogger().isDebugEnabled())
            getLogger().debug("Objects updated");

        notifyQueue.enqueue(new UserCheckCommand());

        fireUpdateEvent( evt );
    }

    public void switchTo(User user) {
        if (user == null) {
            workingUser = originalUser;
            originalUser = null;
        } else {
            originalUser = workingUser;
            workingUser = user;
        }
        //    fireUpdateEvent(new ModificationEvent());
    }

    public boolean canSwitchBack() {
        return originalUser != null;
    }

    public void updateError(RaplaException ex) {
        getLogger().fatalError(ex.getMessage(),ex);
        fireUpdateError(ex);
    }

    public void storageDisconnected() {
        fireStorageDisconnected();
    }

    /******************************
     * Update-module              *
     ******************************/
    public boolean isClientForServer() {
        return operator.supportsActiveMonitoring();
    }

    public void refresh() throws RaplaException {
        synchronized (operator.getLock()) {
            if ( operator.supportsActiveMonitoring())
            {
                operator.refresh();
            }
        }
    }
    
    public void addModificationListener(ModificationListener listener) {
        modificatonListenerList.add(listener);
    }

    public void removeModificationListener(ModificationListener listener) {
        modificatonListenerList.remove(listener);
    }

    public ModificationListener[] getModificationListeners() {
        return (ModificationListener[])modificatonListenerList.toArray(new ModificationListener[]{});
    }

    private Collection getModificationListeners(boolean invokeLater) {
        if (modificatonListenerList.size() == 0)
            return Tools.EMPTY_LIST;
        synchronized (this) {
            Collection list = new ArrayList(3);
            if ( periodModel != null) {
                list.add( periodModel );
            }
            Iterator it = modificatonListenerList.iterator();
            while (it.hasNext()) {
                ModificationListener listener = (ModificationListener) it.next();
                if (listener.isInvokedOnAWTEventQueue() == invokeLater)
                    list.add(listener);
            }
            return list;
        }
    }

    public void addAllocationChangedListener(AllocationChangeListener listener) {
        allocationListenerList.add(listener);
    }

    public void removeAllocationChangedListener(AllocationChangeListener listener) {
        allocationListenerList.remove(listener);
    }

    private Collection getAllocationChangeListeners(boolean invokeLater) {
        if (allocationListenerList.size() == 0)
            return Tools.EMPTY_LIST;
        synchronized (this) {
            Collection list = new ArrayList(3);
            Iterator it = allocationListenerList.iterator();
            while (it.hasNext()) {
                AllocationChangeListener listener = (AllocationChangeListener) it.next();
                if (listener.isInvokedOnAWTEventQueue() == invokeLater)
                    list.add(listener);
            }
            return list;
        }
    }

    public void addUpdateErrorListener(UpdateErrorListener listener) {
        errorListenerList.add(listener);
    }

    public void removeUpdateErrorListener(UpdateErrorListener listener) {
        errorListenerList.remove(listener);
    }

    public UpdateErrorListener[] getUpdateErrorListeners() {
        return (UpdateErrorListener[])errorListenerList.toArray(new UpdateErrorListener[]{});
    }


    protected void fireUpdateError(RaplaException ex) {
        UpdateErrorListener[] listeners = getUpdateErrorListeners();
        for (int i = 0;i<listeners.length; i++) {
            listeners[i].updateError(ex);
        }
    }

    protected void fireStorageDisconnected() {
        UpdateErrorListener[] listeners = getUpdateErrorListeners();
        for (int i = 0;i<listeners.length; i++) {
            listeners[i].disconnected();
        }
    }

    final class UserCheckCommand implements Command {
        public void execute() {
            try {
                if (workingUser == null)
                    return;

                synchronized (operator.getLock()) {
                    Iterator it = operator.getObjects(User.TYPE).iterator();
                    while (it.hasNext()) {
                        User user = (User)it.next();
                        if (user.equals(workingUser)) 
                        {
                            workingUser = user;
                            return;
                        }
                    }
                }
                if (workingUser == null)
                    return;
                throw new EntityNotFoundException("User (" + workingUser + ") not found");
            } catch (RaplaException ex) {
                fireUpdateError(ex);
            }
        }
    }

    private final void initRefresh()
    {
        TimerTask refreshTask = new TimerTask() {
            public void run() {
                initRefresh();
            }
        };
        synchronized (operator.getLock())
        {
            Timer  timer = new Timer( true );  // Start timer as daemon-thread
            int delay = 30000;

            if ( operator.isConnected())
            {
                try
                {
                    delay = operator.getPreferences( null).getEntryAsInteger(UpdateModule.REFRESH_INTERVAL_ENTRY, delay);
                    refresh();
                }
                catch (RaplaException e)
                {
                    getLogger().error("Error refreshing.", e);
                }
            }
            timer.schedule( refreshTask, delay );
        }
    }
        
    final class UpdateCommand implements Runnable,Command {
        Collection listeners;
        boolean bError = false;
        ModificationEvent modificationEvent;
        AllocationChangeEvent[] allocationChangeEvents;

        public UpdateCommand(Collection modificationListeners,Collection allocationChangeListeners,UpdateResult evt) {

            this.listeners = new ArrayList(modificationListeners);
            this.listeners.addAll( allocationChangeListeners );
            if ( evt != null )
            {
                Set storeEvents = new HashSet();
                storeEvents.addAll( evt.getChangeObjects());
                storeEvents.addAll( evt.getAddObjects());
                Set removeEvents = evt.getRemoveObjects();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -