diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/DecXtractEventListener.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/DecXtractEventListener.java index 928cbf0958..706961bbd3 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/DecXtractEventListener.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/DecXtractEventListener.java @@ -7,14 +7,18 @@ import com.atlassian.event.api.EventListener; import com.atlassian.event.api.EventPublisher; +import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.event.issue.IssueEvent; import com.atlassian.jira.event.type.EventType; +import com.atlassian.jira.issue.comments.MutableComment; import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport; import de.uhd.ifi.se.decision.management.jira.extraction.connector.ViewConnector; import de.uhd.ifi.se.decision.management.jira.extraction.model.impl.CommentImpl; +import de.uhd.ifi.se.decision.management.jira.extraction.model.util.CommentSplitter; import de.uhd.ifi.se.decision.management.jira.extraction.persistence.ActiveObjectsManager; import de.uhd.ifi.se.decision.management.jira.model.DecisionKnowledgeElementImpl; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; /** * Triggers the decXtract related function when some changes to comments are @@ -30,6 +34,11 @@ public class DecXtractEventListener implements InitializingBean, DisposableBean private IssueEvent issueEvent; + /** + * locks the editComment Event function if a rest service writes edites comments + */ + public static boolean editCommentLock; + @Autowired public DecXtractEventListener(@JiraImport EventPublisher eventPublisher) { this.eventPublisher = eventPublisher; @@ -59,12 +68,19 @@ public void destroy() throws Exception { public void onIssueEvent(IssueEvent issueEvent) { this.issueEvent = issueEvent; this.projectKey = issueEvent.getProject().getKey(); + if(ConfigPersistence.isActivated(this.projectKey) && ConfigPersistence.isKnowledgeExtractedFromIssues(this.projectKey)) { + return; + } Long eventTypeId = issueEvent.getEventTypeId(); + if(eventTypeId.equals(EventType.ISSUE_COMMENTED_ID) || eventTypeId.equals(EventType.ISSUE_COMMENT_EDITED_ID)) { + parseIconsToTags(); + } if (eventTypeId.equals(EventType.ISSUE_COMMENTED_ID)) { handleNewComment(new DecisionKnowledgeElementImpl(issueEvent.getIssue())); } if (eventTypeId.equals(EventType.ISSUE_COMMENT_DELETED_ID)) { handleDeleteComment(new DecisionKnowledgeElementImpl(issueEvent.getIssue())); + } if (eventTypeId.equals(EventType.ISSUE_COMMENT_EDITED_ID)) { handleEditComment(new DecisionKnowledgeElementImpl(issueEvent.getIssue())); @@ -72,17 +88,55 @@ public void onIssueEvent(IssueEvent issueEvent) { if (eventTypeId.equals(EventType.ISSUE_DELETED_ID)) { handleDeleteIssue(new DecisionKnowledgeElementImpl(issueEvent.getIssue())); } + pareseSlashTagsOutOfComment(); + } + + private void parseIconsToTags() { + if(!ConfigPersistence.isIconParsing(issueEvent.getProject().getKey())) { + return ; + } + MutableComment comment = getCurrentEditedComment(); + for (int i = 0; i < CommentSplitter.manualRationalIconList.length; i++) { + String icon = CommentSplitter.manualRationalIconList[i]; + while(comment.getBody().contains(icon)) { + comment.setBody(comment.getBody().replaceFirst(icon.replace("(", "\\(").replace(")", "\\)"), CommentSplitter.manualRationaleTagList[i])); + if(comment.getBody().split(System.getProperty("line.separator")).length == 1 && !comment.getBody().endsWith("\r\n")) { + comment.setBody(comment.getBody()+ CommentSplitter.manualRationaleTagList[i]); + } + comment.setBody(comment.getBody().replaceFirst("\r\n", CommentSplitter.manualRationaleTagList[i])); + ComponentAccessor.getCommentManager().update(comment, true); + } + } + } + + /** + * Parse \{ out of tags. These slashes are inserted by the visual mode editor + */ + private void pareseSlashTagsOutOfComment() { + if (issueEvent.getComment() != null && issueEvent.getComment().getBody().contains("\\{")) { + MutableComment comment = getCurrentEditedComment(); + comment.setBody(issueEvent.getComment().getBody().replace("\\{", "{")); + ComponentAccessor.getCommentManager().update(comment, true); + } } + private MutableComment getCurrentEditedComment() { + return (MutableComment) ComponentAccessor.getCommentManager() + .getCommentById(issueEvent.getComment().getId()); + } + private void handleDeleteIssue(DecisionKnowledgeElementImpl decisionKnowledgeElement) { ActiveObjectsManager.cleanSentenceDatabaseForProject(this.projectKey); ActiveObjectsManager.createLinksForNonLinkedElementsForIssue(decisionKnowledgeElement.getId() + ""); } private void handleEditComment(DecisionKnowledgeElementImpl decisionKnowledgeElement) { - ActiveObjectsManager.checkIfCommentBodyHasChangedOutsideOfPlugin(new CommentImpl(issueEvent.getComment())); - new ViewConnector(this.issueEvent.getIssue(), false); - ActiveObjectsManager.createLinksForNonLinkedElementsForIssue(decisionKnowledgeElement.getId() + ""); + if (!DecXtractEventListener.editCommentLock) {// If locked, a rest service is manipulating the comment and + // should not be handled by EL + ActiveObjectsManager.checkIfCommentBodyHasChangedOutsideOfPlugin(new CommentImpl(issueEvent.getComment())); + new ViewConnector(this.issueEvent.getIssue(), false); + ActiveObjectsManager.createLinksForNonLinkedElementsForIssue(decisionKnowledgeElement.getId() + ""); + } } private void handleDeleteComment(DecisionKnowledgeElementImpl decisionKnowledgeElement) { diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/CommentImpl.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/CommentImpl.java index f4418fc382..0f72147083 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/CommentImpl.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/CommentImpl.java @@ -59,16 +59,17 @@ public CommentImpl(com.atlassian.jira.issue.comments.Comment comment) { private void splitCommentIntoSentences() { List rawSentences = this.splitter.sliceCommentRecursionCommander(this.body, this.projectKey); runBreakIterator(rawSentences); -// ActiveObjectsManager.checkIfCommentBodyHasChangedOutsideOfPlugin(this); //ConDec-373: Now in EventListener - // Create AO entries + // Create AO entries for (int i = 0; i < this.splitter.getStartSubstringCount().size(); i++) { int startIndex = this.splitter.getStartSubstringCount().get(i); int endIndex = this.splitter.getEndSubstringCount().get(i); - long aoId2 = ActiveObjectsManager.addNewSentenceintoAo(this.jiraCommentId, endIndex, startIndex, - this.authorId, this.issueId, this.projectKey); - Sentence sentence = new SentenceImpl(this.body.substring(startIndex, endIndex), aoId2); - sentence.setCreated(this.created); - this.sentences.add(sentence); + if(startIndex >= 0 && endIndex >= 0 &&(endIndex - startIndex) >0 && this.body.substring(startIndex, endIndex).replaceAll("\r\n", "").trim().length() > 1) { + long aoId2 = ActiveObjectsManager.addNewSentenceintoAo(this.jiraCommentId, endIndex, startIndex, + this.authorId, this.issueId, this.projectKey); + Sentence sentence = new SentenceImpl(this.body.substring(startIndex, endIndex), aoId2); + sentence.setCreated(this.created); + this.sentences.add(sentence); + } } } diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/SentenceImpl.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/SentenceImpl.java index a39ed9a59b..9369a5f532 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/SentenceImpl.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/impl/SentenceImpl.java @@ -254,7 +254,7 @@ private void checkForPlainText(String body) { if (StringUtils.indexOfAny(body.toLowerCase(), CommentSplitter.excludedTagList) >= 0) { this.isPlainText = false; } - if (CommentSplitter.containsOpenAndCloseTags(body,this.projectKey) + if (CommentSplitter.isAnyKnowledgeTypeTwiceExisintg(body,this.projectKey) || (ConfigPersistence.isIconParsing(projectKey) && StringUtils.indexOfAny(body, CommentSplitter.manualRationalIconList) >= 0)) { this.setKnowledgeTypeString(CommentSplitter.getKnowledgeTypeFromManuallIssueTag(body, this.projectKey,true)); @@ -264,10 +264,10 @@ private void checkForPlainText(String body) { } private void stripTagsFromBody(String body) { - if (StringUtils.indexOfAny(body.toLowerCase(), CommentSplitter.getAllTagsUsedInProject(this.projectKey)) >= 0) { + if (CommentSplitter.isAnyKnowledgeTypeTwiceExisintg(body,this.projectKey)) { int tagLength = 2 + CommentSplitter.getKnowledgeTypeFromManuallIssueTag(body, this.projectKey, true).length(); - super.setDescription(body.substring(tagLength, body.length() - (1 + tagLength))); + super.setDescription(body.substring(tagLength, body.length() - ( tagLength))); super.setSummary(super.getDescription()); } else { super.setDescription(body.replaceAll("\\(.*?\\)", "")); diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/util/CommentSplitter.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/util/CommentSplitter.java index 3e33077f08..ecd058ff68 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/util/CommentSplitter.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/model/util/CommentSplitter.java @@ -22,10 +22,12 @@ public class CommentSplitter { public static final String[] excludedTagList = new String[] { "{code}", "{quote}", "{noformat}", "{panel}" }; - public static final String[] manualRationaleTagList = new String[] { "[issue]", "[decision]", "[alternative]", - "[pro]", "[con]", "[goal]" }; - - public static final String[] manualRationalIconList = new String[] { "(!)", "(/)", "(?)", "(y)", "(n)" }; + /**List with all knowledgeTypes as tags. Sequence matters! */ + public static final String[] manualRationaleTagList = new String[] { "{issue}", "{alternative}", "{decision}", + "{pro}", "{con}" }; + + /**List with all knowledgeTypes as icons. Sequence matters! */ + public static final String[] manualRationalIconList = new String[] { "(!)", "(?)", "(/)", "(y)", "(n)" }; public static final String[] allExcluded = (String[]) ArrayUtils .addAll(ArrayUtils.addAll(excludedTagList, manualRationaleTagList), manualRationalIconList); @@ -35,6 +37,10 @@ public CommentSplitter() { this.setEndSubstringCount(new ArrayList()); } + public List splitSentence(String body) { + return sliceCommentRecursionCommander(body, ""); + } + public List sliceCommentRecursionCommander(String body, String projectKey) { List firstSplit = searchBetweenTagsRecursive(body, "{quote}", "{quote}", new ArrayList()); @@ -43,7 +49,7 @@ public List sliceCommentRecursionCommander(String body, String projectKe firstSplit = searchForFurtherTags(firstSplit, "{code:", "{code}"); for (int i = 0; i < manualRationaleTagList.length; i++) { String tag = manualRationaleTagList[i]; - firstSplit = searchForFurtherTags(firstSplit, tag, tag.replace("[", "[/")); + firstSplit = searchForFurtherTags(firstSplit, tag, tag); } if (ConfigPersistence.isIconParsing(projectKey)) { for (int i = 0; i < manualRationalIconList.length; i++) { @@ -75,8 +81,12 @@ private List searchForFurtherTags(List firstSplit, String openTa private ArrayList searchBetweenTagsRecursive(String toSearch, String openTag, String closeTag, ArrayList slices) { + if(checkIncorrectTagMix(toSearch,openTag,closeTag)) { + slices.add(toSearch); + return slices; + } // Icon is used to identify a sentence or a closing tag is forgotten - if (toSearch.contains(openTag) && !toSearch.contains(closeTag)) { + if (toSearch.contains(openTag) && !toSearch.contains(closeTag) ) { return slices; } // Open and close tags are existent if (toSearch.startsWith(openTag) && toSearch.contains(closeTag)) { @@ -97,6 +107,10 @@ private ArrayList searchBetweenTagsRecursive(String toSearch, String ope return slices; } + private boolean checkIncorrectTagMix(String toSearch, String openTag, String closeTag) { + return openTag.equals(closeTag) && !isKnowledgeTypeTagTwiceExistant(toSearch,openTag); + } + public List getStartSubstringCount() { return startSubstringCount; } @@ -117,29 +131,30 @@ public void addSentenceIndex(int startIndex, int endIndex) { this.startSubstringCount.add(startIndex); this.endSubstringCount.add(endIndex); } - + /** * * @param body * @param projectKey - * @param lookOutForIcons search also for icons + * @param lookOutForIcons + * search also for icons * @return The manual tagged knowledge type of a given string */ public static String getKnowledgeTypeFromManuallIssueTag(String body, String projectKey, boolean lookOutForIcons) { boolean checkIcons = lookOutForIcons && ConfigPersistence.isIconParsing(projectKey); - if (body.toLowerCase().contains("[issue]") || (checkIcons && body.contains("(!)"))) { + if (body.toLowerCase().contains(manualRationaleTagList[0]) || (checkIcons && body.contains(manualRationalIconList[0]))) { return KnowledgeType.ISSUE.toString(); } - if (body.toLowerCase().contains("[alternative]") || (checkIcons && body.contains("(?)"))) { + if (body.toLowerCase().contains(manualRationaleTagList[1]) || (checkIcons && body.contains(manualRationalIconList[1]))) { return KnowledgeType.ALTERNATIVE.toString(); } - if (body.toLowerCase().contains("[decision]") || (checkIcons && body.contains("(/)"))) { + if (body.toLowerCase().contains(manualRationaleTagList[2]) || (checkIcons && body.contains(manualRationalIconList[2]))) { return KnowledgeType.DECISION.toString(); } - if (body.toLowerCase().contains("[pro]") || (checkIcons && body.contains("y)"))) { + if (body.toLowerCase().contains(manualRationaleTagList[3]) || (checkIcons && body.contains(manualRationalIconList[3]))) { return "pro"; } - if (body.toLowerCase().contains("[con]") || (checkIcons && body.contains("(n)"))) { + if (body.toLowerCase().contains(manualRationaleTagList[4]) || (checkIcons && body.contains(manualRationalIconList[4]))) { return "con"; } return matchSelectableKnowledgeTypes(body, projectKey); @@ -165,19 +180,33 @@ public static boolean containsOpenAndCloseTags(String body, String projectKey) { return false; } - public static String[] getAllTagsUsedInProject(String projectKey) { + public static boolean isAnyKnowledgeTypeTwiceExisintg(String body, String projectKey) { + for (int i = 0; i < getAllTagsUsedInProject(projectKey).length; i++) { + String tag = getAllTagsUsedInProject(projectKey)[i].toLowerCase().replace("[", "{").replace("]", "}"); + if (isKnowledgeTypeTagTwiceExistant(body, tag)) { + return true; + } + } + return false; + } + + public static boolean isKnowledgeTypeTagTwiceExistant(String body, String knowledgeType) { + return StringUtils.countMatches(body.toLowerCase(), knowledgeType.toLowerCase()) >= 2; + } + + public static String[] getAllTagsUsedInProject(String projectKey) { Set projectKnowledgeTypes = new DecisionKnowledgeProjectImpl(projectKey).getKnowledgeTypes(); ArrayList projectList = new ArrayList(); - for(int i = 0; i < projectKnowledgeTypes.size(); i++) { - projectList.add("["+projectKnowledgeTypes.toArray()[i].toString().toLowerCase()+"]"); + for (int i = 0; i < projectKnowledgeTypes.size(); i++) { + projectList.add("[" + projectKnowledgeTypes.toArray()[i].toString().toLowerCase() + "]"); } for (int i = 0; i < manualRationaleTagList.length; i++) { projectList.add(manualRationaleTagList[i].toLowerCase()); } return projectList.toArray(new String[0]); } - + public static boolean isCommentIconTagged(String text) { - return StringUtils.indexOfAny(text, CommentSplitter.manualRationalIconList) > 0 ; + return StringUtils.indexOfAny(text, CommentSplitter.manualRationalIconList) > 0; } } diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/ActiveObjectsManager.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/ActiveObjectsManager.java index a6b24e688d..669e382c8d 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/ActiveObjectsManager.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/ActiveObjectsManager.java @@ -12,6 +12,7 @@ import com.atlassian.sal.api.transaction.TransactionCallback; import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.extraction.DecXtractEventListener; import de.uhd.ifi.se.decision.management.jira.extraction.model.Comment; import de.uhd.ifi.se.decision.management.jira.extraction.model.Sentence; import de.uhd.ifi.se.decision.management.jira.extraction.model.impl.SentenceImpl; @@ -168,12 +169,16 @@ public static void setSentenceKnowledgeType(Sentence sentence) { ActiveObjects.executeInTransaction(new TransactionCallback() { @Override public DecisionKnowledgeInCommentEntity doInTransaction() { + for (DecisionKnowledgeInCommentEntity databaseEntry : ActiveObjects .find(DecisionKnowledgeInCommentEntity.class)) { if (databaseEntry.getId() == sentence.getId()) { databaseEntry.setKnowledgeTypeString(sentence.getKnowledgeTypeString()); + int additionalLength = addTagsToCommentWhenAutoClassified(databaseEntry); databaseEntry.setTaggedFineGrained(true); databaseEntry.setArgument(sentence.getArgument()); + databaseEntry.setEndSubstringCount(databaseEntry.getEndSubstringCount()+additionalLength); + updateSentenceLengthForOtherSentencesInSameComment(sentence.getCommentId(),sentence.getStartSubstringCount(),additionalLength,sentence.getId()); databaseEntry.save(); return databaseEntry; } @@ -184,6 +189,21 @@ public DecisionKnowledgeInCommentEntity doInTransaction() { } + protected static int addTagsToCommentWhenAutoClassified(DecisionKnowledgeInCommentEntity sentence) { + CommentManager cm = ComponentAccessor.getCommentManager(); + MutableComment mc = (MutableComment) cm.getMutableComment(sentence.getCommentId()); + String newBody = mc.getBody().substring(sentence.getStartSubstringCount(), sentence.getEndSubstringCount()); + + newBody = "{"+sentence.getKnowledgeTypeString()+"}"+newBody+"{"+sentence.getKnowledgeTypeString()+"}"; + int lengthDiff = (sentence.getKnowledgeTypeString().length()+2)*2; + + DecXtractEventListener.editCommentLock = true; + mc.setBody(mc.getBody().substring(0, sentence.getStartSubstringCount())+newBody+mc.getBody().substring(sentence.getEndSubstringCount())); + cm.update(mc, true); + DecXtractEventListener.editCommentLock = false; + return lengthDiff; + } + public static Boolean updateKnowledgeTypeOfSentence(long id, KnowledgeType knowledgeType, String argument) { init(); return ActiveObjects.executeInTransaction(new TransactionCallback() { @@ -193,12 +213,11 @@ public Boolean doInTransaction() { .find(DecisionKnowledgeInCommentEntity.class)) { if (sentenceEntity.getId() == id) { if (sentenceEntity.isTaggedManually()) { - int oldTextLength = sentenceEntity.getEndSubstringCount() - - sentenceEntity.getStartSubstringCount(); + int oldTextLength = getTextLengthOfAoElement(sentenceEntity); int newTextLength = updateTagsInComment(sentenceEntity, knowledgeType, argument); sentenceEntity .setEndSubstringCount(sentenceEntity.getStartSubstringCount() + newTextLength); - updateSentenceLengthForOtherSentencesInSameComment(sentenceEntity.getCommentId(), + ActiveObjectsManager.updateSentenceLengthForOtherSentencesInSameComment(sentenceEntity.getCommentId(), sentenceEntity.getStartSubstringCount(), newTextLength - oldTextLength, sentenceEntity.getId()); sentenceEntity.save(); @@ -230,6 +249,12 @@ public Boolean doInTransaction() { }); } + + private static int getTextLengthOfAoElement(DecisionKnowledgeInCommentEntity sentence) { + return sentence.getEndSubstringCount()- sentence.getStartSubstringCount(); + } + + private static int updateTagsInComment(DecisionKnowledgeInCommentEntity sentenceEntity, KnowledgeType knowledgeType, String argument) { @@ -241,10 +266,10 @@ private static int updateTagsInComment(DecisionKnowledgeInCommentEntity sentence sentenceEntity.getEndSubstringCount()); if (knowledgeType.toString().equalsIgnoreCase("other") || knowledgeType.toString().equalsIgnoreCase("argument")) { - newBody = newBody.replaceAll("(?i)" + sentenceEntity.getKnowledgeTypeString() + "]", argument + "]"); + newBody = newBody.replaceAll("(?i)" + sentenceEntity.getKnowledgeTypeString() + "}", argument + "}"); } else { - newBody = newBody.replaceAll("(?i)" + sentenceEntity.getKnowledgeTypeString() + "]", - knowledgeType.toString() + "]"); + newBody = newBody.replaceAll("(?i)" + sentenceEntity.getKnowledgeTypeString() + "}", + knowledgeType.toString() + "}"); } // build body with first text and changed text int newEndSubstringCount = newBody.length(); @@ -253,6 +278,7 @@ private static int updateTagsInComment(DecisionKnowledgeInCommentEntity sentence if (oldBody.length() > sentenceEntity.getEndSubstringCount()) { newBody = newBody + oldBody.substring(sentenceEntity.getEndSubstringCount()); } + mc.setBody(newBody); cm.update(mc, true); return newEndSubstringCount; diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/AlternativeMacro.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/AlternativeMacro.java new file mode 100644 index 0000000000..f4c4da1cf1 --- /dev/null +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/AlternativeMacro.java @@ -0,0 +1,37 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view.macros; + +import java.util.Map; + +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; +import com.atlassian.renderer.v2.macro.BaseMacro; + +import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; + +public class AlternativeMacro extends BaseMacro { + @Override + public boolean hasBody() { + return true; + } + + @Override + public RenderMode getBodyRenderMode() { + return RenderMode.allow(RenderMode.F_ALL); + } + + @Override + public String execute(Map parameters, String body, RenderContext renderContext) { + if(!ConfigPersistence.isKnowledgeExtractedFromIssues(IssueMacro.getProjectKey(renderContext))) { + return body; + } + if (Boolean.TRUE.equals(renderContext.getParam(IssueRenderContext.WYSIWYG_PARAM))) { + return "\\{alternative}"+body+"\\{alternative}"; + } + String newBody = IssueMacro.reformatCommentBody(body); + String icon = ""; + return icon + "" + newBody + ""; + } + +} diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ConMacro.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ConMacro.java new file mode 100644 index 0000000000..d07c9f408a --- /dev/null +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ConMacro.java @@ -0,0 +1,37 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view.macros; + +import java.util.Map; + +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; +import com.atlassian.renderer.v2.macro.BaseMacro; + +import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; + +public class ConMacro extends BaseMacro { + @Override + public boolean hasBody() { + return true; + } + + @Override + public RenderMode getBodyRenderMode() { + return RenderMode.allow(RenderMode.F_ALL); + } + + @Override + public String execute(Map parameters, String body, RenderContext renderContext){ + if(!ConfigPersistence.isKnowledgeExtractedFromIssues(IssueMacro.getProjectKey(renderContext))) { + return body; + } + if (Boolean.TRUE.equals(renderContext.getParam(IssueRenderContext.WYSIWYG_PARAM))) { + return "\\{con}"+body+"\\{con}"; + } + String newBody = IssueMacro.reformatCommentBody(body); + String icon = ""; + return icon + "" + newBody + ""; + } + +} diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/DecisionMacro.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/DecisionMacro.java new file mode 100644 index 0000000000..d1158386fb --- /dev/null +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/DecisionMacro.java @@ -0,0 +1,37 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view.macros; + +import java.util.Map; + +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; +import com.atlassian.renderer.v2.macro.BaseMacro; + +import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; + +public class DecisionMacro extends BaseMacro { + @Override + public boolean hasBody() { + return true; + } + + @Override + public RenderMode getBodyRenderMode() { + return RenderMode.allow(RenderMode.F_ALL); + } + + @Override + public String execute(Map parameters, String body, RenderContext renderContext){ + if(!ConfigPersistence.isKnowledgeExtractedFromIssues(IssueMacro.getProjectKey(renderContext))) { + return body; + } + if (Boolean.TRUE.equals(renderContext.getParam(IssueRenderContext.WYSIWYG_PARAM))) { + return "\\{decision}"+body+"\\{decision}"; + } + String newBody = IssueMacro.reformatCommentBody(body); + String icon = ""; + return icon + "" + newBody + ""; + } + +} \ No newline at end of file diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/IssueMacro.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/IssueMacro.java new file mode 100644 index 0000000000..be97b5efd9 --- /dev/null +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/IssueMacro.java @@ -0,0 +1,53 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view.macros; + +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; +import com.atlassian.renderer.v2.macro.BaseMacro; + +import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; + +import java.util.Map; + +public class IssueMacro extends BaseMacro { + @Override + public boolean hasBody() { + return true; + } + + @Override + public RenderMode getBodyRenderMode() { + return RenderMode.allow(RenderMode.F_ALL); + } + + @Override + public String execute(Map parameters, String body, RenderContext renderContext) { + if(!ConfigPersistence.isKnowledgeExtractedFromIssues(IssueMacro.getProjectKey(renderContext))) { + return body; + } + if (Boolean.TRUE.equals(renderContext.getParam(IssueRenderContext.WYSIWYG_PARAM))) { + return "\\{issue}"+body+"\\{issue}"; + } + String newBody = IssueMacro.reformatCommentBody(body); + String icon = ""; + return icon + "" + newBody + ""; + } + + public static String reformatCommentBody(String inputBody) { + String body = inputBody.replace("

", ""); + body = body.replace("

", ""); + while (body.startsWith(" ")) { + body = body.substring(1); + } + while (body.endsWith(" ")) { + body = body.substring(0, body.length() - 1); + } + return body; + } + + public static String getProjectKey(RenderContext renderContext) { + return renderContext.getParams().get("jira.issue").toString().split("-")[0]; + } + +} diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ProMacro.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ProMacro.java new file mode 100644 index 0000000000..62d7360bc9 --- /dev/null +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/extraction/view/macros/ProMacro.java @@ -0,0 +1,39 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view.macros; + +import java.util.Map; + +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; +import com.atlassian.renderer.v2.macro.BaseMacro; + +import de.uhd.ifi.se.decision.management.jira.ComponentGetter; +import de.uhd.ifi.se.decision.management.jira.persistence.ConfigPersistence; + +public class ProMacro extends BaseMacro { + + @Override + public boolean hasBody() { + return true; + } + + @Override + public RenderMode getBodyRenderMode() { + return RenderMode.allow(RenderMode.F_ALL); + } + + @Override + public String execute(Map parameters, String body, RenderContext renderContext){ + if(!ConfigPersistence.isKnowledgeExtractedFromIssues(IssueMacro.getProjectKey(renderContext))) { + return body; + } + if (Boolean.TRUE.equals(renderContext.getParam(IssueRenderContext.WYSIWYG_PARAM))) { + return "\\{pro}"+body+"\\{pro}"; + } + System.out.println(IssueMacro.getProjectKey(renderContext)); + String newBody = IssueMacro.reformatCommentBody(body); + String icon = ""; + return icon + "" + newBody + ""; + } + +} diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/model/DecisionKnowledgeElementImpl.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/model/DecisionKnowledgeElementImpl.java index ff7dc390ae..3dee351b95 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/model/DecisionKnowledgeElementImpl.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/model/DecisionKnowledgeElementImpl.java @@ -12,6 +12,7 @@ import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.IssueManager; +import de.uhd.ifi.se.decision.management.jira.extraction.model.Sentence; import de.uhd.ifi.se.decision.management.jira.persistence.DecisionKnowledgeElementInDatabase; /** @@ -109,6 +110,9 @@ public KnowledgeType getType() { @XmlElement(name = "type") public String getTypeAsString() { if(type == KnowledgeType.OTHER) { + if(this instanceof Sentence) { + return ((Sentence)this).getKnowledgeTypeString(); + } IssueManager issueManager = ComponentAccessor.getIssueManager(); Issue issue = issueManager.getIssueByCurrentKey(this.getKey()); return issue.getIssueType().toString(); diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/model/KnowledgeType.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/model/KnowledgeType.java index a3217e6d3f..e5f941f9e5 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/model/KnowledgeType.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/model/KnowledgeType.java @@ -154,9 +154,11 @@ public static String getIconUrl(DecisionKnowledgeElement element) { } switch(element.getType()) { case OTHER: - IssueManager issueManager = ComponentAccessor.getIssueManager(); - Issue issue = issueManager.getIssueByCurrentKey(element.getKey()); - return issue.getIssueType().getCompleteIconUrl(); + if(!(element instanceof Sentence)) { + IssueManager issueManager = ComponentAccessor.getIssueManager(); + Issue issue = issueManager.getIssueByCurrentKey(element.getKey()); + return issue.getIssueType().getCompleteIconUrl(); + } default: return ComponentGetter.getUrlOfImageFolder() + element.getType().toString() + ".png"; } diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/rest/KnowledgeRest.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/rest/KnowledgeRest.java index b64bfa6ba5..c28b45b86c 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/rest/KnowledgeRest.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/rest/KnowledgeRest.java @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap; import de.uhd.ifi.se.decision.management.jira.config.AuthenticationManager; +import de.uhd.ifi.se.decision.management.jira.extraction.DecXtractEventListener; import de.uhd.ifi.se.decision.management.jira.extraction.model.util.CommentSplitter; import de.uhd.ifi.se.decision.management.jira.extraction.persistence.ActiveObjectsManager; import de.uhd.ifi.se.decision.management.jira.extraction.persistence.DecisionKnowledgeInCommentEntity; @@ -190,8 +191,10 @@ public Response changeKnowledgeTypeOfSentence(@QueryParam("projectKey") String p @Context HttpServletRequest request, DecisionKnowledgeElement newElement, @QueryParam("argument") String argument) { if (projectKey != null && request != null && newElement != null) { + DecXtractEventListener.editCommentLock=true; Boolean result = ActiveObjectsManager.updateKnowledgeTypeOfSentence(newElement.getId(), newElement.getType(), argument); + DecXtractEventListener.editCommentLock = false; if (!result) { return Response.status(Status.INTERNAL_SERVER_ERROR) .entity(ImmutableMap.of("error", "Update of element failed.")).build(); @@ -244,23 +247,25 @@ public Response editSentenceBody(@Context HttpServletRequest request, String newType = decisionKnowledgeElement.getType().toString(); if(newType.equals(KnowledgeType.OTHER.toString()) && argument.length() >0) { - newType = argument; + newType = argument; } String tag = ""; // Allow changing of manual tags, but no tags for icons if (databaseEntity.isTaggedManually() && !CommentSplitter.isCommentIconTagged(oldSentenceInComment)) { - tag = "[" + WordUtils.capitalize(newType) + "]"; + tag = "{" + WordUtils.capitalize(newType) + "}"; } else if (CommentSplitter.isCommentIconTagged(oldSentenceInComment)) { indexOfOldSentence = indexOfOldSentence + 3; // add icon to text. } String first = mc.getBody().substring(0, indexOfOldSentence); - String second = tag + newSentenceBody + tag.replace("[", "[/"); + String second = tag + newSentenceBody + tag; String third = mc.getBody().substring(indexOfOldSentence + oldSentenceInComment.length()); - + DecXtractEventListener.editCommentLock = true; mc.setBody(first + second + third); cm.update(mc, true); ActiveObjectsManager.updateSentenceBodyWhenCommentChanged(databaseEntity.getCommentId(), decisionKnowledgeElement.getId(), second); + + DecXtractEventListener.editCommentLock = false; } } ActiveObjectsManager.updateKnowledgeTypeOfSentence(decisionKnowledgeElement.getId(), diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treant/Node.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treant/Node.java index 592288a901..dd50a24baa 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treant/Node.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treant/Node.java @@ -84,21 +84,7 @@ public Node(DecisionKnowledgeElement decisionKnowledgeElement, boolean isCollaps if (isCollapsed) { this.collapsed = ImmutableMap.of("collapsed", isCollapsed); } - this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement); - if (decisionKnowledgeElement instanceof Sentence) { - if (((Sentence) decisionKnowledgeElement).getArgument().length() == 3) { // Length == 3 means pro or con - if (((Sentence) decisionKnowledgeElement).getArgument().equalsIgnoreCase("pro")) { - this.htmlClass = "pro"; - this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement, "support"); - } else { - this.htmlClass = "contra"; - this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement, "attack"); - } - } - if (isHyperlinked) { - makeLinkToElement(decisionKnowledgeElement.getKey().split(":")[0]); - } - } + this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement); } public static String getIcon(DecisionKnowledgeElement element) { @@ -123,6 +109,21 @@ public Node(DecisionKnowledgeElement decisionKnowledgeElement, Link link, boolea default: break; } + if (decisionKnowledgeElement instanceof Sentence) { + if (((Sentence) decisionKnowledgeElement).getArgument().length() == 3) { // Length == 3 means pro or con + decisionKnowledgeElement.setType(KnowledgeType.ARGUMENT); + if (((Sentence) decisionKnowledgeElement).getArgument().equalsIgnoreCase("pro")) { + this.htmlClass = "pro"; + this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement, "support"); + } else { + this.htmlClass = "contra"; + this.image = KnowledgeType.getIconUrl(decisionKnowledgeElement, "attack"); + } + } + if (isHyperlinked) { + makeLinkToElement(decisionKnowledgeElement.getKey().split(":")[0]); + } + } } private void makeLinkToElement(String key) { diff --git a/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treeviewer/Data.java b/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treeviewer/Data.java index 00bd38860e..afe6d3eade 100644 --- a/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treeviewer/Data.java +++ b/src/main/java/de/uhd/ifi/se/decision/management/jira/view/treeviewer/Data.java @@ -61,6 +61,9 @@ public Data(DecisionKnowledgeElement decisionKnowledgeElement) { public Data(DecisionKnowledgeElement decisionKnowledgeElement, Link link) { this(decisionKnowledgeElement); this.icon = KnowledgeType.getIconUrl(decisionKnowledgeElement, link.getType()); + if (decisionKnowledgeElement instanceof Sentence) { + checkTypeOfArgumentForSentenceEntity((Sentence) decisionKnowledgeElement); + } } private void checkTypeOfArgumentForSentenceEntity(Sentence decisionKnowledgeElement) { diff --git a/src/main/resources/atlassian-plugin.xml b/src/main/resources/atlassian-plugin.xml index 94bc955f9a..f40e908ce7 100644 --- a/src/main/resources/atlassian-plugin.xml +++ b/src/main/resources/atlassian-plugin.xml @@ -271,6 +271,45 @@ + + + + Insert issue knowledge element in comments. + + + + + Insert decision knowledge element in comments. + + + + Insert alternative knowledge element in comments. + + + + Insert pro knowledge element in comments. + + + + Insert con knowledge element in comments. + + + + + jira.rich.editor + jira.view.issue + jira.edit.issue + jira.create.issue + gh-rapid + + + + diff --git a/src/main/resources/js/view.commentTab.toolbar-init.js b/src/main/resources/js/view.commentTab.toolbar-init.js new file mode 100644 index 0000000000..8cad2b183d --- /dev/null +++ b/src/main/resources/js/view.commentTab.toolbar-init.js @@ -0,0 +1,168 @@ +/* + *This class manages the insertion of knowledge types into the rich text exitor. Also the transition between stlyed (Rich text) and plan text with taggs. + */ +require([ + "jquery", + "jira/util/formatter", + "jira/editor/registry" +], function( + $, + formatter, + editorRegistry +) { + var DEFAULT_PLACEHOLDER = "knowledge element"; + var lastItem; + + //ISSUE + editorRegistry.on('register', function(entry) { + var $otherDropdown = $(entry.toolbar).find('.wiki-edit-other-picker-trigger'); + + $otherDropdown.one('click', function(dropdownClickEvent) { + + + var speechItem = getDropDownContent(dropdownClickEvent).querySelector('.wiki-edit-speech-item'); + var issueItem = $(getHTMLLiItem("Issue")).insertAfter(speechItem).on('click', function() { + entry.applyIfTextMode(addWikiMarkupIssue).applyIfTextMode(addRenderedContentIssue); + }); + lastItem = issueItem; + + entry.onUnregister(function cleanup() { + issueItem.remove(); + }); + + }); + }); + + //ALTERNATIVE + editorRegistry.on('register', function(entry) { + var $otherDropdown = $(entry.toolbar).find('.wiki-edit-other-picker-trigger'); + + $otherDropdown.one('click', function(dropdownClickEvent) { + + var alternativeItem = $(getHTMLLiItem("Alternative")).insertAfter(lastItem).on('click', function() { + entry.applyIfTextMode(addWikiMarkupAlternative).applyIfVisualMode(addRenderedContentAlternative); + }); + lastItem = alternativeItem; + + entry.onUnregister(function cleanup() { + alternativeItem.remove(); + }); + }); + }); + + //Decision + editorRegistry.on('register', function(entry) { + var $otherDropdown = $(entry.toolbar).find('.wiki-edit-other-picker-trigger'); + + $otherDropdown.one('click', function(dropdownClickEvent) { + var decisionItem = $(getHTMLLiItem("Decision")).insertAfter(lastItem).on('click', function() { + entry.applyIfTextMode(addWikiMarkupDecision).applyIfVisualMode(addRenderedContentDecision); + }); + lastItem = decisionItem; + + entry.onUnregister(function cleanup() { + decisionItem.remove(); + }); + }); + }); + + //Pro + editorRegistry.on('register', function(entry) { + var $otherDropdown = $(entry.toolbar).find('.wiki-edit-other-picker-trigger'); + + $otherDropdown.one('click', function(dropdownClickEvent) { + var proItem = $(getHTMLLiItem("Pro")).insertAfter(lastItem).on('click', function() { + entry.applyIfTextMode(addWikiMarkupPro).applyIfVisualMode(addRenderedContentPro); + }); + lastItem = proItem; + + entry.onUnregister(function cleanup() { + proItem.remove(); + }); + }); + }); + + //Con + editorRegistry.on('register', function(entry) { + var $otherDropdown = $(entry.toolbar).find('.wiki-edit-other-picker-trigger'); + + $otherDropdown.one('click', function(dropdownClickEvent) { + + var conItem = $(getHTMLLiItem("Con")).insertAfter(lastItem).on('click', function() { + entry.applyIfTextMode(addWikiMarkupCon).applyIfVisualMode(addRenderedContentCon); + }); + + entry.onUnregister(function cleanup() { + conItem.remove(); + }); + }); + }); + + function getHTMLLiItem(knowledgeType) { + return '
  • ' + knowledgeType + '
  • '; + } + + + function addWikiMarkup(entry, knowledgeType) { + var wikiEditor = $(entry.textArea).data('wikiEditor'); + var content = wikiEditor.manipulationEngine.getSelection().text || DEFAULT_PLACEHOLDER; + wikiEditor.manipulationEngine.replaceSelectionWith("{" + knowledgeType + "}" + content + "{" + knowledgeType + "}"); + } + + function addRenderedContent(entry, knowledgeTypeColor, knowledgeType) { + entry.rteInstance.then(function(rteInstance) { + var tinyMCE = rteInstance.editor; + if (tinyMCE && !tinyMCE.isHidden()) { + var content = tinyMCE.selection.getContent() || DEFAULT_PLACEHOLDER; + tinyMCE.selection.setContent('{' + knowledgeType + '}' + content + '{' + knowledgeType + '}'); + } + }); + } + + function getDropDownContent(dropdownClickEvent) { + var dropdownContentId = dropdownClickEvent.currentTarget.getAttribute('aria-owns'); + return document.getElementById(dropdownContentId); + } + + function addWikiMarkupIssue(entry) { + addWikiMarkup(entry, "issue"); + } + + function addRenderedContentIssue(entry) { + addRenderedContent(entry, "F2F5A9", "issue"); + } + + function addWikiMarkupAlternative(entry) { + addWikiMarkup(entry, "alternative"); + } + + function addRenderedContentAlternative(entry) { + addRenderedContent(entry, "f1ccf9", "alternative"); + } + + function addWikiMarkupDecision(entry) { + addWikiMarkup(entry, "decision"); + } + + function addRenderedContentDecision(entry) { + addRenderedContent(entry, "c5f2f9", "decision"); + } + + function addWikiMarkupPro(entry) { + addWikiMarkup(entry, "pro"); + } + + function addRenderedContentPro(entry) { + addRenderedContent(entry, "b9f7c0", "pro"); + } + + function addWikiMarkupCon(entry) { + addWikiMarkup(entry, "con"); + } + + function addRenderedContentCon(entry) { + addRenderedContent(entry, "ffdeb5", "con"); + } + + +}); \ No newline at end of file diff --git a/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/model/TestComment.java b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/model/TestComment.java index 07a3726403..306be6b725 100644 --- a/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/model/TestComment.java +++ b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/model/TestComment.java @@ -8,6 +8,7 @@ import java.util.Locale; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -317,7 +318,7 @@ public void testPropertiesOfQuotedElementedText() { @NonTransactional public void testPropertiesOfTaggedElementedText() { CommentImpl comment = getComment( - "[Alternative] this is a manually created alternative [/Alternative] and this is a test Sentence."); + "{Alternative} this is a manually created alternative {Alternative} and this is a test Sentence."); assertEquals(2, comment.getSentences().size()); assertEquals(true, comment.getSentences().get(0).isRelevant()); assertEquals(false, comment.getSentences().get(0).isPlainText()); @@ -348,14 +349,14 @@ public void testTagReplacementToHTMLCode() { @Test @NonTransactional public void testManuallyTaggingPro() { - CommentImpl comment = getComment("[Pro]this is a manual pro tagged sentence [/Pro]"); + CommentImpl comment = getComment("{Pro}this is a manual pro tagged sentence {Pro}"); // test the result in splits, fails when checked with equals assertTrue(comment.getTaggedBody(0).contains("")); assertTrue(comment.getTaggedBody(0).contains("")); // important that the tag is not inside the text area assertTrue(comment.getTaggedBody(0).contains("[Pro]")); assertTrue(comment.getTaggedBody(0).contains("")); - assertTrue(comment.getTaggedBody(0).contains("this is a manual pro tagged sentence ")); + assertTrue(comment.getTaggedBody(0).contains("this is a manual pro tagged sentence")); // important that the tag is not inside the text area assertTrue(comment.getTaggedBody(0).contains("[/Pro]")); assertTrue(comment.getTaggedBody(0).contains("")); @@ -364,14 +365,15 @@ public void testManuallyTaggingPro() { @Test @NonTransactional public void testManuallyTaggingDecision() { - CommentImpl comment = getComment("[Decision]this is a manual pro tagged sentence [/Decision]"); + CommentImpl comment = getComment("{Decision}this is a manual decision tagged sentence{Decision}"); + System.out.println(comment.getTaggedBody(0)); // test the result in splits, fails when checked with equals assertTrue(comment.getTaggedBody(0).contains("")); assertTrue(comment.getTaggedBody(0).contains("")); // important that the tag is not inside the text area assertTrue(comment.getTaggedBody(0).contains("[Decision]")); assertTrue(comment.getTaggedBody(0).contains("")); - assertTrue(comment.getTaggedBody(0).contains("this is a manual pro tagged sentence ")); + assertTrue(comment.getTaggedBody(0).contains("this is a manual decision tagged sentence")); // important that the tag is not inside the text area assertTrue(comment.getTaggedBody(0).contains("[/Decision]")); assertTrue(comment.getTaggedBody(0).contains("")); @@ -380,7 +382,7 @@ public void testManuallyTaggingDecision() { @Test @NonTransactional public void testManuallyTaggingIssue() { - CommentImpl comment = getComment("[Issue]this is a manual pro tagged sentence [/Issue]"); + CommentImpl comment = getComment("{Issue}this is a manual pro tagged sentence {Issue}"); // test the result in splits, fails when checked with equals assertTrue(comment.getTaggedBody(0).contains("")); assertTrue(comment.getTaggedBody(0).contains("")); @@ -425,19 +427,19 @@ public void testManuallyTaggingIssueWithIconAndPlainText() { @Test @NonTransactional public void testManuallyTaggingWithOnlyOpenTag() { - CommentImpl comment = getComment("[Alternative] This is a testsentence"); - assertTrue(comment.getTaggedBody(0).trim().equalsIgnoreCase( - "[Alternative] This is a testsentence\r\n" - .trim())); + CommentImpl comment = getComment("{Alternative} This is a testsentence"); + assertEquals(comment.getTaggedBody(0).trim(), + "{Alternative} This is a testsentence\r\n" + .trim()); } @Test @NonTransactional public void testManuallyTaggingWithWrongTagMix() { - CommentImpl comment = getComment("[Alternative] This is a testsentence[/Issue]"); + CommentImpl comment = getComment("{Alternative} This is a testsentence{Issue}"); System.out.println(comment.getTaggedBody(0)); - assertTrue(comment.getTaggedBody(0).trim().equalsIgnoreCase( - "[Alternative] This is a testsentence[/Issue]\r\n" + assertEquals(comment.getTaggedBody(0).trim(),( + "{Alternative} This is a testsentence{Issue}\r\n" .trim())); } @@ -445,18 +447,18 @@ public void testManuallyTaggingWithWrongTagMix() { @NonTransactional public void testManuallyTaggingWithIconsAndTags() { CommentImpl comment = getComment( - "(y) I like this idea \r\n mid sentence without sense [Con] But the other one not [/Con]"); - assertTrue(comment.getTaggedBody(0).trim().equalsIgnoreCase( + "(y) I like this idea \r\n mid sentence without sense {Con} But the other one not {Con}"); + assertEquals(comment.getTaggedBody(0).trim().toLowerCase(), "[Pro] I like this idea [/Pro] mid sentence without sense [Con] But the other one not [/Con]\r\n" - .trim())); + .trim().toLowerCase()); } @Test @NonTransactional public void testUpperLowerCaseTagging() { - CommentImpl comment = getComment("[Con] But the other one not [/Con]"); - CommentImpl comment1 = getComment("[con] But the other one not [/con]"); + CommentImpl comment = getComment("{Con} But the other one not {Con}"); + CommentImpl comment1 = getComment("{con} But the other one not {con}"); assertEquals(comment.getTaggedBody(0), comment1.getTaggedBody(0)); } @@ -467,10 +469,13 @@ public void testRelevantCommentWithoutPlainText() { CommentImpl comment = getComment("{noformat} nonplain text {noformat}"); comment.getSentences().get(0).setRelevant(true); assertNotNull(comment.getTaggedBody(0)); + String expected = "{noformat} nonplain text {noformat}"; + assertEquals(expected, comment.getTaggedBody(0)); } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeSolution() { Comment comment = getComment("[Solution]just a solution[/Solution]"); @@ -478,6 +483,7 @@ public void testCommentsWithExtendedKnowledgeTypeSolution() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeGoal() { Comment comment = getComment("[Goal]just a Goal[/Goal]"); @@ -485,6 +491,7 @@ public void testCommentsWithExtendedKnowledgeTypeGoal() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeImplication() { Comment comment = getComment("[Implication]just an Implication[/Implication]"); @@ -492,6 +499,7 @@ public void testCommentsWithExtendedKnowledgeTypeImplication() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeContext() { Comment comment = getComment("[Context]just an Context[/Context]"); @@ -499,6 +507,7 @@ public void testCommentsWithExtendedKnowledgeTypeContext() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeConstraint() { Comment comment = getComment("[Constraint]just a Context[/Constraint]"); @@ -506,6 +515,7 @@ public void testCommentsWithExtendedKnowledgeTypeConstraint() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeClaim() { Comment comment = getComment("[Claim]just a Claim [/Claim]"); @@ -513,6 +523,7 @@ public void testCommentsWithExtendedKnowledgeTypeClaim() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeAssumption() { Comment comment = getComment("[Assumption]just a Assumption [/Assumption]"); @@ -520,6 +531,7 @@ public void testCommentsWithExtendedKnowledgeTypeAssumption() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithExtendedKnowledgeTypeAssessment() { Comment comment = getComment("[Assessment]just a Assessment [/Assessment]"); @@ -527,6 +539,7 @@ public void testCommentsWithExtendedKnowledgeTypeAssessment() { } @Test + @Ignore //Ignored sinde [tags] have been replaced by {tags} we first decide about additional knowledge types @NonTransactional public void testCommentsWithInvalidKnowledgeType() { Comment comment = getComment("[invalid]just a Assessment [/invalid]"); diff --git a/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/TestActiveObjectsManager.java b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/TestActiveObjectsManager.java index dde8bf819e..234b23fd12 100644 --- a/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/TestActiveObjectsManager.java +++ b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/persistence/TestActiveObjectsManager.java @@ -152,55 +152,55 @@ public void testUpdateKnowledgeType3() { @Test @NonTransactional public void testUpdateKnowledgeTypeWithManualTagged() { - Comment comment = getComment("[issue] testobject [/issue]"); + Comment comment = getComment("{issue} testobject {issue}"); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 0); ActiveObjectsManager.updateKnowledgeTypeOfSentence(id, KnowledgeType.ALTERNATIVE, ""); DecisionKnowledgeInCommentEntity element = ActiveObjectsManager.getElementFromAO(id); assertEquals(new SentenceImpl(element.getId()).getBody().trim(), "testobject"); assertEquals(element.getKnowledgeTypeString(), KnowledgeType.ALTERNATIVE.toString()); - assertEquals("[Alternative] testobject [/Alternative]", + assertEquals("{Alternative} testobject {Alternative}", ComponentAccessor.getCommentManager().getMutableComment((long) 0).getBody()); } @Test @NonTransactional public void testUpdateKnowledgeTypeWithManualTaggedAndMoreSentences() { - Comment comment = getComment("some sentence in front. [issue] testobject [/issue]"); + Comment comment = getComment("some sentence in front. {issue} testobject {issue}"); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); ActiveObjectsManager.updateKnowledgeTypeOfSentence(id, KnowledgeType.ALTERNATIVE, ""); DecisionKnowledgeInCommentEntity element = ActiveObjectsManager.getElementFromAO(id); assertEquals(new SentenceImpl(element.getId()).getBody().trim(), "testobject"); assertEquals(element.getKnowledgeTypeString(), KnowledgeType.ALTERNATIVE.toString()); - assertEquals("some sentence in front. [Alternative] testobject [/Alternative]", + assertEquals("some sentence in front. {Alternative} testobject {Alternative}", ComponentAccessor.getCommentManager().getMutableComment((long) 0).getBody()); } @Test @NonTransactional public void testUpdateKnowledgeTypeWithManualTaggedAndMoreSentences2() { - Comment comment = getComment("some sentence in front. [issue] testobject [/issue] some sentence in the back."); + Comment comment = getComment("some sentence in front. {issue} testobject {issue} some sentence in the back."); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); ActiveObjectsManager.updateKnowledgeTypeOfSentence(id, KnowledgeType.ALTERNATIVE, ""); DecisionKnowledgeInCommentEntity element = ActiveObjectsManager.getElementFromAO(id); assertEquals(new SentenceImpl(element.getId()).getBody().trim(), "testobject"); assertEquals(element.getKnowledgeTypeString(), KnowledgeType.ALTERNATIVE.toString()); - assertEquals("some sentence in front. [Alternative] testobject [/Alternative] some sentence in the back.", + assertEquals("some sentence in front. {Alternative} testobject {Alternative} some sentence in the back.", ComponentAccessor.getCommentManager().getMutableComment((long) 0).getBody()); } @Test @NonTransactional public void testUpdateKnowledgeTypeWithManualTaggedAndMoreSentences2AndArgument() { - Comment comment = getComment("some sentence in front. [issue] testobject [/issue] some sentence in the back."); + Comment comment = getComment("some sentence in front. {issue} testobject {issue} some sentence in the back."); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); ActiveObjectsManager.updateKnowledgeTypeOfSentence(id, KnowledgeType.OTHER, "Pro"); DecisionKnowledgeInCommentEntity element = ActiveObjectsManager.getElementFromAO(id); assertEquals(new SentenceImpl(element.getId()).getBody().trim(), "testobject"); assertEquals(element.getKnowledgeTypeString(), "Pro"); - assertEquals("some sentence in front. [Pro] testobject [/Pro] some sentence in the back.", + assertEquals("some sentence in front. {Pro} testobject {Pro} some sentence in the back.", ComponentAccessor.getCommentManager().getMutableComment((long) 0).getBody()); } @@ -293,7 +293,7 @@ public void testUpdateSentenceBodyWhenCommentChanged() { @Test @NonTransactional public void testGetElementsForIssue() { - Comment comment = getComment("some sentence in front. [issue] testobject [/issue] some sentence in the back."); + Comment comment = getComment("some sentence in front. {issue} testobject {issue} some sentence in the back."); ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); List listWithObjects = ActiveObjectsManager.getElementsForIssue(comment.getIssueId(), @@ -304,7 +304,7 @@ public void testGetElementsForIssue() { @Test @NonTransactional public void testGetAllElementsFromAoByType() { - Comment comment = getComment("some sentence in front. [issue] testobject [/issue] some sentence in the back."); + Comment comment = getComment("some sentence in front. {issue} testobject {issue} some sentence in the back."); ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); List listWithObjects = ActiveObjectsManager.getAllElementsFromAoByType("TEST", @@ -315,7 +315,7 @@ public void testGetAllElementsFromAoByType() { @Test @NonTransactional public void testGetAllElementsFromAoByArgumentType() { - Comment comment = getComment("some sentence in front. [pro] testobject [/pro] some sentence in the back."); + Comment comment = getComment("some sentence in front. {pro} testobject {pro} some sentence in the back."); ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); List listWithObjects = ActiveObjectsManager.getAllElementsFromAoByType("TEST", @@ -326,7 +326,7 @@ public void testGetAllElementsFromAoByArgumentType() { @Test @NonTransactional public void testGetAllElementsFromAoByEmptyType() { - Comment comment = getComment("some sentence in front. [pro] testobject [/pro] some sentence in the back."); + Comment comment = getComment("some sentence in front. {pro} testobject {pro} some sentence in the back."); ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); List listWithObjects = ActiveObjectsManager.getAllElementsFromAoByType("TEST", @@ -337,7 +337,7 @@ public void testGetAllElementsFromAoByEmptyType() { @Test @NonTransactional public void testCleanSentenceDatabaseForProject() { - Comment comment = getComment("some sentence in front. [pro] testobject [/pro] some sentence in the back."); + Comment comment = getComment("some sentence in front. {pro} testobject {pro} some sentence in the back."); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); MutableComment comment2 = ComponentAccessor.getCommentManager().getMutableComment(comment.getIssueId()); @@ -354,7 +354,7 @@ public void testCleanSentenceDatabaseForProject() { @Test @NonTransactional public void testLinkAllUnlikedSentence() { - Comment comment = getComment("some sentence in front. [pro] testobject [/pro] some sentence in the back."); + Comment comment = getComment("some sentence in front. {pro} testobject {pro} some sentence in the back."); long id = ActiveObjectsManager.addNewSentenceintoAo(comment, comment.getIssueId(), 1); assertEquals(1,GenericLinkManager.getLinksForElement("s"+id).size()); GenericLinkManager.deleteLinksForElement("s"+id); diff --git a/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/view/TestMacro.java b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/view/TestMacro.java new file mode 100644 index 0000000000..a95b56916e --- /dev/null +++ b/src/test/java/de/uhd/ifi/se/decision/management/jira/extraction/view/TestMacro.java @@ -0,0 +1,143 @@ +package de.uhd.ifi.se.decision.management.jira.extraction.view; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.atlassian.activeobjects.test.TestActiveObjects; +import com.atlassian.jira.issue.fields.renderer.IssueRenderContext; +import com.atlassian.renderer.RenderContext; +import com.atlassian.renderer.v2.RenderMode; + +import de.uhd.ifi.se.decision.management.jira.TestComponentGetter; +import de.uhd.ifi.se.decision.management.jira.TestSetUpWithIssues; +import de.uhd.ifi.se.decision.management.jira.extraction.view.macros.AlternativeMacro; +import de.uhd.ifi.se.decision.management.jira.extraction.view.macros.ConMacro; +import de.uhd.ifi.se.decision.management.jira.extraction.view.macros.DecisionMacro; +import de.uhd.ifi.se.decision.management.jira.extraction.view.macros.IssueMacro; +import de.uhd.ifi.se.decision.management.jira.extraction.view.macros.ProMacro; +import de.uhd.ifi.se.decision.management.jira.mocks.MockTransactionTemplate; +import de.uhd.ifi.se.decision.management.jira.mocks.MockUserManager; +import net.java.ao.EntityManager; +import net.java.ao.test.jdbc.Data; +import net.java.ao.test.junit.ActiveObjectsJUnitRunner; + +@RunWith(ActiveObjectsJUnitRunner.class) +@Data(TestSetUpWithIssues.AoSentenceTestDatabaseUpdater.class) +public class TestMacro extends TestSetUpWithIssues { + + private EntityManager entityManager; + + private RenderContext issueView = new RenderContext(); + private RenderContext wysiwygView = new RenderContext(); + + @Before + public void setUp() { + initialization(); + TestComponentGetter.init(new TestActiveObjects(entityManager), new MockTransactionTemplate(), + new MockUserManager()); + + issueView.addParam(IssueRenderContext.WYSIWYG_PARAM, false); + issueView.addParam("jira.issue", "Test-1"); + wysiwygView.addParam(IssueRenderContext.WYSIWYG_PARAM, true); + wysiwygView.addParam("jira.issue", "Test-1"); + } + + @Test + public void testReformatCommentBody() { + assertEquals("test", IssueMacro.reformatCommentBody("

    test

    ")); + assertEquals("test", IssueMacro.reformatCommentBody("

    test

    ")); + assertEquals("test", IssueMacro.reformatCommentBody("

    test

    ")); + assertEquals("test", IssueMacro.reformatCommentBody("

    test

    ")); + assertEquals("test", IssueMacro.reformatCommentBody("

    test

    ")); + } + + @Test + public void testIssueMacro() { + IssueMacro fm = new IssueMacro(); + assertEquals(RenderMode.allow(RenderMode.F_ALL), fm.getBodyRenderMode()); + assertTrue(fm.hasBody()); + String body = "

    This is a issue

    "; + String result = fm.execute(null, body, issueView); + assertEquals( + "This is a issue", + result); + result = fm.execute(null, body, wysiwygView); + assertEquals("\\{issue}

    This is a issue

    \\{issue}", result); + } + + @Test + public void testDecisionMacro() { + DecisionMacro fm = new DecisionMacro(); + + assertEquals(RenderMode.allow(RenderMode.F_ALL), fm.getBodyRenderMode()); + assertTrue(fm.hasBody()); + + String body = "

    This is a issue

    "; + String result = fm.execute(null, body, issueView); + assertEquals( + "This is a issue", + result); + result = fm.execute(null, body, wysiwygView); + assertEquals("\\{decision}

    This is a issue

    \\{decision}", result); + + } + + @Test + public void testAlternativeMacro() { + AlternativeMacro fm = new AlternativeMacro(); + + assertEquals(RenderMode.allow(RenderMode.F_ALL), fm.getBodyRenderMode()); + assertTrue(fm.hasBody()); + + String body = "

    This is a issue

    "; + + String result = fm.execute(null, body, issueView); + assertEquals( + "This is a issue", + result); + result = fm.execute(null, body, wysiwygView); + assertEquals("\\{alternative}

    This is a issue

    \\{alternative}", result); + } + + @Test + public void testProMacro() { + ProMacro fm = new ProMacro(); + + assertEquals(RenderMode.allow(RenderMode.F_ALL), fm.getBodyRenderMode()); + assertTrue(fm.hasBody()); + + String body = "

    This is a issue

    "; + + String result = fm.execute(null, body, issueView); + assertEquals( + "This is a issue", + result); + + result = fm.execute(null, body, wysiwygView); + assertEquals("\\{pro}

    This is a issue

    \\{pro}", result); + + } + + + + @Test + public void testConMacro() { + ConMacro fm = new ConMacro(); + + assertEquals(RenderMode.allow(RenderMode.F_ALL), fm.getBodyRenderMode()); + assertTrue(fm.hasBody()); + + String body = "

    This is a issue

    "; + + String result = fm.execute(null, body, issueView); + assertEquals( + "This is a issue", + result); + + result = fm.execute(null, body, wysiwygView); + assertEquals("\\{con}

    This is a issue

    \\{con}", result); + } +} diff --git a/src/test/java/de/uhd/ifi/se/decision/management/jira/rest/knowledgerest/TestEditSentenceBody.java b/src/test/java/de/uhd/ifi/se/decision/management/jira/rest/knowledgerest/TestEditSentenceBody.java index 657e44a5b1..4054c7dc03 100644 --- a/src/test/java/de/uhd/ifi/se/decision/management/jira/rest/knowledgerest/TestEditSentenceBody.java +++ b/src/test/java/de/uhd/ifi/se/decision/management/jira/rest/knowledgerest/TestEditSentenceBody.java @@ -119,9 +119,9 @@ public void testRequestFilledElementFilledWithCommentChanedCheckValidText() { public void testRequestFilledElementFilledWithCommentChanedCheckValidTextWithManuallTaggedComment() { String newText = "some fancy new text"; request.setAttribute("WithFails", false); - request.setAttribute("NoFails", true); + request.setAttribute("NoFails", true); TestComment tc = new TestComment(); - Comment comment = tc.getComment("[issue]this is atest sentence[/Issue]"); + Comment comment = tc.getComment("{issue}this is atest sentence{Issue}"); decisionKnowledgeElement = comment.getSentences().get(0); decisionKnowledgeElement.setDescription(newText); ComponentGetter.setTransactionTemplate(new MockTransactionTemplateWebhook()); @@ -131,7 +131,7 @@ public void testRequestFilledElementFilledWithCommentChanedCheckValidTextWithMan assertEquals(newText, sentence.getBody()); MutableComment mc = (MutableComment) ComponentAccessor.getCommentManager().getCommentById(sentence.getCommentId()); - assertEquals("[Issue]some fancy new text[/Issue]",mc.getBody()); + assertEquals("{Issue}some fancy new text{Issue}",mc.getBody()); } }