/* * Copyright 2015 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.rf.ide.core.testdata.model.table; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; import org.rf.ide.core.testdata.model.AModelElement; import org.rf.ide.core.testdata.model.FilePosition; import org.rf.ide.core.testdata.model.ICommentHolder; import org.rf.ide.core.testdata.model.ModelType; import org.rf.ide.core.testdata.model.table.exec.descs.ExecutableRowDescriptorBuilder; import org.rf.ide.core.testdata.model.table.exec.descs.IExecutableRowDescriptor; import org.rf.ide.core.testdata.model.table.keywords.UserKeyword; import org.rf.ide.core.testdata.model.table.testcases.TestCase; import org.rf.ide.core.testdata.text.read.IRobotTokenType; import org.rf.ide.core.testdata.text.read.recognizer.RobotToken; import org.rf.ide.core.testdata.text.read.recognizer.RobotTokenType; import org.rf.ide.core.testdata.text.read.separators.TokenSeparatorBuilder.FileFormat; public class RobotExecutableRow<T> extends AModelElement<T> implements ICommentHolder, Serializable { private static final long serialVersionUID = -4158729064542423691L; private final static Pattern TSV_COMMENT = Pattern.compile("(\\s)*\"(\\s)*[#].*\"(\\s)*$"); private RobotToken action; private final List<RobotToken> arguments = new ArrayList<>(); private final List<RobotToken> comments = new ArrayList<>(); public RobotExecutableRow() { this.action = new RobotToken(); } public RobotToken getAction() { fixMissingTypes(); return action; } public void setAction(final RobotToken action) { IRobotTokenType actType = getActionType(); if (actType == null) { actType = RobotTokenType.UNKNOWN; } this.action = updateOrCreate(this.action, action, actType); fixMissingTypes(); } private IRobotTokenType getActionType() { IRobotTokenType actType = null; if (getParent() != null) { final Class<? extends Object> parentClass = getParent().getClass(); if (parentClass == TestCase.class) { actType = RobotTokenType.TEST_CASE_ACTION_NAME; } else if (parentClass == UserKeyword.class) { actType = RobotTokenType.KEYWORD_ACTION_NAME; } } if (actType == null) { actType = RobotTokenType.UNKNOWN; } return actType; } public List<RobotToken> getArguments() { return Collections.unmodifiableList(arguments); } public void setArgument(final int index, final String argument) { final RobotToken token = new RobotToken(); token.setText(argument); setArgument(index, token); } public void setArgument(final int index, final RobotToken argument) { updateOrCreateTokenInside(arguments, index, argument, getArgumentType()); fixMissingTypes(); } public void addArgument(final int index, final RobotToken argument) { final IRobotTokenType argType = getArgumentType(); if (argType != null) { fixForTheType(argument, argType, true); } arguments.add(index, argument); fixMissingTypes(); } public void addArgument(final RobotToken argument) { final IRobotTokenType argType = getArgumentType(); if (argType != null) { fixForTheType(argument, argType, true); } arguments.add(argument); fixMissingTypes(); } public void removeArgument(final int index) { arguments.remove(index); } private IRobotTokenType getArgumentType() { IRobotTokenType argType = null; if (getParent() != null) { final Class<? extends Object> parentClass = getParent().getClass(); if (parentClass == TestCase.class) { argType = RobotTokenType.TEST_CASE_ACTION_ARGUMENT; } else if (parentClass == UserKeyword.class) { argType = RobotTokenType.KEYWORD_ACTION_ARGUMENT; } } return argType; } @Override public void addCommentPart(final RobotToken rt) { fixComment(getComment(), rt); this.comments.add(rt); } @Override public List<RobotToken> getComment() { return Collections.unmodifiableList(comments); } @Override public void setComment(final String comment) { final RobotToken tok = new RobotToken(); tok.setText(comment); setComment(tok); } @Override public void setComment(final RobotToken comment) { this.comments.clear(); addCommentPart(comment); } @Override public void removeCommentPart(final int index) { this.comments.remove(index); } @Override public void clearComment() { this.comments.clear(); } @Override public boolean isPresent() { return true; } @Override public RobotToken getDeclaration() { return action; } @Override public ModelType getModelType() { ModelType type = ModelType.UNKNOWN; final List<IRobotTokenType> types = getAction().getTypes(); if (types.contains(RobotTokenType.TEST_CASE_ACTION_NAME)) { type = ModelType.TEST_CASE_EXECUTABLE_ROW; } else if (types.contains(RobotTokenType.KEYWORD_ACTION_NAME)) { type = ModelType.USER_KEYWORD_EXECUTABLE_ROW; } if (types.contains(RobotTokenType.UNKNOWN) && type == ModelType.UNKNOWN) { final T parent = getParent(); if (parent != null) { final AModelElement<?> parentModel = (AModelElement<?>) parent; if (parentModel.getModelType() == ModelType.TEST_CASE) { type = ModelType.TEST_CASE_EXECUTABLE_ROW; } else if (parentModel.getModelType() == ModelType.USER_KEYWORD) { type = ModelType.USER_KEYWORD_EXECUTABLE_ROW; } } } return type; } @Override public FilePosition getBeginPosition() { return getAction().getFilePosition(); } @Override public List<RobotToken> getElementTokens() { fixMissingTypes(); final List<RobotToken> tokens = new ArrayList<>(); tokens.add(getAction()); tokens.addAll(compact(arguments)); tokens.addAll(compact(comments)); return tokens; } private List<RobotToken> compact(final List<RobotToken> elementsSingleType) { int size = elementsSingleType.size(); for (int i = size - 1; i >= 0; i--) { if (elementsSingleType.size() == 0) { break; } RobotToken t = elementsSingleType.get(i); if (t.getText() == null || t.getText().isEmpty()) { elementsSingleType.remove(i); } else { break; } } return elementsSingleType; } public boolean isExecutable() { boolean result = false; if (action != null) { if (getParent() instanceof IExecutableStepsHolder) { @SuppressWarnings("unchecked") final IExecutableStepsHolder<AModelElement<? extends ARobotSectionTable>> parent = (IExecutableStepsHolder<AModelElement<? extends ARobotSectionTable>>) getParent(); final FileFormat fileFormat = parent.getHolder().getParent().getParent().getParent().getFileFormat(); if (!action.getTypes().contains(RobotTokenType.START_HASH_COMMENT)) { final String text = action.getText().trim(); final List<RobotToken> elementTokens = getElementTokens(); if (text.equals("\\")) { if (elementTokens.size() > 1) { if (!elementTokens.get(1).getTypes().contains(RobotTokenType.START_HASH_COMMENT)) { result = true; } } } else if ("".equals(text)) { if (fileFormat == FileFormat.TSV) { if (elementTokens.size() > 1) { if (!elementTokens.get(1).getTypes().contains(RobotTokenType.START_HASH_COMMENT)) { result = true; } } } } else { result = true; } } } else { result = !action.getTypes().contains(RobotTokenType.START_HASH_COMMENT); } } return result; } public static boolean isTsvComment(final String raw, final FileFormat format) { return (format == FileFormat.TSV && TSV_COMMENT.matcher(raw).matches()); } public IExecutableRowDescriptor<T> buildLineDescription() { return new ExecutableRowDescriptorBuilder().buildLineDescriptor(this); } @Override public boolean removeElementToken(final int index) { return super.removeElementFromList(arguments, index); } public <P> RobotExecutableRow<P> copy() { RobotExecutableRow<P> execRow = new RobotExecutableRow<>(); execRow.setAction(getAction().copyWithoutPosition()); for (final RobotToken arg : getArguments()) { execRow.addArgument(arg.copyWithoutPosition()); } for (final RobotToken cmPart : getComment()) { execRow.addCommentPart(cmPart.copyWithoutPosition()); } return execRow; } private void fixMissingTypes() { if (getParent() != null) { if (action != null && (getArguments().size() > 0 || action.isNotEmpty() || getComment().size() > 0)) { action.getTypes().remove(RobotTokenType.UNKNOWN); fixForTheType(action, getActionType(), true); } for (int i = 0; i < getArguments().size(); i++) { final RobotToken token = getArguments().get(i); token.getTypes().remove(RobotTokenType.UNKNOWN); fixForTheType(token, getArgumentType(), true); } } } }