Aspectual Components Part 2 April 5, 1999. Composition example Use three aspects simultaneously with three classes. Three aspects: –ShowReadWriteAccess.

Slides:



Advertisements
Similar presentations
Object-Oriented Programming Python. OO Paradigm - Review Three Characteristics of OO Languages –Inheritance It isn’t necessary to build every class from.
Advertisements

Programming Paradigms Introduction. 6/15/2005 Copyright 2005, by the authors of these slides, and Ateneo de Manila University. All rights reserved. L1:
Inheritance Inheritance Reserved word protected Reserved word super
Intro to OOP with Java, C. Thomas Wu Inheritance and Polymorphism
Object Oriented Programming Chapter 7 Programming Languages by Ravi Sethi.
Java Generics.
Inheritance. Extending Classes It’s possible to create a class by using another as a starting point  i.e. Start with the original class then add methods,
Fall 2007CS 2251 Inheritance and Class Hierarchies Chapter 3.
OOP in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
1 Chapter 6 Inheritance, Interfaces, and Abstract Classes.
1 Evan Korth New York University Inheritance and Polymorphism Professor Evan Korth New York University.
1 Introduction to CS Agenda Syllabus Schedule Lecture: the management of complexity.
1 Evan Korth New York University Inheritance and Polymorphism Professor Evan Korth New York University.
OOP in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Inheritance. © 2004 Pearson Addison-Wesley. All rights reserved 8-2 Inheritance Inheritance is a fundamental object-oriented design technique used to.
16-Aug-15 Air Force Institute of Technology Electrical and Computer Engineering Object-Oriented Programming in Java Topic : Interfaces, Copying/Cloning,
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Lecture 2 COM 3362, April 5, Composition example Use three aspects simultaneously with three classes. Three aspects: –ShowReadWriteAccess –InstanceLogging.
Abstract Data Types (ADTs) and data structures: terminology and definitions A type is a collection of values. For example, the boolean type consists of.
220 FINAL TEST REVIEW SESSION Omar Abdelwahab. INHERITANCE AND POLYMORPHISM Suppose you have a class FunClass with public methods show, tell, and smile.
Lecture Objectives To understand how Java implements a stack To learn how to implement a stack using an underlying array or linked list Implement a simple.
Introduction to Object Oriented Programming. Object Oriented Programming Technique used to develop programs revolving around the real world entities In.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
Chapter 7 Stacks. © 2004 Pearson Addison-Wesley. All rights reserved 7-2 The Abstract Data Type: Developing an ADT During the Design of a Solution Specifications.
Inheritance Extending Class Functionality. Polymorphism Review Earlier in the course, we examined the topic of polymorphism. Many times in coding, we.
Chapter 2 Introducing Interfaces Summary prepared by Kirk Scott.
Inheritance - Polymorphism ITI 1121 Nour El Kadri.
1 CSC/ECE 517 Fall 2010 Lec. 3 Overview of Eclipse Lectures Lecture 2 “Lecture 0” Lecture 3 1.Overview 2.Installing and Running 3.Building and Running.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Java Software Solutions Foundations of Program Design Sixth Edition by Lewis.
Programming With Java ICS201 University Of Ha’il1 Chapter 7 Inheritance.
Inheritance CSI 1101 Nour El Kadri. OOP  We have seen that object-oriented programming (OOP) helps organizing and maintaining large software systems.
Application development with Java Lecture 21. Inheritance Subclasses Overriding Object class.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Introduction to Object-Oriented Programming Lesson 2.
Interfaces and Inner Classes
Lecture Objectives  To understand how Java implements a stack  To learn how to implement a stack using an underlying array or linked list  Implement.
Interfaces F What is an Interface? F Creating an Interface F Implementing an Interface F What is Marker Interface?
DJ: traversal-visitor-style programming in Java Josh Marshall/ Doug Orleans Want to add more on traversal through collections and Aspectual Components.
COM S 228 Introduction to Data Structures Instructor: Ying Cai Department of Computer Science Iowa State University Office: Atanasoff.
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Inheritance and Class Hierarchies Chapter 3. Chapter Objectives  To understand inheritance and how it facilitates code reuse  To understand how Java.
CSSE501 Object-Oriented Development. Chapter 10: Subclasses and Subtypes  In this chapter we will explore the relationships between the two concepts.
AOP/cross-cutting What is an aspect?. An aspect is a modular unit that cross-cuts other modular units. What means cross-cutting? Apply AOP to AOP. Tease.
Variations on Inheritance Object-Oriented Programming Spring
OOP in Java : © W. Milner 2005 : Slide 1 Java and OOP Part 3 – Extending classes.
R-customizers Goal: define relation between graph and its customizers, study domains of adaptive programs, merging of interface class graphs.
Author: DoanNX Time: 45’.  OOP concepts  OOP in Java.
POLYMORPHISM Chapter 6. Chapter Polymorphism  Polymorphism concept  Abstract classes and methods  Method overriding  Concrete sub classes and.
OOP Basics Classes & Methods (c) IDMS/SQL News
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Outline Creating Subclasses Overriding Methods Class Hierarchies Inheritance.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
1 DemoBasic_v3, DemoBasic_v4 JButton JLabel. 2 Registering an ActionListener Register by invoking the following from within constructor DemoBasicFrame.
Features of AOP languages AOP languages have the following main elements: –a join point model (JPM) wrt base PL –a specification language for expressing.
Java Programming: Guided Learning with Early Objects Chapter 9 Inheritance and Polymorphism.
Modern Programming Tools And Techniques-I
Sixth Lecture ArrayList Abstract Class and Interface
Inheritance ITI1121 Nour El Kadri.
Lecture 12 Inheritance.
7.1 What Is An Object Object-oriented program - Description or simulation of application Object-oriented programming is done by adopting or extending an.
Interface.
Methods Attributes Method Modifiers ‘static’
Inheritance "Question: What is the object oriented way of getting rich? Answer: Inheritance.“ “Inheritance is new code that reuses old code. Polymorphism.
CS 302 Week 11 Jim Williams, PhD.
Subroutines Idea: useful code can be saved and re-used, with different data values Example: Our function to find the largest element of an array might.
Inheritance Inheritance is a fundamental Object Oriented concept
APPCs revisited 2/25/2019 APPCs revisited.
CIS 199 Final Review.
Nested Collaborations
Jim Fawcett CSE687 – Object Oriented Design Spring 2014
Presentation transcript:

Aspectual Components Part 2 April 5, 1999

Composition example Use three aspects simultaneously with three classes. Three aspects: –ShowReadWriteAccess –InstanceLogging –AutoReset Three classes: Point, Line, Rectangle

Shapes (Point, Line, Rectangle)AutoReset ShowReadWriteAccess InstanceLogging Point Line Rectangle Weaved Code

Inheritance between components component ShowReadWriteAccess extends ShowReadAccess { participant DataToAccess { expect void writeOp(Object[] args); replace void writeOp(Object[] args){ System.out.println( "Write access on " + this.toString()); expected(args);}} }

InstanceLogging component (first part) component InstanceLogging { participant DataToLog { expect public DataToLog(Object[] args); replace public DataToLog(Object[] args) { expected(args); long time = System.currentTimeMillis(); try { String class = this.class.getName() + " "; logObject.writeBytes(""New instance of " + class + at "" " + time + "" " \n"); } catch (IOException e) {System.out.println(e.toString());} }

InstanceLogging component (second part) protected DataOutputStream logObject = null; public init() { try {logObject = new DataOutputStream( new FileOutputStream(log));} catch (IOException e) {System.out.println(e.toString());} }

AutoReset component component AutoReset { participant DataToReset { expect void setOp(Object[] args); expect void reset(); protected int count = 0; replace void setOp(Object[] args) { if ( ++count >= 100 ) { expected(args); count = 0; reset(); }} }

Composition of components connector CompositionConn1 { {Line, Point} is ShowReadWriteAccess.DataToAccess with { readOp = get*; writeOp = set*;}; Point is AutoReset.DataToReset with { setOp = set*; void reset() { x = 0; y = 0; } }; {Line, Point, Rectangle} is InstanceLogging.DataToLog;}

ShapesAutoReset ShowReadWriteAccesses InstanceLogging Point Line Rectangle Weaved Code

Composition of components Connector graph CompositionConn1 Line, Point, Rectangle ShowReadWriteAccess.DataToAccess * * AutoReset.DataToReset * InstanceLogging.DataToLog * * *

Modified composition connector CompositionConn2 extends CompositionConn1 { Line is AutoReset.DataToReset with { setOp = set*; void reset() {init();} }; }

Composition of components Connector graph CompositionConn1 Line, Point, Rectangle ShowReadWriteAccess.DataToAccess * * AutoReset.DataToReset * InstanceLogging.DataToLog * * * Connector graph CompositionConn2 Line, Point, Rectangle ShowReadWriteAccess.DataToAccess * * AutoReset.DataToReset * * InstanceLogging.DataToLog * * *

Modify existing connection statements connector CompositionConn3 extends CompositionConn1 { Point is AutoReset.DataToReset with { { setOp = set; void reset() { x = 0; y = 0; }} { setOp = setX; void reset() { x = 0;}} { setOp = setY; void reset() { y = 0;}} }; }

Composition of components Connector graph CompositionConn3 Line, Point, Rectangle ShowReadWriteAccess.DataToAccess * * AutoReset.DataToReset *** InstanceLogging.DataToLog * * * overridden: ***

New example: Feature-oriented Programming Dependent aspects Order of deployment is relevant

DataWithCounter component pairwise interaction Data/Counter component DataWithCounter { private participant Counter { int i=0; void reset(){i=0;}; void inc(){…}; void dec(){…};} participant DataStructure { protected Counter counter; expect void initCounter(); expect void make_empty(); expect void push(Object a); expect void pop(); replace void make_empty(){counter.reset();expected();} replace void push(Object a){counter.inc(); expected(a);} replace void pop() {counter.dec();expected();} }

DataWithLock Component pairwise interaction Data/Lock component DataWithLock { participant Data { Lock lock; expect void initLock(); expect AnyType method_to_wrap(Object[] args); replace AnyType method_to_wrap(Object[] args) { if (lock.is_unlocked()) { lock.lock(); expected(Object[] args); lock.unlock(); }}} private participant Lock {boolean l = true; void lock(){…}; void unlock(){…}; boolean is_unlocked(){return l};}

StackImpl QueueImpl DataWithCounter DataWithLock Counter Lock

First connector connector addCounter&Lock { StackImpl is DataWithCounter.DataStructure with { void initCounter() {counter = new Counter();} void push(Object obj) {push(obj));} // use name map instead Object top() {return top();}... } is DataWithLock.Data with { method_to_wrap = {pop, push, top, make_empty, initCounter}; }; QueueImpl is DataWithCounter.DataStructure with {... } is DataWithLock.Data with {... }; }

DataWithCounter DataWithLock DataWithCounter&Lock

Create composed aspects prior to deployment component DataWithCounterAndLock { participant Data = DataWithCounter.DataStructure is DataWithLock.Data with { method-to-wrap = {make_empty, pop, top, push}}; }

Second connector: Deploy composed component connector addCounter&Lock { StackImpl is DataWithCounterAndLock.Data with { void make_empty() {empty();} void initCounter() { counter = new Counter();} void push(Object obj) {push(obj);}... }; QueueImpl is DataWithCounterAndLock.Data with {...}; }

Defining New Behavior: The Publisher- Subscriber Aspect an aspect can be multiply deployed with the same application, each deployment with its own mappings.

Publisher component PublisherSubscriberProtocol { participant Publisher { expect void changeOp(Object[] args); protected Vector subscribers = new Vector(); public void attach(Subscriber subsc) { subscribers.addElement(subsc);} public void detach(Subscriber subsc) { subscribers.removeElement(subsc);} replace void changeOp() { expected(); for (int i = 0; i < subscribers.size(); i++) {((Subscriber)subscribers.elementAt(i)). newUpdate(this);}}

Subscriber participant Subscriber { expect void subUpdate(Publisher publ); protected Publisher publ; public void newUpdate(Publisher aPubl) { publ = aPubl; subUpdate(publ);} }

Class for deployment class ChangePrinter { void public printR() { System.out.println("Printer: " + this.toString() + " read access has occurred..." + \n); } void public printW() { System.out.println("Printer: " + this.toString() + " write access has occurred..." + \n); } void public notifyChange() { System.out.println("CHANGE..."); }

Deployment 1 connector PubSubConn1 { Point is Publisher with { changeOp = {set*, get*};} ChangePrinter is Subscriber with { void subUpdate(Publisher publ) { notifyChange(); System.out.println(”on Point object " + ((Point) publ).toString()); }

Deployment 2 connector PubSubConn2 { TicTacToe is Publisher with { changeOp = {startGame, newPlayer, putMark, endGame}}; {BoardDisplay, StatusDisplay} is Subscriber with { void subUpdate(Publisher publ) { setGame((Game) publ); repaint(); } }; }

Deployment/write connector PubSubConn3 { Point is Publisher with { changeOp = set*;} ChangePrinter is Subscriber with { void subUpdate(Publisher publ) { printW(); System.out.println("on point object " + ((Point) publ).toString()); }

Deployment/read connector PubSubConn4 { Point is Publisher with { changeOp = get*;} ChangePrinter is Subscriber with { void subUpdate(Publisher publ) { printR(); System.out.println("on point object " + ((Point) publ).toString()); }

Overlap between connectors The sets of operations of Point that are mapped to different notification operations of the subscriber participant need not be disjoint. For instance, we may want to distinguish between set operations that affect the x-coordinate, respectively, the y- coordinate of a point. The set(int, int), however, will then fall in both categories. This is expressed by the connectors PubSubConn3_1 and PubSubConn3_2 below.

Deployment/write connector PubSubConn3_1 { Point is Publisher with { changeOp = {set,setX};} ChangePrinter is Subscriber with { void subUpdate(Publisher publ) { printW(); System.out.println("on point object " + ((Point) publ).toString()); }

Deployment/write connector PubSubConn3_2 { Point is Publisher with { changeOp = {set, setY};} ChangePrinter is Subscriber with { void subUpdate(Publisher publ) { printW(); System.out.println("on point object " + ((Point) publ).toString()); }

Mapping Participant Graphs Is the deployment of a component giving the intended result? Example: Three participants: A, B, C –A has 0..* B; B has 1..* C. –A::f(int x1){for each b: f(x1);} –B::f(int x1){for each c: f(x);} // x a data member local to B –C::f(int x1){print(“at C: number at previous B”); print(x1);}

Expected output at C: number at previous B 78 at C: number at previous B 8

Mapping A C B A B C 1..* 0..*

Refinement This property must hold between a PG and a corresponding CG or another PG. The intent of the refinement relation is to ensure that the behavior in the component will be properly instantiated at the place of use without ``surprising'' behavior.

A A BB C C D D E E F F G1G1 G2G2 G 1 refinement G 2 refinement: connectivity of G 2 is in pure form in G 1 Allows extra connectivity.

A A BB C C D D E E F F G1G1 G2G2 G 1 refinement G 2 refinement: connectivity of G 2 is in pure form in G 1

A A BB C C D D E E F F G1G1 G2G2 G 1 compatible G 2 Compatible: connectivity of G 2 is in G 1

A A BB C C D D E E F F G1G1 G2G2 G 1 strong refinement G 2 refinement: connectivity of G 2 is in pure form in G 1 and G 1 contains no new connections in terms of nodes of G 2

Key concepts: refinement Let G1=(V1,E1) and G2=(V2,E2) be directed graphs with V2 a subset of V1. Graph G 1 is a refinement of G 2 if for all u,v in V 2 we have that (u,v) in E 2 implies that there exists a path in G 1 between u and v which does not use in its interior a node in V 2. Polynomial time.

Refinement For each edge in G2 there must be a corresponding pure path in G1. Pure path = in interior no nodes of G2. Refinement = strong refinement with “if and only if” replaced by “implies”.

A A BB C C D D E E F F G1G1 G2G2 G 1 refinement G 2 Implementation: create strategy constraint map: bypassing all nodes

A A B B G1G1 G2G2 not G 1 refinement G 2 C C Refinement means: no surprises

A A B B G1G1 G2G2 G 1 refinement G 2 C C Refinement means: no surprises X

A B G2G2 G1G1 not G 1 refinement G 2 C Refinement means: no surprises A B C

Alternative definition a graph G is a refinement of a graph S, if S is a connected subgraph of the pure transitive closure of G with respect to the node set of S.

Pure transitive closure The pure transitive closure of G=(V,E) with respect to a subset W of V is the graph G*=(V,E*), where E*={(i,j): there is a W- pure path from vertex i to vertex j in G}. A W-pure path from i to j is a path where i and j are in W and none of the inner nodes of the path are in W.

Implementation issues Translate to AspectJ: requires source code access. What if aspectual components only in binary? Want separate compilation of application and aspectual components.

Interfaces between components and application Usage interface –expected in order to be used by participants Modification interface –expected in order to be replaced by the aspect

Writing components directly in Java Benefit: no new language to learn

Participants as abstract classes class AutoReset { abstract class DataToReset { abstract void reset(); protected int count = 0; void replaced_setOp(Object thisObject, Class thisClass, Method expected_setOp, Object[] args) { if ( ++count >= 100 ) { expected_setOp.invoke(thisObject, args); count = 0; reset(); }

AutoReset component component AutoReset { participant DataToReset { expect void setOp(Object[] args); expect void reset(); protected int count = 0; replace void setOp(Object[] args) { if ( ++count >= 100 ) { expected(args); count = 0; reset(); }} }

What about connectors in Java? Translation to Java not straight-forward

Approach Methods in –usage interface: abstract methods –modification interface: x() translated to replaced_x(). Expected implementation of x() will be a parameter to replaced_x(). x=setOp void replaced_setOp(Object thisObject, Class thisClass, Method expected_setOp, Object[] args) { if ( ++count >= 100 ) { expected_setOp.invoke(thisObject, args);

Approach Question: Why is thisClass used as an argument? Is not used in this example. void replaced_setOp(Object thisObject, Class thisClass, Method expected_setOp, Object[] args) { if ( ++count >= 100 ) { expected_setOp.invoke(thisObject, args);

Binary Adaptation of Application Classes Application classes are turned into event publishers by adding a field that stores a set of subscribers (from connectors). Any application operation op that is mapped to expected operation in modification interface: renamed to expected_op new implementation of op : invokes notify on subscribers

Pseudo-code simulating binary adaptation class Point { public static java.util.Vector aspectSubscribers; // added variable public void addSubscriber(AspectSubscriber sub) { // added operation aspectSubscribers.addElement((Object) sub);} private int x = 0; private int y = 0;

Pseudo-code simulating binary adaptation void expected_set(int x, int y) { // renamed this.x = x; this.y = y;} void set(int x, int y) { // reimplemented Object[] args = {(Object) new Integer(x), (Object) new Integer(y)}; Class[] argTypes = {Integer.TYPE, Integer.TYPE}; Method expected_set = thisClass.getMethod("expected_set", argTypes); Enumeration subscribers = aspectSubscribers.elements(); while (subscribers.hasElements()) { Object sub = subscribers.next(); sub.notify(this, this.getClass(), expected_set, args);}} …}

Generating Connector Classes Generate a class for each connector Example: CompositionConn3

Recall: CompositionConn1 connector CompositionConn1 { {Line, Point} is ShowReadWriteAccess.DataToAccess with { readOp = get*; writeOp = set*;}; Point is AutoReset.DataToReset with { setOp = set*; void reset() { x = 0; y = 0; } }; {Line, Point, Rectangle} is InstanceLogging.DataToLog;}

Recall: CompositionConn3 connector CompositionConn3 extends CompositionConn1 { Point is AutoReset.DataToReset with { { setOp = set; void reset() { x = 0; y = 0; }} { setOp = setX; void reset() { x = 0;}} { setOp = setY; void reset() { y = 0;}} }; }

Connector Class code interface AspectSubscriber { void notify(Object thisObject, Class thisClass, Method expected_meth, Object[] args);} interface Evaluable { void eval(Object thisObject, Class thisClass, Method expected_meth, Object[] args);}

Connector class generated class CompositionConn3 implements AspectSubscriber { public static singleInstance = new CompositionConn3(); java.util.Hashtable mappings = new java.util.Hashtable(); abstract class Point_DataToReset_setOp extends AutoReset.DataToReset implements Evaluable { private Point host; public void eval(Object thisObject, Class thisClass, Method expected_meth, Object[] args) { host = (Point) thisObject; replaced_setOp(thisObject, thisClass, expected_meth, args); }

public CompositionConn3() { Object[] argTypes = {Integer.TYPE, Integer.TYPE}; Method expected_set = Point.getMethod("expected_set", argTypes); argTypes = {Integer.TYPE}; Method expected_setX = Point.getMethod("expected_setX", argTypes); Method expected_setY = Point.getMethod("expected_setY", argTypes); mappings.put((Object) expected_set, (Object) new Point_DataToReset_setOp() { void reset() {host.expected_set(0, 0);}}); mappings.put((Object) expected_setX, (Object) new Point_DataToReset_setOp() { void reset() {host.expected_setX(0);}}); mappings.put((Object) expected_setY, (Object) (Object) new Point_DataToReset_setOp() { void reset() {host.expected_setY(0);}}); Point.addSubscriber(this);}

ComponentPackage Component Participant expectedOp() Op(){expectedOp(); getHost()} getHost() ConnectorPackage HostPackage Host // to play role of participant toModify(){} // to be mapped to Op() Johan’s solution 1 based on Mira’s inner class solution. Modification interface is represented also by abstract class, not by Method argument as proposed by Mira. “outer.super.toModify()” simulated with aux() is not elegant MyHost toModify(){part.Op();}// override aux(){super.toModify()} part ParticipantAnonymousExtended expectedOp(){aux()} getHost(){MyHost.this} main(){new MyHost().toModify() }

ComponentPackage Component Participant expectedOp() Op(){expectedOp(); getHost()} getHost() ConnectorPackage MyHost toModify(){part.Op();} aux(){super.toModify()} part HostPackage ParticipantAnonymousExtended expectedOp(){aux()} getHost(){MyHost.this} main(){new MyHost().toModify() } Host toModify(){} Does it work with multiple participants? With multiple hosts? Looks like. Problem: when we have a Host-object and want to get modified behavior, need to create a MyHost object.

ComponentPackage Component Participant expectedOp() Op(){expectedOp(); getHost()} getHost() ConnectorPackage More complex connector: one host but multiple methods are modified. Creates multiple inheritance!? Is this why Mira’s implementation is more complex? part2 ParticipantAnonymousExtended expectedOp(){aux2()} getHost(){MyHost.this} main(){new MyHost().toModify2()} toModify2(){part2.Op();}//override aux2(){super.toModify2()} ParticipantAnonymousExtended expectedOp(){aux1()} getHost(){MyHost.this} main(){new MyHost().toModify1()} MyHost toModify1(){part1.Op();}//overrride aux1(){super.toModify1()} part1