Skip to content

Commit

Permalink
[ISSUE #85][UML_VIEW] Add possibility to specify values for absent pa…
Browse files Browse the repository at this point in the history
…rts of UML sequence

1. [x] Have you followed the guidelines in our [Contributing document](../blob/master/CONTRIBUTING.md)?
2. [x] Have you checked to ensure there aren't other open [Pull Requests](../pulls) for the same update/change?
3. [x] Have you built the project, and performed manual testing of your functionality for all supported platforms - Linux and Windows?
4. [x] Is your change backward-compatible with the previous version of the plugin?

>>> Change description:

- Extension of UML view functionality, as requested in issue #85
- Extension of the README to cover the implemented feature-extension
- Fix bug with wrong highlighting within the "Search view", in cases with heavy usage of nested groups
- Addition of representation of the non-variable group names to the "Filters view"

>>> Verification criteria:

- Manually tested on Windows and Linux
- All sanity checks on Git hub passed
  • Loading branch information
svlad-90 committed Aug 9, 2020
1 parent 910843b commit 21f02c7
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 160 deletions.
281 changes: 162 additions & 119 deletions dltmessageanalyzerplugin/src/common/Definitions.cpp

Large diffs are not rendered by default.

48 changes: 41 additions & 7 deletions dltmessageanalyzerplugin/src/common/Definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,20 @@ typedef QVector<QColor> QColorVec;

typedef QString tVarName;
typedef QPair<bool, tVarName> tOptionalVarName;
typedef QPair<bool, eUML_ID> tOptional_UML_ID;

struct tOptional_UML_ID_Item
{
// optional string, which can be assigned by the user in form of e.g. <US_myService>.
// In above case this variable will be filled in with "myService" value
QString UML_Custom_Value;
};

typedef std::map<eUML_ID, tOptional_UML_ID_Item> tOptional_UML_IDMap;

struct tOptional_UML_ID
{
tOptional_UML_IDMap optional_UML_IDMap;
};

///////////////////////////REGEX_SCRIPTING_METADATA/////////////////////////////////

Expand All @@ -390,7 +403,7 @@ struct tRegexScriptingMetadataItem
tOptionalVarName varName;

// UML_ID data
tOptional_UML_ID UML_ID;
tOptional_UML_ID optionalUML_ID;
};

typedef std::shared_ptr<tRegexScriptingMetadataItem> tRegexScriptingMetadataItemPtr;
Expand Down Expand Up @@ -426,15 +439,20 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo

////////////////////////////////////////////////////////////

typedef QPair<int, tHighlightingRangeSet> tCalcRangesCoverageMulticolorResult;
struct tCalcRangesCoverageMulticolorResult
{
tHighlightingRangeSet highlightingRangeSet;
};

typedef std::map<int /*group id*/, int /*gradient color id*/> tGroupIdToColorMap;

/**
* @brief calcRangesCoverageMulticolor - determines in which way set of ranges coveres the inputRange.
* @param pMatchesTree - tree of the matches
* @param inputRange - input range, which we try to analyze.
* @param regexScriptingMetadata - regex scripting metadata, which contains colors, which were scripted by the user.
* @param gradientColors - gradiant colors, which are assigned to ranges in case if there are no corresponding scripted colors. Scripted colors have higher priority.
* @param prevColorCounter - previous color counhter, to be used within this call
* @param groupIdToColorMap - group ids to colors mapping
* @return - QPair, with:
* first - updated prevColorCounter value
* second - set of ranges, which shows in which way rangeList coveres the inputRange.
Expand All @@ -444,7 +462,7 @@ tCalcRangesCoverageMulticolorResult calcRangesCoverageMulticolor( const tTreeIte
const tRange& inputRange,
const tRegexScriptingMetadata& regexScriptingMetadata,
const QVector<QColor>& gradientColors,
const int& prevColorCounter);
const tGroupIdToColorMap& groupIdToColorMap);

/**
* @brief getMatchesTree - forms a tree from the found matches, which then can be used in other methods, like calcRangesCoverageMulticolor
Expand All @@ -455,8 +473,24 @@ tCalcRangesCoverageMulticolorResult calcRangesCoverageMulticolor( const tTreeIte
*/
tTreeItemSharedPtr getMatchesTree( const tFoundMatches& foundMatches );

typedef std::map<eSearchResultColumn, tRange> tStringCoverageMap;
typedef std::map<eUML_ID, tStringCoverageMap /*range of id-s in the searched string*/> tUMLDataMap;
struct tStringCoverageItem
{
tRange range;
/*whether we should add separator after the string*/
bool bAddSeparator = false;
};

typedef std::map<eSearchResultColumn, tStringCoverageItem> tStringCoverageMap;

struct tUMLDataItem
{
QString UML_Custom_Value;
tStringCoverageMap stringCoverageMap;
};

typedef std::vector<tUMLDataItem> tUMLDataItemsVec;

typedef std::map<eUML_ID, tUMLDataItemsVec> tUMLDataMap;
struct tUMLInfo
{
bool bUMLConstraintsFulfilled = false;
Expand Down
7 changes: 4 additions & 3 deletions dltmessageanalyzerplugin/src/filtersView/CFiltersModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ QPair<bool,QString> CFiltersModel::packRegex()

if(false == groupName.isEmpty())
{
const eGroupSyntaxType& gorupSyntaxType = static_cast<eGroupSyntaxType>(pItem->data(static_cast<int>(eRegexFiltersColumn::GroupSyntaxType)).get<int>());
const eGroupSyntaxType& groupSyntaxType = static_cast<eGroupSyntaxType>(pItem->data(static_cast<int>(eRegexFiltersColumn::GroupSyntaxType)).get<int>());

switch(gorupSyntaxType)
switch(groupSyntaxType)
{
case eGroupSyntaxType::SYNTAX_1:
regexStr.append("?<");
Expand All @@ -320,7 +320,7 @@ QPair<bool,QString> CFiltersModel::packRegex()

regexStr.append(groupName);

switch(gorupSyntaxType)
switch(groupSyntaxType)
{
case eGroupSyntaxType::SYNTAX_1:
case eGroupSyntaxType::SYNTAX_3:
Expand Down Expand Up @@ -772,6 +772,7 @@ void CFiltersModel::setUsedRegex(const QString& regexStr)
else
{
pCurrentParsingDataItem->name = "Group";
pCurrentParsingDataItem->value = pCurrentParsingDataItem->groupName;
}

pCurrentParsingDataItem->colorWrapper.optColor = pRegexMetadataItem->highlightingColor;
Expand Down
103 changes: 74 additions & 29 deletions dltmessageanalyzerplugin/src/searchView/CSearchResultModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ QString CSearchResultModel::getDataStrFromMsg(const QModelIndex& modelIndex, con
strRes = pMsg->getPayload();
}
break;
case eSearchResultColumn::UML_Applicability:
{
strRes = ""; // no string value provided for this column
}
break;
case eSearchResultColumn::Last:
{
strRes = "Unhandled field type!";
Expand Down Expand Up @@ -347,42 +352,82 @@ std::pair<int /*rowNumber*/, QString /*diagramContent*/> CSearchResultModel::get

if(foundUMLDataItem != itemMetadata.UMLInfo.UMLDataMap.end())
{
for(const auto& fieldRange : foundUMLDataItem->second)
for(const auto& item : foundUMLDataItem->second)
{
QModelIndex modelIndex = createIndex(itemMetadata.msgId, static_cast<int>(fieldRange.first));
QString message = getDataStrFromMsg(modelIndex, pMsg, static_cast<eSearchResultColumn>(modelIndex.column()));

auto messageSize = message.size();
if(fieldRange.second.from >= 0 && fieldRange.second.from < messageSize &&
fieldRange.second.to >= 0 && fieldRange.second.to < messageSize )
if(true == item.UML_Custom_Value.isEmpty()) // if there is no client-defined value
{
switch(UML_ID)
// let's use value from the corresponding group
for(const auto& stringCoverageMapItem : item.stringCoverageMap)
{
case eUML_ID::UML_REQUEST:
UMLRepresentationResult.second.append("->");
break;
case eUML_ID::UML_RESPONSE:
case eUML_ID::UML_EVENT:
UMLRepresentationResult.second.append("<-");
break;
case eUML_ID::UML_ARGUMENTS:
{
int numberOfCharacters = fieldRange.second.to - fieldRange.second.from + 1;
QString argString = message.mid(fieldRange.second.from, numberOfCharacters);
argString.replace("[[", "[ [");
argString.replace("]]", "] ]");
UMLRepresentationResult.second.append(argString);
}
break;
default:
QModelIndex modelIndex = createIndex(itemMetadata.msgId, static_cast<int>(stringCoverageMapItem.first));
QString message = getDataStrFromMsg(modelIndex, pMsg, static_cast<eSearchResultColumn>(modelIndex.column()));

auto messageSize = message.size();
const auto& range = stringCoverageMapItem.second.range;

if(range.from >= 0 && range.from < messageSize &&
range.to >= 0 && range.to < messageSize )
{
UMLRepresentationResult.second.append(message.mid(fieldRange.second.from, fieldRange.second.to - fieldRange.second.from + 1));
switch(UML_ID)
{
case eUML_ID::UML_REQUEST:
UMLRepresentationResult.second.append("->");
break;
case eUML_ID::UML_RESPONSE:
case eUML_ID::UML_EVENT:
UMLRepresentationResult.second.append("<-");
break;
case eUML_ID::UML_ARGUMENTS:
{
int numberOfCharacters = range.to - range.from + 1;
QString argString = message.mid(range.from, numberOfCharacters);
argString.replace("[[", "[ [");
argString.replace("]]", "] ]");
UMLRepresentationResult.second.append(argString);

if(true == stringCoverageMapItem.second.bAddSeparator)
{
UMLRepresentationResult.second.append(" ");
}
}
break;
case eUML_ID::UML_CLIENT:
case eUML_ID::UML_SERVICE:
{
QString str;
str.append(message.mid(range.from, range.to - range.from + 1));

if(true == stringCoverageMapItem.second.bAddSeparator)
{
str.append(" ");
}

str.replace(" ", "_");
UMLRepresentationResult.second.append(str);
}
break;
default:
{
UMLRepresentationResult.second.append(message.mid(range.from, range.to - range.from + 1));

if(true == stringCoverageMapItem.second.bAddSeparator)
{
UMLRepresentationResult.second.append(" ");
}
}
break;
}
}
break;

UMLRepresentationResult.first = true;
}
}

UMLRepresentationResult.first = true;
else // otherwise
{
// let's directly use client-defined value, ignoring value from the group
UMLRepresentationResult.first = true;
UMLRepresentationResult.second.append(item.UML_Custom_Value);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions md/debug_console/debug_console.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ help -> get list of supported commands
- support -> represent the support message
- version -> represent the version of the plugin
- web-link -> represent link to plugin's web-site
- uml-id -> represent list of the supported UML types, which is used for cretion of the sequence diagrams

List of the supported commands will be extended in future releases.

Expand Down
69 changes: 67 additions & 2 deletions md/plant_uml/plant_uml.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ In case if provided regex will contain ALL mandatory fields, the plugin will con

----

## Example
## Simple example

Let's provide an example.
Imagine that we have the following 3 messages, which represent the communication between components "Alice" and "Bob":

![Screenshot of messages between Alice and Bob components](./plant_uml_alice_bob_messages.png)

The above way of tracing is unified and contains all required parts to create a sequence out of it.
We can use the following regex expression for sequence creation:
We can use the following regex expression for creation of the sequence diagram:
<pre>^(SYS).*?: Informational: (?&lt;UCL&gt;[\w]+):.*?((?&lt;URT&gt;RQ)|(?&lt;URS&gt;RP)|(?&lt;UEV&gt;EV)).*?(to|from) (?&lt;US&gt;[\w]+) - (?&lt;UM&gt;.*?)\((?&lt;UA&gt;.*?)\)</pre>

Result of search would look like:
Expand Down Expand Up @@ -113,6 +113,71 @@ Use the following context menu item to trigger save operation:

----

## Advanced example

First example was quite simple, as log has contained all required parts.
But what if you need a sequence for a set of the messages, which does not contain all required parts?
E.g. there is no service name, client name or method name.

Still, as a develoepr you might understand the context, and want to fulfil the missing parts and have a sequence without modification of logs.
Fortunately, the DLT-Message-Analyzer allows you to do this.

Imagine that we have the following 3 messages, which represent the communication between components "Alice" and "Bob":

![Screenshot of another set of messages between Alice and Bob components](./plant_uml_alice_bob_messages_advanced.png)

Let's also imagine that result diagram should have actor Alex instead of actor Alice.
The above way of tracing is not quite unified and does not contain all required parts to create a sequence out of it.
Also it contains a typo - Alice instead of Alex.
Still, we can use the following regex expression for sequence creation:

<pre>^(SYS).*?: Informational: ((?&lt;UCL_Alex&gt;CAlice):.*?(?&lt;US_Bob&gt;(?&lt;UM_sayMyName&gt;(?&lt;URT&gt;sentName)|(?&lt;URS&gt;response))).*?\((?&lt;UA&gt;.*)\)|(?&lt;UCL_AND_US&gt;Bob): (?&lt;URT&gt;processRequest)\("(?&lt;UM&gt;[\w]+)"\))</pre>

Specific parts of behavior:

- UCL_Alex will replace CAlice to Alex in the diagram's content
- US_Bob will add Bob service, despite, that it is not presented in the message
- UM_sayMyName will add sayMyName method, despite that it is not presented in the message
- URT & URP are stick to the parts of the message, which only indirectly show whether it is request or response
- UCL_AND_US will add Bob client and service, despite that it is not part of the message

Result of search would look like:

![Screenshot of the result, which contains UML items](./plant_uml_search_result_advanced.png)

As you can see above, all found messages have active checkbox items in the "UML" column.
It means, that they can be used for diagram creation.
Let's select those rows:

![Screenshot of the result with selected UML items](./plant_uml_search_result_advanced_selected_UML_items.png)

Now, let's switch to the "UML view" and trigger diagram creation:

![Screenshot of triggering creation of UML sequence diagram](./plant_uml_trigger_creation_of_diagram.png)

The resulting diagram looks like this:

![Screenshot of the created UML sequences diagram](./plant_uml_alice_bob_diagram_advanced.png)

----
> **Note!**
>
> There is a possibility to combine multiple UML items in the name of one group.
> E.g. US_AND_UCL, or US_Alex_AND_UCL_Alex.
>
> Still, there is no possibility to mention the same UML item type in same group name more than once.
> E.g. in case of US_Alex_AND_US_Alice "last win" strategy is applied, meaning that US_Alice will win.
----

----
> **Note!**
>
> Imagine the case, when one UML type is specified in one regex more than once:
> <pre>(?&lt;UM_one&gt;[\w]+):(?&lt;UM__two&gt;[\w]+)</pre>
> In such case, if one UML type will be found in a result log more than once, all found results of the same type will be concatenated.
> With above example result qould be: "one_two".
----

## Settings

----
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added md/plant_uml/plant_uml_search_result_advanced.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 21f02c7

Please sign in to comment.