/* * Copyright 2013 the original author or authors. * * 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.springframework.xd.dirt.stream.dsl; import static org.springframework.xd.dirt.stream.dsl.XDDSLMessages.UNRECOGNIZED_MODULE_REFERENCE; import static org.springframework.xd.dirt.stream.dsl.XDDSLMessages.UNRECOGNIZED_STREAM_REFERENCE; import java.util.ArrayList; import java.util.List; /** * @author Andy Clement * @author David Turanski */ public class ChannelNode extends AstNode { private ChannelType channelType; private List<String> nameComponents; private List<String> indexingElements; public ChannelNode(ChannelType channelType, int startpos, int endpos, List<String> nameElements, List<String> indexingElements) { super(startpos, endpos); this.channelType = channelType; this.nameComponents = nameElements; this.indexingElements = indexingElements; } @Override public String stringify(boolean includePositionalInfo) { StringBuilder s = new StringBuilder(); s.append("("); produceStringRepresentation(s); if (includePositionalInfo) { s.append(":"); s.append(getStartPos()).append(">").append(getEndPos()); } s.append(")"); return s.toString(); } @Override public String toString() { StringBuilder s = new StringBuilder(); produceStringRepresentation(s); return s.toString(); } private void produceStringRepresentation(StringBuilder s) { int t = 0; if (channelType.isTap()) { s.append(channelType.getStringRepresentation()); } if (nameComponents.size() > 0 && channelType.isTap() && nameComponents.get(0).equalsIgnoreCase(channelType.tapSource().name())) { t = 1; } for (int max = nameComponents.size(); t < max; t++) { s.append(nameComponents.get(t)); if (t < nameComponents.size() - 1) { s.append(":"); } } if (indexingElements.size() != 0) { for (int t2 = 0, max = indexingElements.size(); t2 < max; t2++) { s.append("."); s.append(indexingElements.get(t2)); } } } String getChannelName() { StringBuilder s = new StringBuilder(); if (channelType.isTap()) { s.append("tap:"); } s.append(getNameComponents()); s.append(getIndexingComponents()); return s.toString(); } private int getLengthOfPrefixPlusNameComponents() { int length = 0; if (channelType.isTap()) { length += 4; } for (int i = 0; i < nameComponents.size(); i++) { if (i > 0) { length++; } length += nameComponents.get(i).length(); } return length; } private String getNameComponents() { StringBuilder s = new StringBuilder(); for (int t = 0, max = nameComponents.size(); t < max; t++) { if (t > 0) { s.append(":"); } s.append(nameComponents.get(t)); } return s.toString(); } private String getIndexingComponents() { StringBuilder s = new StringBuilder(); for (int t = 0, max = indexingElements.size(); t < max; t++) { s.append("."); s.append(indexingElements.get(t)); } return s.toString(); } ChannelType getChannelType() { return this.channelType; } public ChannelNode copyOf() { // TODO not a deep copy, is that ok? return new ChannelNode(this.channelType, startpos, endpos, nameComponents, indexingElements); } public void resolve(StreamLookupEnvironment env, String expressionString) { if (channelType == ChannelType.TAP_STREAM) { String streamName = nameComponents.get(1); StreamNode sn = env.lookupStream(streamName); if (sn == null) { int offset = this.startpos + channelType.getStringRepresentation().length(); throw new StreamDefinitionException(expressionString, offset, UNRECOGNIZED_STREAM_REFERENCE, streamName); } if (indexingElements.isEmpty()) { // Point to the first element of the stream indexingElements = new ArrayList<String>(); indexingElements.add(sn.getModuleNodes().get(0).getName() + ".0"); } else { // Easter Egg: can use index of module in a stream when tapping. try { int index = Integer.parseInt(indexingElements.get(0)); indexingElements.remove(0); indexingElements.add(0, sn.getModuleNodes().get(index).getName() + "." + index); } catch (NumberFormatException nfe) { // this is ok, probably wasn't a number String indexString = toString(indexingElements); int index = sn.getIndexOfLabel(indexString); if (index != -1) { indexingElements.clear(); indexingElements.add(0, sn.getModuleNodes().get(index).getName() + "." + index); } else { int offset = this.startpos + getLengthOfPrefixPlusNameComponents() + 1; throw new StreamDefinitionException(expressionString, offset, UNRECOGNIZED_MODULE_REFERENCE, indexString); } } } } } private String toString(List<String> elements) { StringBuilder s = new StringBuilder(); for (int i = 0; i < elements.size(); i++) { if (i > 0) { s.append('.'); } s.append(elements.get(i)); } return s.toString(); } }