class urn_perun_resource_attribute_def_def_unixGroupName_namespace extends ResourceAttributesModuleAbstract implements ResourceAttributesModuleImplApi {

	@Override
	public void checkAttributeSemantics(PerunSessionImpl sess, Resource resource, Attribute attribute) throws WrongReferenceAttributeValueException, WrongAttributeAssignmentException{
		//prepare namespace and groupName value variables
		String groupName = null;
		if(attribute.getValue() != null) groupName = attribute.valueAsString();
		String groupNameNamespace = attribute.getFriendlyNameParameter();

		if(groupName == null) {
			// if this is resource, its not ok
			throw new WrongReferenceAttributeValueException(attribute, null, resource, null, "Attribute groupName-namespace for resourece can't be null.");
		}

		try {
			//prepare attributes group and resource unixGroupName
			Attribute groupUnixGroupName = new Attribute(sess.getPerunBl().getAttributesManagerBl().getAttributeDefinition(sess, A_G_unixGroupName_namespace + ":" + groupNameNamespace));
			Attribute resourceUnixGroupName = attribute;
			groupUnixGroupName.setValue(attribute.getValue());

			//prepare lists of groups and resources with the same groupName value in the same namespace

			//Fill lists of groups and resources
			List<Group> groupsWithSameGroupNameInTheSameNamespace = new ArrayList<>(sess.getPerunBl().getGroupsManagerBl().getGroupsByAttribute(sess, groupUnixGroupName));
			List<Resource> resourcesWithSameGroupNameInTheSameNamespace = new ArrayList<>(sess.getPerunBl().getResourcesManagerBl().getResourcesByAttribute(sess, resourceUnixGroupName));
			//Remove self from the list of resources with the same namespace
			//FIXME This behavior is not correct, because there are two possible situations:
			// - This is the Check right after setting a new value (correct behavior), we need to skip this value from checking
			// - This is the Check without setting a new value (not correct), and if this resource is the only one with the value, we will lose the right for it
			resourcesWithSameGroupNameInTheSameNamespace.remove(resource);

			//If there is no group or resource with same GroupNameInTheSameNamespace, its ok
			if(groupsWithSameGroupNameInTheSameNamespace.isEmpty() && resourcesWithSameGroupNameInTheSameNamespace.isEmpty()) return;

			//First need to know that i have right to write any of duplicit groupName-namespace attribute
			boolean haveRights = sess.getPerunBl().getModulesUtilsBl().haveRightToWriteAttributeInAnyGroupOrResource(sess, groupsWithSameGroupNameInTheSameNamespace, resourcesWithSameGroupNameInTheSameNamespace, groupUnixGroupName, resourceUnixGroupName);
			if(!haveRights) throw new WrongReferenceAttributeValueException(attribute, null, resource, null, "This groupName is already used for other group or resource and user has no rights to use it.");

			//Now if rights are ok, prepare lists of UnixGIDs attributes of this group (also equivalent resource GID)
			List<Attribute> resourceUnixGIDs = sess.getPerunBl().getAttributesManagerBl().getAllAttributesStartWithNameWithoutNullValue(sess, resource, A_R_unixGID_namespace + ":");
			List<Attribute> groupVersionUnixGIDs = sess.getPerunBl().getModulesUtilsBl().getListOfGroupGIDsFromListOfResourceGIDs(sess, resourceUnixGIDs);

			//In list of duplicit groups looking for GID in same namespace but with different value, thats not correct
			if(!groupsWithSameGroupNameInTheSameNamespace.isEmpty()) {
				for(Group g: groupsWithSameGroupNameInTheSameNamespace) {
					for(Attribute a: groupVersionUnixGIDs) {
						int compare;
						compare = sess.getPerunBl().getModulesUtilsBl().haveTheSameAttributeWithTheSameNamespace(sess, g, a);

						if(compare > 0) {
							throw new WrongReferenceAttributeValueException(attribute, a, resource, null, g, null, "One of the group GIDs is from the same namespace like other group GID but with different values.");
						}
					}
				}
			}

			//In list of duplicit resources looking for GID in same namespace but with different value, thats not correct
			if(!resourcesWithSameGroupNameInTheSameNamespace.isEmpty()) {
				for(Resource r: resourcesWithSameGroupNameInTheSameNamespace) {
					for(Attribute a: resourceUnixGIDs) {
						int compare;
						compare = sess.getPerunBl().getModulesUtilsBl().haveTheSameAttributeWithTheSameNamespace(sess, r, a);

						if(compare > 0) {
							throw new WrongReferenceAttributeValueException(attribute, a, resource, null, r, null, "One of the group GIDs is from the same namespace like other resource GIDs but with different values.");
						}
					}
				}
			}

		} catch(AttributeNotExistsException ex) {
			throw new ConsistencyErrorException(ex);
		}
	}

}