/*
* 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.definition.adapter;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
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.morph.MorphDefinition;
import org.kie.workbench.common.stunner.core.definition.morph.MorphProperty;
import org.kie.workbench.common.stunner.core.definition.morph.PropertyMorphDefinition;
import org.kie.workbench.common.stunner.core.util.DefinitionUtils;
public abstract class AbstractMorphAdapter<S> implements MorphAdapter<S> {
protected DefinitionUtils definitionUtils;
protected FactoryManager factoryManager;
protected final List<MorphDefinition> morphDefinitions = new LinkedList<>();
public AbstractMorphAdapter(final DefinitionUtils definitionUtils,
final FactoryManager factoryManager) {
this.definitionUtils = definitionUtils;
this.factoryManager = factoryManager;
}
protected abstract <T> T doMerge(final S source,
final MorphDefinition definition,
final T result);
@Override
@SuppressWarnings("unchecked")
public <T> Iterable<MorphDefinition> getMorphDefinitions(final T definition) {
if (null != definition && hasMorphDefinitions()) {
final String[] ids = getDefinitionIds(definition);
final String definitionId = ids[0];
final String baseId = ids[1];
return getMorphDefinitions(definitionId,
baseId);
}
return null;
}
protected Iterable<MorphDefinition> getMorphDefinitions(final String id,
final String baseId) {
if (null != id) {
final List<MorphDefinition> result = new LinkedList<>();
for (MorphDefinition morphDefinition : morphDefinitions) {
if (morphDefinition.accepts(id) ||
(null != baseId && morphDefinition.accepts(baseId))) {
result.add(morphDefinition);
}
}
return result;
}
return null;
}
@Override
public <T> Iterable<MorphProperty> getMorphProperties(final T definition) {
if (null != definition && hasMorphDefinitions()) {
final String[] ids = getDefinitionIds(definition);
final String definitionId = ids[0];
final String baseId = ids[1];
return getMorphProperties(definitionId,
baseId);
}
return null;
}
protected Iterable<MorphProperty> getMorphProperties(final String definitionId,
final String baseId) {
if (null != definitionId) {
final List<MorphProperty> result = new LinkedList<>();
for (MorphDefinition morphDefinition : morphDefinitions) {
final boolean acceptsDefinition = morphDefinition.accepts(definitionId) ||
(null != baseId && morphDefinition.accepts(baseId));
if (acceptsDefinition && (morphDefinition instanceof PropertyMorphDefinition)) {
final PropertyMorphDefinition propertyMorphDefinition = (PropertyMorphDefinition) morphDefinition;
final Iterable<MorphProperty> morphProperties = propertyMorphDefinition.getMorphProperties(definitionId);
addAll(result,
morphProperties);
final Iterable<MorphProperty> baseMorphProperties = null != baseId ?
propertyMorphDefinition.getMorphProperties(definitionId) : null;
if (null != baseMorphProperties) {
addAll(result,
baseMorphProperties);
}
}
}
return result;
}
return null;
}
@Override
public <T> Iterable<String> getTargets(final T definition,
final MorphDefinition morphDefinition) {
final String[] ids = definitionUtils.getDefinitionIds(definition);
final String definitionId = ids[0];
final String baseId = ids[1];
return getTargets(definition.getClass(),
definitionId,
baseId);
}
protected Iterable<String> getTargets(final Class<?> type,
final String definitionId,
final String baseId) {
if (null != definitionId) {
final List<String> result = new LinkedList<>();
for (MorphDefinition morphDefinition : morphDefinitions) {
final boolean acceptsDefinition = morphDefinition.accepts(definitionId) ||
(null != baseId && morphDefinition.accepts(baseId));
if (acceptsDefinition) {
final Iterable<String> t1 = morphDefinition.getTargets(definitionId);
addAll(result,
t1);
if (null != baseId) {
final Iterable<String> t2 = morphDefinition.getTargets(baseId);
addAll(result,
t2);
}
}
}
return result;
}
return null;
}
@Override
public <T> T morph(final S source,
final MorphDefinition morphDefinition,
final String targetId) {
if (null == source) {
throw new IllegalArgumentException("Cannot morph from unspecified source.");
}
if (null == morphDefinition) {
throw new IllegalArgumentException("Cannot morph from unspecified Morph Definition.");
}
if (null == targetId) {
throw new IllegalArgumentException("Cannot morph to unspecified target.");
}
final T target = factoryManager.newDefinition(targetId);
if (null == target) {
throw new RuntimeException("Morph failed. Cannot build a Definition instance for [" + targetId + "]");
}
return doMerge(source,
morphDefinition,
target);
}
protected <T> String[] getDefinitionIds(final T definition) {
return definitionUtils.getDefinitionIds(definition);
}
protected DefinitionManager getDefinitionManager() {
return definitionUtils.getDefinitionManager();
}
protected <T> void addAll(final Collection<T> source,
final Iterable<T> values) {
if (null != values && values.iterator().hasNext()) {
for (final T value : values) {
source.add(value);
}
}
}
protected boolean contains(final Iterable<String> iterable,
final String value) {
if (null != iterable && iterable.iterator().hasNext()) {
for (final String v : iterable) {
if (value.equals(v)) {
return true;
}
}
}
return false;
}
protected boolean hasMorphDefinitions() {
return !morphDefinitions.isEmpty();
}
}