/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.stunner.core.util;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.kie.workbench.common.stunner.core.api.DefinitionManager;
import org.kie.workbench.common.stunner.core.api.FactoryManager;
import org.kie.workbench.common.stunner.core.definition.adapter.DefinitionAdapter;
import org.kie.workbench.common.stunner.core.definition.adapter.MorphAdapter;
import org.kie.workbench.common.stunner.core.definition.adapter.binding.HasInheritance;
import org.kie.workbench.common.stunner.core.definition.morph.MorphDefinition;
import org.kie.workbench.common.stunner.core.definition.morph.MorphPolicy;
import org.kie.workbench.common.stunner.core.definition.property.PropertyMetaTypes;
import org.kie.workbench.common.stunner.core.factory.graph.EdgeFactory;
import org.kie.workbench.common.stunner.core.factory.graph.ElementFactory;
import org.kie.workbench.common.stunner.core.factory.graph.NodeFactory;
import org.kie.workbench.common.stunner.core.graph.content.Bounds;
import org.kie.workbench.common.stunner.core.graph.content.view.BoundImpl;
import org.kie.workbench.common.stunner.core.graph.content.view.BoundsImpl;
import org.kie.workbench.common.stunner.core.registry.factory.FactoryRegistry;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
@ApplicationScoped
public class DefinitionUtils {
private static Logger LOGGER = Logger.getLogger(DefinitionUtils.class.getName());
private final DefinitionManager definitionManager;
private final FactoryManager factoryManager;
protected DefinitionUtils() {
this(null,
null);
}
@Inject
@SuppressWarnings("all")
public DefinitionUtils(final DefinitionManager definitionManager,
final FactoryManager factoryManager) {
this.definitionManager = definitionManager;
this.factoryManager = factoryManager;
}
public <T> Object getProperty(final T definition,
final String propertyId) {
final Set<?> properties = definitionManager.adapters().forDefinition().getProperties(definition);
if (null != properties && !properties.isEmpty()) {
for (final Object property : properties) {
final String pId = definitionManager.adapters().forProperty().getId(property);
if (pId.equals(propertyId)) {
return property;
}
}
}
return null;
}
public <T> String getName(final T definition) {
final Object name =
definitionManager.adapters().forDefinition().getMetaProperty(PropertyMetaTypes.NAME,
definition);
if (null != name) {
return (String) definitionManager.adapters().forProperty().getValue(name);
}
return null;
}
@SuppressWarnings("unchecked")
public Bounds buildBounds(final Object definition,
final double x,
final double y) {
final DefinitionAdapter<Object> adapter = definitionManager.adapters().registry().getDefinitionAdapter(definition.getClass());
final Object r = adapter.getMetaProperty(PropertyMetaTypes.RADIUS,
definition);
double width = 30;
double height = 30;
boolean found = false;
if (null != r) {
final double rv = (double) definitionManager.adapters().forProperty().getValue(r);
width = rv * 2;
height = width;
found = true;
} else {
final Object w = adapter.getMetaProperty(PropertyMetaTypes.WIDTH,
definition);
final Object h = adapter.getMetaProperty(PropertyMetaTypes.HEIGHT,
definition);
if (null != w && null != h) {
width = (double) definitionManager.adapters().forProperty().getValue(w);
height = (double) definitionManager.adapters().forProperty().getValue(h);
found = true;
}
}
if (!found) {
LOGGER.log(Level.WARNING,
"Cannot build Bounds for [" + definition.getClass() + "]. Using defaults...");
}
return new BoundsImpl(new BoundImpl(x,
y),
new BoundImpl(x + width,
y + height));
}
public <T> String getNameIdentifier(final T definition) {
final Object name = definitionManager.adapters().forDefinition().getMetaProperty(PropertyMetaTypes.NAME,
definition);
if (null != name) {
return definitionManager.adapters().forProperty().getId(name);
}
return null;
}
public <T> MorphDefinition getMorphDefinition(final T definition) {
final MorphAdapter<Object> adapter = definitionManager.adapters().registry().getMorphAdapter(definition.getClass());
final Iterable<MorphDefinition> definitions = adapter.getMorphDefinitions(definition);
if (null != definitions && definitions.iterator().hasNext()) {
return definitions.iterator().next();
}
return null;
}
public boolean hasMorphTargets(final Object definition) {
final MorphAdapter<Object> morphAdapter = definitionManager.adapters().registry().getMorphAdapter(definition.getClass());
final Iterable<MorphDefinition> morphDefinitions = morphAdapter.getMorphDefinitions(definition);
if (null != morphDefinitions && morphDefinitions.iterator().hasNext()) {
for (final MorphDefinition morphDefinition : morphDefinitions) {
final Iterable<String> morphTargets = morphAdapter.getTargets(definition,
morphDefinition);
if (null != morphTargets && morphTargets.iterator().hasNext()) {
return true;
}
}
}
return false;
}
/**
* Returns the identifiers for the defintion type and its parent, if any.
*/
public <T> String[] getDefinitionIds(final T definition) {
final Class<?> type = definition.getClass();
final DefinitionAdapter<Object> definitionAdapter = definitionManager.adapters().registry().getDefinitionAdapter(type);
final String definitionId = definitionAdapter.getId(definition);
String baseId = null;
if (definitionAdapter instanceof HasInheritance) {
baseId = ((HasInheritance) definitionAdapter).getBaseType(type);
}
return new String[]{definitionId, baseId};
}
public String getDefaultConnectorId(final String definitionSetId) {
final Object defSet = getDefinitionManager().definitionSets().getDefinitionSetById(definitionSetId);
if (null != defSet) {
final Set<String> definitions = definitionManager.adapters().forDefinitionSet().getDefinitions(defSet);
if (null != definitions && !definitions.isEmpty()) {
for (final String defId : definitions) {
// TODO: Find a way to have a default connector for a DefSet or at least do not create objects here.
final Object def = factoryManager.newDefinition(defId);
if (null != def) {
final Class<? extends ElementFactory> graphElement = definitionManager.adapters().forDefinition().getGraphFactoryType(def);
if (isEdgeFactory(graphElement,
factoryManager.registry())) {
return defId;
}
}
}
}
}
return null;
}
public boolean isAllPolicy(final MorphDefinition definition) {
return MorphPolicy.ALL.equals(definition.getPolicy());
}
public boolean isNonePolicy(final MorphDefinition definition) {
return MorphPolicy.NONE.equals(definition.getPolicy());
}
public boolean isDefaultPolicy(final MorphDefinition definition) {
return MorphPolicy.DEFAULT.equals(definition.getPolicy());
}
public Annotation getQualifier(final String defSetId) {
checkNotNull("defSetId",
defSetId);
final Object ds = definitionManager.definitionSets().getDefinitionSetById(defSetId);
return definitionManager.adapters().forDefinitionSet().getQualifier(ds);
}
/**
* Returns all properties from Definition's property sets.
*/
public Set<?> getPropertiesFromPropertySets(final Object definition) {
final Set<Object> properties = new HashSet<>();
// And properties on each definition's PropertySet instance.
final Set<?> propertySets = definitionManager.adapters().forDefinition().getPropertySets(definition);
if (null != propertySets && !propertySets.isEmpty()) {
for (Object propertySet : propertySets) {
final Set<?> setProperties = definitionManager.adapters().forPropertySet().getProperties(propertySet);
if (null != setProperties && !setProperties.isEmpty()) {
for (final Object property : setProperties) {
if (null != property) {
properties.add(property);
}
}
}
}
}
return properties;
}
@SuppressWarnings("unchecked")
public Object getPropertyAllowedValue(final Object property,
final String value) {
final Map<Object, String> allowedValues = definitionManager.adapters().forProperty().getAllowedValues(property);
if (null != value && null != allowedValues && !allowedValues.isEmpty()) {
for (final Map.Entry<Object, String> entry : allowedValues.entrySet()) {
final String v = entry.getValue();
if (value.equals(v)) {
return entry.getKey();
}
}
}
return null;
}
public static boolean isNodeFactory(final Class<? extends ElementFactory> graphFactoryClass,
final FactoryRegistry registry) {
if (!graphFactoryClass.equals(NodeFactory.class)) {
ElementFactory factory = registry.getElementFactory(graphFactoryClass);
return factory instanceof NodeFactory;
}
return true;
}
public static boolean isEdgeFactory(final Class<? extends ElementFactory> graphFactoryClass,
final FactoryRegistry registry) {
if (!graphFactoryClass.equals(EdgeFactory.class)) {
ElementFactory factory = registry.getElementFactory(graphFactoryClass);
return factory instanceof EdgeFactory;
}
return true;
}
public DefinitionManager getDefinitionManager() {
return definitionManager;
}
}