/*
* Copyright (c) 2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.resource.utils;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.model.FSExportMap;
import com.emc.storageos.db.client.model.FileExport;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.SMBFileShare;
import com.emc.storageos.db.client.model.SMBShareMap;
import com.emc.storageos.db.client.model.StorageHADomain;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.StringSetMap;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedFSExport;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedFSExportMap;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedSMBFileShare;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedSMBShareMap;
import com.emc.storageos.util.ExportUtils;
public class PropertySetterUtil {
private static final Logger _logger = LoggerFactory.getLogger(PropertySetterUtil.class);
/**
* Mapping between Key present in VolumeInfo's StringSetMap
* and Method Name used in Model Object.
* e.g.ALLOCATED_CAPACITY("setAllocatedCapacity")
* setAllocatedCapacity is the method Name used in Volume Model
* to persist Allocated Capacity.
*
* This logic helps me to avoid writing lot of lines of code
* for each property within Volume Object.
*
*/
public enum VolumeObjectProperties {
ALLOCATED_CAPACITY("setAllocatedCapacity"),
PROVISIONED_CAPACITY("setProvisionedCapacity"),
TOTAL_CAPACITY("setCapacity"),
STORAGE_POOL("setPool"),
WWN("setWWN"),
IS_THINLY_PROVISIONED("setThinlyProvisioned"),
NATIVE_ID("setNativeId"),
NAME("setAlternateName");
private String _methodName;
VolumeObjectProperties(String methodName) {
_methodName = methodName;
}
public String getMethodName() {
return _methodName;
}
}
/**
* Mapping between Key present in FileSystemInfo's StringSetMap
* and Method Name used in Model Object.
* e.g.ALLOCATED_CAPACITY("setAllocatedCapacity")
* setAllocatedCapacity is the method Name used in FileSystem Model
* to persist Allocated Capacity.
*
* This logic helps me to avoid writing lot of lines of code
* for each property within FileSystem Object.
*
*/
public enum FileSystemObjectProperties {
ALLOCATED_CAPACITY("setAllocatedCapacity"),
PROVISIONED_CAPACITY("setProvisionedCapacity"),
TOTAL_CAPACITY("setCapacity"),
STORAGE_POOL("setPool"),
IS_THINLY_PROVISIONED("setThinlyProvisioned"),
NATIVE_ID("setNativeId"),
NAME("setAlternateName");
private String _methodName;
FileSystemObjectProperties(String methodName) {
_methodName = methodName;
}
public String getMethodName() {
return _methodName;
}
}
/**
* TypeCast based on the argument type
* In reality, the setter Method in Model Object will be always one
* and also , we would be having 2 -3 different datatypes within a Model.
* This logic helps to avoid lot of coding within Block Service, while creating
* a Model Object.
*
* @param value
* @param method
* @return
*/
public static Object typeCast(String value, Method method) {
Class[] parameterTypes = method.getParameterTypes();
if (parameterTypes[0].toString().contains("Long")) {
return Long.parseLong(value);
} else if (parameterTypes[0].toString().contains("String")) {
return value;
} else if (parameterTypes[0].toString().contains("Boolean")) {
return Boolean.parseBoolean(value);
}
return null;
}
/**
* get Method Name
*
* @param methodName
* @param instance
*
* @return Method
*/
public static Method getMethod(String methodName, Object instance) {
Method[] methods = instance.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equalsIgnoreCase(methodName)) {
return m;
}
}
return null;
}
/**
* VolumeObjectProperties, an enum, associating key with its MethodName
* e.g. invoke volume.setAllocatedCapacity(allocatedCapacity).
*
* In the above example, AllocatedCapacity is the key , and its methodName is
* setAllocatedCapacity. This relation is maintained in VolumeObjectproperties Enum.
*
* The code looks clumsy, if we get each property from set, and invoke its
* associated Method on Volume instance.
*
* Instead, the idea here is to use reflection to invoke the right Method on volume
* Instance, based on the key Provided.
*
* @param volumeObjectproperties
* @param value
* @param instance
*/
public static void addPropertyIntoObject(VolumeObjectProperties key, String value, Object instance) throws Exception {
if (null != value) {
Method method = PropertySetterUtil.getMethod(key.getMethodName(), instance);
if (null == method) {
return;
}
Object typeCastedValue = PropertySetterUtil.typeCast(value, method);
if (null == typeCastedValue) {
return;
}
Object[] args = new Object[] { typeCastedValue };
if (null != method) {
method.invoke(instance, args);
}
}
}
/**
* filesystemObjectProperties, an enum, associating key with its MethodName
* e.g. invoke FileSystem.setAllocatedCapacity(allocatedCapacity).
*
* In the above example, AllocatedCapacity is the key , and its methodName is
* setAllocatedCapacity. This relation is maintained in FileSystemObjectProperties Enum.
*
*
* Instead, the idea here is to use reflection to invoke the right Method on filesystem
* Instance, based on the key Provided.
*
* @param filesystemObjectproperties
* @param value
* @param instance
*/
public static void addPropertyIntoObject(FileSystemObjectProperties key, String value, Object instance) throws Exception {
if (null != value) {
Method method = PropertySetterUtil.getMethod(key.getMethodName(), instance);
if (null == method) {
return;
}
Object typeCastedValue = PropertySetterUtil.typeCast(value, method);
if (null == typeCastedValue) {
return;
}
Object[] args = new Object[] { typeCastedValue };
if (null != method) {
method.invoke(instance, args);
}
}
}
/**
* extract value from a String Set
* This method is used, to get value from a StringSet of size 1.
*
* @param key
* @param volumeInformation
* @return String
*/
public static String extractValueFromStringSet(String key, StringSetMap volumeInformation) {
try {
StringSet availableValueSet = volumeInformation.get(key);
if (null != availableValueSet) {
for (String value : availableValueSet) {
return value;
}
}
} catch (Exception e) {
_logger.error(e.getMessage(), e);
}
return null;
}
/**
* extract values from a String Set
* This method is used, to get value from a StringSet of variable size.
*
* @param key
* @param volumeInformation
* @return String[]
*/
public static StringSet extractValuesFromStringSet(String key, StringSetMap volumeInformation) {
try {
StringSet returnSet = new StringSet();
StringSet availableValueSet = volumeInformation.get(key);
if (null != availableValueSet) {
for (String value : availableValueSet) {
returnSet.add(value);
}
}
return returnSet;
} catch (Exception e) {
_logger.error(e.getMessage(), e);
}
return null;
}
/**
* VolumeObjectProperties, an enum, associating key with its MethodName
* e.g. invoke volume.setAllocatedCapacity(allocatedCapacity).
*
* In the above example, AllocatedCapacity is the key , and its methodName is
* setAllocatedCapacity. This relation is maintained in VolumeObjectproperties Enum.
*
* The code looks clumsy, if we get each property from set, and invoke its
* associated Method on Volume instance.
*
* Instead, the idea here is to use reflection to invoke the right Method on volume
* Instance, based on the key Provided.
*
* @param volumeInformation
* @param volume
* @param key
*/
private static void addVolumeDetail(
StringSetMap volumeInformation, Volume volume, VolumeObjectProperties key)
throws Exception {
String value = PropertySetterUtil.extractValueFromStringSet(key.toString(), volumeInformation);
PropertySetterUtil.addPropertyIntoObject(key, value, volume);
}
/**
* FileSystemObjectProperties, an enum, associating key with its MethodName
* e.g. invoke filesystem.setAllocatedCapacity(allocatedCapacity).
*
* In the above example, AllocatedCapacity is the key , and its methodName is
* setAllocatedCapacity. This relation is maintained in FileSystemObjectproperties Enum.
*
* The code looks clumsy, if we get each property from set, and invoke its
* associated Method on FileSystem instance.
*
* Instead, the idea here is to use reflection to invoke the right Method on filesystem
* Instance, based on the key Provided.
*
* @param filesystemInformation
* @param filesystem
* @param key
*/
private static void addFileSystemDetail1(
StringSetMap filesystemInformation, FileShare filesystem, FileSystemObjectProperties key)
throws Exception {
String value = PropertySetterUtil.extractValueFromStringSet(key.toString(), filesystemInformation);
PropertySetterUtil.addPropertyIntoObject(key, value, filesystem);
}
/**
* Extract Details from UnManaged Volume Object and add to Volume Object.
*
* @param volumeInformation
* @param volumeInfo
* @param volume
* @return
*/
public static Volume addVolumeDetails(StringSetMap volumeInformation, Volume volume)
throws Exception {
for (VolumeObjectProperties volumeObjectProp : VolumeObjectProperties.values()) {
addVolumeDetail(volumeInformation, volume, volumeObjectProp);
}
return volume;
}
/**
* Extract Details from UnManaged filesystem Object and add to filesystem Object.
*
* @param filesystemInformation
* @param filesystemInfo
* @param filesystem
* @return
*/
public static FileShare addFileSystemDetails(StringSetMap filesystemInformation, FileShare filesystem)
throws Exception {
for (FileSystemObjectProperties filesystemObjectProp : FileSystemObjectProperties.values()) {
addFileSystemDetail1(filesystemInformation, filesystem, filesystemObjectProp);
}
return filesystem;
}
/**
* Extract SMB data from UnManaged to Managed
*
* @param unManagedSMBShareMap
* @return
*/
public static SMBShareMap convertUnManagedSMBMapToManaged(
UnManagedSMBShareMap unManagedSMBShareMap, StoragePort storagePort, StorageHADomain dataMover) {
SMBShareMap smbShareMap = new SMBShareMap();
if (unManagedSMBShareMap == null) {
return smbShareMap;
}
SMBFileShare smbshare = null;
for (UnManagedSMBFileShare unManagedSMBFileShare : unManagedSMBShareMap.values()) {
smbshare = new SMBFileShare();
smbshare.setName(unManagedSMBFileShare.getName());
smbshare.setNativeId(unManagedSMBFileShare.getNativeId());
smbshare.setDescription(unManagedSMBFileShare.getDescription());
if (storagePort != null) {
smbshare.setMountPoint("\\\\" + storagePort.getPortNetworkId() + "\\" + unManagedSMBFileShare.getName());
} else {
smbshare.setMountPoint(unManagedSMBFileShare.getMountPoint());
}
smbshare.setPath(unManagedSMBFileShare.getPath());
// need to removed
smbshare.setMaxUsers(unManagedSMBFileShare.getMaxUsers());
smbshare.setPermission(unManagedSMBFileShare.getPermission());
smbshare.setPermissionType(unManagedSMBFileShare.getPermissionType());
smbshare.setPortGroup(storagePort.getPortGroup());
// share name
smbShareMap.put(unManagedSMBFileShare.getName(), smbshare);
}
return smbShareMap;
}
/**
* extract value from a String Set
* This method is used, to get value from a StringSet of size 1.
*
* @param key
* @param volumeInformation
* @return String
*/
public static FSExportMap convertUnManagedExportMapToManaged(
UnManagedFSExportMap unManagedFSExportMap, StoragePort storagePort, StorageHADomain dataMover) {
FSExportMap fsExportMap = new FSExportMap();
if (unManagedFSExportMap == null) {
return fsExportMap;
}
for (UnManagedFSExport export : unManagedFSExportMap.values()) {
FileExport fsExport = new FileExport();
if (null != export.getIsilonId()) {
fsExport.setIsilonId(export.getIsilonId());
}
if (null != export.getNativeId()) {
fsExport.setNativeId(export.getNativeId());
}
if (null != storagePort) {
fsExport.setStoragePort(storagePort.getPortName());
if ((export.getMountPath() != null) && (export.getMountPath().length() > 0)) {
fsExport.setMountPoint(ExportUtils.getFileMountPoint(storagePort.getPortNetworkId(), export.getMountPath()));
} else {
fsExport.setMountPoint(ExportUtils.getFileMountPoint(storagePort.getPortNetworkId(), export.getPath()));
}
} else if (null != export.getStoragePort()) {
fsExport.setStoragePort(export.getStoragePort());
if (null != export.getMountPoint()) {
fsExport.setMountPoint(export.getMountPoint());
}
}
if (null != dataMover) {
fsExport.setStoragePortName(dataMover.getName());
} else if (null != storagePort) {
fsExport.setStoragePortName(storagePort.getPortName());
} else if (null != export.getStoragePortName()) {
fsExport.setStoragePortName(export.getStoragePortName());
}
if (null != export.getMountPath()) {
fsExport.setMountPath(export.getMountPath());
}
fsExport.setPath(export.getPath());
fsExport.setPermissions(export.getPermissions());
fsExport.setProtocol(export.getProtocol());
fsExport.setRootUserMapping(export.getRootUserMapping());
fsExport.setSecurityType(export.getSecurityType());
fsExport.setClients(export.getClients());
fsExportMap.put(fsExport.getFileExportKey(), fsExport);
}
return fsExportMap;
}
}