/*
* Copyright (c) Members of the EGEE Collaboration. 2006-2010.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.glite.authz.common.model.util;
import org.glite.authz.common.model.Action;
import org.glite.authz.common.model.Attribute;
import org.glite.authz.common.model.AttributeAssignment;
import org.glite.authz.common.model.Environment;
import org.glite.authz.common.model.Obligation;
import org.glite.authz.common.model.Request;
import org.glite.authz.common.model.Resource;
import org.glite.authz.common.model.Response;
import org.glite.authz.common.model.Result;
import org.glite.authz.common.model.Status;
import org.glite.authz.common.model.StatusCode;
import org.glite.authz.common.model.Subject;
import org.glite.authz.common.model.util.Strings;
import org.opensaml.Configuration;
import org.opensaml.xacml.XACMLObjectBuilder;
import org.opensaml.xacml.ctx.ActionType;
import org.opensaml.xacml.ctx.AttributeType;
import org.opensaml.xacml.ctx.AttributeValueType;
import org.opensaml.xacml.ctx.DecisionType;
import org.opensaml.xacml.ctx.EnvironmentType;
import org.opensaml.xacml.ctx.RequestType;
import org.opensaml.xacml.ctx.ResourceContentType;
import org.opensaml.xacml.ctx.ResourceType;
import org.opensaml.xacml.ctx.ResponseType;
import org.opensaml.xacml.ctx.ResultType;
import org.opensaml.xacml.ctx.StatusCodeType;
import org.opensaml.xacml.ctx.StatusMessageType;
import org.opensaml.xacml.ctx.StatusType;
import org.opensaml.xacml.ctx.SubjectType;
import org.opensaml.xacml.ctx.DecisionType.DECISION;
import org.opensaml.xacml.policy.AttributeAssignmentType;
import org.opensaml.xacml.policy.EffectType;
import org.opensaml.xacml.policy.ObligationType;
import org.opensaml.xacml.policy.ObligationsType;
import org.opensaml.xml.XMLObjectBuilder;
/**
* A helper class for converting to/from XACML objects.
*
* <strong>NOTE</strong> the OpenSAML library must already be bootstrapped before any method in this helper class is
* invoked.
*/
@SuppressWarnings("unchecked")
public class XACMLConverter {
/** XACML status code builder. */
private static XACMLObjectBuilder<StatusCodeType> statusCodeBuilder;
/** XACML status builder. */
private static XACMLObjectBuilder<StatusType> statusBuilder;
/** XACML status message builder. */
private static XMLObjectBuilder<StatusMessageType> statusMessageBuilder;
/** XACML obligation builder. */
private static XACMLObjectBuilder<ObligationsType> obligationsBuilder;
/** XACML obligations builder. */
private static XACMLObjectBuilder<ObligationType> obligationBuilder;
/** XACML attribute assignment builder. */
private static XACMLObjectBuilder<AttributeAssignmentType> attributeAssignmentBuilder;
/** XACML result builder. */
private static XACMLObjectBuilder<ResultType> resultBuilder;
/** XACML decision builder. */
private static XACMLObjectBuilder<DecisionType> decisionBuilder;
/** XACML response builder. */
private static XACMLObjectBuilder<ResponseType> responseBuilder;
/** XACML attribute builder. */
private static XACMLObjectBuilder<AttributeType> attributeBuilder;
/** XACML attribute value builder. */
private static XACMLObjectBuilder<AttributeValueType> attributeValueBuilder;
/** XACML action builder. */
private static XACMLObjectBuilder<ActionType> actionBuilder;
/** XACML environment builder. */
private static XACMLObjectBuilder<EnvironmentType> environmentBuilder;
/** XACML resource builder. */
private static XACMLObjectBuilder<ResourceType> resourceBuilder;
/** XACML resource content value builder. */
private static XACMLObjectBuilder<ResourceContentType> resourceContentBuilder;
/** XACML subject builder. */
private static XACMLObjectBuilder<SubjectType> subjectBuilder;
/** XACML request builder. */
private static XACMLObjectBuilder<RequestType> requestBuilder;
static {
statusCodeBuilder = (XACMLObjectBuilder<StatusCodeType>) Configuration.getBuilderFactory().getBuilder(
StatusCodeType.DEFAULT_ELEMENT_NAME);
statusBuilder = (XACMLObjectBuilder<StatusType>) Configuration.getBuilderFactory().getBuilder(
StatusType.DEFAULT_ELEMENT_NAME);
statusMessageBuilder = (XMLObjectBuilder<StatusMessageType>) Configuration.getBuilderFactory().getBuilder(
StatusMessageType.DEFAULT_ELEMENT_NAME);
obligationsBuilder = (XACMLObjectBuilder<ObligationsType>) Configuration.getBuilderFactory().getBuilder(
ObligationsType.DEFAULT_ELEMENT_QNAME);
obligationBuilder = (XACMLObjectBuilder<ObligationType>) Configuration.getBuilderFactory().getBuilder(
ObligationType.DEFAULT_ELEMENT_QNAME);
attributeAssignmentBuilder = (XACMLObjectBuilder<AttributeAssignmentType>) Configuration.getBuilderFactory()
.getBuilder(AttributeAssignmentType.DEFAULT_ELEMENT_NAME);
resultBuilder = (XACMLObjectBuilder<ResultType>) Configuration.getBuilderFactory().getBuilder(
ResultType.DEFAULT_ELEMENT_NAME);
decisionBuilder = (XACMLObjectBuilder<DecisionType>) Configuration.getBuilderFactory().getBuilder(
DecisionType.DEFAULT_ELEMENT_NAME);
responseBuilder = (XACMLObjectBuilder<ResponseType>) Configuration.getBuilderFactory().getBuilder(
ResponseType.DEFAULT_ELEMENT_NAME);
attributeBuilder = (XACMLObjectBuilder<AttributeType>) Configuration.getBuilderFactory().getBuilder(
AttributeType.DEFAULT_ELEMENT_NAME);
attributeValueBuilder = (XACMLObjectBuilder<AttributeValueType>) Configuration.getBuilderFactory().getBuilder(
AttributeValueType.DEFAULT_ELEMENT_NAME);
actionBuilder = (XACMLObjectBuilder<ActionType>) Configuration.getBuilderFactory().getBuilder(
ActionType.DEFAULT_ELEMENT_NAME);
environmentBuilder = (XACMLObjectBuilder<EnvironmentType>) Configuration.getBuilderFactory().getBuilder(
EnvironmentType.DEFAULT_ELEMENT_NAME);
resourceBuilder = (XACMLObjectBuilder<ResourceType>) Configuration.getBuilderFactory().getBuilder(
ResourceType.DEFAULT_ELEMENT_NAME);
resourceContentBuilder = (XACMLObjectBuilder<ResourceContentType>) Configuration.getBuilderFactory()
.getBuilder(ResourceContentType.DEFAULT_ELEMENT_NAME);
subjectBuilder = (XACMLObjectBuilder<SubjectType>) Configuration.getBuilderFactory().getBuilder(
SubjectType.DEFAULT_ELEMENT_NAME);
requestBuilder = (XACMLObjectBuilder<RequestType>) Configuration.getBuilderFactory().getBuilder(
RequestType.DEFAULT_ELEMENT_NAME);
}
/**
* Converts a XACML {@link ActionType} to a simple model {@link Action}.
*
* @param xacmlAction the XACML action to be converted
*
* @return the simple model object
*/
public static final Action actionFromXACML(ActionType xacmlAction) {
if (xacmlAction == null) {
return null;
}
Action action = new Action();
if (xacmlAction.getAttributes() != null) {
for (AttributeType xacmlAttribute : xacmlAction.getAttributes()) {
action.getAttributes().add(attributeFromXACML(xacmlAttribute));
}
}
return action;
}
/**
* Converts a {@link Action} to a XACML {@link ActionType}.
*
* @param action the simple model action to be converted
*
* @return the XACML object
*/
public static final ActionType actionToXACML(Action action) {
if (action == null) {
return null;
}
ActionType xacmlAction = actionBuilder.buildObject();
if (action.getAttributes() != null) {
for (Attribute attribute : action.getAttributes()) {
xacmlAction.getAttributes().add(attributeToXACML(attribute));
}
}
return xacmlAction;
}
/**
* Converts a XACML {@link AttributeType} to a simple model {@link Attribute}.
*
* @param xacmlAttribute the XACML attribute to be converted
*
* @return the simple model object
*/
public static final Attribute attributeFromXACML(AttributeType xacmlAttribute) {
if (xacmlAttribute == null) {
return null;
}
Attribute attribute = new Attribute();
attribute.setDataType(Strings.safeTrimOrNullString(xacmlAttribute.getDataType()));
attribute.setId(Strings.safeTrimOrNullString(xacmlAttribute.getAttributeID()));
attribute.setIssuer(Strings.safeTrimOrNullString(xacmlAttribute.getIssuer()));
if (xacmlAttribute.getAttributeValues() != null) {
for (AttributeValueType xacmlAttributeValue : xacmlAttribute.getAttributeValues()) {
// null value are not valid in Hessian
String value= xacmlAttributeValue.getValue();
if (value != null) {
attribute.getValues().add(Strings.safeTrimOrNullString(xacmlAttributeValue.getValue()));
}
}
}
return attribute;
}
/**
* Converts a {@link Attribute} to a XACML {@link AttributeType}. Attribute values are converted to string by means
* of the {@link Object#toString()} method.
*
* @param attribute the simple model attribute to be converted
*
* @return the XACML object
*/
public static final AttributeType attributeToXACML(Attribute attribute) {
if (attribute == null) {
return null;
}
AttributeType xacmlAttribute = attributeBuilder.buildObject();
xacmlAttribute.setAttributeID(Strings.safeTrimOrNullString(attribute.getId()));
String datatype = Strings.safeTrimOrNullString(attribute.getDataType());
if (datatype != null) {
xacmlAttribute.setDataType(datatype);
} else {
xacmlAttribute.setDataType(Attribute.DT_STRING);
}
xacmlAttribute.setIssuer(Strings.safeTrimOrNullString(attribute.getIssuer()));
if (attribute.getValues() != null) {
AttributeValueType xacmlAttributeValue;
for (Object attributeValue : attribute.getValues()) {
String value= Strings.safeTrimOrNullString(attributeValue.toString());
if (value != null) {
xacmlAttributeValue = attributeValueBuilder.buildObject();
xacmlAttributeValue.setValue(value);
xacmlAttribute.getAttributeValues().add(xacmlAttributeValue);
}
}
}
return xacmlAttribute;
}
/**
* Converts a XACML {@link EnvironmentType} to a simple model {@link Environment}.
*
* @param xacmlEnvironment the XACML environment to be converted
*
* @return the simple model object
*/
public static final Environment environmentFromXACML(EnvironmentType xacmlEnvironment) {
if (xacmlEnvironment == null) {
return null;
}
Environment environment = new Environment();
if (xacmlEnvironment.getAttributes() != null) {
for (AttributeType xacmlAttribute : xacmlEnvironment.getAttributes()) {
environment.getAttributes().add(attributeFromXACML(xacmlAttribute));
}
}
return environment;
}
/**
* Converts a {@link Environment} to a XACML {@link EnvironmentType}.
*
* @param environment the simple model environment to be converted
*
* @return the XACML object
*/
public static final EnvironmentType environmentToXACML(Environment environment) {
if (environment == null) {
return null;
}
EnvironmentType xacmlEnvironment = environmentBuilder.buildObject();
if (environment.getAttributes() != null) {
for (Attribute attribute : environment.getAttributes()) {
xacmlEnvironment.getAttributes().add(attributeToXACML(attribute));
}
}
return xacmlEnvironment;
}
/**
* Converts a XACML {@link ObligationType} to a simple model {@link Obligation}. Note, this conversion only supports
* string content attribute assignments.
*
* @param xacmlObligation the XACML obligations to be converted
*
* @return the simple model object
*/
public static final Obligation obligationFromXACML(ObligationType xacmlObligation) {
if (xacmlObligation == null) {
return null;
}
Obligation obligation = new Obligation();
AttributeAssignment attributeAssignment;
if (xacmlObligation.getAttributeAssignments() != null) {
for (AttributeAssignmentType xacmlAttributeAssignment : xacmlObligation.getAttributeAssignments()) {
attributeAssignment = new AttributeAssignment();
attributeAssignment.setAttributeId(Strings.safeTrimOrNullString(xacmlAttributeAssignment
.getAttributeId()));
attributeAssignment.setDataType(Strings.safeTrimOrNullString(xacmlAttributeAssignment.getDataType()));
attributeAssignment.setValue(Strings.safeTrimOrNullString(xacmlAttributeAssignment.getValue()));
}
}
switch (xacmlObligation.getFulfillOn()) {
case Deny:
obligation.setFulfillOn(Result.DECISION_DENY);
break;
case Permit:
obligation.setFulfillOn(Result.DECISION_PERMIT);
break;
}
obligation.setId(Strings.safeTrimOrNullString(xacmlObligation.getObligationId()));
return obligation;
}
/**
* Converts a simple model {@link Obligation} in to a XACML {@link ObligationType}. Multi-value attribute
* assignments are not supported.
*
* @param obligation the simple model obligation to convert
*
* @return the XACML object
*/
public static final ObligationType obligationToXACML(Obligation obligation) {
if (obligation == null) {
return null;
}
ObligationType xacmlObligation = obligationBuilder.buildObject();
AttributeAssignmentType xacmlAttributeAssignment;
if (obligation.getAttributeAssignments() != null) {
for (AttributeAssignment attributeAssignment : obligation.getAttributeAssignments()) {
attributeAssignment = obligation.getAttributeAssignments().get(0);
xacmlAttributeAssignment = attributeAssignmentBuilder.buildObject();
xacmlAttributeAssignment.setAttributeId(Strings.safeTrimOrNullString(attributeAssignment
.getAttributeId()));
xacmlAttributeAssignment.setDataType(attributeAssignment.getDataType());
xacmlAttributeAssignment.setValue(attributeAssignment.getValue());
}
}
if (obligation.getFulfillOn() == Result.DECISION_PERMIT) {
xacmlObligation.setFulfillOn(EffectType.Permit);
} else {
xacmlObligation.setFulfillOn(EffectType.Deny);
}
xacmlObligation.setObligationId(Strings.safeTrimOrNullString(obligation.getId()));
return xacmlObligation;
}
/**
* Converts a XACML {@link RequestType} to a simple model {@link Request}.
*
* @param xacmlRequest the XACML request to be converted
*
* @return the simple model object
*/
public static final Request requestFromXACML(RequestType xacmlRequest) {
Request request = new Request();
request.setAction(actionFromXACML(xacmlRequest.getAction()));
request.setEnvironment(environmentFromXACML(xacmlRequest.getEnvironment()));
if (xacmlRequest.getResources() != null) {
for (ResourceType xacmlResource : xacmlRequest.getResources()) {
request.getResources().add(resourceFromXACML(xacmlResource));
}
}
if (xacmlRequest.getSubjects() != null) {
for (SubjectType xacmlSubject : xacmlRequest.getSubjects()) {
request.getSubjects().add(subjectFromXACML(xacmlSubject));
}
}
return request;
}
/**
* Converts a {@link Request} to a XACML {@link RequestType}.
*
* @param request the simple model request to be converted
*
* @return the XACML object
*/
public static final RequestType requestToXACML(Request request) {
if (request == null) {
return null;
}
RequestType xacmlRequest = requestBuilder.buildObject();
xacmlRequest.setAction(actionToXACML(request.getAction()));
xacmlRequest.setEnvironment(environmentToXACML(request.getEnvironment()));
if (request.getResources() != null) {
for (Resource resource : request.getResources()) {
xacmlRequest.getResources().add(resourceToXACML(resource));
}
}
if (request.getSubjects() != null) {
for (Subject subject : request.getSubjects()) {
xacmlRequest.getSubjects().add(subjectToXACML(subject));
}
}
return xacmlRequest;
}
/**
* Converts a XACML {@link ResourceType} to a simple model {@link Resource}. Only simple strings are supported as
* resource content values.
*
* @param xacmlResource the XACML resource to be converted
*
* @return the simple model object
*/
public static final Resource resourceFromXACML(ResourceType xacmlResource) {
if (xacmlResource == null) {
return null;
}
Resource resource = new Resource();
if (xacmlResource.getResourceContent() != null) {
resource.setResourceContent(Strings.safeTrimOrNullString(xacmlResource.getResourceContent().getValue()));
}
if (xacmlResource.getAttributes() != null) {
for (AttributeType xacmlAttribute : xacmlResource.getAttributes()) {
resource.getAttributes().add(attributeFromXACML(xacmlAttribute));
}
}
return resource;
}
/**
* Converts a {@link Resource} to a XACML {@link ResourceType}.
*
* @param resource the simple model resource to be converted
*
* @return the XACML object
*/
public static final ResourceType resourceToXACML(Resource resource) {
if (resource == null) {
return null;
}
ResourceType xacmlResource = resourceBuilder.buildObject();
if (!Strings.isEmpty(resource.getResourceContent())) {
ResourceContentType xacmlResourceContent = resourceContentBuilder.buildObject();
xacmlResourceContent.setValue(Strings.safeTrimOrNullString(resource.getResourceContent()));
xacmlResource.setResourceContent(xacmlResourceContent);
}
if (resource.getAttributes() != null) {
for (Attribute attribute : resource.getAttributes()) {
xacmlResource.getAttributes().add(attributeToXACML(attribute));
}
}
return xacmlResource;
}
/**
* Converts a XACML {@link ResponseType} to a simple model {@link Response}.
*
* @param xacmlResponse the XACML response to be converted
* @param xacmlRequest the XACML request which rendered the given response, may be null
*
* @return the simple model object
*/
public static final Response responseFromXACML(ResponseType xacmlResponse, RequestType xacmlRequest) {
if (xacmlResponse == null) {
return null;
}
Response response = new Response();
response.getResults().add(resultFromXACML(xacmlResponse.getResult()));
if (xacmlRequest != null) {
response.setRequest(requestFromXACML(xacmlRequest));
}
return response;
}
/**
* Converts a {@link Response} to a XACML {@link ResponseType}. If the response contains a {@link Request} it must
* be converted separately. Only the first {@link Result} in the response is converted.
*
* @param response the simple model response to be converted
*
* @return the XACML object
*/
public static final ResponseType responseToXACML(Response response) {
if (response == null) {
return null;
}
ResponseType xacmlResponse = responseBuilder.buildObject();
xacmlResponse.setResult(resultToXACML(response.getResults().get(0)));
return xacmlResponse;
}
/**
* Converts a XACML {@link ResultType} to a simple model {@link Result}.
*
* @param xacmlResult the XACML result to be converted
*
* @return the simple model object
*/
public static final Result resultFromXACML(ResultType xacmlResult) {
if (xacmlResult == null) {
return null;
}
Result result = new Result();
result.setResourceId(xacmlResult.getResourceId());
switch (xacmlResult.getDecision().getDecision()) {
case Deny:
result.setDecision(Result.DECISION_DENY);
break;
case Indeterminate:
result.setDecision(Result.DECISION_INDETERMINATE);
break;
case NotApplicable:
result.setDecision(Result.DECISION_NOT_APPLICABLE);
break;
case Permit:
result.setDecision(Result.DECISION_PERMIT);
break;
}
result.setStatus(statusFromXACML(xacmlResult.getStatus()));
if (xacmlResult.getObligations() != null && xacmlResult.getObligations().getObligations() != null) {
for (ObligationType xacmlObligation : xacmlResult.getObligations().getObligations()) {
result.getObligations().add(obligationFromXACML(xacmlObligation));
}
}
return result;
}
/**
* Converts a simple model {@link Result} in to a XACML {@link ResultType}.
*
* @param result the simple model result to convert
*
* @return the XACML object
*/
public static final ResultType resultToXACML(Result result) {
if (result == null) {
return null;
}
ResultType xacmlResult = resultBuilder.buildObject();
DecisionType decision = decisionBuilder.buildObject();
switch (result.getDecision()) {
case Result.DECISION_DENY:
decision.setDecision(DECISION.Deny);
break;
case Result.DECISION_INDETERMINATE:
decision.setDecision(DECISION.Indeterminate);
break;
case Result.DECISION_NOT_APPLICABLE:
decision.setDecision(DECISION.NotApplicable);
break;
case Result.DECISION_PERMIT:
decision.setDecision(DECISION.Permit);
break;
}
xacmlResult.setDecision(decision);
xacmlResult.setStatus(statusToXACML(result.getStatus()));
if (result.getObligations() != null) {
ObligationsType xacmlObligations = obligationsBuilder.buildObject();
for (Obligation obligation : result.getObligations()) {
xacmlObligations.getObligations().add(obligationToXACML(obligation));
}
xacmlResult.setObligations(xacmlObligations);
}
return xacmlResult;
}
/**
* Converts a XACML {@link StatusCodeType} to a simple model {@link StatusCode}.
*
* @param xacmlStatusCode the XACML status code to be converted
*
* @return the simple model object
*/
public static final StatusCode statusCodeFromXACML(StatusCodeType xacmlStatusCode) {
if (xacmlStatusCode == null) {
return null;
}
StatusCode statusCode = new StatusCode();
statusCode.setCode(Strings.safeTrimOrNullString(xacmlStatusCode.getValue()));
statusCode.setSubCode(statusCodeFromXACML(xacmlStatusCode.getStatusCode()));
return statusCode;
}
/**
* Converts a simple model {@link StatusCode} in to a XACML {@link StatusCodeType}.
*
* @param statusCode the simple model status code to convert
*
* @return the XACML object
*/
public static final StatusCodeType statusCodeToXACML(StatusCode statusCode) {
if (statusCode == null) {
return null;
}
StatusCodeType xacmlStatusCode = statusCodeBuilder.buildObject();
xacmlStatusCode.setValue(Strings.safeTrimOrNullString(statusCode.getCode()));
xacmlStatusCode.setStatusCode(statusCodeToXACML(statusCode.getSubCode()));
return xacmlStatusCode;
}
/**
* Converts a XACML {@link StatusType} to a simple model {@link Status}. Note, this conversion does not support the
* XACML status details.
*
* @param xacmlStatus the XACML status to be converted
*
* @return the simple model object
*/
public static final Status statusFromXACML(StatusType xacmlStatus) {
if (xacmlStatus == null) {
return null;
}
Status status = new Status();
status.setCode(statusCodeFromXACML(xacmlStatus.getStatusCode()));
if (xacmlStatus.getStatusMessage() != null) {
status.setMessage(Strings.safeTrimOrNullString(xacmlStatus.getStatusMessage().getValue()));
}
return status;
}
/**
* Converts a simple model {@link Status} in to a XACML {@link StatusType}.
*
* @param status the simple model status to convert
*
* @return the XACML object
*/
public static final StatusType statusToXACML(Status status) {
if (status == null) {
return null;
}
StatusType xacmlStatus = statusBuilder.buildObject();
xacmlStatus.setStatusCode(statusCodeToXACML(status.getCode()));
if (!Strings.isEmpty(status.getMessage())) {
StatusMessageType xacmlStatusMessage = statusMessageBuilder.buildObject(
StatusMessageType.DEFAULT_ELEMENT_NAME, StatusMessageType.TYPE_NAME);
xacmlStatusMessage.setValue(Strings.safeTrimOrNullString(status.getMessage()));
xacmlStatus.setStatusMessage(xacmlStatusMessage);
}
return xacmlStatus;
}
/**
* Converts a XACML {@link SubjectType} to a simple model {@link Subject}.
*
* @param xacmlSubject the XACML subject to be converted
*
* @return the simple model object
*/
public static final Subject subjectFromXACML(SubjectType xacmlSubject) {
if (xacmlSubject == null) {
return null;
}
Subject subject = new Subject();
subject.setCategory(Strings.safeTrimOrNullString(xacmlSubject.getSubjectCategory()));
if (xacmlSubject.getAttributes() != null) {
for (AttributeType xacmlAttribute : xacmlSubject.getAttributes()) {
subject.getAttributes().add(attributeFromXACML(xacmlAttribute));
}
}
return subject;
}
/**
* Converts a {@link Subject} to a XACML {@link SubjectType}.
*
* @param subject the simple model subject to be converted
*
* @return the XACML object
*/
public static final SubjectType subjectToXACML(Subject subject) {
if (subject == null) {
return null;
}
SubjectType xacmlSubject = subjectBuilder.buildObject();
xacmlSubject.setSubjectCategory(Strings.safeTrimOrNullString(subject.getCategory()));
if (subject.getAttributes() != null) {
for (Attribute attribute : subject.getAttributes()) {
xacmlSubject.getAttributes().add(attributeToXACML(attribute));
}
}
return xacmlSubject;
}
}