MapOp.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.functional.core.operation;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Represents a map operation in a stream pipeline.
*/
public final class MapOp implements Operation {
private final String expression;
private final String targetType;
private final String outputVariableName;
private final boolean sideEffect;
private final List<String> associatedComments;
/**
* Creates a MapOp with all parameters.
* @param expression the mapping expression
* @param targetType the target type (can be null)
* @param outputVariableName the variable name for the output of this map (can be null)
* @param sideEffect if true, this is a side-effect map: map(var -> { stmt; return var; })
*/
public MapOp(String expression, String targetType, String outputVariableName, boolean sideEffect) {
this.expression = Objects.requireNonNull(expression, "expression must not be null");
this.targetType = targetType;
this.outputVariableName = outputVariableName;
this.sideEffect = sideEffect;
this.associatedComments = new ArrayList<>();
}
/**
* Creates a MapOp with expression, target type, and output variable name.
* @param expression the mapping expression
* @param targetType the target type (can be null)
* @param outputVariableName the variable name for the output of this map (can be null)
*/
public MapOp(String expression, String targetType, String outputVariableName) {
this(expression, targetType, outputVariableName, false);
}
/**
* Creates a MapOp with expression and target type.
* @param expression the mapping expression
* @param targetType the target type (can be null)
*/
public MapOp(String expression, String targetType) {
this(expression, targetType, null, false);
}
/**
* Creates a MapOp with just an expression and no target type.
* @param expression the mapping expression
*/
public MapOp(String expression) {
this(expression, null, null, false);
}
@Override
public String expression() {
return expression;
}
public String targetType() {
return targetType;
}
/**
* Returns the output variable name for this map operation.
* When chaining maps, the next operation should use this as its lambda parameter.
* @return the output variable name, or null if not specified
*/
public String outputVariableName() {
return outputVariableName;
}
/**
* Returns whether this is a side-effect map.
* Side-effect maps render as: {@code map(var -> { statements; return var; })}
* @return true if this is a side-effect map
*/
public boolean isSideEffect() {
return sideEffect;
}
@Override
public String operationType() {
return "map";
}
/**
* Adds a comment associated with this operation.
* @param comment the comment text
*/
public void addComment(String comment) {
if (comment != null && !comment.isBlank()) {
this.associatedComments.add(comment);
}
}
/**
* Adds multiple comments associated with this operation.
* @param comments the list of comment texts
*/
public void addComments(List<String> comments) {
if (comments != null) {
comments.forEach(this::addComment);
}
}
/**
* Returns all comments associated with this operation.
* @return unmodifiable view of the comments list
*/
public List<String> getComments() {
return List.copyOf(associatedComments);
}
/**
* Checks if this operation has any associated comments.
* @return true if there are comments, false otherwise
*/
public boolean hasComments() {
return !associatedComments.isEmpty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MapOp)) return false;
MapOp mapOp = (MapOp) o;
return sideEffect == mapOp.sideEffect &&
expression.equals(mapOp.expression) &&
Objects.equals(targetType, mapOp.targetType) &&
Objects.equals(outputVariableName, mapOp.outputVariableName);
}
@Override
public int hashCode() {
return Objects.hash(expression, targetType, outputVariableName, sideEffect);
}
@Override
public String toString() {
return "MapOp[expression=" + expression +
", targetType=" + targetType +
", comments=" + associatedComments.size() + "]";
}
}