Aspect-Oriented Programming with AspectJ™ AspectJ.org Xerox PARC Erik Hilsdale Gregor Kiczales with Bill Griswold, Jim Hugunin, Wes Isberg, Mik Kersten.

Slides:



Advertisements
Similar presentations
A Brief Introduction to Aspect-Oriented Programming Zhenxiao Yang.
Advertisements

Aspect Oriented Programming. AOP Contents 1 Overview 2 Terminology 3 The Problem 4 The Solution 4 Join point models 5 Implementation 6 Terminology Review.
1 An Aspect-Aware Outline Viewer Michihiro Horie and Shigeru Chiba Tokyo Institute of Technology, Japan.
An Overview of AspectJ Sabine Hauert. Today's Deserts  Whipped introduction served with its three berries syrup  Chocolate history soufflé  Design.
Secure Systems Research Group - FAU Aspect Oriented Programming Carlos Oviedo Secure Systems Research Group.
20-May-15 Aspect-Oriented Programming Dave Matuszek University of Pennsylvania.
Overview of AspectJ Aspect Oriented Software Development Seminar Technion presented by Oren Mishali.
Aspect-Oriented Programming In Eclipse ® Aspect-Oriented Programming in Eclipse with AspectJ Dr Helen Hawkins and Sian January.
University of British Columbia Software Practices Lab Fluid AOP Join Point Models Terry Hon Gregor Kiczales.
Java.sun.com/javaone/sf | 2004 JavaOne SM Conference | Session BUS JavaOne 2004 What is AOP? Gregor Kiczales AspectMentor.com and University of.
Aspect-Oriented Programming Gregor Kiczales University of British Columbia © Copyright 2004, Gregor Kiczales. All rights reserved.
359C 10/1/05 Eric Wohlstadter Introductions –Name –Degree objective/Year –Research Area (or interests) Syllabus Aspect-Oriented Programming –AspectJ –AspectC.
1 Aspect Oriented Programming Programming Languages Seminar Presenter: Barış Aktemur University of Illinois 18 Feb Mostly taken from Bedir Tekinerdogan’s.
Aspect-Oriented Software Development (AOSD) Tutorial #2 AspectJ Basics.
Superimpositions and Aspect- Oriented Programming Marcelo Sihman Department of Computer Science Technion – Israel 1Institute of Technology.
University of British Columbia Software Practices Lab CAS Seminar 06 Fluid AJ - A Simple Fluid AOP Tool Terry Hon Gregor Kiczales.
Aspect-oriented programming Laura Ricci A.A
Aspect-Oriented Software Development (AOSD) Tutorial #2 AspectJ Basics.
26-Jun-15 Aspect-Oriented Programming. 2 Programming paradigms Procedural programming Executing a set of commands in a given sequence Fortran, C, Cobol,
(c) Copyright Palo Alto Research Center Incroporated. All rights reserved.1 AO Tools: State of the (AspectJ™) Art and Open Problems Mik Kersten.
Software modularity group Gregor Kiczales Professor and NSERC/Xerox/Sierra Systems Software Design Chair University of British Columbia Principal Scientist.
Technion Israel 1 Aspect-Oriented Software Development (AOSD) An Introduction Shmuel Katz Part of this lecture: Johan Brichau & Theo D’Hondt
More on AspectJ. aspect MoveTracking { private static boolean _flag = false; public static boolean testAndClear() { boolean result = _flag; _flag = false;
Session 15 Modeling Traceability of Concerns in Architectural Views Mark Stobbe October 29,
Aspect-Oriented Software Development (AOSD) Tutorial #3 AspectJ - continued.
Introduction to Aspect- Oriented Programming CS 3360 Gregor Kiczales, et. al. Getting started with AspectJ, CACM, 44(10):59-65, October Fall 2012.
An Introduction to AOP Original slides developed by Julie Waterhouse and Mik Kersten for OOPSLA 2004 AspectJ Tutorial ( kerstens.org/mik/publications/aspectj-
Aspect-Oriented Programming with AspectJ Using slides from Jorrit N. Herder ( Mik Kersten ( aspectj.org Palo Alto.
Introduction to Aspect Oriented Programming Presented By: Kotaiah Choudary. Ravipati M.Tech IInd Year. School of Info. Tech.
Session 2: AspectJ Mark Stobbe September 13,
1 An Aspect-oriented Weaving Mechanism Based on Component-and-Connector Architecture Naoyasu Ubayashi (Kyushu Institute of Technology) February 12, 2008.
Aspect Oriented Programming Sumathie Sundaresan CS590 :: Summer 2007 June 30, 2007.
1 A Parameterized Interpreter for Modeling Different AOP Mechanisms Naoyasu Ubayashi(Kyushu Institute of Technology, Japan) Genki Moriyama(Kyushu Institute.
Aspect Oriented Programming Gülşah KARADUMAN.
Kiczales and Mezini - FOAL AOP and Modular Reasoning [ICSE05] Start with first-principles definition of modularity and modular reasoning –localization,
Design Rules for Increasing Modularity with CaesarJ Carlos Eduardo Pontual Advisor: Paulo Borba 17/06/2010.
AOSD1 Aspect-Oriented Software Design Karl Lieberherr Theo Skotiniotis.
AOP-1 Aspect Oriented Programming. AOP-2 Aspects of AOP and Related Tools Limitation of OO Separation of Concerns Aspect Oriented programming AspectJ.
Devon M. Simmonds Computer Science Department, CSC592 1 Devon M. Simmonds Computer Science Department University of North Carolina, Wilmington
Aspect-Oriented Programming and Modular Reasoning G. KiczalesM. Mezini Presented by Alex Berendeyev.
Features of AOP languages AOP languages have the following main elements: –a join point model (JPM) wrt base PL –a specification language for expressing.
Inter-Type Declarations in AspectJ Awais Rashid Steffen Zschaler © Awais Rashid, Steffen Zschaler 2009.
AspectJ – AOP for Java Tom Janofsky. Instructor at Penn State Abington Consultant with Chariot Solutions JUG Member.
1 Contract-based Verification for Aspect-oriented Refactoring Naoyasu Ubayashi(Kyushu Institute of Technology) Jinji Piao(Kyushu Institute of Technology)
Demeter Aspects We study techniques for the emerging area of Aspect-Oriented Software Development and focus on the following areas:  Aspectual Collaborations.
Shanghai Jiao Tong University 上海交通大学软件工程中心 Object Oriented Analysis and Design Aspect-Oriented Software Development (AOSD)
Applying Translucid Contracts for Modular Reasoning about Aspect and Object Oriented Events Mehdi Bagherzadeh Gary T. Leavens Robert Dyer Foundations of.
Chapter 8: Aspect Oriented Programming Omar Meqdadi SE 3860 Lecture 8 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.
Aspect Oriented Development Alex Beatty.  Purpose  Cross-cutting Concerns  Join Points, Pointcuts, and Advices  Weaving  Invasive vs. Non-Invasive.
Alloy-based Lightweight Verification for Aspect-oriented Architecture Naoyasu Ubayashi(Kyushu Institute of Technology) Yuki Sato(Kyushu Institute of Technology)
AOP and observer pattern. Design pattern General reusable solution to a commonly occurring problem in software design Not a finished design that can be.
Extending the Field Access Pointcuts of AspectJ to Arrays ICS 2006 – Taipei, December 2006 Kung Chen and Chin-Hung Chien* National Chengchi University.
问题 Code scattering Blocks of duplicated code Blocks of complementary code, and different modules implementing complementary parts of the concern Code.
Comparison of Different AOP Approaches Presented by: Xiaojing Wang.
aspectj tools new and noteworthy Mik Kersten University of British Columbia Adrian Colyer IBM Hursley OOPSLA, October
R R R A Brief Introduction to Aspect-Oriented Programming.
Introduction to Aspect- Oriented Programming CS 3360 Gregor Kiczales, et. al. Getting started with AspectJ, CACM, 44(10):59-65, October Spring 2012.
CSC450 Software Engineering Devon M. Simmonds University of North Carolina, Wilmington 1.
AspectScope: An Outline Viewer for AspectJ Programs Michihiro Horie, Shigeru Chiba Tokyo Institute of Technology, Japan.
UBC software modularity group 1/14/02 UCSD1 Discussion with Kiczales at UBC Ontology of AOP Ontology is the study of what there is, an inventory of what.
AspectJ Development Tools Mik Kersten University of British Columbia October 28, 2003.
Features of AOP languages AOP languages have the following main elements: –a join point model (JPM) wrt base PL –a specification language for expressing.
An Interface Mechanism for Encapsulating Weaving in Class-based AOP
Aspect-Oriented Programming with the Eclipse AspectJ plug-in
Discussion with Gregor Kiczales at UBC
A Brief Introduction to Aspect-Oriented Programming
Aspect Oriented Programming
Aspect-oriented programming
Presentation transcript:

Aspect-Oriented Programming with AspectJ™ AspectJ.org Xerox PARC Erik Hilsdale Gregor Kiczales with Bill Griswold, Jim Hugunin, Wes Isberg, Mik Kersten partially funded by DARPA under contract F C0246 © Copyright Xerox Corporation, All Rights Reserved

2 good modularity XML parsing in org.apache.tomcat –red shows relevant lines of code –nicely fits in one box XML parsing

3 good modularity URL pattern matching in org.apache.tomcat –red shows relevant lines of code –nicely fits in two boxes (using inheritance) URL pattern matching

4 problems like… where is logging in org.apache.tomcat –red shows lines of code that handle logging –not in just one place –not even in a small number of places logging is not modularized

5 AspectJ™ is… a small and well-integrated extension to Java a general-purpose AO language –just as Java is a general-purpose OO language

6 expected benefits of using AOP good modularity, even for crosscutting concerns –less tangled code –more natural code –shorter code –easier maintenance and evolution easier to reason about, debug, change –more reusable library aspects plug and play aspects when appropriate

Part II Basic Mechanisms of AspectJ

8 basic mechanisms 1 overlay onto Java –dynamic join points “points in the execution” of Java programs 4 small additions to Java –pointcuts pick out join points and values at those points –primitive pointcuts –user-defined pointcuts –advice additional action to take at join points in a pointcut –intra-class declarations (aka “open classes”) –aspect a modular unit of crosscutting behavior –comprised of advice, intra-class declarations, field,constructor and method declarations

9 a simple figure editor FigureElement Display Point setX(int) setY(int) Line setP1(Point) setP2(Point) Figure * 2 makePoint(..) makeLine(..) moveBy(int, int) operations that move elements factory methods

10 a simple figure editor class Line implements FigureElement{ private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } void moveBy(int dx, int dy) {... } } class Point implements FigureElement { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; } void moveBy(int dx, int dy) {... } }

11 display updating collection of figure elements –that move periodically –must refresh the display as needed –complex collection –asynchronous events other examples –session liveness –value caching we will initially assume just a single display

12 a Figure a Line join points and returns or throws a method is called dispatch key points in dynamic call graph a method is called and returns or throws a method executes and returns or throws a method executes

13 join point terminology several kinds of join points –method & constructor call join points –method & constructor execution join points –field get & set join points –exception handler execution join points –static & dynamic initialization join points a Line dispatch method call join points method execution join points

14 join point terminology repeated calls result in new join points a Linea Figure all join points on this slide are within the control flow of this join point key points in dynamic call graph

15 call(void Line.setP1(Point)) primitive pointcuts a pointcut is like a predicate on join points that: –can match or not match any given join point and –optionally, can pull out some of the values at that join point “a means of identifying join points” matches if the join point is a method call with this signature

16 pointcut composition each time a Line receives a “void setP1(Point)” or “void setP2(Point)” method call or a “void Line.setP2(Point)” call a “void Line.setP1(Point)” call call(void Line.setP1(Point)) || call(void Line.setP2(Point)) pointcuts compose like predicates, using &&, || and !

17 user-defined pointcuts user-defined (aka named) pointcuts –can be used in the same way as primitive pointcuts defined use of the pointcut construct pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); nameparameters more on parameters and how pointcuts can expose values at join points in a few slides

18 pointcuts primitive pointcut designator, can be: - call, execution - this, target, args - get, set - within, withincode - handler - cflow, cflowbelow - initialization, staticinitialization pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); user-defined pointcut designator summary so far

19 pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { } after advice action to take after computation under join points a Line after advice runs “on the way back out”

20 a simple aspect an aspect defines a special class that can crosscut other classes DisplayUpdating v1 box means complete running code aspect DisplayUpdating { pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { Display.update(); }

21 without AspectJ what you would expect –update calls are tangled through the code –“what is going on” is less explicit class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(); } void setP2(Point p2) { this.p2 = p2; Display.update(); } DisplayUpdating v1

22 pointcuts can cut across multiple classes pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int));

23 pointcuts can use interface signatures pointcut move(): call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int));

24 a multi-class aspect DisplayUpdating v2 aspect DisplayUpdating { pointcut move(): call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int)); after() returning: move() { Display.update(); }

25 pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe) returning: move(fe) { } using values at join points pointcut can explicitly expose certain values advice can use value demonstrate first, explain in detail afterwards parameter mechanism being used

26 explaining parameters… in this, target & args pointcut designators –typed variable pulls corresponding value out of join points variable bound in user-defined pointcut designator –makes value accessible on pointcut pointcut parameters pointcut move(Line l): target(l) && (call(void Line.setP1(Point)) || call(void Line.setP2(Point))); after(Line line): move(line) { } typed variable of pointcut designators

27 explaining parameters… variable bound in advice variable in place of type name in pointcut designator –pulls corresponding value out of join points –makes value accessible within advice pointcut move(Line l): target(l) && (call(void Line.setP1(Point)) || call(void Line.setP2(Point))); after(Line line): move(line) { } typed variableadvice parameters of advice

28 explaining parameters… value is ‘pulled’ –right to left across ‘:’ left side : right side –from pointcut designators to user-defined pointcut designators –from pointcut to advice pointcut move(Line l): target(l) && (call(void Line.setP1(Point)) || call(void Line.setP2(Point))); after(Line line): move(line) { }

29 target target( ) any join point at which target object is an instance of type (or class) name target(Point) target(Line) target(FigureElement) “any join point” means it matches join points of all kinds method & constructor call join points method & constructor execution join points field get & set join points exception handler execution join points static & dynamic initialization join points primitive pointcut designator

30 an idiom for… target( ) && does not further restrict the join points does pick up the target object getting target object in a polymorphic pointcut pointcut move(FigureElement figElt): target(figElt) && (call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe): move(fe) { }

31 context & multiple classes DisplayUpdating v3 aspect DisplayUpdating { pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe): move(fe) { Display.update(fe); }

32 without AspectJ class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } class Point { private int x = 0, y= 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

33 class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(); } void setP2(Point p2) { this.p2 = p2; Display.update(); } class Point { private int x = 0, y= 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; } without AspectJ DisplayUpdating v1

34 class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(); } void setP2(Point p2) { this.p2 = p2; Display.update(); } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; Display.update(); } void setY(int y) { this.y = y; Display.update(); } without AspectJ DisplayUpdating v2

35 class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(this); } void setP2(Point p2) { this.p2 = p2; Display.update(this); } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; Display.update(this); } void setY(int y) { this.y = y; Display.update(this); } without AspectJ non-modular “display updating” –evolution is cumbersome –changes in all classes –have to track & change all callers DisplayUpdating v3

36 with AspectJ class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

37 with AspectJ aspect DisplayUpdating { pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { Display.update(); } DisplayUpdating v1 class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

38 with AspectJ DisplayUpdating v2 aspect DisplayUpdating { pointcut move(): call(void FigureElement.moveBy(int, int) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int)); after() returning: move() { Display.update(); } class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

39 modular “display updating” aspect –all changes in single aspect –evolution is modular aspect DisplayUpdating { pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe) returning: move(fe) { Display.update(fe); } with AspectJ DisplayUpdating v3 class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

40 advice is before before proceeding at join point after returning a value to join point after throwing a throwable to join point after returning to join point either way around on arrival at join point gets explicit control over when&if program proceeds additional action to take at join points

41 special static method proceed(arg1, arg2, …) available only in around advice means “run what would have run if this around advice had not been defined”

42 other primitive pointcuts this( ) within( ) withincode( ) any join point at which currently executing object is an instance of type or class name currently executing code is contained within class name currently executing code is specified method or constructor get(int Point.x) set(int Point.x) field reference or assignment join points

43 wildcarding in pointcuts target(Point) target(graphics.geom.Point) target(graphics.geom.*) any type in graphics.geom target(graphics..*) any type in any sub-package of graphics call(void Point.setX(int)) call(public * Point.*(..)) any public method on Point call(public * *(..)) any public method on any type call(void Point.getX()) call(void Point.getY()) call(void Point.get*()) call(void get*()) any getter call(Point.new(int, int)) call(new(..)) any constructor “*” is wild card “..” is multi-part wild card

44 special value thisJoinPoint. Signature getSignature() Object[] getArgs()... available in any advice thisJoinPoint is abbreviated to ‘tjp’ in these slides to save slide space * introspective subset of reflection consistent with Java reflective* access to the join point

45 using thisJoinPoint aspect PointCoordinateTracing { before(Point p, int newVal): set(int Point.*) && target(p) && args(newVal) { System.out.println("At " + tjp.getSignature() + " field is set to " + newVal + "."); } in highly polymorphic advice using thisJoinPoint makes it possible for advice to recover information about where it is running

46 other primitive pointcuts execution(void Point.setX(int)) method/constructor execution join points (actual running method) initialization(Point) object initialization join points staticinitialization(Point) class initialization join points (as the class is loaded)

47 other primitive pointcuts cflow(pointcut designator) all join points within the dynamic control flow of any join point in pointcut designator cflowbelow(pointcut designator) all join points within the dynamic control flow below any join point in pointcut designator

48 context sensitive aspects aspect DisplayUpdating { pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe): move(fe) { Display.update(fe); } what happens when moveBy is called on a Line?

49 context sensitive aspects aspect DisplayUpdating { pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); pointcut topLevelMove(FigureElement figElt): move(figElt) && !cflowbelow(move(FigureElement)); after(FigureElement fe) returning: topLevelMove(fe) { Display.update(fe); } DisplayUpdating v4 the non-reentrant calls idiom: ptc && !cflowbelow(ptc)

50 intra-type declarations 1 aspect DisplayUpdating { private Display FigureElement.display; static void setDisplay(FigureElement fe, Display d) { fe.display = d; } pointcut move(FigureElement figElt): ; after(FigureElement fe): move(fe) { fe.display.update(fe); } DisplayUpdating v5 adds members to target interface/class 1. recently termed “open classes”

51 field/getter/setter idiom aspect DisplayUpdating { private Display FigureElement.display; static void setDisplay(FigureElement fe, Display d) { fe.display = d; } pointcut move(FigureElement figElt): ; after(FigureElement fe): move(fe) { fe.display.update(fe); } private with respect to enclosing aspect declaration the display field –is a field of FigureElement, but –belongs to DisplayUpdating aspect –so DisplayUpdating aspect should provide getter/setter

52 inheritance & specialization pointcuts can have additional advice –aspect with concrete pointcut perhaps no advice on the pointcut –in figure editor move() can have advice from multiple aspects –module can expose certain well-defined pointcuts abstract pointcuts can be specialized –aspect with abstract pointcut concrete advice on the abstract pointcut

53 summary dispatch advice before after around declare error intra-type decls pointcuts - primitive- call execution handler get set initialization this target args within withincode cflow cflowbelow - user-defined- pointcut declaration abstract overriding join points method & constructor call execution field get set exception handler execution initialization aspects crosscutting type pertarget perthis percflow percflowbelow