/******************************************************************************* * Copyright (c) 2015 Pivotal, Inc. * 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: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.editor.support.yaml.ast; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeTuple; import org.yaml.snakeyaml.nodes.SequenceNode; /** * A node reference represents a 'pointer' to a location where a Node is stored. * The concept is useful because when looking for a 'path' inside an Yaml AST a * NodeRef makes it explicit where the node is with respect to some 'container'. * For example it allows distinguishing between a reference to Node which is * obtained from map key versus a map value. * * @author Kris De Volder */ public abstract class NodeRef<Parent> { public static enum Kind { ROOT, SEQ, KEY, VAL } private Parent parent; public NodeRef(Parent parent) { this.parent = parent; } public Parent getParent() { return parent; } public abstract Node get(); public abstract void put(Node value); public abstract String toString(); public abstract Kind getKind(); /** * Represents a reference to a root node, contained directly * inside a {@link YamlFileAST} */ public static class RootRef extends NodeRef<YamlFileAST> { private int index; public RootRef(YamlFileAST file, int index) { super(file); this.index = index; } @Override public Node get() { return getParent().get(index); } @Override public void put(Node value) { getParent().put(index, value); } @Override public String toString() { return "ROOT["+index+"]"; } @Override public Kind getKind() { return Kind.ROOT; } public int getIndex() { return index; } } public static class SeqRef extends NodeRef<SequenceNode> { private int index; public SeqRef(SequenceNode seq, int index) { super(seq); this.index = index; } @Override public Node get() { return getParent().getValue().get(index); } @Override public void put(Node value) { getParent().getValue().set(index, value); } @Override public String toString() { return "["+index+"]"; } @Override public Kind getKind() { return Kind.SEQ; } public int getIndex() { return index; } } /** * Abstract, represent reference to either a key or * value inside a map tuple. Concrete subclasses define whether * key or value is being accessed. */ public static abstract class TupleRef extends NodeRef<MappingNode> { protected int index; public TupleRef(MappingNode map, int index) { super(map); this.index = index; } public NodeTuple getTuple() { return getParent().getValue().get(index); } public void putTuple(NodeTuple value) { getParent().getValue().set(index, value); } } /** * References a key of a map entry */ public static class TupleKeyRef extends TupleRef { public TupleKeyRef(MappingNode parent, int index) { super(parent, index); } @Override public Node get() { return getTuple().getKeyNode(); } @Override public void put(Node newKey) { NodeTuple tuple = getTuple(); putTuple(new NodeTuple(newKey, tuple.getValueNode())); } @Override public String toString() { return "@key["+index+"]"; } @Override public Kind getKind() { return Kind.KEY; } } /** * References a value of a map entry */ public static class TupleValueRef extends TupleRef { public TupleValueRef(MappingNode parent, int index) { super(parent, index); } @Override public Node get() { return getTuple().getValueNode(); } @Override public void put(Node newValue) { NodeTuple t = getTuple(); putTuple(new NodeTuple(t.getKeyNode(), newValue)); } @Override public String toString() { String keyString = NodeUtil.asScalar(getTuple().getKeyNode()); if (keyString!=null) { //more readable to use the key value than the index of the tuple return "@val['"+keyString+"']"; } return "@val["+index+"]"; } @Override public Kind getKind() { return Kind.VAL; } public Node getKey() { return getTuple().getKeyNode(); } } }