/*
* Copyright (c) 2010-2016 Evolveum
*
* 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 com.evolveum.midpoint.web.page.admin.resources;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.evolveum.midpoint.common.SynchronizationUtils;
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.box.InfoBoxPanel;
import com.evolveum.midpoint.web.component.box.InfoBoxType;
import com.evolveum.midpoint.web.component.data.BoxedTablePanel;
import com.evolveum.midpoint.web.component.data.column.ColumnTypeDto;
import com.evolveum.midpoint.web.component.data.column.ColumnUtils;
import com.evolveum.midpoint.web.component.data.column.LinkPanel;
import com.evolveum.midpoint.web.component.util.ListDataProvider;
import com.evolveum.midpoint.web.component.util.SelectableBean;
import com.evolveum.midpoint.web.page.admin.resources.dto.ResourceConfigurationDto;
import com.evolveum.midpoint.web.page.admin.server.PageTaskEdit;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AvailabilityStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectSynchronizationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationalStateType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceActivationDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceAttributeDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourcePasswordDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
public class ResourceDetailsTabPanel extends Panel {
private static final Trace LOGGER = TraceManager.getTrace(ResourceDetailsTabPanel.class);
private static final String DOT_CLASS = ResourceDetailsTabPanel.class.getName() + ".";
private static final String OPERATION_SEARCH_TASKS_FOR_RESOURCE = DOT_CLASS + "seachTasks";
public static final String ID_LAST_AVAILABILITY_STATUS = "lastStatus";
private static final String ID_SOURCE_TARGET = "sourceTarget";
private static final String ID_SCHEMA_STATUS = "schemaStatus";
private static final String PANEL_CAPABILITIES = "capabilities";
private static final long serialVersionUID = 1L;
LoadableModel<CapabilitiesDto> capabilitiesModel;
private PageBase parentPage;
public ResourceDetailsTabPanel(String id, final IModel<?> model, PageBase parentPage) {
super(id, model);
this.parentPage = parentPage;
capabilitiesModel = new LoadableModel<CapabilitiesDto>() {
private static final long serialVersionUID = 1L;
@Override
protected CapabilitiesDto load() {
PrismObject<ResourceType> resource = (PrismObject<ResourceType>) model.getObject();
return new CapabilitiesDto(resource.asObjectable());
}
};
initLayout(model, parentPage);
}
protected void initLayout(IModel model, PageBase parentPage) {
PrismObject<ResourceType> resourceObject = (PrismObject<ResourceType>) model.getObject();
ResourceType resource = resourceObject.asObjectable();
add(createLastAvailabilityStatusInfo(resource));
add(createSourceTargetInfo(resource));
add(createSchemaStatusInfo(resource));
CapabilitiesPanel capabilities = new CapabilitiesPanel(PANEL_CAPABILITIES, capabilitiesModel);
add(capabilities);
List<ResourceConfigurationDto> resourceConfigList = createResourceConfigList(resource);
ListDataProvider<ResourceConfigurationDto> resourceConfigProvider = new ListDataProvider<ResourceConfigurationDto>(
ResourceDetailsTabPanel.this, new ListModel<ResourceConfigurationDto>(resourceConfigList));
List<ColumnTypeDto<String>> columns = Arrays.asList(
new ColumnTypeDto<String>("ShadowType.kind", "objectTypeDefinition.kind",
ShadowType.F_KIND.getLocalPart()),
new ColumnTypeDto<String>("ShadowType.objectClass",
"objectTypeDefinition.objectClass.localPart",
ShadowType.F_OBJECT_CLASS.getLocalPart()),
new ColumnTypeDto<String>("ShadowType.intent", "objectTypeDefinition.intent",
ShadowType.F_INTENT.getLocalPart()),
new ColumnTypeDto<String>("ResourceType.isSync", "sync", null));
List<IColumn<SelectableBean<ResourceType>, String>> tableColumns = ColumnUtils.createColumns(columns);
PropertyColumn tasksColumn = new PropertyColumn(
PageBase.createStringResourceStatic(this, "ResourceType.tasks"), "definedTasks") {
@Override
public void populateItem(Item item, String componentId, final IModel rowModel) {
ResourceConfigurationDto conf = (ResourceConfigurationDto) rowModel.getObject();
RepeatingView repeater = new RepeatingView(componentId);
for (final TaskType task : conf.getDefinedTasks()) {
repeater.add(new LinkPanel(repeater.newChildId(),
new Model<String>(task.getName().getOrig())) {
@Override
public void onClick(AjaxRequestTarget target) {
ResourceDetailsTabPanel.this.taskDetailsPerformed(target, task.getOid());
}
});
}
item.add(repeater);
}
};
tableColumns.add(tasksColumn);
BoxedTablePanel<ResourceConfigurationDto> resourceConfig = new BoxedTablePanel("resourceConfig",
resourceConfigProvider, tableColumns);
resourceConfig.setAdditionalBoxCssClasses("box-success");
add(resourceConfig);
}
private List<ResourceConfigurationDto> createResourceConfigList(ResourceType resource) {
OperationResult result = new OperationResult(OPERATION_SEARCH_TASKS_FOR_RESOURCE);
List<PrismObject<TaskType>> tasks = WebModelServiceUtils.searchObjects(TaskType.class,
QueryBuilder.queryFor(TaskType.class, parentPage.getPrismContext())
.item(TaskType.F_OBJECT_REF).ref(resource.getOid())
.build(),
result, parentPage);
List<ResourceConfigurationDto> configs = new ArrayList<>();
if (resource.getSchemaHandling() == null) {
return configs;
}
List<ResourceObjectTypeDefinitionType> objectTypes = resource.getSchemaHandling().getObjectType();
if (objectTypes == null) {
return configs;
}
try {
for (ResourceObjectTypeDefinitionType objectType : objectTypes) {
ObjectSynchronizationType obejctSynchronization = null;
if (resource.getSynchronization() != null
&& resource.getSynchronization().getObjectSynchronization() != null) {
obejctSynchronization = getSynchronizationFor(objectType,
resource.getSynchronization().getObjectSynchronization(),
resource.asPrismObject());
}
List<TaskType> syncTask = new ArrayList<>();
if (obejctSynchronization != null) {
syncTask = getTaskFor(tasks, obejctSynchronization, resource.asPrismObject());
}
ResourceConfigurationDto resourceConfig = new ResourceConfigurationDto(objectType,
obejctSynchronization != null, syncTask);
configs.add(resourceConfig);
}
} catch (SchemaException ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Could not determine resource configuration", ex);
}
return configs;
}
private void taskDetailsPerformed(AjaxRequestTarget target, String taskOid) {
PageParameters parameters = new PageParameters();
parameters.add(OnePageParameterEncoder.PARAMETER, taskOid);
((PageBase) getPage()).navigateToNext(PageTaskEdit.class, parameters);
}
private InfoBoxPanel createSourceTargetInfo(ResourceType resource) {
String backgroundColor = "bg-aqua";
SourceTarget sourceTarget = determineIfSourceOrTarget(resource);
String numberKey = null;
switch (sourceTarget) {
case SOURCE:
numberKey = "PageResource.resource.source";
break;
case TARGET:
numberKey = "PageResource.resource.target";
break;
case SOURCE_TARGET:
numberKey = "PageResource.resource.sourceAndTarget";
break;
default:
backgroundColor = "bg-gray";
numberKey = "PageResource.resource.noMappings";
break;
}
InfoBoxType infoBoxType = new InfoBoxType(backgroundColor, sourceTarget.getCssClass(),
parentPage.getString("PageResource.resource.mappings"));
infoBoxType.setNumber(parentPage.getString(numberKey));
if (isSynchronizationDefined(resource)) {
infoBoxType.setDescription(parentPage.getString("PageResource.resource.sync"));
}
Model<InfoBoxType> boxModel = new Model<InfoBoxType>(infoBoxType);
return new InfoBoxPanel(ID_SOURCE_TARGET, boxModel);
}
private InfoBoxPanel createLastAvailabilityStatusInfo(ResourceType resource) {
String messageKey = "PageResource.resource.availabilityUnknown";
String backgroundColor = "bg-gray";
String icon = "fa-question";
OperationalStateType operationalState = resource.getOperationalState();
if (operationalState != null) {
AvailabilityStatusType lastAvailabilityStatus = operationalState.getLastAvailabilityStatus();
if (lastAvailabilityStatus != null) {
if (lastAvailabilityStatus == AvailabilityStatusType.UP) {
messageKey = "PageResource.resource.up";
backgroundColor = "bg-green";
icon = "fa-power-off";
} else if (lastAvailabilityStatus == AvailabilityStatusType.DOWN) {
backgroundColor = "bg-red";
messageKey = "PageResource.resource.down";
icon = "fa-ban";
} else if (lastAvailabilityStatus == AvailabilityStatusType.BROKEN) {
backgroundColor = "bg-yellow";
messageKey = "PageResource.resource.broken";
icon = "fa-warning";
}
}
}
InfoBoxType infoBoxType = new InfoBoxType(backgroundColor, icon, parentPage.getString(messageKey));
ConnectorType connectorType = resource.getConnector();
if (connectorType == null) {
// Connector not found. Probably bad connectorRef reference.
infoBoxType.setNumber("--");
infoBoxType.setDescription("--");
} else {
String connectorName = StringUtils.substringAfterLast(
WebComponentUtil.getEffectiveName(connectorType, ConnectorType.F_CONNECTOR_TYPE), ".");
String connectorVersion = connectorType.getConnectorVersion();
infoBoxType.setNumber(connectorName);
infoBoxType.setDescription(connectorVersion);
}
Model<InfoBoxType> boxModel = new Model<InfoBoxType>(infoBoxType);
InfoBoxPanel lastAvailabilityStatus = new InfoBoxPanel(ID_LAST_AVAILABILITY_STATUS, boxModel);
lastAvailabilityStatus.setOutputMarkupId(true);
return lastAvailabilityStatus;
}
private InfoBoxPanel createSchemaStatusInfo(ResourceType resource) {
String backgroundColor = "bg-gray";
String icon = "fa-times";
String numberMessage = null;
String description = null;
Integer progress = null;
RefinedResourceSchema refinedSchema = null;
try {
refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource);
if (refinedSchema != null) {
backgroundColor = "bg-purple";
icon = "fa-cubes";
int numObjectTypes = 0;
List<? extends RefinedObjectClassDefinition> refinedDefinitions = refinedSchema
.getRefinedDefinitions();
for (RefinedObjectClassDefinition refinedDefinition : refinedDefinitions) {
if (refinedDefinition.getKind() != null) {
numObjectTypes++;
}
}
int numAllDefinitions = refinedDefinitions.size();
numberMessage = numObjectTypes + " " + parentPage.getString("PageResource.resource.objectTypes");
if (numAllDefinitions != 0) {
progress = numObjectTypes * 100 / numAllDefinitions;
if (progress > 100) {
progress = 100;
}
}
description = numAllDefinitions + " " + parentPage.getString("PageResource.resource.schemaDefinitions");
} else {
numberMessage = parentPage.getString("PageResource.resource.noSchema");
}
} catch (SchemaException e) {
backgroundColor = "bg-danger";
icon = "fa-warning";
numberMessage = parentPage.getString("PageResource.resource.schemaError");
}
InfoBoxType infoBoxType = new InfoBoxType(backgroundColor, icon,
parentPage.getString("PageResource.resource.schema"));
infoBoxType.setNumber(numberMessage);
infoBoxType.setProgress(progress);
infoBoxType.setDescription(description);
Model<InfoBoxType> boxModel = new Model<InfoBoxType>(infoBoxType);
return new InfoBoxPanel(ID_SCHEMA_STATUS, boxModel);
}
private ObjectSynchronizationType getSynchronizationFor(
ResourceObjectTypeDefinitionType obejctTypesDefinition,
List<ObjectSynchronizationType> synchronizationPolicies, PrismObject<ResourceType> resource)
throws SchemaException {
for (ObjectSynchronizationType synchronizationPolicy : synchronizationPolicies) {
if (SynchronizationUtils.isPolicyApplicable(obejctTypesDefinition.getObjectClass(),
obejctTypesDefinition.getKind(), obejctTypesDefinition.getIntent(), synchronizationPolicy,
resource)) {
if (synchronizationPolicy.getObjectClass().isEmpty()) {
synchronizationPolicy.getObjectClass().add(obejctTypesDefinition.getObjectClass());
}
return synchronizationPolicy;
}
}
return null;
}
private List<TaskType> getTaskFor(List<PrismObject<TaskType>> tasks,
ObjectSynchronizationType synchronizationPolicy, PrismObject<ResourceType> resource)
throws SchemaException {
List<TaskType> syncTasks = new ArrayList<TaskType>();
for (PrismObject<TaskType> task : tasks) {
PrismProperty<ShadowKindType> taskKind = task
.findProperty(new ItemPath(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_KIND));
ShadowKindType taskKindValue = null;
if (taskKind != null) {
taskKindValue = taskKind.getRealValue();
}
PrismProperty<String> taskIntent = task
.findProperty(new ItemPath(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_INTENT));
String taskIntentValue = null;
if (taskIntent != null) {
taskIntentValue = taskIntent.getRealValue();
}
PrismProperty<QName> taskObjectClass = task.findProperty(
new ItemPath(TaskType.F_EXTENSION, SchemaConstants.OBJECTCLASS_PROPERTY_NAME));
QName taskObjectClassValue = null;
if (taskObjectClass != null) {
taskObjectClassValue = taskObjectClass.getRealValue();
}
// TODO: unify with determineObjectClass in Utils (model-impl, which
// is not accessible in admin-gui)
if (taskObjectClassValue == null) {
ObjectClassComplexTypeDefinition taskObjectClassDef = null;
RefinedResourceSchema schema = RefinedResourceSchemaImpl.getRefinedSchema(resource);
if (schema == null) {
throw new SchemaException(
"No schema defined in resource. Possible configuration problem?");
}
if (taskKindValue == null && taskIntentValue == null) {
taskObjectClassDef = schema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT);
}
if (taskKindValue != null) {
if (StringUtils.isEmpty(taskIntentValue)) {
taskObjectClassDef = schema.findDefaultObjectClassDefinition(taskKindValue);
} else {
taskObjectClassDef = schema.findObjectClassDefinition(taskKindValue, taskIntentValue);
}
}
if (taskObjectClassDef != null) {
taskObjectClassValue = taskObjectClassDef.getTypeName();
}
}
if (SynchronizationUtils.isPolicyApplicable(taskObjectClassValue, taskKindValue, taskIntentValue,
synchronizationPolicy, resource)) {
syncTasks.add(task.asObjectable());
}
}
return syncTasks;
}
// TODO: ####### start of move to ResourceTypeUtil ###########
private boolean isOutboundDefined(ResourceAttributeDefinitionType attr) {
return attr.getOutbound() != null
&& (attr.getOutbound().getSource() != null || attr.getOutbound().getExpression() != null);
}
private boolean isInboundDefined(ResourceAttributeDefinitionType attr) {
return attr.getInbound() != null && CollectionUtils.isNotEmpty(attr.getInbound())
&& (attr.getInbound().get(0).getTarget() != null
|| attr.getInbound().get(0).getExpression() != null);
}
private boolean isSynchronizationDefined(ResourceType resource) {
if (resource.getSynchronization() == null) {
return false;
}
if (resource.getSynchronization().getObjectSynchronization().isEmpty()) {
return false;
}
for (ObjectSynchronizationType syncType : resource.getSynchronization().getObjectSynchronization()) {
if (syncType.isEnabled() != null && !syncType.isEnabled()) {
continue;
}
if (CollectionUtils.isEmpty(syncType.getReaction())) {
continue;
}
return true;
}
return false;
}
private SourceTarget determineCredentialsMappings(ResourceType resource) {
if (resource.getSchemaHandling() != null
&& CollectionUtils.isNotEmpty(resource.getSchemaHandling().getObjectType())) {
boolean hasOutbound = false;
boolean hasInbound = false;
for (ResourceObjectTypeDefinitionType resourceObjectTypeDefinition : resource.getSchemaHandling()
.getObjectType()) {
if (hasInbound && hasOutbound) {
return SourceTarget.SOURCE_TARGET;
}
if (resourceObjectTypeDefinition.getCredentials() == null) {
continue;
}
if (resourceObjectTypeDefinition.getCredentials().getPassword() == null) {
continue;
}
ResourcePasswordDefinitionType passwordDef = resourceObjectTypeDefinition.getCredentials()
.getPassword();
if (!hasOutbound) {
hasOutbound = passwordDef.getOutbound() != null;
}
if (!hasInbound) {
hasInbound = CollectionUtils.isNotEmpty(passwordDef.getInbound());
}
}
if (hasInbound) {
return SourceTarget.SOURCE;
}
if (hasOutbound) {
return SourceTarget.TARGET;
}
}
return SourceTarget.NOT_DEFINED;
}
private SourceTarget determineActivationMappings(ResourceType resource) {
if (resource.getSchemaHandling() != null
&& CollectionUtils.isNotEmpty(resource.getSchemaHandling().getObjectType())) {
boolean hasOutbound = false;
boolean hasInbound = false;
for (ResourceObjectTypeDefinitionType resourceObjectTypeDefinition : resource.getSchemaHandling()
.getObjectType()) {
if (hasInbound && hasOutbound) {
return SourceTarget.SOURCE_TARGET;
}
if (resourceObjectTypeDefinition.getActivation() == null) {
continue;
}
if (!hasOutbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getAdministrativeStatus() != null && CollectionUtils
.isNotEmpty(activationDef.getAdministrativeStatus().getOutbound())) {
hasOutbound = true;
}
}
if (!hasOutbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getValidFrom() != null
&& CollectionUtils.isNotEmpty(activationDef.getValidFrom().getOutbound())) {
hasOutbound = true;
}
}
if (!hasOutbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getValidTo() != null
&& CollectionUtils.isNotEmpty(activationDef.getValidTo().getOutbound())) {
hasOutbound = true;
}
}
if (!hasOutbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getExistence() != null
&& CollectionUtils.isNotEmpty(activationDef.getExistence().getOutbound())) {
hasOutbound = true;
}
}
if (!hasInbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getAdministrativeStatus() != null && CollectionUtils
.isNotEmpty(activationDef.getAdministrativeStatus().getInbound())) {
hasInbound = true;
}
}
if (!hasInbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getValidFrom() != null
&& CollectionUtils.isNotEmpty(activationDef.getValidFrom().getInbound())) {
hasInbound = true;
}
}
if (!hasInbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getValidTo() != null
&& CollectionUtils.isNotEmpty(activationDef.getValidTo().getInbound())) {
hasInbound = true;
}
}
if (!hasInbound) {
ResourceActivationDefinitionType activationDef = resourceObjectTypeDefinition
.getActivation();
if (activationDef.getExistence() != null
&& CollectionUtils.isNotEmpty(activationDef.getExistence().getInbound())) {
hasInbound = true;
}
}
}
if (hasInbound) {
return SourceTarget.SOURCE;
}
if (hasOutbound) {
return SourceTarget.TARGET;
}
}
return SourceTarget.NOT_DEFINED;
}
private SourceTarget determineIfSourceOrTarget(ResourceType resource) {
if (resource.getSchemaHandling() != null
&& CollectionUtils.isNotEmpty(resource.getSchemaHandling().getObjectType())) {
boolean hasOutbound = false;
boolean hasInbound = false;
for (ResourceObjectTypeDefinitionType resourceObjectTypeDefinition : resource.getSchemaHandling()
.getObjectType()) {
if (CollectionUtils.isEmpty(resourceObjectTypeDefinition.getAttribute())) {
continue;
}
if (hasInbound && hasOutbound) {
return SourceTarget.SOURCE_TARGET;
}
for (ResourceAttributeDefinitionType attr : resourceObjectTypeDefinition.getAttribute()) {
if (hasInbound && hasOutbound) {
return SourceTarget.SOURCE_TARGET;
}
if (!hasOutbound) {
hasOutbound = isOutboundDefined(attr);
}
if (!hasInbound) {
hasInbound = isInboundDefined(attr);
}
}
// TODO: what about situation that we have only
}
if (hasOutbound) {
return SourceTarget.TARGET;
}
if (hasInbound) {
return SourceTarget.SOURCE;
}
}
return SourceTarget.NOT_DEFINED;
}
// TODO: ####### end of move to ResourceTypeUtil ###########
private enum SourceTarget {
NOT_DEFINED("fa-square-o"), SOURCE("fa-sign-in"), TARGET("fa-sign-out"), SOURCE_TARGET("fa-exchange");
private String cssClass;
SourceTarget(String cssClass) {
this.cssClass = cssClass;
}
public String getCssClass() {
return cssClass;
}
}
}