/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.sa.model.dao; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.constraint.NamedElementQueryResultList.NamedElement; import com.emc.storageos.db.client.model.*; import com.emc.storageos.db.client.model.uimodels.*; import com.google.common.collect.Maps; import java.net.URI; import java.util.Calendar; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Chris Dail */ public class ModelClient { /** Pattern for finding the 'type' from an ID. */ private static final Pattern TYPE_PATTERN = Pattern.compile("urn\\:storageos\\:([^\\:]+)"); /** The mapping of 'type' to classes. */ private static Map<String, Class<? extends DataObject>> CLASSES = Maps.newHashMap(); static { initClasses(); } private DBClientWrapper client; // JM -- Don't attempt to instantiate the DAO fields directly, this will be called before the client field // is initialized in the constructor causing NPEs private ApprovalRequestFinder approvalRequestDAO; private CatalogCategoryFinder catalogCategoryDAO; private CatalogServiceFinder catalogServiceDAO; private CatalogServiceFieldFinder catalogServiceFieldDAO; private CatalogImageFinder catalogImageDAO; private DatacenterFinder datacenterDAO; private ESXHostFinder esxHostDAO; private ModelFinder<ExecutionLog> executionLogDAO; private ModelFinder<ExecutionState> executionStateDAO; private ModelFinder<ExecutionTaskLog> executionTaskLogDAO; private ExecutionWindowFinder executionWindowDAO; private OrderFinder orderModelDAO; private OrderParameterFinder orderParameterDAO; private ScheduledEventFinder scheduledEventModelDAO; private RecentServiceFinder recentServiceDAO; private VCenterFinder vcenterDAO; private VirtualMachineFinder virtualMachineDAO; private PreferencesFinder preferencesFinder; private HostFinder hostDAO; private InitiatorFinder initiatorDAO; private IpInterfaceFinder ipInterfaceDAO; private ClusterFinder clusterDAO; private ActionableEventFinder actionableEventDAO; public ModelClient(DBClientWrapper client) { this.client = client; } public DBClientWrapper getModelClient() { return client; } public <T extends DataObject> ModelFinder<T> of(final Class<T> clazz) { return new ModelFinder<T>(clazz, client); } public <T extends DataObject> void save(T model) throws DataAccessException { boolean isNew = isNew(model); setIdIfRequired(model); setInactiveIfRequired(model); setCreationTimeIfRequired(model); setLastUpdatedIfRequired(model); if (isNew) { // Force setting the inactive flag model.setInactive(model != null && model.getInactive()); client.create(model); } else { client.update(model); } } public <T extends DataObject> void delete(T model) throws DataAccessException { client.delete(model); } public <T extends DataObject> void delete(List<T> models) throws DataAccessException { client.delete(models); } public <T extends DataObject> List<URI> findByType(Class<T> clazz) { return client.findAllIds(clazz); } public <T extends DataObject> List<T> findByIds(Class<T> clazz, List<URI> ids) { return client.findByIds(clazz, ids); } public <T extends DataObject> T findById(Class<T> clazz, URI id) { return client.findById(clazz, id); } public <T extends DataObject> List<NamedElement> findBy(Class<T> clazz, String columnField, URI id) { return client.findBy(clazz, columnField, id); } /** * Finds an object by ID. * * @param id * the ID of the object. * @return the object. */ public <T extends DataObject> T findById(URI id) { if (id == null) { throw new DataAccessException("ID provided was null"); } Class<T> modelClass = getModelClass(id); if (modelClass != null) { return of(modelClass).findById(id); } else { return null; } } /** * Finds an object by ID. * * @param id * the ID of the object. * @return the object. */ public <T extends DataObject> T findById(String id) { if (id == null) { throw new DataAccessException("ID provided was null"); } return findById(URI.create(id)); } public <T extends DataObject> List<NamedElement> findByAlternateId(Class<T> clazz, String columnField, String value) { return client.findByAlternateId(clazz, columnField, value); } public <T extends DataObject> List<NamedElement> findByLabel(Class<T> clazz, String label) { return client.findByPrefix(clazz, "label", label); } public ApprovalRequestFinder approvalRequests() { if (approvalRequestDAO == null) { approvalRequestDAO = new ApprovalRequestFinder(client); } return approvalRequestDAO; } public CatalogCategoryFinder catalogCategories() { if (catalogCategoryDAO == null) { catalogCategoryDAO = new CatalogCategoryFinder(client); } return catalogCategoryDAO; } public CatalogServiceFinder catalogServices() { if (catalogServiceDAO == null) { catalogServiceDAO = new CatalogServiceFinder(client); } return catalogServiceDAO; } public CatalogServiceFieldFinder catalogServiceFields() { if (catalogServiceFieldDAO == null) { catalogServiceFieldDAO = new CatalogServiceFieldFinder(client); } return catalogServiceFieldDAO; } public CatalogImageFinder catalogImages() { if (catalogImageDAO == null) { catalogImageDAO = new CatalogImageFinder(client); } return catalogImageDAO; } public DatacenterFinder datacenters() { if (datacenterDAO == null) { datacenterDAO = new DatacenterFinder(client); } return datacenterDAO; } public ESXHostFinder esxHosts() { if (esxHostDAO == null) { esxHostDAO = new ESXHostFinder(client); } return esxHostDAO; } public ModelFinder<ExecutionLog> executionLogs() { if (executionLogDAO == null) { executionLogDAO = of(ExecutionLog.class); } return executionLogDAO; } public ModelFinder<ExecutionState> executionStates() { if (executionStateDAO == null) { executionStateDAO = of(ExecutionState.class); } return executionStateDAO; } public ModelFinder<ExecutionTaskLog> executionTaskLogs() { if (executionTaskLogDAO == null) { executionTaskLogDAO = of(ExecutionTaskLog.class); } return executionTaskLogDAO; } public ExecutionWindowFinder executionWindows() { if (executionWindowDAO == null) { executionWindowDAO = new ExecutionWindowFinder(client); } return executionWindowDAO; } public OrderFinder orders() { if (orderModelDAO == null) { orderModelDAO = new OrderFinder(client); } return orderModelDAO; } public OrderParameterFinder orderParameters() { if (orderParameterDAO == null) { orderParameterDAO = new OrderParameterFinder(client); } return orderParameterDAO; } public ScheduledEventFinder scheduledEvents() { if (scheduledEventModelDAO == null) { scheduledEventModelDAO = new ScheduledEventFinder(client); } return scheduledEventModelDAO; } @Deprecated public RecentServiceFinder recentServices() { if (recentServiceDAO == null) { recentServiceDAO = new RecentServiceFinder(client); } return recentServiceDAO; } public VCenterFinder vcenters() { if (vcenterDAO == null) { vcenterDAO = new VCenterFinder(client); } return vcenterDAO; } public VirtualMachineFinder virtualMachines() { if (virtualMachineDAO == null) { virtualMachineDAO = new VirtualMachineFinder(client); } return virtualMachineDAO; } public PreferencesFinder preferences() { if (preferencesFinder == null) { preferencesFinder = new PreferencesFinder(client); } return preferencesFinder; } public HostFinder hosts() { if (hostDAO == null) { hostDAO = new HostFinder(client); } return hostDAO; } public ActionableEventFinder actionableEvents() { if (actionableEventDAO == null) { actionableEventDAO = new ActionableEventFinder(client); } return actionableEventDAO; } public InitiatorFinder initiators() { if (initiatorDAO == null) { initiatorDAO = new InitiatorFinder(client); } return initiatorDAO; } public IpInterfaceFinder ipInterfaces() { if (ipInterfaceDAO == null) { ipInterfaceDAO = new IpInterfaceFinder(client); } return ipInterfaceDAO; } public ClusterFinder clusters() { if (clusterDAO == null) { clusterDAO = new ClusterFinder(client); } return clusterDAO; } private TenantPreferencesFinder tenantPreferencesDAO; public TenantPreferencesFinder tenantPreferences() { if (tenantPreferencesDAO == null) { tenantPreferencesDAO = new TenantPreferencesFinder(client); } return tenantPreferencesDAO; } private <T extends DataObject> boolean isNew(T model) { if (model != null) { // We automatically set ID/creation time so they will be null for new objects only // Occasionally ID has to be set before save, so check either field return (model.getId() == null) || (model.getCreationTime() == null); } return false; } private <T extends DataObject> void setIdIfRequired(T model) { if (model != null && model.getId() == null) { model.setId(URIUtil.createId(model.getClass())); } } private <T extends DataObject> void setInactiveIfRequired(T model) { if (model != null && (model.getInactive() == null)) { model.setInactive(false); } } private <T extends DataObject> void setCreationTimeIfRequired(T model) { if (model != null && model.getCreationTime() == null) { model.setCreationTime(Calendar.getInstance()); } } private <T extends DataObject> void setLastUpdatedIfRequired(T model) { if (model instanceof ModelObject) { ((ModelObject) model).markUpdated(); } else if (model instanceof ModelObjectWithACLs) { ((ModelObjectWithACLs) model).markUpdated(); } } public static String getTypeName(URI id) { return getTypeName(id.toString()); } public static String getTypeName(String id) { Matcher m = TYPE_PATTERN.matcher(id); if (m.find()) { return m.group(1); } return null; } @SuppressWarnings("unchecked") public static synchronized <T extends DataObject> Class<T> getModelClass(URI id) { initClasses(); String typeName = getTypeName(id); return (Class<T>) CLASSES.get(typeName); } @SuppressWarnings("deprecation") private static synchronized void initClasses() { addClass(ApprovalRequest.class); addClass(CatalogCategory.class); addClass(CatalogService.class); addClass(CatalogServiceField.class); addClass(ExecutionLog.class); addClass(ExecutionState.class); addClass(ExecutionWindow.class); addClass(ExecutionTaskLog.class); addClass(Host.class); addClass(Initiator.class); addClass(IpInterface.class); addClass(Order.class); addClass(OrderParameter.class); addClass(RecentService.class); addClass(Vcenter.class); addClass(VcenterDataCenter.class); addClass(VirtualMachine.class); addClass(UserPreferences.class); addClass(InitialSetup.class); } private static synchronized <T extends DataObject> void addClass(Class<T> modelClass) { CLASSES.put(modelClass.getSimpleName(), modelClass); } }