/*
* Copyright (c) 2008-2011 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.response;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ConcurrentMap;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockMirror;
import com.emc.storageos.db.client.model.DataObject;
import com.emc.storageos.db.client.model.ProtectionSet;
import com.emc.storageos.db.client.model.RemoteDirectorGroup;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.VplexMirror;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.model.ResourceTypeEnum;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
public final class RestLinkFactory
{
static private volatile DbClient _dbClient;
static private ConcurrentMap<URI, URI> _linkCache = new ConcurrentLinkedHashMap.Builder<URI, URI>()
.maximumWeightedCapacity(1000) // max 1000 entries
.build();
/* Public Interfaces */
public static URI newLink(DataObject resource) {
if (resource == null) {
throw new NullPointerException();
}
ResourceTypeEnum res = ResourceTypeMapping.getResourceType(resource);
try {
URI parentId;
if (res == null) {
return new URI("/");
}
switch (res) {
case STORAGE_POOL:
parentId = ((StoragePool) resource).getStorageDevice();
return secondaryResourceLink(res.getService(), resource.getId(), parentId);
case STORAGE_PORT:
parentId = ((StoragePort) resource).getStorageDevice();
return secondaryResourceLink(res.getService(), resource.getId(), parentId);
case RDF_GROUP:
parentId = ((RemoteDirectorGroup) resource).getSourceStorageSystemUri();
return secondaryResourceLink(res.getService(), resource.getId(), parentId);
case BLOCK_MIRROR:
parentId = ((BlockMirror) resource).getSource().getURI();
return secondaryResourceLink(res.getService(), resource.getId(), parentId);
case VPLEX_MIRROR:
parentId = ((VplexMirror) resource).getSource().getURI();
return secondaryResourceLink(res.getService(), resource.getId(), parentId);
case PROTECTION_SET:
// any volume in the volume string set is valid
StringSet volumeIDs = ((ProtectionSet) resource).getVolumes();
if (volumeIDs != null && !volumeIDs.isEmpty()) {
for (String volumeID : volumeIDs) {
// No .get(), same as iterator.
return secondaryResourceLink(res.getService(), resource.getId(), new URI(volumeID));
}
}
// This will not produce a good URI, but it's impossible to get here with the dependent data model.
return simpleServiceLink(res.getService(), resource.getId());
default:
return simpleServiceLink(res, resource.getId());
}
} catch (URISyntaxException ex) {
return null; // impossible;
}
}
public static URI newLink(ResourceTypeEnum res, URI resource_id) {
try {
if (resource_id == null) {
return new URI("/");
}
if (res == null) {
return new URI("/" + resource_id);
}
if (res == ResourceTypeEnum.STORAGE_POOL ||
res == ResourceTypeEnum.STORAGE_PORT ||
res == ResourceTypeEnum.BLOCK_MIRROR ||
res == ResourceTypeEnum.RDF_GROUP ||
res == ResourceTypeEnum.VPLEX_MIRROR) {
URI link = _linkCache.get(resource_id);
if (link == null) {
DataObject resource = _dbClient.queryObject(ResourceTypeMapping.getDataObjectClass(res), resource_id);
if (resource != null) {
link = newLink(resource);
_linkCache.put(resource_id, link);
} else {
link = NullColumnValueGetter.getNullURI();
}
}
return link;
}
else {
return simpleServiceLink(res, resource_id);
}
} catch (URISyntaxException ex) {
return null; // impossible;
} catch (DatabaseException ex) {
return null;
}
}
public static URI newLink(ResourceTypeEnum res, URI resourceId, URI parentId) {
try {
if (resourceId == null) {
return new URI("/");
}
if (res == ResourceTypeEnum.STORAGE_POOL ||
res == ResourceTypeEnum.STORAGE_PORT ||
res == ResourceTypeEnum.RDF_GROUP ||
res == ResourceTypeEnum.BLOCK_MIRROR ||
res == ResourceTypeEnum.VPLEX_MIRROR ||
res == ResourceTypeEnum.PROTECTION_SET) {
return secondaryResourceLink(res.getService(), resourceId, parentId);
}
else {
return simpleServiceLink(res, resourceId);
}
} catch (URISyntaxException ex) {
return null; // impossible;
}
}
public static URI newTaskLink(DataObject resource, String op_id)
{
try {
StringBuilder build = (new StringBuilder()).
append(newLink(resource)).
append("/tasks/").
append(op_id);
return new URI(build.toString());
} catch (URISyntaxException ex) {
return null; // imposssible
}
}
public static URI simpleServiceLink(ResourceTypeEnum res, URI resourceId)
throws URISyntaxException {
return simpleServiceLink(res.getService(), resourceId);
}
private static URI simpleServiceLink(String service, URI resourceId) throws URISyntaxException {
StringBuilder build = (new StringBuilder(service)).
append('/').
append(resourceId);
return new URI(build.toString());
}
private static URI secondaryResourceLink(String service, URI resourceId, URI parentId) throws URISyntaxException {
StringBuilder build = (new StringBuilder(String.format(service, parentId))).
append('/').
append(resourceId);
return new URI(build.toString());
}
/**
* Set db client
*
* @param dbClient
*/
public void setDbClient(DbClient dbClient) {
_dbClient = dbClient;
}
}