package com.temenos.interaction.winkext;
/*
* #%L
* interaction-winkext
* %%
* Copyright (C) 2012 - 2013 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.wink.common.DynamicResource;
import org.apache.wink.common.WinkApplication;
import org.apache.wink.common.internal.registry.ProvidersRegistry;
import org.apache.wink.server.internal.registry.ResourceRegistry;
import org.apache.wink.spring.Registrar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.temenos.interaction.core.rim.HTTPResourceInteractionModel;
import com.temenos.interaction.core.rim.ResourceInteractionModel;
import com.temenos.interaction.springdsl.RIMRegistration;
/**
* Extend the Wink Spring support to be able to bind Providers such as JAXB / JSON.
* This class requires the wink-spring-support be a 'compile' time dependency.
* @author aphethean
*/
public class RegistrarWithSingletons extends Registrar implements RIMRegistration {
private Set<Object> singletons = Collections.emptySet();
private static final Logger LOGGER = LoggerFactory.getLogger(RegistrarWithSingletons.class);
// key = resourcePath
private Map<String, DynamicResourceDelegate> resources = new HashMap<String, DynamicResourceDelegate>();
ResourceRegistry resourceRegistry;
public RegistrarWithSingletons() {
if (this.getInstances() == null) {
this.setInstances(new HashSet<Object>());
}
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
public void setSingletons(final Set<Object> singletons) {
this.singletons = singletons;
}
/**
* Using a ServiceRootFactory get a set of service roots to bind to this instance of wink.
*/
public void setServiceRootFactory(ServiceRootFactory drs) {
setServiceRoots(drs.getServiceRoots());
}
/**
* @precondition Set<HTTPResourceInteractionModel> != null
* @param rootRIMs
*/
public void setServiceRoots(Set<HTTPResourceInteractionModel> rootRIMs) {
if (rootRIMs == null)
throw new IllegalArgumentException("Must provide a set of resource interaction models");
for (HTTPResourceInteractionModel rim : rootRIMs)
registerAll(rim);
}
public void setServiceRoot(HTTPResourceInteractionModel rootRIM) {
registerAll(rootRIM);
}
private void registerAll(ResourceInteractionModel rim) {
register((HTTPResourceInteractionModel) rim);
Collection<ResourceInteractionModel> children = rim.getChildren();
if (children != null) {
for (ResourceInteractionModel child : children) {
register((HTTPResourceInteractionModel) child);
}
}
}
/**
* Using the path lookup the resource; return null if a resource has not been previously registered.
* @param path
* @return
*/
public HTTPResourceInteractionModel getDynamicResource(String path) {
return resources.get(path);
}
@Override
public void register(HTTPResourceInteractionModel rim) {
LOGGER.info("Attempting to add resource: " + rim.getResourcePath());
assert this.getInstances() != null;
String rimKey = rim.getFQResourcePath();
if (resources.get(rimKey) != null)
return;
DynamicResource parent = null;
// is this a root resource
if (rim.getParent() != null) {
// climb back up the graph adding parent if necessary
String parentKey = rim.getParent().getFQResourcePath();
if (resources.get(parentKey) == null) {
register((HTTPResourceInteractionModel) rim.getParent());
}
parent = resources.get(parentKey);
}
//Register the resource
HTTPResourceInteractionModel parentResource = parent != null ? (HTTPResourceInteractionModel) parent : null;
DynamicResourceDelegate dr = new DynamicResourceDelegate(parentResource, rim);
resources.put(rimKey, dr);
if(resourceRegistry != null) {
resourceRegistry.addResource(dr, WinkApplication.DEFAULT_PRIORITY);
}
this.getInstances().add(dr);
//Ensure OData collection resources are available with and without empty brackets (e.g. /customers() and /customers)
if(rimKey.endsWith("()")) {
String pathWithoutBrackets = rimKey.substring(0, rimKey.length() - 2);
final DynamicResourceDelegate drWithoutBrackets = new DynamicResourceDelegate(parentResource, rim) {
@Override
public String getPath() {
String resourcePath = super.getResourcePath();
return resourcePath.substring(0, resourcePath.length() - 2);
}
};
resources.put(pathWithoutBrackets, drWithoutBrackets);
if(resourceRegistry != null) {
resourceRegistry.addResource(drWithoutBrackets, WinkApplication.DEFAULT_PRIORITY);
}
this.getInstances().add(drWithoutBrackets);
}
}
@Override
public void register(ResourceRegistry resourceRegistry, ProvidersRegistry providersRegistry) {
super.register(resourceRegistry, providersRegistry);
this.resourceRegistry = resourceRegistry;
}
}