/* * Copyright 2015 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.model; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.transform; import java.io.Serializable; import java.util.List; import java.util.Optional; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Position; import org.rf.ide.core.testdata.model.presenter.CommentServiceHandler; import org.rf.ide.core.testdata.model.presenter.CommentServiceHandler.ETokenSeparator; import org.rf.ide.core.testdata.model.table.variables.AVariable; import org.rf.ide.core.testdata.model.table.variables.AVariable.VariableType; import org.rf.ide.core.testdata.model.table.variables.DictionaryVariable; import org.rf.ide.core.testdata.model.table.variables.DictionaryVariable.DictionaryKeyValuePair; import org.rf.ide.core.testdata.model.table.variables.ListVariable; import org.rf.ide.core.testdata.model.table.variables.ScalarVariable; import org.rf.ide.core.testdata.model.table.variables.UnknownVariable; import org.rf.ide.core.testdata.text.read.recognizer.RobotToken; import org.robotframework.ide.eclipse.main.plugin.RedImages; import com.google.common.base.Joiner; import com.google.common.base.Strings; public class RobotVariable implements RobotFileInternalElement, Serializable { private static final long serialVersionUID = 1L; // this has to be transient in order not to try serializing whole model instead of simply // its small part private transient RobotVariablesSection parent; private AVariable holder; public RobotVariable(final RobotVariablesSection parent, final AVariable variableHolder) { this.parent = parent; this.holder = variableHolder; } @Override public RobotVariablesSection getParent() { return parent; } public void setParent(final RobotVariablesSection variablesSection) { this.parent = variablesSection; } @Override public AVariable getLinkedElement() { return holder; } public void setLinkedElement(final AVariable holder) { this.holder = holder; } @Override public List<RobotElement> getChildren() { return newArrayList(); } @Override public int getIndex() { return parent == null ? -1 : parent.getChildren().indexOf(this); } public String getPrefix() { return holder.getType().getIdentificator() + "{"; } public String getSuffix() { return "}"; } public VariableType getType() { return holder.getType(); } @Override public String getName() { return Strings.nullToEmpty(holder.getName()); } public String getValue() { if (getType() == VariableType.SCALAR) { final ScalarVariable variable = (ScalarVariable) holder; final List<RobotToken> values = variable.getValues(); return values.isEmpty() ? "" : values.get(0).getText(); } else if (getType() == VariableType.SCALAR_AS_LIST) { final ScalarVariable variable = (ScalarVariable) holder; final List<RobotToken> values = variable.getValues(); return "[" + Joiner.on(", ").join(transform(values, TokenFunctions.tokenToString())) + "]"; } else if (getType() == VariableType.LIST) { final ListVariable variable = (ListVariable) holder; final List<RobotToken> values = variable.getItems(); return "[" + Joiner.on(", ").join(transform(values, TokenFunctions.tokenToString())) + "]"; } else if (getType() == VariableType.DICTIONARY) { final DictionaryVariable variable = (DictionaryVariable) holder; final List<DictionaryKeyValuePair> values = variable.getItems(); return "{" + Joiner.on(", ").join(transform(values, TokenFunctions.pairToString(" = "))) + "}"; } else if (getType() == VariableType.INVALID) { final UnknownVariable variable = (UnknownVariable) holder; final List<RobotToken> values = variable.getItems(); return "[" + Joiner.on(", ").join(transform(values, TokenFunctions.tokenToString())) + "]"; } throw new IllegalStateException("Variable defined in variables table cannot have type " + getType().name()); } @Override public String getComment() { return CommentServiceHandler.consolidate(holder, ETokenSeparator.PIPE_WRAPPED_WITH_SPACE); } @Override public ImageDescriptor getImage() { switch (getType()) { case SCALAR: return RedImages.getRobotScalarVariableImage(); case SCALAR_AS_LIST: return RedImages.getRobotScalarVariableImage(); case LIST: return RedImages.getRobotListVariableImage(); case DICTIONARY: return RedImages.getRobotDictionaryVariableImage(); case INVALID: return RedImages.getRobotUnknownVariableImage(); default: return null; } } @Override public OpenStrategy getOpenRobotEditorStrategy() { return new PageActivatingOpeningStrategy(this); } @Override public RobotSuiteFile getSuiteFile() { return parent.getSuiteFile(); } @Override public Position getPosition() { final int begin = holder.getDeclaration().getStartOffset(); int maxStart = -1; int end = -1; for (final RobotToken token : holder.getElementTokens()) { if (token.getStartOffset() > maxStart) { maxStart = token.getStartOffset(); end = maxStart + token.getText().length(); } } // it may happen that begin == -1 when there is no declaration (only comment in variable table) final int beginToUse = begin == -1 ? maxStart : begin; return new Position(beginToUse, end - beginToUse); } @Override public DefinitionPosition getDefinitionPosition() { return new DefinitionPosition(holder.getDeclaration().getFilePosition(), holder.getDeclaration().getText().length()); } @Override public Optional<? extends RobotElement> findElement(final int offset) { final AVariable linkedElement = holder; if (!linkedElement.getBeginPosition().isNotSet() && linkedElement.getBeginPosition().getOffset() <= offset && offset <= linkedElement.getEndPosition().getOffset()) { return Optional.of(this); } return Optional.empty(); } @Override public String toString() { // for debugging purposes only return getPrefix() + getName() + getSuffix() + "= " + getValue() + "# " + getComment(); } }