diff --git a/build.txt b/build.txt index 7ca279b61e7eb3f58b89fd71e108fe5b6fce8e59..5c043274090df73c3e3f404581298950fbc78fe9 100644 --- a/build.txt +++ b/build.txt @@ -1 +1 @@ -14759 \ No newline at end of file +14761 \ No newline at end of file diff --git a/src/main/java/avatartranslator/AvatarError.java b/src/main/java/avatartranslator/AvatarError.java index c4cc8d85a5457d5c36868d6333227da4e74b8853..40d139617afbe6d223fdbf0fd548ff13c09a887e 100644 --- a/src/main/java/avatartranslator/AvatarError.java +++ b/src/main/java/avatartranslator/AvatarError.java @@ -69,7 +69,17 @@ public class AvatarError { "Invalid attribute in action on signal", "Invalid type in signal definition", "Invalid int expression in action on signal", - /*20*/"Invalid bool expression in action on signal" + /*20*/"Invalid bool expression in action on signal", + "Invalid number of parameters in action", + "Invalid integer value in method call", + "Invalid boolean value in method call", + "Invalid expression in method call", + /*25*/"Invalid type in method call", + "Invalid attribute before assignment", + "Invalid attribute type before assignment", + "Incompatible types in expression", + "Invalid integer expression", + /*30*/"Invalid boolean expression", }; diff --git a/src/main/java/avatartranslator/AvatarSyntaxChecker.java b/src/main/java/avatartranslator/AvatarSyntaxChecker.java index 08840066197609d42c0c65b804c23c5376806b34..ebd50cf469a289f31c195f5db95b4a2566574a08 100644 --- a/src/main/java/avatartranslator/AvatarSyntaxChecker.java +++ b/src/main/java/avatartranslator/AvatarSyntaxChecker.java @@ -521,6 +521,70 @@ public class AvatarSyntaxChecker { return errors; } + public static AvatarError checkAvatarTermFunction(AvatarSpecification avspec, AvatarBlock block, + AvatarTransition asme, AvatarTermFunction atf) { + int size = atf.getMethod().getListOfAttributes().size(); + + if (size != atf.getArgs().components.size()) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = atf; + error.error = 21; + return error; + } + + for(int i=0; i<size; i++) { + // Check that each value correspond to the expected type + AvatarAttribute param = atf.getMethod().getListOfAttributes().get(i); + AvatarTerm term = atf.getArgs().components.get(i); + + + if (term instanceof AvatarAttribute) { + if ( ((AvatarAttribute)term).getType() != param.getType()) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 25; + return error; + } + } else { + String value = term.toString(); + TraceManager.addDev("Value:>" + value + "< of class>" + term.getClass().toString() + "<"); + if (param.getType() == AvatarType.INTEGER) { + TraceManager.addDev("Trying to parse int expr: " + value); + AvatarIBSExpressions.IExpr e1 = AvatarIBSolver.parseInt(block, value); + if (e1 == null) { + TraceManager.addDev("Parse error in int expr: " + value); + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 22; + return error; + } + TraceManager.addDev("Parse ok in int expr: " + value); + } else if (param.getType() == AvatarType.BOOLEAN) { + IBSExpressions.BExpr e1 = AvatarIBSolver.parseBool(block, value); + if (e1 == null) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 23; + return error; + } + } else { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 18; + return error; + } + } + + + } + return null; + } + public static ArrayList<AvatarError> checkActions(AvatarSpecification avspec) { ArrayList<AvatarError> errors = new ArrayList<>(); @@ -529,13 +593,213 @@ public class AvatarSyntaxChecker { if (asm != null) { for (AvatarStateMachineElement asme : asm.getListOfElements()) { if (asme instanceof AvatarTransition) { - + for(AvatarAction aa: ((AvatarTransition)(asme)).getActions()) { + AvatarError ae = checkAction(avspec, block, ((AvatarTransition)(asme)), aa); + if (ae != null) + errors.add( ae ); + } } } } } return errors; } + public static AvatarError checkAction(AvatarSpecification avspec, AvatarBlock block, AvatarTransition asme, AvatarAction aa) { + if (aa instanceof AvatarTermFunction) { + AvatarTermFunction atf = (AvatarTermFunction) aa; + AvatarError err = checkAvatarTermFunction(avspec, block, asme, atf); + if (err != null) { + return err; + } + } + + // We assume that this is a variable setting, possibly with a method call + // v = method() + // v = expr + // v = w + + TraceManager.addDev("Class>" + aa.getClass().toString() + "<"); + if (aa instanceof avatartranslator.AvatarActionAssignment) { + + AvatarActionAssignment aaa = (AvatarActionAssignment)aa; + + AvatarLeftHand alh = aaa.leftHand; + + // Left hand must be an attribute or a tuple with attributes + if (!(alh instanceof AvatarAttribute) && (!(alh instanceof AvatarTuple))) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 26; + return error; + } + + ArrayList<AvatarType> listOfTypes = new ArrayList<>(); + + if (alh instanceof AvatarAttribute) { + AvatarAttribute avat = (AvatarAttribute) alh; + if (block.getAvatarAttributeWithName(avat.getName()) == null) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 26; + return error; + } + + // Type of attribute must be int or boolean + if ((avat.getType() != AvatarType.INTEGER) && (avat.getType() != AvatarType.BOOLEAN)) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 27; + return error; + } + + listOfTypes.add(avat.getType()); + + } + + if (alh instanceof AvatarTuple) { + AvatarTuple at = (AvatarTuple) alh; + if (! ((AvatarTuple) alh).areComponentsAvatarAttributes()) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 26; + return error; + } + + for(AvatarTerm avatTerm: at.getComponents()) { + AvatarAttribute avatAttri = (AvatarAttribute) avatTerm; + if ((avatAttri.getType() != AvatarType.INTEGER) && (avatAttri.getType() != AvatarType.BOOLEAN)) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 27; + return error; + } + listOfTypes.add(avatAttri.getType()); + + } + } + + // Now that the left hand is correct, we must ensure that the right hand is correct + // and corresponds to what is expected in the left hand + if( listOfTypes.size() < 1) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + + AvatarTerm right = aaa.rightHand; + + TraceManager.addDev("Class of right expr:>" + right.getClass().toString() + "<"); + + if (right instanceof AvatarTermFunction) { + AvatarTermFunction atf = (AvatarTermFunction) right; + AvatarError err = checkAvatarTermFunction(avspec, block, asme, atf); + if (err != null) { + return err; + } + + // Must also check return types + if (listOfTypes.size() != atf.method.returnParameters.size()) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + for(int i=0; i<listOfTypes.size(); i++) { + if (listOfTypes.get(i) != atf.method.returnParameters.get(i).getType()) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + } + } + + + + if (right instanceof AvatarAttribute) { + // Check the compatible type and the existence of the attribute + if ( ((AvatarAttribute)right).getType() != listOfTypes.get(0)) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + } + + + if (right instanceof AvatarArithmeticOp) { + // Check that only one return type and that the two have the same type + if (listOfTypes.size() != 1) { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + + if (listOfTypes.get(0) == AvatarType.INTEGER) { + String value = right.toString(); + TraceManager.addDev("Trying to parse int expr: " + value); + AvatarIBSExpressions.IExpr e1 = AvatarIBSolver.parseInt(block, value); + if (e1 == null) { + TraceManager.addDev("Parse error in int expr: " + value); + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 29; + return error; + } + TraceManager.addDev("Parse ok in int expr: " + value); + + } else if (listOfTypes.get(0) == AvatarType.BOOLEAN) { + String value = right.toString(); + TraceManager.addDev("Trying to parse int expr: " + value); + IBSExpressions.BExpr e1 = AvatarIBSolver.parseBool(block, value); + if (e1 == null) { + TraceManager.addDev("Parse error in int expr: " + value); + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 30; + return error; + } + TraceManager.addDev("Parse ok in int expr: " + value); + + } else { + AvatarError error = new AvatarError(avspec); + error.block = block; + error.firstAvatarElement = asme; + error.error = 28; + return error; + } + + + // We now evaluate the expression + + + } + + // All done :-) + + + } + + + + return null; + + } + public static int isAValidGuard(AvatarSpecification _as, AvatarStateMachineOwner _ab, String _guard) { diff --git a/src/main/java/avatartranslator/AvatarTransition.java b/src/main/java/avatartranslator/AvatarTransition.java index 0d8c3f612a648e2cdda245a4096584cef5688e40..c1bc9b4aeec0eb367d209730ca0ee2cc32e26d96 100644 --- a/src/main/java/avatartranslator/AvatarTransition.java +++ b/src/main/java/avatartranslator/AvatarTransition.java @@ -102,7 +102,7 @@ public class AvatarTransition extends AvatarStateMachineElement { public AvatarTransition(AvatarStateMachineOwner _block, String _name, Object _referenceObject) { super(_name, _referenceObject, _block); - actions = new LinkedList<AvatarAction>(); + actions = new LinkedList<>(); this.guard = new AvatarGuardEmpty(); this.block = _block; guardSolver = null; diff --git a/src/main/java/avatartranslator/AvatarTuple.java b/src/main/java/avatartranslator/AvatarTuple.java index 06eeaee902bb36432aec302241c3d2755a47a484..a5c08e609ee55ecfbb6a0e21d8d38b0b815ce2b6 100644 --- a/src/main/java/avatartranslator/AvatarTuple.java +++ b/src/main/java/avatartranslator/AvatarTuple.java @@ -159,4 +159,14 @@ public class AvatarTuple extends AvatarLeftHand { } this.components = components; } + + public boolean areComponentsAvatarAttributes() { + for(AvatarTerm at: components) { + if (!(at instanceof AvatarAttribute)) { + return false; + } + } + + return true; + } } diff --git a/src/main/java/ui/util/DefaultText.java b/src/main/java/ui/util/DefaultText.java index 1a195d9f0813d7abf4d7c23d4392ae023ffcc9a3..9b71449b28cbbd6dab061ecd2c4bce221d569647 100755 --- a/src/main/java/ui/util/DefaultText.java +++ b/src/main/java/ui/util/DefaultText.java @@ -50,8 +50,8 @@ package ui.util; */ public class DefaultText { - public static String BUILD = "14758"; - public static String DATE = "2024/04/24 03:22:32 CET"; + public static String BUILD = "14760"; + public static String DATE = "2024/04/26 03:22:34 CET"; public static StringBuffer sbAbout = makeAbout(); diff --git a/src/main/java/ui/window/JDialogAttack.java b/src/main/java/ui/window/JDialogAttack.java index f97c58e58c1eca8f727497baace4967112d968ac..1b85366b709050a7e4f76dbf158356d1e47194f4 100644 --- a/src/main/java/ui/window/JDialogAttack.java +++ b/src/main/java/ui/window/JDialogAttack.java @@ -68,7 +68,8 @@ public class JDialogAttack extends JDialogBase implements ActionListener { private Frame frame; //protected JTextField taskName; - protected JTextField name, description, attackCostField; + protected JTextField name, attackCostField; + protected JTextArea description; protected JComboBox<String> attackExperienceBox; protected JCheckBox isRootAttack; @@ -128,8 +129,12 @@ public class JDialogAttack extends JDialogBase implements ActionListener { c1.fill = GridBagConstraints.HORIZONTAL; panel2.add(new JLabel("Description:"), c2); c1.gridwidth = GridBagConstraints.REMAINDER; //end row - description = new JTextField(attack.getDescription()); - panel2.add(description, c1); + description = new JTextArea(4, 20); + description.setText(attack.getDescription()); + JScrollPane scrollPane = new JScrollPane(description); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + panel2.add(scrollPane, c1); c1.gridwidth = 1; c1.fill = GridBagConstraints.HORIZONTAL; diff --git a/src/main/java/ui/window/JFrameAI.java b/src/main/java/ui/window/JFrameAI.java index a5df9a47821e4c7206e24b95018a45061c5b47ea..a96d201015341831e966f492dd6230dbcf94f5ee 100644 --- a/src/main/java/ui/window/JFrameAI.java +++ b/src/main/java/ui/window/JFrameAI.java @@ -85,8 +85,8 @@ public class JFrameAI extends JFrame implements ActionListener { "DEPRECATED - Identify system blocks (knowledge type #2) - Provide a system specification", "Identify system blocks - Provide a system specification", "DEPRECATED - Identify software blocks - Provide a system specification", - "DEPRECATED - Identify state machines - Select a block diagram. Additionally, you can provide a system specification", - "Identify state machines and attributes - Select a block diagram. Additionally, you can provide a system specification", + "DEPRECATED - Identify state machines - Select a block diagram. you may provide a system specification", + "Identify state machines and attributes - Select a block diagram. You may provide a system specification", "Model mutation - A(I)MULET - Select a block diagram first", "Diagram coherency", "Diagram coherency with formal rules", @@ -218,12 +218,11 @@ public class JFrameAI extends JFrame implements ActionListener { panelTop.setBorder(new javax.swing.border.TitledBorder("Options")); listOfPossibleActions = new JComboBox<>(POSSIBLE_ACTIONS); - JPanel chatPanelAction = new JPanel(); - chatPanelAction.add(new JLabel("Selected chat:")); - chatPanelAction.add(listOfPossibleActions); - panelTop.add(chatPanelAction, BorderLayout.CENTER); listOfPossibleActions.addActionListener(this); - listOfPossibleActions.setMinimumSize(new Dimension(50, 100)); + //listOfPossibleActions.setMinimumSize(new Dimension(50, 100)); + panelTop.add(new JLabel("Selected chat:", SwingConstants.CENTER), BorderLayout.NORTH); + panelTop.add(listOfPossibleActions, BorderLayout.CENTER); + //panelTop.setMinimumSize(new Dimension(50, 100)); JPanel modelSelectionPanel = new JPanel(); modelSelectionPanel.add(new JLabel("Selected AI model:")); @@ -232,14 +231,13 @@ public class JFrameAI extends JFrame implements ActionListener { } else { listOfPossibleModels = new JComboBox<>(AIInterface.MODEL_GPT_35.split(" ")); } - modelSelectionPanel.add(listOfPossibleModels); - JPanel numAtsSelectPanel = new JPanel(); + /*JPanel numAtsSelectPanel = new JPanel(); numAtsSelectPanel.add(new JLabel("Number of attack trees to be created: ")); numAtsModel = new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1); JSpinner numAtsSpinner = new JSpinner(numAtsModel); - numAtsSpinner.setPreferredSize(new Dimension(100, 24)); + numAtsSpinner.setPreferredSize(new Dimension(100, 50)); numAtsSelectPanel.add(numAtsSpinner); numAtsSelectPanel.setVisible(false); @@ -247,12 +245,30 @@ public class JFrameAI extends JFrame implements ActionListener { numLvlsSelectPanel.add(new JLabel("Number of max levels per attack tree: ")); numLvlsModel = new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1); JSpinner numLvlsSpinner = new JSpinner(numLvlsModel); - numLvlsSpinner.setPreferredSize(new Dimension(100, 24));; + numLvlsSpinner.setPreferredSize(new Dimension(100, 50));; numLvlsSelectPanel.add(numLvlsSpinner); - numLvlsSelectPanel.setVisible(false); + numLvlsSelectPanel.setVisible(false);*/ + + JLabel labelAtsSpinner = new JLabel("Number of attack trees to be created: "); + modelSelectionPanel.add(labelAtsSpinner); + numAtsModel = new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1); + JSpinner numAtsSpinner = new JSpinner(numAtsModel); + //numAtsSpinner.setPreferredSize(new Dimension(100, 50)); + modelSelectionPanel.add(numAtsSpinner); + labelAtsSpinner.setVisible(false); + numAtsSpinner.setVisible(false); + + JLabel labelnumLvlsSpinner = new JLabel("Number of max levels per attack tree: "); + modelSelectionPanel.add(labelnumLvlsSpinner); + numLvlsModel = new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1); + JSpinner numLvlsSpinner = new JSpinner(numLvlsModel); + //numLvlsSpinner.setPreferredSize(new Dimension(100, 50));; + modelSelectionPanel.add(numLvlsSpinner); + labelnumLvlsSpinner.setVisible(false); + numLvlsSpinner.setVisible(false); - numAtsSelectPanel.add(numLvlsSelectPanel, BorderLayout.SOUTH); - modelSelectionPanel.add(numAtsSelectPanel, BorderLayout.SOUTH); + //numAtsSelectPanel.add(numLvlsSelectPanel, BorderLayout.SOUTH); + //modelSelectionPanel.add(numAtsSelectPanel, BorderLayout.SOUTH); panelTop.add(modelSelectionPanel, BorderLayout.SOUTH); framePanel.add(panelTop, BorderLayout.NORTH); @@ -261,19 +277,25 @@ public class JFrameAI extends JFrame implements ActionListener { assert selectedAction != null; if (selectedAction.equals(POSSIBLE_ACTIONS[14])) { - numLvlsSelectPanel.setVisible(false); modelSelectionPanel.setVisible(false); - numAtsSelectPanel.setVisible(false); + labelAtsSpinner.setVisible(false); + numAtsSpinner.setVisible(false); + numLvlsSpinner.setVisible(false); + labelnumLvlsSpinner.setVisible(false); } else if (selectedAction.equals(POSSIBLE_ACTIONS[17])) { modelSelectionPanel.setVisible(true); - numLvlsSelectPanel.setVisible(true); - numAtsSelectPanel.setVisible(true); + labelAtsSpinner.setVisible(true); + numAtsSpinner.setVisible(true); + numLvlsSpinner.setVisible(true); + labelnumLvlsSpinner.setVisible(true); } else { modelSelectionPanel.setVisible(true); - numLvlsSelectPanel.setVisible(false); - numAtsSelectPanel.setVisible(false); + labelAtsSpinner.setVisible(false); + numAtsSpinner.setVisible(false); + numLvlsSpinner.setVisible(false); + labelnumLvlsSpinner.setVisible(false); } }); @@ -716,6 +738,7 @@ public class JFrameAI extends JFrame implements ActionListener { inform("Enhancing attack tree diagram with ai answer: done\n"); } + @SuppressWarnings("unchecked") private void applyAttackTrees(Object spec) { if (spec == null) { error("Empty attack tree diagram list generated by AI"); diff --git a/ttool/src/test/java/avatartranslator/AvatarIBSStdParserTest.java b/ttool/src/test/java/avatartranslator/AvatarIBSStdParserTest.java index a3edd47ab6c03d297a90dc3bf38a93530c962e01..2afac7aac6d2187d3c2f8e9899de2ca31325db5d 100644 --- a/ttool/src/test/java/avatartranslator/AvatarIBSStdParserTest.java +++ b/ttool/src/test/java/avatartranslator/AvatarIBSStdParserTest.java @@ -81,6 +81,9 @@ public class AvatarIBSStdParserTest { block1.addAttribute(a1); AvatarAttribute b1 = new AvatarAttribute("key2", AvatarType.BOOLEAN, block1, null); block1.addAttribute(b1); + + AvatarAttribute t = new AvatarAttribute("t", AvatarType.TIMER, block1, null); + block1.addAttribute(t); x1.setInitialValue("10"); y1.setInitialValue("5"); @@ -277,6 +280,9 @@ public class AvatarIBSStdParserTest { //assertTrue(e15!=null); //TraceManager.addDev("Testing e15 done"); + AvatarIBSExpressions.IExpr e16 = AvatarIBSolver.parseInt(block1,"t+3"); + assertTrue(e16!=null); + assertTrue(e1.eval(specBlock) == 15); assertTrue(e2.eval(specBlock)); diff --git a/ttool/src/test/java/avatartranslator/AvatarIntegerExprParsingAndEvaluationTests.java b/ttool/src/test/java/avatartranslator/AvatarIntegerExprParsingAndEvaluationTests.java index d94a42b4e3c9601fb2ae2ea4efac769b7f4dcf23..c9e7f0f81f8c1e21356793fb6f2ffea02f5c1b29 100644 --- a/ttool/src/test/java/avatartranslator/AvatarIntegerExprParsingAndEvaluationTests.java +++ b/ttool/src/test/java/avatartranslator/AvatarIntegerExprParsingAndEvaluationTests.java @@ -142,6 +142,7 @@ public class AvatarIntegerExprParsingAndEvaluationTests { testExpr("x = x*((x + y)*z + (x+z)/z)/x", 36, true); + }