/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.model;
import com.emc.storageos.model.usergroup.UserAttributeParam;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
/**
* ViPR user group configuration data object
*/
@Cf("UserGroup")
@AllowedGeoVersion(version = "2.3")
@DbKeyspace(DbKeyspace.Keyspaces.GLOBAL)
public class UserGroup extends DataObject {
private static final Logger _log = LoggerFactory.getLogger(UserGroup.class);
private String _domain;
private StringSet _attributes;
@Name("domain")
@PrefixIndex(cf = "DomainPrefixIndex", minChars = 1)
public String getDomain() {
return _domain;
}
public void setDomain(String _domain) {
this._domain = _domain;
setChanged("domain");
}
@Name("attributes")
public StringSet getAttributes() {
if (_attributes == null) {
_attributes = new StringSet();
}
return _attributes;
}
public void setAttributes(StringSet _attributes) {
this._attributes = _attributes;
setChanged("attributes");
}
@Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
_domain = _domain.toLowerCase();
return mapper.writeValueAsString(this);
} catch (IOException e) {
_log.error("Failed to convert user group to string.", e);
}
return null;
}
public static UserGroup fromString(String userMappingString) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(userMappingString, UserGroup.class);
} catch (IOException e) {
_log.error("Failed to convert user group from string.", e);
}
return null;
}
private StringSet getAttributeKeySet() {
StringSet attributeKeySet = new StringSet();
for (String attributeParamString : _attributes) {
UserAttributeParam attributeParam = UserAttributeParam.fromString(attributeParamString);
if (attributeParam == null) {
_log.warn("Failed to convert attributes param string {} to object.", attributeParamString);
continue;
}
attributeKeySet.add(attributeParam.getKey());
}
return attributeKeySet;
}
/***
* Common compare method for both isEqual and overlap.
*
* @param userGroup to be compared.
* @return true if userGroup's _domain matches with
* the object otherwise false.
*/
private boolean commonCompare(UserGroup userGroup) {
if (userGroup == null) {
_log.warn("Invalid user group to compare");
return false;
}
_log.debug("Comparing user groups {}, {}",
userGroup.toString(), this.toString());
// Now compare the domain of both user group.
if (StringUtils.isBlank(this._domain) ||
StringUtils.isBlank(userGroup._domain) &&
!this._domain.equalsIgnoreCase(userGroup._domain)) {
String[] toTrace = { this._domain, this.getLabel(), userGroup._domain, userGroup.getLabel() };
_log.debug("Domain {} of {} does not match with domain {} of {}.", toTrace);
return false;
}
return true;
}
/***
* Checks if the given userGroup is matching with the object or not
* The comparison is done based on the _domain and _attributes.
*
* @param userGroup to be compared.
* @return true if userGroup's _domain and _attributes matches with
* the object otherwise false.
*/
public boolean isEqual(UserGroup userGroup) {
boolean isEqual = false;
if (!commonCompare(userGroup)) {
return isEqual;
}
// Now compare the size of attributes list.
if (CollectionUtils.isEmpty(this._attributes) ||
CollectionUtils.isEmpty(userGroup._attributes) ||
this._attributes.size() != userGroup._attributes.size()) {
_log.debug("Invalid attributes or attributes size does not match.");
return isEqual;
}
// Now compare the each individual attribute of the group.
for (String attributeParamString : this._attributes) {
isEqual = compareUserAttributeParam(userGroup, attributeParamString);
if (!isEqual) {
break;
}
}
return isEqual;
}
/***
* Checks if the object's _attributes is available in the
* userGroup's attributes or not .
*
* @param userGroup to be compared.
* @param attributeParamString attribute of the object to be compared.
* @return true if object's _attribute matches with one of
* userGroup's _attributes matches with otherwise false.
*/
private boolean compareUserAttributeParam(UserGroup userGroup, String attributeParamString) {
boolean isEqual = false;
if (StringUtils.isBlank(attributeParamString)) {
_log.warn("Invalid attribute string {} in user group {}.", attributeParamString, this.getLabel());
return isEqual;
}
UserAttributeParam attributeParam = UserAttributeParam.fromString(attributeParamString);
if (attributeParam == null) {
_log.warn("Failed to convert attributes param string {} to object.", attributeParamString);
return isEqual;
}
if (CollectionUtils.isEmpty(userGroup._attributes)) {
_log.info("No attributes to compare");
return isEqual;
}
for (String comparingAttributeParamString : userGroup._attributes) {
if (StringUtils.isBlank(comparingAttributeParamString)) {
_log.info("Invalid attribute string {}", comparingAttributeParamString);
break;
}
UserAttributeParam comparingAttributeParam = UserAttributeParam.fromString(comparingAttributeParamString);
if (comparingAttributeParam == null) {
_log.info("Failed to convert attributes param string {} to object.", comparingAttributeParamString);
return isEqual;
}
if (comparingAttributeParam.isEqual(attributeParam)) {
_log.debug("Attributes {} match with {}", attributeParamString, comparingAttributeParamString);
isEqual = true;
break;
}
}
return isEqual;
}
/***
* Checks if the keys of object's all the _attributes is available
* in the userGroup's attributes or not .
*
* @param userGroup to be compared.
* @return true if all the keys of object attributes are also available
* in the userGroup's attributes otherwise false.
*/
private boolean checkIfAllKeysAvailable(UserGroup userGroup) {
boolean isAllKeysFound = true;
StringSet objectAttributeKeySet = getAttributeKeySet();
StringSet comparingAttributeKeySet = userGroup.getAttributeKeySet();
for (String objectKey : objectAttributeKeySet) {
boolean keyFound = false;
for (String comparingKey : comparingAttributeKeySet) {
if (comparingKey.equalsIgnoreCase(objectKey)) {
keyFound = true;
break;
}
}
if (!keyFound) {
isAllKeysFound = false;
break;
}
}
return isAllKeysFound;
}
/***
* Checks if the object's _attribute overlaps with
* userGroup's attributes or not .
*
* @param userGroup to be compared.
* @param attributeParamString attribute of the object to be compared.
* @return true if object's _attribute overlaps with one of
* userGroup's _attributes otherwise false.
*/
private boolean checkOverlappingAttributes(UserGroup userGroup, String attributeParamString) {
boolean overlaps = false;
if (StringUtils.isBlank(attributeParamString)) {
_log.warn("Invalid attribute string {} in user group {}.", attributeParamString, this.getLabel());
return overlaps;
}
UserAttributeParam attributeParam = UserAttributeParam.fromString(attributeParamString);
if (attributeParam == null) {
_log.warn("Failed to convert attributes param string {} to object.", attributeParamString);
return overlaps;
}
if (CollectionUtils.isEmpty(userGroup._attributes)) {
_log.info("No attributes to compare");
return overlaps;
}
for (String comparingAttributeParamString : userGroup._attributes) {
if (StringUtils.isBlank(comparingAttributeParamString)) {
_log.info("Invalid attribute string {}", comparingAttributeParamString);
break;
}
UserAttributeParam comparingAttributeParam = UserAttributeParam.fromString(comparingAttributeParamString);
if (comparingAttributeParam == null) {
_log.info("Failed to convert attributes param string {} to object.", comparingAttributeParamString);
return overlaps;
}
if (comparingAttributeParam.containsOverlappingAttributeValues(attributeParam)) {
_log.debug("Attributes {} match with {}", attributeParamString, comparingAttributeParamString);
overlaps = true;
break;
}
}
return overlaps;
}
/***
* Checks if the given userGroup overlapping with the object or not.
* The comparison is done based on the _domain and _attributes.
*
* @param userGroup to be compared.
* @return true if userGroup's _domain and _attributes become overlaps with
* object otherwise false.
*/
public boolean overlap(UserGroup userGroup) {
boolean overlaps = false;
if (!commonCompare(userGroup)) {
return overlaps;
}
// Now compare the attribute keys. To overlap, object's all the attribute keys
// should be available in the userGroup.
if (!checkIfAllKeysAvailable(userGroup)) {
_log.debug("User group {} does not contain all the attribute keys of {}", userGroup.getLabel(), this.getLabel());
return overlaps;
}
// Now compare the each individual attribute of the group.
for (String attributeParamString : this._attributes) {
overlaps = checkOverlappingAttributes(userGroup, attributeParamString);
if (!overlaps) {
break;
}
}
return overlaps;
}
}