Search code examples
javaaspectjpointcut

How to make my JLabels red with use of aspectJ?


my Project has a MessageUtil class, which has methods to show messages, I'm trying to make the texts of my Jlabels red using aspectJ, without use of aspectJ it is enough to add 'for loop' to one of the methods wich makes multiLabel text message:

public static JLabel[] createMultiLabel(String msg) {

        JLabel[] messages = null;
        if (msg.contains("\n")) {
        messages =  createMultiLabelBySlashN(msg);
        } else {
            messages = createMultiLabelByPixel(msg);
        }
        //this for loop makes the text red
        for (int i = 0; i < messages.length; i++) {
            messages[i].setForeground(Color.RED);
        }
        return messages;
    }

The two methods createMultiLabelByPixel(msg) and createMultiLabelBySlashN(msg) are in this form:

private static JLabel[] createMultiLabelBySlashN(String msg) { 
// the code here 
}

I want to use aspectJ inorder to make the JLabels red, not using the for loop in the body of method createMultiLabel,I don't have any idea how to do this, I'm trying to make a class containing aspecJ annotation with the pointCut below to make the array messages red before the messages is sent to createMultiLabelBySlashN() and createMultiLabelByPixel() as their parameter, but I don't know if it is correct or how to define the JLabel messages[] from the method createMultiLabel in my aspectJ class to make it red using the same for loop and send the String rezult to createMultiLabelBySlashN.

@Pointcut ("execution(public static JLabel[] mehad.util.MessageUtil.createMultiLabelBySlashN(..)) || execution(public static JLabel[] mehad.util.MessageUtil.createMultiLabelByPixel(..)" )

even when I'm calling the pointCut it seems there are errors with my code that says:

no match for this type name: JLabel

Solution

  • no match for this type name: JLabel

    This is because you do not use the fully qualified class name javax.swing.JLabel.

    Now let us assume your class looks like this (just a simple fake):

    package mehad.util;
    
    import javax.swing.JLabel;
    
    public class MessageUtil {
        public static void main(String[] args) {
            for (JLabel label : createMultiLabel("Albert Einstein\nWerner Heisenberg\nMax Planck"))
                System.out.println(label.getText() + " / " + label.getForeground());
            System.out.println();
            for (JLabel label : createMultiLabel("Albert Einstein, Werner Heisenberg, Max Planck"))
                System.out.println(label.getText() + " / " + label.getForeground());
        }
    
        public static JLabel[] createMultiLabel(String msg) {
            return msg.contains("\n")
                ? createMultiLabelBySlashN(msg)
                : createMultiLabelByPixel(msg);
        }
    
        private static JLabel[] createMultiLabelBySlashN(String msg) {
            String[] lines = msg.split("\n+");
            JLabel[] labels = new JLabel[lines.length];
            for (int i = 0; i < lines.length; i++)
                labels[i] = new JLabel(lines[i]);
            return labels;
        }
    
        private static JLabel[] createMultiLabelByPixel(String msg) {
            String[] words = msg.split("[, ]+");
            JLabel[] labels = new JLabel[words.length];
            for (int i = 0; i < words.length; i++)
                labels[i] = new JLabel(words[i]);
            return labels;
        }
    }
    

    Now if you run the main method without AspectJ, you will see this console output:

    Albert Einstein / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Werner Heisenberg / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Max Planck / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    
    Albert / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Einstein / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Werner / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Heisenberg / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Max / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    Planck / sun.swing.PrintColorUIResource[r=51,g=51,b=51]
    

    I.e. all labels have a default grey colour. Now add this aspect:

    package de.scrum_master.aspect;
    
    import java.awt.Color;
    
    import javax.swing.JLabel;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class RedLabelAspect {
        @Pointcut("execution(static javax.swing.JLabel[] createMultiLabel(..))")
        public void multilabelCreation() {}
    
        @Around("multilabelCreation()")
        public JLabel[] changeLabelColours(ProceedingJoinPoint thisJoinPoint) throws Throwable {
            JLabel[] labels = (JLabel[]) thisJoinPoint.proceed();
            for (JLabel label : labels)
                label.setForeground(Color.RED);
            return labels;
        }
    }
    

    The aspect modifies the labels contained in the result array in place, i.e. the for loop now resides in your aspect code, no longer in the core code. The console output changes to:

    Albert Einstein / java.awt.Color[r=255,g=0,b=0]
    Werner Heisenberg / java.awt.Color[r=255,g=0,b=0]
    Max Planck / java.awt.Color[r=255,g=0,b=0]
    
    Albert / java.awt.Color[r=255,g=0,b=0]
    Einstein / java.awt.Color[r=255,g=0,b=0]
    Werner / java.awt.Color[r=255,g=0,b=0]
    Heisenberg / java.awt.Color[r=255,g=0,b=0]
    Max / java.awt.Color[r=255,g=0,b=0]
    Planck / java.awt.Color[r=255,g=0,b=0]
    

    Voilà - the cross-cutting concern of colouring the labels has been modularised into an aspect.