/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.system.server.profileservice.persistence;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.jboss.managed.api.ManagedComponent;
import org.jboss.managed.api.ManagedObject;
import org.jboss.managed.api.factory.ManagedObjectFactory;
import org.jboss.system.server.profileservice.persistence.component.ComponentMapper;
import org.jboss.system.server.profileservice.persistence.component.ComponentMapperRegistry;
import org.jboss.system.server.profileservice.persistence.xml.ModificationInfo;
import org.jboss.system.server.profileservice.persistence.xml.PersistedComponent;
import org.jboss.system.server.profileservice.persistence.xml.PersistenceRoot;
/**
* The abstract persistence factory.
*
* @author <a href="mailto:emuckenh@redhat.com">Emanuel Muckenhuber</a>
* @version $Revision$
*/
public class AbstractPersistenceFactory extends PersistenceFactory
{
/** The component mapper registry. */
private final ComponentMapperRegistry componentMapper = ComponentMapperRegistry.getInstance();
/** The delegating persistence plugin. */
private final DelegatingPersistencePlugin persistencePlugin;
/** The recreation helper. */
private final ManagedObjectRecreationHelper recreationHelper;
public AbstractPersistenceFactory()
{
this(ManagedObjectFactory.getInstance());
}
public AbstractPersistenceFactory(ManagedObjectFactory managedObjectFactory)
{
super(managedObjectFactory);
this.recreationHelper = new ManagedObjectRecreationHelper(managedObjectFactory);
this.persistencePlugin = new DelegatingPersistencePlugin(recreationHelper);
}
/**
* {@inheritDoc}
*/
public ManagedObjectPersistencePlugin getPersistencePlugin()
{
return persistencePlugin;
}
/**
* Apply the persisted information to a attachment.
*
* @param root the persistence root
* @param attachment the root attachment
* @param classLoader the classloader
*/
@Override
public void restorePersistenceRoot(PersistenceRoot root, Object parentAttachment, ClassLoader classLoader)
{
if(root == null)
throw new IllegalArgumentException("null root");
if(parentAttachment == null)
throw new IllegalArgumentException("null attachment");
if(root.getComponents() != null && root.getComponents().isEmpty() == false)
{
// Set the classloader
recreationHelper.setLoader(classLoader);
try
{
// Restore the components
ComponentMapper mapper = getComponentMapper(root);
for(PersistedComponent component : root.getComponents())
{
mapper.restoreComponent(parentAttachment, component);
}
}
finally
{
recreationHelper.setLoader(null);
}
}
}
/**
* Add a ManagedComponent.
*
* @param root the persistence root
* @param parent the parent managed object
* @param component the managed component
* @return the updated persistence root
*/
@Override
public PersistenceRoot addComponent(PersistenceRoot root, ManagedObject parent, ManagedComponent component)
{
if(root == null)
throw new IllegalArgumentException("null persistence root");
ComponentMapper mapper = getComponentMapper(parent);
PersistedComponent persistedComponent = mapper.addComponent(parent.getAttachment(), component);
return addPersistedComponent(root, persistedComponent);
}
/**
* Remove a ManagedComponent.
*
* @param root the persistence root
* @param parent the parent managed object
* @param component the managed component
* @return the updated persistence root
*/
@Override
public PersistenceRoot removeComponent(PersistenceRoot root, ManagedObject parent, ManagedComponent component)
{
if(root == null)
throw new IllegalArgumentException("null persistence root");
ComponentMapper mapper = getComponentMapper(parent);
PersistedComponent persistedComponent = mapper.removeComponent(parent.getAttachment(), component);
return addPersistedComponent(root, persistedComponent);
}
/**
* Update a ManagedComponent.
*
* @param root the persistence root
* @param parent the parent managed object
* @param component the managed component
* @return the updated persistence root
*/
@Override
public PersistenceRoot updateComponent(PersistenceRoot root, ManagedObject parent, ManagedComponent component)
{
if(root == null)
throw new IllegalArgumentException("null persistence root");
ComponentMapper mapper = getComponentMapper(parent);
PersistedComponent persistedComponent = mapper.updateComponent(parent.getAttachment(), component);
return addPersistedComponent(root, persistedComponent);
}
/**
* Reset a component. This will remove the persisted information.
*
* @param root the persistence root
* @param parent the parent managed object
* @param component the managed component
* @return the updated persistence root
*/
@Override
public PersistenceRoot resetComponent(PersistenceRoot root, ManagedObject parent, ManagedComponent component)
{
ComponentMapper mapper = getComponentMapper(parent);
PersistedComponent persistedComponent = mapper.updateComponent(parent.getAttachment(), component);
// Map the components
Map<String, PersistedComponent> components = mapComponents(root);
// Remove the component
PersistedComponent previous = components.remove(persistedComponent.getOriginalName());
if(previous == null)
previous = components.remove(persistedComponent.getName());
// Set the new values
root.setComponents(new ArrayList<PersistedComponent>(components.values()));
return root;
}
/**
* Add a persisted component to the root. This will map and override
* existing components.
*
* @param root the persistence root
* @param component the persisted component
* @return the update persistence root
*/
protected PersistenceRoot addPersistedComponent(PersistenceRoot root, PersistedComponent component)
{
Map<String, PersistedComponent> components = mapComponents(root);
PersistedComponent previous = components.remove(component.getOriginalName());
if(previous == null)
previous = components.remove(component.getName());
// Add the persisted component
components.put(component.getName(), component);
// Override with some previous information
if(previous != null)
{
// A added component should remain on added
if(previous.getModificationInfo() == ModificationInfo.ADDED
&& component.getModificationInfo() == ModificationInfo.MODIFIED)
component.setModificationInfo(ModificationInfo.ADDED);
// Just remove a previously added component
if(previous.getModificationInfo() == ModificationInfo.ADDED
&& component.getModificationInfo() == ModificationInfo.REMOVED)
components.remove(component.getName());
// Override the name
if(previous.getOriginalName() != null)
component.setOriginalName(previous.getOriginalName());
}
root.setComponents(new ArrayList<PersistedComponent>(components.values()));
return root;
}
/**
* Get the component mapper for a given ManagedObject.
*
* @param parent the managed object
* @return the component mapper
* @throws IllegalStateException if no mapper is registered for this type
*/
protected ComponentMapper getComponentMapper(ManagedObject parent)
{
ComponentMapper mapper = null;
if(parent.getAttachmentName() != null)
mapper = getComponentMapper(parent.getAttachmentName());
if(mapper == null && parent.getAttachment() != null)
mapper = getComponentMapper(parent.getAttachment().getClass().getName());
if(mapper == null)
throw new IllegalStateException("no mapper registered for type: " + parent.getAttachmentName());
return mapper;
}
/**
* Get the component mapper for a persistence root.
*
* @param root the persistence root
* @return the component mapper
* @throws IllegalStateException if no mapper is registered for this type
*/
protected ComponentMapper getComponentMapper(PersistenceRoot root)
{
ComponentMapper mapper = null;
if(root.getName() != null)
mapper = getComponentMapper(root.getName());
if(root.getClassName() != null)
mapper = getComponentMapper(root.getClassName());
if(mapper == null)
throw new IllegalStateException("no mapper registered for type: " + root);
return mapper;
}
/**
* Get the component mapper for a given type.
*
* @param type the type
* @return the component mapper, null if not registered
* @throw IllegalArgumentException for a null type
*/
protected ComponentMapper getComponentMapper(String type)
{
if(type == null)
throw new IllegalArgumentException("null type");
return componentMapper.getMapper(type);
}
/**
* Map the components based on their names.
*
* @param root the persistence root
* @return a map of persisted components
*/
protected static Map<String, PersistedComponent> mapComponents(PersistenceRoot root)
{
Map<String, PersistedComponent> map = new HashMap<String, PersistedComponent>();
if(root.getComponents() != null && root.getComponents().isEmpty() == false)
{
for(PersistedComponent component : root.getComponents())
{
// Map this based on the name, as this should
// match the original name of the new component
map.put(component.getName(), component);
}
}
return map;
}
/**
* InstallCallback for adding a component mapper.
*
* @param mapper the component mapper
*/
public void addComponentMapper(ComponentMapper mapper)
{
componentMapper.addMapper(mapper);
}
/**
* UnInstallCallback for removing a component mapper.
*
* @param mapper the component mapper
* @return the removed component mapper
*/
public ComponentMapper removeComponentMapper(ComponentMapper mapper)
{
return componentMapper.removeComponentMapper(mapper);
}
/**
* InstallCallback for adding a persistence plugin.
*
* @param plugin the persistence plugin
*/
public void addPersistencePlugin(ManagedObjectPersistencePlugin plugin)
{
persistencePlugin.addPlugin(plugin);
}
/**
* UnInstallCallback for removing a persistence plugin.
*
* @param plugin the plugin
*/
public void removePersistencePlugin(ManagedObjectPersistencePlugin plugin)
{
persistencePlugin.removePlugin(plugin);
}
}