Aspect-orientation (after/before) does not work at child classes #1027

Open
ahmedvc opened this Issue Mar 30, 2017 · 5 comments

Comments

@ahmedvc
Contributor

ahmedvc commented Mar 30, 2017

Aspect-orientation works fine at a class (see Test), but oes not work in subclasses (see Sub). Try generating the code below, and you will find that aspect-oriented code in the subclass will be ignored.

class Test{
name;
before getName{
//I will work
}
}

class Sub{
isA Test;
before getName{
//I will not
}
}

@TimLethbridge

This comment has been minimized.

Show comment
Hide comment
@TimLethbridge

TimLethbridge Dec 8, 2017

Member

Logically, this ought to result in a getName that calls the super getName, and injects the relevant code.

Member

TimLethbridge commented Dec 8, 2017

Logically, this ought to result in a getName that calls the super getName, and injects the relevant code.

@TimLethbridge TimLethbridge added this to the April 2018 for release 1.28 milestone Dec 8, 2017

@TimLethbridge

This comment has been minimized.

Show comment
Hide comment
@TimLethbridge

TimLethbridge Mar 9, 2018

Member

Here's another case, where the injection is only in the subclass

class Test{
  name;

}

class Sub{
  isA Test;
  before all getName{
    //I will not
  }
}

Currently nothing happens in the subclass Sub. But it would be logical for the following to be newly generated Java in this case (and in the original example for this issue).

public String getName() 
{
  //I will not
  super.getName()
}

Similar code would be needed for PhP, Ruby etc.

Member

TimLethbridge commented Mar 9, 2018

Here's another case, where the injection is only in the subclass

class Test{
  name;

}

class Sub{
  isA Test;
  before all getName{
    //I will not
  }
}

Currently nothing happens in the subclass Sub. But it would be logical for the following to be newly generated Java in this case (and in the original example for this issue).

public String getName() 
{
  //I will not
  super.getName()
}

Similar code would be needed for PhP, Ruby etc.

@TimLethbridge

This comment has been minimized.

Show comment
Hide comment
@TimLethbridge

TimLethbridge Mar 9, 2018

Member

When done, also add a page to the aspect oriented part of the user manual.

Member

TimLethbridge commented Mar 9, 2018

When done, also add a page to the aspect oriented part of the user manual.

@hugessen hugessen self-assigned this Mar 16, 2018

@hugessen

This comment has been minimized.

Show comment
Hide comment
@hugessen

hugessen Mar 16, 2018

Contributor

So it turns out there is functionality already built to do this, but it only works for set methods, not get. I'd like to know if this was done intentionally. The line is at JavaClassGenerator.java:4740

For example:

class SCTest{
  name;
}

class Sub{
  isA SCTest;
  
  before all setName{
    System.out.println("Before");
  }
  after all getName{
    System.out.println("After");
  }
}

Produces the following:

// line 5 "SubclassTesting.ump"
public class Sub extends SCTest
{

  //------------------------
  // MEMBER VARIABLES
  //------------------------

  //------------------------
  // CONSTRUCTOR
  //------------------------

  public Sub(String aName)
  {
    super(aName);
  }

  //------------------------
  // INTERFACE
  //------------------------
  /* Code from template attribute_Set_subclass */
  public boolean setName(String aName)
  {
    boolean wasSet = false;
    // line 9 "SubclassTesting.ump"
    System.out.println("Before");
    // END OF UMPLE BEFORE INJECTION
      wasSet = super.setName(aName);
    return wasSet;
  }

  public void delete()
  {
    super.delete();
  }
}
Contributor

hugessen commented Mar 16, 2018

So it turns out there is functionality already built to do this, but it only works for set methods, not get. I'd like to know if this was done intentionally. The line is at JavaClassGenerator.java:4740

For example:

class SCTest{
  name;
}

class Sub{
  isA SCTest;
  
  before all setName{
    System.out.println("Before");
  }
  after all getName{
    System.out.println("After");
  }
}

Produces the following:

// line 5 "SubclassTesting.ump"
public class Sub extends SCTest
{

  //------------------------
  // MEMBER VARIABLES
  //------------------------

  //------------------------
  // CONSTRUCTOR
  //------------------------

  public Sub(String aName)
  {
    super(aName);
  }

  //------------------------
  // INTERFACE
  //------------------------
  /* Code from template attribute_Set_subclass */
  public boolean setName(String aName)
  {
    boolean wasSet = false;
    // line 9 "SubclassTesting.ump"
    System.out.println("Before");
    // END OF UMPLE BEFORE INJECTION
      wasSet = super.setName(aName);
    return wasSet;
  }

  public void delete()
  {
    super.delete();
  }
}
@ZainabAlShowely

This comment has been minimized.

Show comment
Hide comment
@ZainabAlShowely

ZainabAlShowely Jun 21, 2018

Contributor

It seems like it was implemented only for set methods (both before and after), but it is not only get methods that cause the issue, as this code:

class A 
{
  attr;
  * -- * C;
}

class B 
{
  isA A;
  before getAttr { /*before getAttr */}
  before setAttr { /*before setAttr */ }
  before addC { /*before addC */ }
  before removeC { /*before removeC */ }
  before getCs { /*before getCs */ }
  before numberOfCs { /*before numberOfCs */ }
  before indexOfC { /*before indexOfC */ }
  
  after getAttr { /*after getAttr */}
  after setAttr { /*after setAttr */ }
  after addC { /*after addC */ }
  after removeC { /*after removeC */ }
  after getCs { /*after getCs */ }
  after numberOfCs { /*after numberOfCs */ }
  after indexOfC { /*after indexOfC */ }
}

class C
{
  attr2;
}

Produces the following code for class B in Java:

import java.util.*;
public class B extends A
{

  //------------------------
  // MEMBER VARIABLES
  //------------------------

  //------------------------
  // CONSTRUCTOR
  //------------------------

  public B(String aAttr)
  {
    super(aAttr);
  }

  //------------------------
  // INTERFACE
  //------------------------
  /* Code from template attribute_Set_subclass */
  public boolean setAttr(String aAttr)
  {
    boolean wasSet = false;
    // line 11 "A.ump"
    /*before setAttr */
    // END OF UMPLE BEFORE INJECTION
      wasSet = super.setAttr(aAttr);
    // line 19 "A.ump"
    /*after setAttr */
    // END OF UMPLE AFTER INJECTION
    return wasSet;
  }

  public void delete()
  {
    super.delete();
  }

}

A similar result is generated for PHP and Ruby.

Contributor

ZainabAlShowely commented Jun 21, 2018

It seems like it was implemented only for set methods (both before and after), but it is not only get methods that cause the issue, as this code:

class A 
{
  attr;
  * -- * C;
}

class B 
{
  isA A;
  before getAttr { /*before getAttr */}
  before setAttr { /*before setAttr */ }
  before addC { /*before addC */ }
  before removeC { /*before removeC */ }
  before getCs { /*before getCs */ }
  before numberOfCs { /*before numberOfCs */ }
  before indexOfC { /*before indexOfC */ }
  
  after getAttr { /*after getAttr */}
  after setAttr { /*after setAttr */ }
  after addC { /*after addC */ }
  after removeC { /*after removeC */ }
  after getCs { /*after getCs */ }
  after numberOfCs { /*after numberOfCs */ }
  after indexOfC { /*after indexOfC */ }
}

class C
{
  attr2;
}

Produces the following code for class B in Java:

import java.util.*;
public class B extends A
{

  //------------------------
  // MEMBER VARIABLES
  //------------------------

  //------------------------
  // CONSTRUCTOR
  //------------------------

  public B(String aAttr)
  {
    super(aAttr);
  }

  //------------------------
  // INTERFACE
  //------------------------
  /* Code from template attribute_Set_subclass */
  public boolean setAttr(String aAttr)
  {
    boolean wasSet = false;
    // line 11 "A.ump"
    /*before setAttr */
    // END OF UMPLE BEFORE INJECTION
      wasSet = super.setAttr(aAttr);
    // line 19 "A.ump"
    /*after setAttr */
    // END OF UMPLE AFTER INJECTION
    return wasSet;
  }

  public void delete()
  {
    super.delete();
  }

}

A similar result is generated for PHP and Ruby.

TimLethbridge added a commit that referenced this issue Jun 25, 2018

Merge pull request #1316 from umple/Issue_1027_2
Progress on #1027 Adds before/after code injection to get methods for subclasses
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment