package husacct.analyse.task.analyse.java.analysing; import java.util.List; import org.antlr.v4.runtime.tree.TerminalNode; import org.apache.log4j.Logger; import husacct.analyse.domain.IModelCreationService; import husacct.analyse.domain.famix.FamixCreationServiceImpl; import husacct.analyse.task.analyse.VisibilitySet; import husacct.analyse.task.analyse.java.parsing.JavaParser.CatchClauseContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.CatchTypeContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.ConstDeclarationContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.ConstantDeclaratorContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.EnhancedForControlContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.FieldDeclarationContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.LocalVariableDeclarationContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.ModifierContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.QualifiedNameContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.ResourceContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.TypeArgumentContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.TypeArgumentsContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.TypeTypeContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.VariableDeclaratorContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.VariableDeclaratorIdContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.VariableDeclaratorsContext; import husacct.analyse.task.analyse.java.parsing.JavaParser.VariableModifierContext; class VariableAnalyser extends JavaGenerator{ private String name = ""; private String visibility = ""; private boolean hasClassScope = false; private boolean isFinal = false; private String belongsToClass = ""; private int lineNumber = 0; private String belongsToMethod = ""; private String declareType = ""; // Type of the attribute. In case of an instance variable with a generic type e.g. ArrayList<Person>, this value is ArrayList. private boolean isComposite = false; // False if the type allows one value only, like Person; True in case of a generic type, or e.g. Person[]. private String typeInClassDiagram = ""; // E.g. in case of an instance variable with a generic type ArrayList<Person>, this value is Person. private boolean isLocalVariable = false; private IModelCreationService modelService = new FamixCreationServiceImpl(); private Logger logger = Logger.getLogger(VariableAnalyser.class); public VariableAnalyser(String belongsToClass) { this.belongsToClass = belongsToClass; } public void analyseVariable(List<ModifierContext> modifierList, FieldDeclarationContext fieldDeclaration) { /* Test helpers if (belongsToClass.contains("husacct.analyse.task.reconstruct.ReconstructArchitectureDTOList")) { if (fieldDeclaration.start.getLine() == 37) { boolean breakpoint = true; } } */ try { this.isLocalVariable = false; this.visibility = determineVisibility(modifierList); this.isFinal = determineIsFinal(modifierList); this.hasClassScope = determineIsStatic(modifierList); if (hasClassScope) { } else { } dispatchAnnotationsOfMember(modifierList, belongsToClass); this.declareType = determineTypeOfTypeType(fieldDeclaration.typeType(), belongsToClass); if (!hasClassScope) { determine_isComposite_and_typeInClassDiagram(fieldDeclaration.typeType()); } determine_name(fieldDeclaration.variableDeclarators()); dispatchAssignment(fieldDeclaration.variableDeclarators()); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + fieldDeclaration.start.getLine() + " " + e.getMessage()); } } public void analyseLocalVariable(LocalVariableDeclarationContext localVariableDeclaration, String belongsToMethod) { try { this.isLocalVariable = true; this.isFinal = determine_IsFinalForLocalVariable(localVariableDeclaration); this.belongsToMethod = belongsToMethod; dispatchAnnotationsOfLocalVariable(localVariableDeclaration.variableModifier()); this.declareType = determineTypeOfTypeType(localVariableDeclaration.typeType(), belongsToClass); determine_name(localVariableDeclaration.variableDeclarators()); dispatchAssignment(localVariableDeclaration.variableDeclarators()); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + localVariableDeclaration.start.getLine() + " " + e.getMessage()); } } public void analyseForControlVariable(EnhancedForControlContext enhancedForControl, String belongsToMethod) { try { this.isLocalVariable = true; this.belongsToMethod = belongsToMethod; dispatchAnnotationsOfLocalVariable(enhancedForControl.variableModifier()); this.declareType = determineTypeOfTypeType(enhancedForControl.typeType(), belongsToClass); determine_name(enhancedForControl.variableDeclaratorId()); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + enhancedForControl.start.getLine() + " " + e.getMessage()); } } public void analyseCatchClauseVariable(CatchClauseContext catchClause, String belongsToMethod) { try { this.isLocalVariable = true; this.belongsToMethod = belongsToMethod; dispatchAnnotationsOfLocalVariable(catchClause.variableModifier()); this.declareType = determine_type(catchClause.catchType()); this.name = catchClause.Identifier().getText(); this.lineNumber = catchClause.start.getLine(); createObject(); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + catchClause.start.getLine() + " " + e.getMessage()); } } public void analyseResourceVariable(ResourceContext resource, String belongsToMethod) { try { this.isLocalVariable = true; this.belongsToMethod = belongsToMethod; dispatchAnnotationsOfLocalVariable(resource.variableModifier()); this.declareType = resource.classOrInterfaceType().getText(); determine_name(resource.variableDeclaratorId()); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + resource.start.getLine() + " " + e.getMessage()); } } public void analyseConstant(List<ModifierContext> modifierList, ConstDeclarationContext constDeclaration) { try { this.isLocalVariable = false; this.visibility = VisibilitySet.PUBLIC.toString(); this.isFinal = true; this.hasClassScope = true; dispatchAnnotationsOfMember(modifierList, belongsToClass); this.declareType = determineTypeOfTypeType(constDeclaration.typeType(), belongsToClass); for (ConstantDeclaratorContext constantDeclarator : constDeclaration.constantDeclarator()) { if (constantDeclarator.Identifier() != null) { this.lineNumber = constantDeclarator.start.getLine(); this.name = constantDeclarator.Identifier().getText(); createObject(); } if ((constantDeclarator.variableInitializer() != null) && (constantDeclarator.variableInitializer().expression() != null)) { new ExpressionAnalyser(belongsToClass, belongsToMethod, constantDeclarator.variableInitializer().expression()); } } } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + constDeclaration.start.getLine() + " " + e.getMessage()); } } public void analyseEnumConstant(TerminalNode identifier) { try { this.isLocalVariable = false; this.visibility = VisibilitySet.PUBLIC.toString(); this.isFinal = true; this.hasClassScope = true; this.declareType = belongsToClass; this.name = identifier.getText(); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + identifier.getText()); } } public void analyseAnnotationConstant(List<ModifierContext> modifierList, TypeTypeContext typeType, VariableDeclaratorsContext variableDeclarators) { try { this.isLocalVariable = false; this.visibility = VisibilitySet.PUBLIC.toString(); this.isFinal = true; this.hasClassScope = true; dispatchAnnotationsOfMember(modifierList, belongsToClass); this.declareType = determineTypeOfTypeType(typeType, belongsToClass); determine_name(variableDeclarators); } catch (Exception e) { logger.warn(" Exception while processing: " + belongsToClass + " Line: " + typeType.start.getLine() + " " + e.getMessage()); } } private void determine_name(VariableDeclaratorsContext variableDeclaratorsList) { for (VariableDeclaratorContext variableDeclarator : variableDeclaratorsList.variableDeclarator()) { determine_name(variableDeclarator.variableDeclaratorId()); } } private void determine_name(VariableDeclaratorIdContext variableDeclaratorId) { if (variableDeclaratorId != null) { if (variableDeclaratorId.Identifier() != null) { this.lineNumber = variableDeclaratorId.start.getLine(); this.name = variableDeclaratorId.getText(); createObject(); } } } private String determine_type(CatchTypeContext catchType) { String returnValue = ""; for (QualifiedNameContext qualifiedName : catchType.qualifiedName()) { returnValue = qualifiedName.getText(); } return returnValue; } private void dispatchAssignment(VariableDeclaratorsContext attributeTree) { for (VariableDeclaratorContext variableDeclarator : attributeTree.variableDeclarator()) { if (variableDeclarator.variableInitializer() != null) { if (variableDeclarator.variableInitializer().expression() != null) { new ExpressionAnalyser(belongsToClass, belongsToMethod, variableDeclarator.variableInitializer().expression()); } } } } private void determine_isComposite_and_typeInClassDiagram(TypeTypeContext typeType) { if (typeType.classOrInterfaceType() != null) { if (typeType.stop.getText().equals("]")) { // In case of array, e.g. VariableDTO[] this.isComposite = true; if (!hasClassScope) { this.typeInClassDiagram = this.declareType; } } else if (typeType.classOrInterfaceType().typeArguments() != null) { // Check on (generic) type parameters. for (TypeArgumentsContext typeArguments : typeType.classOrInterfaceType().typeArguments()) { for (TypeArgumentContext typeArgument : typeArguments.typeArgument()) { if (typeArgument.typeType() != null) { this.typeInClassDiagram = transformIdentifierToString(typeArgument.typeType().classOrInterfaceType().Identifier()); // Note in both cases Person will be assigned: ArrayList<Person>, HashMap<String, Person>. this.isComposite = true; } } } } } if (!isComposite) { this.typeInClassDiagram = this.declareType; } } private boolean determine_IsFinalForLocalVariable(LocalVariableDeclarationContext localVariableDeclaration) { boolean isFinalReturn = false; if (localVariableDeclaration.variableModifier() != null) { int size = localVariableDeclaration.variableModifier().size(); for (int i = 0; i < size; i++) { if (localVariableDeclaration.variableModifier(i).annotation() == null) { String modifier = localVariableDeclaration.variableModifier(i).getText(); if (modifier.equals("final")) { isFinalReturn = true; } } } } return isFinalReturn; } private void dispatchAnnotationsOfLocalVariable(List<VariableModifierContext> variableModifierList) { for (VariableModifierContext variableModifier : variableModifierList) { if (variableModifier.annotation() != null) { new AnnotationAnalyser(variableModifier.annotation(), this.belongsToClass); } } } private void createObject() { if (isLocalVariable) { createLocalVariableObject(); } else { createAttributeObject(); } } private void createAttributeObject() { if ((name != null) && !name.trim().equals("") && (declareType != null) && !declareType.trim().equals("")) { if (declareType.endsWith(".")) { declareType = declareType.substring(0, declareType.length() - 1); //deleting the last point } if (SkippedJavaTypes.isSkippable(declareType)) { modelService.createAttributeOnly(hasClassScope, isFinal, visibility, belongsToClass, declareType, name, belongsToClass + "." + name, lineNumber, typeInClassDiagram, isComposite); } else { modelService.createAttribute(hasClassScope, isFinal, visibility, belongsToClass, declareType, name, belongsToClass + "." + name, lineNumber, typeInClassDiagram, isComposite); } } } private void createLocalVariableObject() { if ((declareType != null) && !declareType.trim().equals("")) { if (declareType.endsWith(".")) { declareType = declareType.substring(0, declareType.length() - 1); //deleting the last point } if (SkippedJavaTypes.isSkippable(declareType)) { modelService.createLocalVariableOnly(belongsToClass, declareType, name, belongsToClass + "." + belongsToMethod + "." + this.name, lineNumber, this.belongsToMethod); } else { modelService.createLocalVariable(belongsToClass, declareType, name, belongsToClass + "." + belongsToMethod + "." + this.name, lineNumber, this.belongsToMethod); } } } }