/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* 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.picketlink.idm.internal;
import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import org.picketlink.idm.AttributedTypeManager;
import org.picketlink.idm.IdGenerator;
import org.picketlink.idm.IdentityManagementException;
import org.picketlink.idm.event.EventBridge;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.AttributedType;
import org.picketlink.idm.model.Partition;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.spi.AttributeStore;
import org.picketlink.idm.spi.IdentityContext;
import org.picketlink.idm.spi.StoreSelector;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.picketlink.idm.IDMInternalMessages.MESSAGES;
/**
* @author pedroigor
*/
public abstract class AbstractAttributedTypeManager<T extends AttributedType> implements AttributedTypeManager<T> {
private final IdentityContext identityContext;
private final PartitionManagerConfiguration configuration;
AbstractAttributedTypeManager(PartitionManagerConfiguration configuration, Partition partition) {
this.configuration = configuration;
this.identityContext = createIdentityContext(partition, configuration.getEventBridge(), configuration.getIdGenerator());
}
public AbstractAttributedTypeManager(PartitionManagerConfiguration configuration) {
this(configuration, null);
}
public AbstractAttributedTypeManager(DefaultPartitionManager partitionManager) {
this(partitionManager.getConfiguration(), null);
}
@Override
public void add(T attributedType) throws IdentityManagementException {
if (attributedType == null) {
throw MESSAGES.nullArgument("AttributedType");
}
checkUniqueness(attributedType);
try {
doAdd(attributedType);
addAttributes(identityContext, attributedType);
fireAttributedTypeAddedEvent(attributedType);
} catch (Exception e) {
throw MESSAGES.attributedTypeAddFailed(attributedType, e);
}
}
protected abstract void fireAttributedTypeAddedEvent(T attributedType);
protected abstract void doAdd(T attributedType);
@Override
public void update(T attributedType) throws IdentityManagementException {
if (attributedType == null) {
throw MESSAGES.nullArgument("AttributedType");
}
checkIfExists(attributedType);
try {
doUpdate(attributedType);
T storedType = lookupById((Class<T>) attributedType.getClass(), attributedType.getId());
removeAttributes(identityContext, attributedType, storedType);
addAttributes(identityContext, attributedType);
fireAttributedTypeUpdatedEvent(attributedType);
} catch (Exception e) {
throw MESSAGES.attributedTypeUpdateFailed(attributedType, e);
}
}
protected abstract void fireAttributedTypeUpdatedEvent(T attributedType);
protected abstract void doUpdate(T attributedType);
@Override
public void remove(T attributedType) throws IdentityManagementException {
if (attributedType == null) {
throw MESSAGES.nullArgument("AttributedType");
}
checkIfExists(attributedType);
try {
T storedType = lookupById((Class<T>) attributedType.getClass(), attributedType.getId());
removeAllAttributes(storedType);
doRemove(attributedType);
fireAttributedTypeRemovedEvent(attributedType);
} catch (Exception e) {
throw MESSAGES.attributedTypeRemoveFailed(attributedType, e);
}
}
protected abstract void fireAttributedTypeRemovedEvent(T attributedType);
protected abstract void doRemove(T attributedType);
protected abstract void checkUniqueness(T attributedType) throws IdentityManagementException;
protected abstract void checkIfExists(T attributedType) throws IdentityManagementException;
protected void fireEvent(Object event) {
getEventBridge().raiseEvent(event);
}
protected EventBridge getEventBridge() {
return getIdentityContext().getEventBridge();
}
protected IdentityContext createIdentityContext(Partition partition, EventBridge eventBridge, IdGenerator idGenerator) {
return new DefaultIdentityContext(partition, eventBridge, idGenerator);
}
protected IdGenerator getIdGenerator() {
return getIdentityContext().getIdGenerator();
}
protected void addAttributes(IdentityContext identityContext, AttributedType identityType) {
AttributeStore<?> attributeStore = getStoreSelector().getStoreForAttributeOperation(identityContext);
if (attributeStore != null) {
for (Attribute<? extends Serializable> attribute : getAttributes(identityContext, identityType).values()) {
attributeStore.setAttribute(identityContext, identityType, attribute);
}
}
}
protected void removeAttributes(IdentityContext identityContext, AttributedType identityType, AttributedType storedType) {
AttributeStore<?> attributeStore = getStoreSelector().getStoreForAttributeOperation(identityContext);
if (attributeStore != null) {
if (storedType != null) {
Map<String, Attribute> attributes = getAttributes(identityContext, identityType);
for (Attribute<? extends Serializable> attribute : storedType.getAttributes()) {
if (attributes.get(attribute.getName()) == null) {
attributeStore.removeAttribute(identityContext, identityType, attribute.getName());
}
}
}
}
}
protected void removeAllAttributes(AttributedType storedType) {
AttributeStore<?> attributeStore = getStoreSelector().getStoreForAttributeOperation(identityContext);
if (attributeStore != null) {
for (Attribute<? extends Serializable> attribute : storedType.getAttributes()) {
attributeStore.removeAttribute(identityContext, storedType, attribute.getName());
}
}
}
private Map<String, Attribute> getAttributes(IdentityContext identityContext, AttributedType identityType) {
Map<String, Attribute> attributes = new HashMap<String, Attribute>();
for (Attribute attribute : identityType.getAttributes()) {
attributes.put(attribute.getName(), attribute);
}
List<Property<Object>> properties = PropertyQueries.createQuery(identityType.getClass())
.addCriteria(new AnnotatedPropertyCriteria(AttributeProperty.class))
.getResultList();
for (Property property : properties) {
AttributeProperty attributeProperty = property.getAnnotatedElement().getAnnotation(AttributeProperty.class);
if (attributeProperty.managed()) {
String attributeName = property.getName();
Object attributeValue = property.getValue(identityType);
if (attributeValue != null) {
attributes.put(attributeName, new Attribute(attributeName, (Serializable) attributeValue));
} else {
attributes.remove(attributeName);
}
}
}
return attributes;
}
public StoreSelector getStoreSelector() {
return this.configuration.getStoreSelector();
}
public IdentityContext getIdentityContext() {
return this.identityContext;
}
protected PartitionManagerConfiguration getConfiguration() {
return this.configuration;
}
}