Select Git revision
Main$1WorkerThread.class
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
diagramParser.py 6.07 KiB
import pandas as pd
import ERFormatConstants as const
import components as component
import logging as log
import matrices as matrix
# Function will parse a csv file and extract the necessary information, this is step 1 of the parse
def parseDiagramFile(csvFile) -> component.Diagram:
df = pd.read_csv(csvFile)
df.drop(["Shape Library", "Page ID", "Contained By", "Group", "Comments", "property 1"], axis=1, inplace=True) #Removing unecessary data
diagram = component.Diagram() # Defines the diagram object
diagram = matrix.parseTable(df, diagram) #Parse the table and finds all indicators
diagram = parseArchitectureDiagram(df, diagram) #Parse the architecture diagram and finds all ER components along with indicators and reasoning
diagram = parseThreats(df, diagram) #
diagram = parseConsequences(df, diagram)
diagram = parseAttacks(df, diagram)
print("Diagram successfully parsed")
return diagram
# Function will parse the threats and add them to the dictionary
def parseThreats(df,diagram: component.Diagram):
for i in range(len(df)):
if df[const.ThreatComponent][i] == const.Threat: #If the row in the dataframe is a threat
threat = component.Threat(
df[const.Id][i], # Component ID
df[const.ThreatMethodID][i], # ID from ER
df[const.ThreatName][i], # Name of the threat
df[const.ThreatDescription][i],
df[const.ThreatSource][i],
df[const.Likelihood][i],
)
diagram.threats[df[const.ThreatMethodID][i]] = threat
threat.findIndicatorsThreat(df, diagram) # Find the indicators associated with the threat
return diagram
#Parses consequences and adds it to dictionary
def parseConsequences(df, diagram: component.Diagram):
for i in range(len(df)):
if df[const.ConsequenceComponent][i] == const.Consequence:
consequence = component.Consequence(
df[const.Id][i],
df[const.ConsequenceID][i],
df[const.ConsequenceName][i],
df[const.ConsequenceDescription][i],
df[const.ConsequenceScore][i],
)
diagram.consequences[df[const.ConsequenceID][i]] = consequence
consequence.findIndicatorsConsequence(df, diagram) # Find the indicators associated with the consequence
return diagram
def parseAttacks(df, diagram: component.Diagram):
for i in range(len(df)):
if df[const.AttackComponent][i] == const.Attack:
attack = component.Attack(
df[const.Id][i],
df[const.AttackType][i],
df[const.AttackDescription][i],
)
diagram.attacks[df.Id[i]] = attack #! Note that the ID is the component ID from LucidChart, not my ID
return diagram
#Parses metrics components and adds it to list
def parseArchitectureDiagram(df, diagram: component.Diagram):
for i in range(len(df)):
# Iterates through the dataframe
if df[const.textArea1][i] == const.relationship: # If the component is a dynamic component
if df[const.typeField][i] == "ER": # * If the component is an ER component # Find the line where the component is the source
diagram = parseRelationshipComponentER(df, diagram, i)
return diagram
def parseRelationshipComponentER(df: pd.DataFrame, diagram: component.Diagram, row) -> None:
relationshipComponent = df.loc[row] # Define the relationship component
indicatorList = {} # Define a list over relevant indicators to individual relationship component
erComponents = {} # Define a list over ER components
#* Iterate over the Relationship component to find all the indicators, and the reasoning for each
for i in range(6 ,len(relationshipComponent), 2):
if pd.isnull(relationshipComponent[f"Text Area {i}"]) == True:
break
indicatorID = relationshipComponent[f"Text Area {i}"]
indicatorReason = relationshipComponent[f"Text Area {i+1}"]
indicatorList[indicatorID] = indicatorReason
# * Find all the lines associated with the component
linesFrom = df.loc[df[const.From] == relationshipComponent[const.Id].item()] # Find the component associated with the line
linesTo = df.loc[df[const.To] == relationshipComponent[const.Id].item()] # Find the component associated with the line
allLines = pd.concat([linesFrom, linesTo]) # Merge the two dataframes
# * Iterate through both lines, and find the ER components related to the relationship component
for index, row in allLines.iterrows():
objectTo = row[const.To]
objectFrom = row[const.From]
if df.loc[df[const.Id] == objectTo][const.typeField].item() == "ER":
row = df.loc[df[const.Id] == objectFrom]
else:
row = df.loc[df[const.Id] == objectTo]
# Defines values
name = row[const.erName].item()
entityRelationshipId = row[const.erID].item()
description = row[const.erDescription].item()
entityrelationshipType = row[const.erType].item()
# Create ER component
erComponent = component.ERComponent(name,entityRelationshipId, description, entityrelationshipType)
# Add indicators to the ER component
erComponent.linkedIndicators.update(indicatorList)
erComponents[erComponent.id]= erComponent
for i in indicatorList.keys():
# We need to update the indicators with the ER components and the reasoning for the indicator annotation
index = int(i)
diagram.indicators[index].erAssociates.update(erComponents)
return diagram