blob: 8cd32075df40ad145536a2520cf9006ff4045ef4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2016 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvtp2qvts;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtcorebase.NavigationAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.analysis.DomainUsage;
import org.eclipse.qvtd.pivot.qvtcorebase.utilities.QVTcoreBaseUtil;
import org.eclipse.qvtd.pivot.schedule.ClassDatum;
/**
* Nodes provides factory instances for creating the various forms of nodes.
*/
public class Nodes
{
private static enum ClassableEnum { DATATYPE, CLASS };
private static enum GuardableEnum { STEP, GUARD, HEAD };
private static enum NavigableEnum { UNNAVIGABLE, NAVIGABLE };
private static @NonNull ClassableEnum asClassable(boolean isClass) {
return isClass ? ClassableEnum.CLASS : ClassableEnum.DATATYPE;
}
private static @NonNull NavigableEnum asNavigable(boolean isNavigable) {
return isNavigable ? NavigableEnum.NAVIGABLE : NavigableEnum.UNNAVIGABLE;
}
private static abstract class AbstractSimpleNodeRole extends AbstractNodeRole
{
protected AbstractSimpleNodeRole(@NonNull Phase phase) {
super(phase);
}
public @NonNull TypedNode createNode(@NonNull Node sourceNode, @NonNull Property source2targetProperty) {
Region region = sourceNode.getRegion();
assert sourceNode.isClass();
SchedulerConstants schedulerConstants = region.getSchedulerConstants();
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)source2targetProperty.getType();
assert type != null;
Type elementType = PivotUtil.getElementalType(type);
TypedModel typedModel = elementType instanceof DataType ? schedulerConstants.getDomainAnalysis().getPrimitiveTypeModel() : sourceNode.getClassDatumAnalysis().getTypedModel();
assert typedModel != null;
ClassDatum classDatum = schedulerConstants.getClassDatum(type, typedModel);
ClassDatumAnalysis classDatumAnalysis = schedulerConstants.getClassDatumAnalysis(classDatum);
String name = source2targetProperty.getName();
assert name != null;
return new TypedNode(this, region, name, classDatumAnalysis);
}
@Override
public @NonNull TypedNode createNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return new TypedNode(this, region, name, classDatumAnalysis);
}
@Override
public @NonNull TypedNode createNode(@NonNull Region region, @NonNull String name, @NonNull TypedElement typedElement) {
return new TypedNode(this, region, name, typedElement);
}
}
private static abstract class AbstractVariableNodeRole extends AbstractSimpleNodeRole
{
protected final @NonNull ClassableEnum classable;
protected AbstractVariableNodeRole(@NonNull Phase phase, @NonNull ClassableEnum classable) {
super(phase);
this.classable = classable;
}
public @NonNull VariableNode createNode(@NonNull Region region, @NonNull VariableDeclaration variable) {
assert isClass() == !(variable.getType() instanceof DataType);
return region.createVariableNode(this, variable);
}
@Override
public boolean isClass() {
return classable == ClassableEnum.CLASS;
}
@Override
public boolean isDataType() {
return classable == ClassableEnum.DATATYPE;
}
}
private static final class ComposingNodeRole extends AbstractSimpleNodeRole
{
public static final @NonNull NodeRole COMPOSING = new ComposingNodeRole();
protected ComposingNodeRole() {
super(Role.Phase.LOADED);
}
@Override
public boolean isClass() {
return true;
}
@Override
public boolean isNavigable() {
return true;
}
}
private static final class ErrorNodeRole extends AbstractSimpleNodeRole
{
public static final @NonNull NodeRole ERROR = new ErrorNodeRole();
protected ErrorNodeRole() {
super(Role.Phase.OTHER);
}
@Override
public @NonNull String getColor() {
return ERROR_COLOR;
}
@Override
public @NonNull Integer getPenwidth() {
return GUARD_WIDTH;
}
@Override
public @NonNull String getShape() {
return "circle";
}
}
private static class ExtraGuardNodeRole extends AbstractSimpleNodeRole
{
public static final @NonNull NodeRole EXTRA_GUARD = new ExtraGuardNodeRole();
protected ExtraGuardNodeRole() {
super(Role.Phase.PREDICATED);
}
@Override
public boolean isDataType() {
return true;
}
@Override
public boolean isExtraGuardVariable() {
return true;
}
@Override
public boolean isGuard() {
return true;
}
@Override
public boolean isHead() {
return true;
}
}
private static final class InputNodeRole extends AbstractNodeRole
{
private static final @NonNull InputNodeRole CONSTANT_INPUT = new InputNodeRole(Role.Phase.CONSTANT); //, true);
private static final @NonNull InputNodeRole LOADED_INPUT = new InputNodeRole(Role.Phase.LOADED); //, true);
// private static final @NonNull InputNodeRole PREDICATED_INPUT = new InputNodeRole(Role.Phase.PREDICATED); //, true);
// private static final @NonNull InputNodeRole REALIZED_INPUT = new InputNodeRole(Role.Phase.REALIZED); //, true);
public static @NonNull Node createInputNode(@NonNull Region region, NodeRole.@NonNull Phase nodeRolePhase, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
switch (nodeRolePhase) {
case CONSTANT: return CONSTANT_INPUT.createNode(region, name, classDatumAnalysis);
case LOADED: return LOADED_INPUT.createNode(region, name, classDatumAnalysis);
// case PREDICATED: return PREDICATED_INPUT.createNode(region, name, classDatumAnalysis);
// case REALIZED: return REALIZED_INPUT.createNode(region, name, classDatumAnalysis);
}
throw new UnsupportedOperationException();
}
protected InputNodeRole(@NonNull Phase phase) {
super(phase);
}
@Override
public @NonNull Node createNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
throw new UnsupportedOperationException(); // FIXME Only used for obsolete cyclic regions.
}
@Override
public @NonNull Node createNode(@NonNull Region region, @NonNull String name, @NonNull TypedElement typedElement) {
throw new UnsupportedOperationException();
}
@Override
public @NonNull Integer getPenwidth() {
return Role.HEAD_WIDTH; //isHead ? Role.HEAD_WIDTH : Role.GUARD_WIDTH;
}
@Override
public boolean isHead() {
return true;
}
}
private static final class IteratorNodeRole extends AbstractVariableNodeRole
{
private static final @NonNull IteratorNodeRole CONSTANT_DATATYPE_ITERATOR = new IteratorNodeRole(Role.Phase.CONSTANT, ClassableEnum.DATATYPE);
private static final @NonNull IteratorNodeRole CONSTANT_CLASS_ITERATOR = new IteratorNodeRole(Role.Phase.CONSTANT, ClassableEnum.CLASS);
private static final @NonNull IteratorNodeRole LOADED_DATATYPE_ITERATOR = new IteratorNodeRole(Role.Phase.LOADED, ClassableEnum.DATATYPE);
private static final @NonNull IteratorNodeRole LOADED_CLASS_ITERATOR = new IteratorNodeRole(Role.Phase.LOADED, ClassableEnum.CLASS);
private static final @NonNull IteratorNodeRole PREDICATED_DATATYPE_ITERATOR = new IteratorNodeRole(Role.Phase.PREDICATED, ClassableEnum.DATATYPE);
private static final @NonNull IteratorNodeRole PREDICATED_CLASS_ITERATOR = new IteratorNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS);
public static @NonNull IteratorNodeRole getIteratorNodeRole(@NonNull Phase phase, @NonNull ClassableEnum classable) {
switch (classable) {
case CLASS: {
switch (phase) {
case CONSTANT: return CONSTANT_CLASS_ITERATOR;
case LOADED: return LOADED_CLASS_ITERATOR;
case PREDICATED: return PREDICATED_CLASS_ITERATOR;
}
break;
}
case DATATYPE: {
switch (phase) {
case CONSTANT: return CONSTANT_DATATYPE_ITERATOR;
case LOADED: return LOADED_DATATYPE_ITERATOR;
case PREDICATED: return PREDICATED_DATATYPE_ITERATOR;
}
break;
}
}
throw new UnsupportedOperationException();
}
protected IteratorNodeRole(@NonNull Phase phase, @NonNull ClassableEnum classable) {
super(phase, classable);
}
@Override
public @NonNull IteratorNodeRole asPhase(@NonNull Phase phase) {
return getIteratorNodeRole(phase, classable);
}
@Override
public boolean isInternal() {
return true;
}
@Override
public boolean isIterator() {
return true;
}
@Override
public @NonNull NodeRole merge(@NonNull NodeRole nodeRole) {
if (nodeRole instanceof IteratorNodeRole) {
return RegionUtil.mergeToMoreKnownPhase(this, nodeRole);
}
else {
return super.merge(nodeRole);
}
}
}
private static class NullNodeRole extends AbstractSimpleNodeRole
{
private static final @NonNull NullNodeRole NULL = new NullNodeRole();
private NullNodeRole() {
super(Role.Phase.CONSTANT);
}
@Override
public @Nullable String getStyle() {
return "rounded";
}
@Override
public boolean isNull() {
return true;
}
@Override
public boolean isPattern() {
return true;
}
}
private static class OperationNodeRole extends AbstractSimpleNodeRole
{
private static final @NonNull OperationNodeRole CONSTANT_OPERATION = new OperationNodeRole(Role.Phase.CONSTANT);
private static final @NonNull OperationNodeRole LOADED_OPERATION = new OperationNodeRole(Role.Phase.LOADED);
private static final @NonNull OperationNodeRole PREDICATED_OPERATION = new OperationNodeRole(Role.Phase.PREDICATED);
private static final @NonNull OperationNodeRole REALIZED_OPERATION = new OperationNodeRole(Role.Phase.REALIZED);
public static @NonNull Phase getOperationNodePhase(@NonNull Region region, @NonNull TypedElement typedElement, @NonNull Node... argNodes) {
boolean isLoaded = false;
boolean isPredicated = false;
boolean isRealized = false;
if (argNodes != null) {
for (Node argNode : argNodes) {
if (argNode.isRealized()) {
isRealized = true;
}
else if (argNode.isPredicated()) {
isPredicated = true;
}
else if (argNode.isLoaded()) {
isLoaded = true;
}
}
}
if (typedElement instanceof OperationCallExp) {
Operation asOperation = ((OperationCallExp)typedElement).getReferredOperation();
if (QVTbaseUtil.isIdentification(asOperation)) {
DomainUsage usage = region.getSchedulerConstants().getDomainUsage(typedElement);
if (!usage.isInput()) {
isRealized = true;
}
}
}
if (isRealized) {
return Phase.REALIZED;
}
else if (isPredicated) {
return Phase.PREDICATED;
}
else if (isLoaded) {
return Phase.LOADED;
}
else {
return Phase.CONSTANT;
}
}
public static @NonNull OperationNodeRole getOperationNodeRole(@NonNull Phase phase) {
switch (phase) {
case CONSTANT: return CONSTANT_OPERATION;
case LOADED: return LOADED_OPERATION;
case PREDICATED: return PREDICATED_OPERATION;
case REALIZED: return REALIZED_OPERATION;
}
throw new UnsupportedOperationException();
}
protected OperationNodeRole(@NonNull Phase phase) {
super(phase);
}
@Override
public @NonNull OperationNodeRole asPhase(@NonNull Phase phase) {
return getOperationNodeRole(phase);
}
@Override
public @NonNull Integer getPenwidth() {
return LINE_WIDTH;
}
@Override
public @NonNull String getShape() {
return "ellipse";
}
@Override
public boolean isExpression() {
return true;
}
@Override
public boolean isOperation() {
return true;
}
}
private static class PatternNodeRole extends AbstractVariableNodeRole
{
private static final @NonNull PatternNodeRole CONSTANT_NAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.CONSTANT, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole CONSTANT_UNNAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.CONSTANT, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole LOADED_NAVIGABLE_CLASS_HEAD = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.HEAD);
private static final @NonNull PatternNodeRole LOADED_NAVIGABLE_DATATYPE_GUARD = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
private static final @NonNull PatternNodeRole LOADED_NAVIGABLE_CLASS_GUARD = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
private static final @NonNull PatternNodeRole LOADED_NAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole LOADED_NAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole LOADED_UNNAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole LOADED_UNNAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.LOADED, ClassableEnum.CLASS, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole PREDICATED_NAVIGABLE_CLASS_HEAD = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.HEAD);
private static final @NonNull PatternNodeRole PREDICATED_NAVIGABLE_DATATYPE_GUARD = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
private static final @NonNull PatternNodeRole PREDICATED_NAVIGABLE_CLASS_GUARD = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
private static final @NonNull PatternNodeRole PREDICATED_NAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole PREDICATED_NAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole PREDICATED_UNNAVIGABLE_DATATYPE_HEAD = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.HEAD);
private static final @NonNull PatternNodeRole PREDICATED_UNNAVIGABLE_CLASS_HEAD = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS, NavigableEnum.UNNAVIGABLE, GuardableEnum.HEAD);
private static final @NonNull PatternNodeRole PREDICATED_UNNAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole PREDICATED_UNNAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.PREDICATED, ClassableEnum.CLASS, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole REALIZED_NAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.REALIZED, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole REALIZED_UNNAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.REALIZED, ClassableEnum.CLASS, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole REALIZED_UNNAVIGABLE_DATATYPE_STEP = new PatternNodeRole(Role.Phase.REALIZED, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
private static final @NonNull PatternNodeRole SPECULATED_NAVIGABLE_CLASS_HEAD = new PatternNodeRole(Role.Phase.SPECULATED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.HEAD);
private static final @NonNull PatternNodeRole SPECULATED_NAVIGABLE_CLASS_GUARD = new PatternNodeRole(Role.Phase.SPECULATED, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
private static final @NonNull PatternNodeRole SPECULATION_NAVIGABLE_CLASS_STEP = new PatternNodeRole(Role.Phase.SPECULATION, ClassableEnum.CLASS, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
public static @NonNull PatternNodeRole getDataTypeNodeRole(@NonNull Node sourceNode, @NonNull Property property) {
Phase phase;
switch (sourceNode.getNodeRole().getPhase()) {
case REALIZED: phase = Phase.REALIZED; break;
case PREDICATED: phase = Phase.PREDICATED; break;
case LOADED: {
boolean isDirty = sourceNode.getRegion().getSchedulerConstants().isDirty(property);
phase = isDirty ? Phase.PREDICATED : Phase.LOADED; break;
}
case CONSTANT: phase = Phase.CONSTANT; break;
default: throw new UnsupportedOperationException();
}
NavigableEnum navigableEnum = Nodes.asNavigable(sourceNode.isNavigable());
return getPatternNodeRole(phase, ClassableEnum.DATATYPE, navigableEnum, GuardableEnum.STEP);
}
public static @NonNull PatternNodeRole getPatternNodeRole(@NonNull Phase phase, @NonNull ClassableEnum classable, @NonNull NavigableEnum navigable, @NonNull GuardableEnum guardable) {
switch (navigable) {
case NAVIGABLE: {
switch (guardable) {
case HEAD: {
switch (classable) {
case CLASS: {
switch (phase) {
case LOADED: return LOADED_NAVIGABLE_CLASS_HEAD;
case PREDICATED: return PREDICATED_NAVIGABLE_CLASS_HEAD;
case SPECULATED: return SPECULATED_NAVIGABLE_CLASS_HEAD;
}
break;
}
case DATATYPE: {
switch (phase) {
}
break;
}
}
break;
}
case GUARD: {
switch (classable) {
case CLASS: {
switch (phase) {
case LOADED: return LOADED_NAVIGABLE_CLASS_GUARD;
case PREDICATED: return PREDICATED_NAVIGABLE_CLASS_GUARD;
case SPECULATED: return SPECULATED_NAVIGABLE_CLASS_GUARD;
}
break;
}
case DATATYPE: {
switch (phase) {
case LOADED: return LOADED_NAVIGABLE_DATATYPE_GUARD;
case PREDICATED: return PREDICATED_NAVIGABLE_DATATYPE_GUARD;
}
break;
}
}
break;
}
case STEP: {
switch (classable) {
case CLASS: {
switch (phase) {
case LOADED: return LOADED_NAVIGABLE_CLASS_STEP;
case PREDICATED: return PREDICATED_NAVIGABLE_CLASS_STEP;
case SPECULATION: return SPECULATION_NAVIGABLE_CLASS_STEP;
}
break;
}
case DATATYPE: {
switch (phase) {
case CONSTANT: return CONSTANT_NAVIGABLE_DATATYPE_STEP;
case LOADED: return LOADED_NAVIGABLE_DATATYPE_STEP;
case PREDICATED: return PREDICATED_NAVIGABLE_DATATYPE_STEP;
case REALIZED: return REALIZED_NAVIGABLE_DATATYPE_STEP;
}
break;
}
}
break;
}
}
break;
}
case UNNAVIGABLE: {
switch (guardable) {
case HEAD: {
switch (classable) {
case CLASS: {
switch (phase) {
case PREDICATED: return PREDICATED_UNNAVIGABLE_CLASS_HEAD;
}
break;
}
case DATATYPE: {
switch (phase) {
case PREDICATED: return PREDICATED_UNNAVIGABLE_DATATYPE_HEAD;
}
break;
}
}
break;
}
case GUARD: {
break;
}
case STEP: {
switch (classable) {
case CLASS: {
switch (phase) {
case LOADED: return LOADED_UNNAVIGABLE_CLASS_STEP;
case PREDICATED: return PREDICATED_UNNAVIGABLE_CLASS_STEP;
case REALIZED: return REALIZED_UNNAVIGABLE_CLASS_STEP;
}
break;
}
case DATATYPE: {
switch (phase) {
case CONSTANT: return CONSTANT_UNNAVIGABLE_DATATYPE_STEP;
case LOADED: return LOADED_UNNAVIGABLE_DATATYPE_STEP;
case PREDICATED: return PREDICATED_UNNAVIGABLE_DATATYPE_STEP;
case REALIZED: return REALIZED_UNNAVIGABLE_DATATYPE_STEP;
}
break;
}
}
break;
}
}
break;
}
}
throw new UnsupportedOperationException();
}
private final @NonNull NavigableEnum navigable;
private final @NonNull GuardableEnum guardable;
private PatternNodeRole(@NonNull Phase phase, @NonNull ClassableEnum classable, @NonNull NavigableEnum navigable, @NonNull GuardableEnum guardable) {
super(phase, classable);
this.navigable = navigable;
this.guardable = guardable;
}
@Override
public @NonNull NodeRole asNavigable() {
return getPatternNodeRole(phase, classable, NavigableEnum.NAVIGABLE, guardable);
}
@Override
public @NonNull PatternNodeRole asPhase(@NonNull Phase phase) {
return getPatternNodeRole(phase, classable, navigable, guardable);
}
@Override
public @NonNull NodeRole asSpeculated() {
return getPatternNodeRole(Phase.SPECULATED, classable, NavigableEnum.NAVIGABLE, GuardableEnum.HEAD);
}
@Override
public @NonNull NodeRole asSpeculation() {
return getPatternNodeRole(Phase.SPECULATION, classable, NavigableEnum.NAVIGABLE, guardable);
}
@Override
public boolean isGuard() {
return guardable != GuardableEnum.STEP;
}
@Override
public boolean isHead() {
return guardable == GuardableEnum.HEAD;
}
@Override
public boolean isNavigable() {
return navigable == NavigableEnum.NAVIGABLE;
}
@Override
public boolean isPattern() {
return true;
}
@Override
public @NonNull NodeRole merge(@NonNull NodeRole nodeRole) {
assert nodeRole instanceof PatternNodeRole;
assert isClass() == nodeRole.isClass();
Phase mergedPhase = RegionUtil.mergeToMoreKnownPhase(this, nodeRole).getPhase();
NavigableEnum mergedNavigable;
GuardableEnum mergedGuardable;
if (mergedPhase == Phase.REALIZED) {
mergedNavigable = NavigableEnum.UNNAVIGABLE;
mergedGuardable = GuardableEnum.STEP;
}
else {
mergedNavigable = Nodes.asNavigable(isNavigable() || nodeRole.isNavigable());
mergedGuardable = (isHead() && nodeRole.isHead()) ? GuardableEnum.HEAD : isGuard() || nodeRole.isGuard() ? GuardableEnum.GUARD : GuardableEnum.STEP;
}
return getPatternNodeRole(mergedPhase, classable, mergedNavigable, mergedGuardable);
}
@Override
public @NonNull NodeRole resetHead() {
return getPatternNodeRole(phase, classable, navigable, !isGuard() ? GuardableEnum.STEP : GuardableEnum.GUARD);
}
@Override
public @NonNull NodeRole setHead() {
return getPatternNodeRole(phase, classable, navigable, GuardableEnum.HEAD);
}
@Override
public String toString() {
return phase + (isNavigable() ? "-Navigable" : "-Unnavigable") + (isClass() ? "-Class" : "-DataType") + (isHead() ? "Head-" : isGuard() ? "Guard-" : "Step-") + getClass().getSimpleName();
}
}
// FIXME Can this be merged into PatternNodeRole ??
private static final class PredicatedInternalNodeRole extends AbstractSimpleNodeRole
{
public static final @NonNull PredicatedInternalNodeRole PREDICATED_INTERNAL_CLASS = new PredicatedInternalNodeRole();
private PredicatedInternalNodeRole() {
super(Role.Phase.PREDICATED);
}
@Override
public boolean isDataType() {
return true;
}
@Override
public boolean isInternal() {
return true;
}
@Override
public boolean isPattern() {
return true;
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}
private static final class TrueNodeRole extends AbstractSimpleNodeRole
{
private static final @NonNull TrueNodeRole TRUE = new TrueNodeRole();
private TrueNodeRole() {
super(Role.Phase.CONSTANT);
}
@Override
public @Nullable String getStyle() {
return null;
}
@Override
public boolean isHead() {
return true;
}
@Override
public boolean isPattern() {
return true;
}
@Override
public boolean isTrue() {
return true;
}
}
private static final class UnknownNodeRole extends AbstractSimpleNodeRole
{
public static final @NonNull NodeRole UNKNOWN = new UnknownNodeRole();
protected UnknownNodeRole() {
super(Role.Phase.OTHER);
}
@Override
public @NonNull String getColor() {
return ERROR_COLOR;
}
}
public static @NonNull Node createComposingNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return ComposingNodeRole.COMPOSING.createNode(region, name, classDatumAnalysis);
}
public static @NonNull TypedNode createDataTypeNode(@NonNull Node sourceNode, @NonNull Property property) {
PatternNodeRole patternNodeRole = PatternNodeRole.getDataTypeNodeRole(sourceNode, property);
return patternNodeRole.createNode(sourceNode, property);
}
public static @NonNull TypedNode createDataTypeNode(@NonNull Node sourceNode, @NonNull NavigationCallExp navigationCallExp) {
Property property = PivotUtil.getReferredProperty(navigationCallExp);
PatternNodeRole patternNodeRole = PatternNodeRole.getDataTypeNodeRole(sourceNode, property);
assert sourceNode.isClass();
String name = property.getName();
assert name != null;
return patternNodeRole.createNode(sourceNode.getRegion(), name, navigationCallExp);
}
public static @NonNull Node createDataTypeNode(@NonNull Node targetNode, @NonNull NavigationAssignment navigationAssignment) {
Role.Phase phase;
switch (targetNode.getNodeRole().getPhase()) {
case REALIZED: phase = Role.Phase.REALIZED; break;
case PREDICATED: phase = Role.Phase.PREDICATED; break;
case LOADED: phase = Role.Phase.LOADED; break;
case CONSTANT: phase = Role.Phase.CONSTANT; break;
default: throw new UnsupportedOperationException();
}
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(phase, ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
Property property = QVTcoreBaseUtil.getTargetProperty(navigationAssignment);
// PatternNodeRole patternNodeRole = PatternNodeRole.getDataTypeNodeRole(targetNode, property);
// assert sourceNode.isClass();
String name = property.getName();
assert name != null;
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)property.getType();
assert type != null;
TypedModel typedModel = targetNode.getClassDatumAnalysis().getTypedModel();
Region region = targetNode.getRegion();
ClassDatum classDatum = region.getSchedulerConstants().getClassDatum(type, typedModel);
// DomainUsage domainUsage = parentNode.getClassDatumAnalysis().getDomainUsage();
ClassDatumAnalysis classDatumAnalysis = region.getSchedulerConstants().getClassDatumAnalysis(classDatum);
return patternNodeRole.createNode(region, name, classDatumAnalysis);
}
public static @NonNull Node createErrorNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return ErrorNodeRole.ERROR.createNode(region, name, classDatumAnalysis);
}
public static @NonNull Node createExtraGuardNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return ExtraGuardNodeRole.EXTRA_GUARD.createNode(region, name, classDatumAnalysis);
}
public static @NonNull VariableNode createGuardNode(@NonNull Region region, @NonNull VariableDeclaration variable) {
DomainUsage domainUsage = region.getSchedulerConstants().getDomainUsage(variable);
boolean isEnforceable = domainUsage.isOutput() || domainUsage.isMiddle();
ClassableEnum classable = asClassable(!(variable.getType() instanceof DataType));
Role.Phase phase = isEnforceable ? Role.Phase.PREDICATED : Role.Phase.LOADED;
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(phase, classable, NavigableEnum.NAVIGABLE, GuardableEnum.GUARD);
return patternNodeRole.createNode(region, variable);
}
public static @NonNull Node createInputNode(@NonNull Region region, NodeRole.@NonNull Phase nodeRolePhase, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return InputNodeRole.createInputNode(region, nodeRolePhase, name, classDatumAnalysis);
}
public static @NonNull VariableNode createIteratorNode(@NonNull Variable iterator, @NonNull Node sourceNode) {
ClassableEnum classable = asClassable(!(iterator.getType() instanceof DataType));
IteratorNodeRole nodeRole = IteratorNodeRole.getIteratorNodeRole(sourceNode.getNodeRole().getPhase(), classable);
return nodeRole.createNode(sourceNode.getRegion(), iterator);
}
public static @NonNull VariableNode createLetVariableNode(@NonNull Variable letVariable, @NonNull Node inNode) {
ClassableEnum classable = asClassable(!(letVariable.getType() instanceof DataType));
NavigableEnum resolvedIsNavigable = asNavigable(inNode.isNavigable());
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(inNode.getNodeRole().getPhase(), classable, resolvedIsNavigable, GuardableEnum.STEP);
return patternNodeRole.createNode(inNode.getRegion(), letVariable);
}
public static @NonNull VariableNode createLoadedStepNode(@NonNull Region region, @NonNull VariableDeclaration stepVariable) {
ClassableEnum classable = asClassable(!(stepVariable.getType() instanceof DataType));
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.LOADED, classable, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(region, stepVariable);
}
public static @NonNull TypedNode createNullNode(@NonNull Region region, @Nullable TypedElement typedElement) {
if (typedElement != null) {
return NullNodeRole.NULL.createNode(region, "«null»", typedElement);
}
else {
return NullNodeRole.NULL.createNode(region, "«null»", region.getSchedulerConstants().getOclVoidClassDatumAnalysis());
}
}
public static @NonNull TypedNode createOperationElementNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis, @NonNull Node sourceNode) {
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(sourceNode.getNodeRole().getPhase(), ClassableEnum.DATATYPE, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(region, name, classDatumAnalysis);
}
public static @NonNull TypedNode createOperationNode(@NonNull Region region, @NonNull String name, @NonNull TypedElement typedElement, @NonNull Node... argNodes) {
Role.Phase nodePhase = OperationNodeRole.getOperationNodePhase(region, typedElement, argNodes);
OperationNodeRole nodeRole = OperationNodeRole.getOperationNodeRole(nodePhase);
return nodeRole.createNode(region, name, typedElement);
}
public static @NonNull TypedNode createOperationParameterNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
ClassableEnum classable = asClassable(!(classDatumAnalysis.getClassDatum().getType() instanceof DataType));
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.PREDICATED, classable, NavigableEnum.UNNAVIGABLE, GuardableEnum.HEAD);
return patternNodeRole.createNode(region, name, classDatumAnalysis);
}
public static @NonNull TypedNode createOperationResultNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis, @NonNull Node sourceNode) {
ClassableEnum classable = asClassable(!(classDatumAnalysis.getClassDatum().getType() instanceof DataType));
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(sourceNode.getNodeRole().getPhase(), classable, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(region, name, classDatumAnalysis);
}
public static @NonNull Node createPredicatedInternalClassNode(@NonNull Node parentNode, @NonNull NavigationAssignment navigationAssignment) {
assert parentNode.isClass();
SchedulerConstants schedulerConstants = parentNode.getRegion().getSchedulerConstants();
Property property = QVTcoreBaseUtil.getTargetProperty(navigationAssignment);
assert property != null;
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)property.getType();
assert type != null;
TypedModel typedModel = parentNode.getClassDatumAnalysis().getTypedModel();
ClassDatum classDatum = schedulerConstants.getClassDatum(type, typedModel);
// DomainUsage domainUsage = parentNode.getClassDatumAnalysis().getDomainUsage();
ClassDatumAnalysis classDatumAnalysis = schedulerConstants.getClassDatumAnalysis(classDatum);
String name = property.getName();
assert name != null;
return PredicatedInternalNodeRole.PREDICATED_INTERNAL_CLASS.createNode(parentNode.getRegion(), name, classDatumAnalysis);
}
public static @NonNull Node createPredicatedInternalClassNode(@NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
return PredicatedInternalNodeRole.PREDICATED_INTERNAL_CLASS.createNode(region, name, classDatumAnalysis);
}
public static @NonNull TypedNode createRealizedDataTypeNode(@NonNull Node sourceNode, @NonNull Property source2targetProperty) {
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.REALIZED, ClassableEnum.DATATYPE, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(sourceNode, source2targetProperty);
}
public static @NonNull VariableNode createRealizedStepNode(@NonNull Region region, @NonNull Variable stepVariable) {
ClassableEnum classable = asClassable(!(stepVariable.getType() instanceof DataType));
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.REALIZED, classable, NavigableEnum.UNNAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(region, stepVariable);
}
public static @NonNull TypedNode createStepNode(@NonNull String name, @NonNull CallExp callExp, @NonNull Node sourceNode, boolean isNavigable) {
Region region = sourceNode.getRegion();
DomainUsage domainUsage = region.getSchedulerConstants().getDomainUsage(callExp);
boolean isMiddleOrOutput = domainUsage.isOutput() || domainUsage.isMiddle();
boolean isDirty = false;
if (callExp instanceof NavigationCallExp) {
Property referredProperty = PivotUtil.getReferredProperty((NavigationCallExp)callExp);
isDirty = region.getSchedulerConstants().isDirty(referredProperty);
}
Role.Phase phase = sourceNode.isPredicated() || isMiddleOrOutput || isDirty ? Role.Phase.PREDICATED : Role.Phase.LOADED;
NavigableEnum navigableEnum = isNavigable ? NavigableEnum.NAVIGABLE : NavigableEnum.UNNAVIGABLE;
ClassableEnum classable = asClassable(sourceNode.isClass());
PatternNodeRole stepNodeRole = PatternNodeRole.getPatternNodeRole(phase, classable, navigableEnum, GuardableEnum.STEP);
return stepNodeRole.createNode(region, name, callExp);
}
public static @NonNull Node createStepNode(@NonNull Region region, @NonNull TypedNode typedNode) {
NodeRole stepNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.PREDICATED, asClassable(typedNode.isClass()), NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
return stepNodeRole.createNode(region, typedNode.getName(), typedNode.getClassDatumAnalysis());
}
public static @NonNull TypedNode createTrueNode(@NonNull Region region) {
SchedulerConstants schedulerConstants = region.getSchedulerConstants();
org.eclipse.ocl.pivot.Class booleanType = schedulerConstants.getStandardLibrary().getBooleanType();
DomainUsage primitiveUsage = schedulerConstants.getDomainAnalysis().getPrimitiveUsage();
ClassDatumAnalysis classDatumAnalysis = schedulerConstants.getClassDatumAnalysis(booleanType, ClassUtil.nonNullState(primitiveUsage.getTypedModel(null)));
return TrueNodeRole.TRUE.createNode(region, "«true»", classDatumAnalysis);
}
public static @NonNull Node createUnknownNode(@NonNull Region region, @NonNull String name, @NonNull TypedElement typedElement) {
return UnknownNodeRole.UNKNOWN.createNode(region, name, typedElement);
}
/* public static @NonNull VariableNode createUnrealizedStepNode(@NonNull Region region, @NonNull VariableDeclaration stepVariable) {
/* SchedulerConstants schedulerConstants = region.getSchedulerConstants();
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)stepVariable.getType();
assert type != null;
Type elementType = QVTbaseUtil.getElementalType(type);
TypedModel typedModel = elementType instanceof DataType ? schedulerConstants.getDomainAnalysis().getPrimitiveTypeModel() : sourceNode.getClassDatumAnalysis().getTypedModel();
assert typedModel != null;
ClassDatum classDatum = schedulerConstants.getClassDatum(type, typedModel);
ClassDatumAnalysis classDatumAnalysis = schedulerConstants.getClassDatumAnalysis(classDatum); * /
// throw new UnsupportedOperationException(); // FIXME experimenting
ClassableEnum classable = asClassable(!(stepVariable.getType() instanceof DataType));
PatternNodeRole patternNodeRole = PatternNodeRole.getPatternNodeRole(Role.Phase.LOADDED, classable, NavigableEnum.NAVIGABLE, GuardableEnum.STEP);
return patternNodeRole.createNode(region, stepVariable);
} */
}