org.alfresco.util.registry.NamedObjectRegistry.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.util.registry.NamedObjectRegistry.java

Source

/*
 * Copyright (C) 2005-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 */
package org.alfresco.util.registry;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.ParameterCheck;

/**
 * An generic registry of objects held by name.  This is effectively a strongly-typed,
 * synchronized map. 
 * 
 * @author Derek Hulley
 * @since 3.2
 */
@AlfrescoPublicApi
public class NamedObjectRegistry<T> {
    private static final Log logger = LogFactory.getLog(NamedObjectRegistry.class);

    private final ReentrantReadWriteLock.ReadLock readLock;
    private final ReentrantReadWriteLock.WriteLock writeLock;

    private Class<T> storageType;
    private Pattern namePattern;
    private final Map<String, T> objects;

    /**
     * Default constructor.  The {@link #setStorageType(Class)} method must be called.
     */
    public NamedObjectRegistry() {
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        readLock = lock.readLock();
        writeLock = lock.writeLock();
        this.namePattern = null; // Deliberately null
        this.storageType = null; // Deliberately null
        this.objects = new HashMap<String, T>(13);
    }

    /**
     * Constructor that takes care of {@link #setStorageType(Class)}.
     * 
     * @see #setStorageType(Class)
     */
    public NamedObjectRegistry(Class<T> type) {
        this();
        setStorageType(type);
    }

    /**
     * Set the type of class that the registry holds.  Any attempt to register a
     * an instance of another type will be rejected.
     * 
     * @param clazz                     the type to store
     */
    public void setStorageType(Class<T> clazz) {
        writeLock.lock();
        try {
            this.storageType = clazz;
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * Optionally set a pattern to which all object names must conform
     * @param namePattern   a regular expression
     */
    public void setNamePattern(String namePattern) {
        writeLock.lock();
        try {
            this.namePattern = Pattern.compile(namePattern);
        } catch (PatternSyntaxException e) {
            throw new AlfrescoRuntimeException(
                    "Regular expression compilation failed for property 'namePrefix': " + e.getMessage(), e);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * Register a named object instance.
     * 
     * @param name          the name of the object
     * @param object        the instance to register, which correspond to the type
     */
    public void register(String name, T object) {
        ParameterCheck.mandatoryString("name", name);
        ParameterCheck.mandatory("object", object);

        if (!storageType.isAssignableFrom(object.getClass())) {
            throw new IllegalArgumentException(
                    "This NameObjectRegistry only accepts objects of type " + storageType);
        }
        writeLock.lock();
        try {
            if (storageType == null) {
                throw new IllegalStateException(
                        "The registry has not been configured (setStorageType not yet called yet)");
            }
            if (namePattern != null) {
                if (!namePattern.matcher(name).matches()) {
                    throw new IllegalArgumentException(
                            "Object name '" + name + "' does not match required pattern: " + namePattern);
                }
            }
            T prevObject = objects.put(name, object);
            if (prevObject != null && prevObject != object) {
                logger.warn("Overwriting name object in registry: \n" + "   Previous: " + prevObject + "\n"
                        + "   New:      " + object);
            }
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * Get a named object if it has been registered
     * 
     * @param name          the name of the object to retrieve
     * @return              Returns the instance of the object, which will necessarily
     *                      be of the correct type, or <tt>null</tt>
     */
    public T getNamedObject(String name) {
        readLock.lock();
        try {
            // Get it
            return objects.get(name);
        } finally {
            readLock.unlock();
        }
    }

    /**
     * @return              Returns a copy of the map of instances 
     */
    public Map<String, T> getAllNamedObjects() {
        readLock.lock();
        try {
            // Get it
            return new HashMap<String, T>(objects);
        } finally {
            readLock.unlock();
        }
    }

    public void reset() {
        writeLock.lock();
        try {
            if (storageType == null)
                objects.clear();
        } finally {
            writeLock.unlock();
        }
    }
}