/*
* Copyright 2003-2017 JetBrains s.r.o.
*
* 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 jetbrains.mps.generator.impl.plan;
import jetbrains.mps.generator.impl.cache.MappingsMemento;
import jetbrains.mps.generator.plan.CheckpointIdentity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.annotations.Immutable;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Keep information about mapping labels known at checkpoint step.
*
* CheckpointState represents state at a given Checkpoint. Model-wide state that records states for all checkpoints
* of the given model is accessible though {@link ModelCheckpoints}
*
* @author Artem Tikhomirov
* @since 3.3
*/
@Immutable
public class CheckpointState {
@NotNull
private final MappingsMemento myState;
private final SModel myCheckpointModel;
private final CheckpointIdentity myCheckpoint;
public CheckpointState(@NotNull MappingsMemento memento, @NotNull SModel checkpointModel, @NotNull CheckpointIdentity cp) {
myState = memento;
myCheckpointModel = checkpointModel;
myCheckpoint = cp;
}
public SModel getCheckpointModel() {
return myCheckpointModel;
}
public CheckpointIdentity getCheckpoint() {
return myCheckpoint;
}
@NotNull
public Collection<String> getMappingLabels() {
// FIXME wrap it (ML + inputs + outputs) into an object like MapLabelState, with getLabel(), getInputs() and getOutput(input).
// MapLabelState.getInput may return object (LabelAssociatedValues), which in turn has getOutput()
return myState.getMappingNameAndInputNodeToOutputNodeMap().keySet();
}
/*package*/ Collection<SNodeId> getInputs(String mappingLabel) {
Map<SNodeId, Object> values = myState.getMappingNameAndInputNodeToOutputNodeMap().get(mappingLabel);
assert values != null; // provided getMappingLabels().contains(mappingLabel)
return values.keySet();
}
@NotNull
public Collection<SNode> getOutput(String mappingLabel, SNode input) {
Map<SNodeId, Object> values = myState.getMappingNameAndInputNodeToOutputNodeMap().get(mappingLabel);
assert values != null; // provided getMappingLabels().contains(mappingLabel)
Object outputNodes = values.get(input.getNodeId());
Collection<SNodeId> rv = null;
if (outputNodes instanceof Collection) {
rv = (Collection<SNodeId>) outputNodes;
} else if (outputNodes instanceof SNodeId) {
rv = Collections.singleton((SNodeId) outputNodes);
}
return rv == null ? Collections.<SNode>emptyList() : resolve(rv);
}
@NotNull
public List<SNode> getOutputWithoutInput(String mappingLabel) {
return resolve(myState.getNewOutputNodes(mappingLabel));
}
private List<SNode> resolve(Collection<SNodeId> output) {
ArrayList<SNode> rv = new ArrayList<SNode>(output.size());
for (SNodeId id : output) {
SNode node = myCheckpointModel.getNode(id);
assert node != null : "provided SNodeId comes from getOutput() it's unreasonable to expect model misses the node";
rv.add(node);
}
return rv;
}
}