1. Modeling Attributes in the Object Model

Previously we presented how to model classes and objects. Classes define attributes and operations. The purpose of this chapter is to describe attributes in the object model. The major topics are:

What is an attribute?

How to identify attributes.

How to show attributes on a class diagram.

How to update a class specification with attribute information.

How to generate C++ with a CASE tool script and how to understand the C++ source code.

The purpose of this section is to define an attribute and present to how to identify attributes, show attributes on a class diagram, describe attributes in a class specification, and generate C++ code for attributes.

  1. What is an Attribute?

An attribute is a characteristic or property of an object. An attribute is typically an atomic literal, such as an integer, float, character, etc. An attribute may be set of literals, such as a string of characters. For example, an attribute of a car is gasQuantity which is a float. An attribute is specified with the attribute name and attribute class. The table below shows some sample attributes.

Table Sample attributes.

----------------------------------------------------------------------------------------------------------

Class Attribute Name Attribute Data Type/Class

-----------------------------------------------------------------------------------------------------------

Car gasQuantity float

Motor rpm integer

Passenger name string

Customer creditOK boolean

Product description string

Order quantity integer

----------------------------------------------------------------------------------------------------------

  1. Identifying Attributes

To identify attributes ask the following questions for each class. What are the characteristics or properties of objects of the class? Peter Coad and Ed Yourdon suggest that the developer consider himself as an object of the class [Coad-91]. Ask the questions: As an object of the class, how am I described? As an object of the class, what do I need to know? As an object of the class, what information do I remember?

  1. Showing Attributes on the Class Diagram

Attributes are shown on class diagrams. In the Rumbaugh OMT and the Coad-Yourdon class diagram attributes are shown in the middle section of the class symbol. Additionally, you may show the attribute class/type and initial value on the class diagram [Rumbaugh-91].

Figure Class diagram with attributes in the middle section.
  1. Creating the Attribute Specification and Reports

The attribute specification lists important text information for each attribute. Its purpose is to state adequate information to document and to code each attribute. We will first present a CASE tool specification input form, define the specification information, and present a sample report. The steps to create the attribute specification using a CASE tool are listed below.

>> Run the CASE tool from Windows

>> Select "File - Open" e.g. c:\car.omt

>> Double click on a class, e.g. Car

>> Double click on an attribute in the class, e.g. gasQuantity to bring up the attribute specification form

>> Enter attribute information, e.g. description, access, etc.

>> Select "Generate - Generate Class Report and enter the report script, e.g. RPTATTR.SCT or TABATTR.SCT

>> Select "File - Edit File" and enter the report file name to view the report

  1. Attribute Specification Input Form

The figure below is a sample attribute form in a CASE tool for the gasQuantity attribute.

Figure sample attribute form in a CASE tool.
  1. Attribute Specification Information

A complete specification of an attribute includes the following information for the car class attribute gasQuantity. These specification items are defined in the next paragraph. Some information may not be required of each attribute. Some information is provided that may be placed in a user field in the CASE specification form above.

- Attribute name provides the name of the attribute.

- Attribute type provides the attribute type or class. It is important for code generation to state the attribute type or class.

- Description provides other information about the attribute.

- Access (visibility) states the visibility of the attribute, e.g. public, protected, private, or implementation.

- Initial value provides the initial value of the attribute. This is important for code generation to set the initial value of the attribute. For code generation ensure the initial value is filled-in.

- Minimum value provides the minimum value of the attribute.

- Maximum value provides the maximum value of the attribute.

- Constraints (limits or restrictions) provides rules, limits, or restrictions of the attribute. A constraint is a rule or limitation on a attribute value, e.g. worker_salary must be less than the boss_salary.

- User1, User2, and User3 provide user defined fields for comments or other information.

There are Static, Constant, and Index check boxes to designate a static, constant, or index attribute. If neither check box is checked then the attribute is a normal attribute (not static and not constant and not index).

The following is additional information that may be collected for each attribute.

- Class name provides the name of the class.

- Form (object/class) states whether the attribute is an object attribute or class attribute.

- Key (Yes/No) states if the attribute is a lookup key.

- Qualifier (Yes/No) states if the attribute is qualifier that distinguishes among the set of objects at the

"many" side of an association.

- Derived (Yes/No) states if the attribute is a derived attribute that is computed from other attributes.

- Implementation states language specific information, e.g. C++ friend, const, static.

- Size states the estimated amount of memory consumed.

Attribute access is the degree that another object can use or manipulate an attribute value. The forms of access in this book are based upon C++ access definitions. They are applicable to several object-oriented languages. Private access is the most restrictive access. With private access an object cannot directly manipulate an attribute value. For example, a user object cannot directly access the gasQuantity attribute a car object. A user object cannot directly set or get a car's gasQuantity. Protected access is a less restrictive access than private access. With protected access an object cannot access a protected attribute. However, protected access has special rules that permit access to a protected attribute from a subclass. Public access is the least restrictive form of access. With public access an object can use or manipulate a public data member or function member. Attributes are rarely defined with public access.

Attribute constraints are limits or restrictions on an attribute value. It is a rule for correctness. A very simple constraint is that an attribute value must be within a minimum and maximum value. For example, a bank account balance must always be greater than zero. A constraint can show a relationship between two objects. For example, a football player's salary must be within the football team's salary cap.

Most attributes are object attributes. As an object attribute, each object of a class may have a unique value for the attribute. For example, the object car1 has a unique value of 14.0 for the gasQuantity attribute. Some attributes are class attributes. As a class attribute, the attribute value is applicable to all objects of the class. The attribute value is shared by all objects of the class. For example, maxNumberPassengers could be a class attribute because all objects of the car class would have the same attribute value of six. Another example of a class attribute is the number of cars created in the car class. The guideline is to create an object attribute if you can answer yes to the following question: Can the attribute have a unique value for each object? Create a class attribute if you answer yes to the following question: Does the attribute value apply to all objects of the class and is the attribute value shared by all objects of the class?

  1. Attribute Specification CASE Tool Script Variables

To access the attribute specification information, you need to know the script variable for each piece of information in the attribute specification input form. The following are sample script variables from the attribute specification in a CASE tool. A brief description states what occurs when the script variable appears in a script. Attribute variables access attribute information. Since there are multiple attributes for each class, these variables are used within the [] (Repeat Operator), e.g. [ATTRIBUTE_NAME, ] prints out all the attributes for each class.

ATTRIBUTE_NAME Prints attribute name

ATTRIBUTE_TYPE Prints attribute type

ATTRIBUTE_INITIAL_VALUE Prints attribute initial value

ATTRIBUTE_ACCESS Prints attribute visibility

ATTRIBUTE_MAX_VALUE Prints attribute maximum value

ATTRIBUTE_MIN_VALUE Prints attribute minimum value

ATTRIBUTE_CONSTRAINT Prints attribute constraint or rule

ATTRIBUTE_DESCRIPTION Prints attribute information (remarks)

ATTRIBUTE_USER1 Prints user supplied information

ATTRIBUTE_USER2 Prints user supplied information

ATTRIBUTE_USER3 Prints user supplied information

CPP_ATTRIBUTE_STATIC Prints static if the attribute is static

CPP_ATTRIBUTE_CONSTANT Prints const if the attribute is const

  1. Attribute Specification Report and Script

The following is a sample specification report for the attribute gasQuantity.

Attribute Specification Report

Attribute Name: gasQuantity

Attribute Type/Class: float

Attribute Initial Value: 0.0

Attribute Access: private

Attribute Maximum Value: 99.9

Attribute Minimum Value: 0.0

Attribute Constraint: must be within minimum and maximum value

Attribute Description: gasQuantity is the amount of available gasoline in the car

Attribute User1: N/A

Attribute User2: N/A

Attribute User3: N/A

Figure Attribute Specification Report

The abbreviated script (RPTATTR.SCT) to generate this report from the class diagram is shown below.

Script to Generate the Attribute Specification Report

[Attribute Name: ATTRIBUTE_NAME

Attribute Type/Class: ATTRIBUTE_TYPE

Attribute Initial Value: ATTRIBUTE_INITIAL_VALUE

Attribute Access: ATTRIBUTE_ACCESS

Attribute Maximum Value: ATTRIBUTE_MAX_VALUE

Attribute Minimum Value: ATTRIBUTE_MIN_VALUE

Attribute Constraint: ATTRIBUTE_CONSTRAINT

Attribute Description: ATTRIBUTE_DESCRIPTION

Attribute User1: ATTRIBUTE_USER1

Attribute User2: ATTRIBUTE_USER2

Attribute User3: ATTRIBUTE_USER3 ]

The following is sample additional information on the attribute gasQuantity. This information may be placed in a user field.

- Form of attribute - object attribute

- Key - no,

- Qualifier - no,

- Derived - no,

- Implementation - C++ private data member,

- Size - small,

  1. Attribute Table and Script

The following is a sample attribute table for all attributes in the Car Simulation System. It lists key information for all attributes from the class diagram in the Car Simulation System.

Attribute Table

Class NameAttribute Name Attribute TypeInitial Value Description
Vehicleweightfloat 0The weight in pounds for the vehicle.
CargasQuantityfloat 0The amount of gasoline in a car.
Carspeedint 0The velocity of a car.
CartotalCarsBuiltint 0The total number of cars built.
CarmaxNumberOfTiresint 4The maximum number of tires on a car.
CarmaxNumberOfPassengers int4The maximum number of passengers in a car.
PassengerseatBeltStatus int0The status of the seat belt - fastened or unfastened.
CellularPhonephoneNumber long0The phone number of person being called.
Tirepressureint 0The pressure of a tire in PSI (pounds per square inch).
Motorrpmint 0The revolutions per minute of a motor.

The abbreviated script (TABATTR.SCT) to generate this table is shown below.

Script to Generate an Attribute Table

SCRIPT_NOREPEAT_HEADER_BEGIN

Class Name, Attribute Name, Attribute Type, Initial Value, Description SCRIPT_NOREPEAT_HEADER_END

[CLASS_NAME, ATTRIBUTE_NAME, ATTRIBUTE_TYPE, ATTRIBUTE_INITIAL_VALUE, ATTRIBUTE_DESCRIPTION]

  1. Coding Attributes in C++

Once the class diagram and the attribute forms have been completed, then C++ code can be automatically generated with a CASE tool. We are briefly presenting how to code attributes in C++ to be able to understand and modify the generated C++.

Attributes are coded in C++ as data members. The purpose of this section is to present the how to code of C++ data members for object attributes and static data members for class attributes. An example of C++ code generated from a CASE tool is presented. The table below is a comparison of the O-O modeling terms and C++ terms for attributes.

Table Comparison of O-O modeling and C++ terms for attributes.

-----------------------------------------------------------------------------

O-O Modeling C++

-----------------------------------------------------------------------------

object attribute data member

class attribute static data member

-----------------------------------------------------------------------------

There are object attributes and class attributes. An object attribute holds a value that is applicable for a specific object. To code an object attribute in C++ declare a data member in the following form: <class or type name> <data member name>. An example is as follows: float gasQuantity.

A data member may be declared as an automatic object or a dynamic object. A data member as an automatic object has the form of <class or type name> <object name> as shown in the example above. A data member as a dynamic object has the form of <class or type name> *<object name>. An example is as follows: char * name.

A class attribute holds a value that is shared by all objects of the class. To code a class attribute, create a C++ static object. Memory is allocated as soon as the object is created. The object remains for the duration of the program. The following is the form for a C++ static data member declaration: static <class or type name> <object name>. An example follows: static int maxNumberPassengers. A static data member must be initialized outside the class declaration.

Based upon the class diagram in the figure below, the generated C++ code is presented with constructors and destructors in the listing below.

Figure Class diagram showing attributes

Listing Generated C++ source code.

C++ Class Declaration - Header File

--------------------Car Class Declaration - car.h ------------------

class Car {

int speed; //private data member

float gasQuantity; //private data member

public:

Car(){speed = 0; gasQuantity = 0.0;} //constructor updated

//to initialize data members

~Car(){} //destructor

};

-----------------Motor Class Declaration - motor.h -----------------

class Motor {

int rpm; //private data member

int displacement; //private data member

public:

Motor(){rpm = 0; displacement = 0;}//constructor updated

//to initialize data members

~Motor(){} //destructor

};

-------------Passenger Class Declaration - passenge.h --------------

#include <strng.h> //include file for String

enum boolean {OK, NotOK}; //enumerated data type for

//for seatBeltStatus

class Passenger {

String name; //private data member

boolean seatBeltStatus; //private data member

public:

Passenger(){name = ""; seatBeltStatus = OK;} // constructor

// updated to initialize data members

~Passenger(){} // destructor

};

The CASE tool provided all the C++ source code in the listing above except the enum boolean {OK, NotOK} statement.

  1. Minimum C++ Code for Data Members

To code attributes in C++, you should declare the class, declare the attributes as data members, and initialize the data members in the default constructor. The sample C++ code below was generated by a CASE tool. This example shows the normal data member "speed", the constant data member "minimumSpeed", the static data member "totalCarsBuilt", and the global constant "INITIAL_NUMBER".

Figure Class Diagram Showing Three Data Members

Listing C++ to Show Data Member Declarations

C++ Class Declaration - Header File

//////////////////////////////////Car.h ////////////////////////////

#ifndef __CAR_H

#define __CAR_H

const int INITIAL_NUMBER = 1; //Symbolic const declaration and initialization

class Car

{ int speed; //Normal data member

const int minimumSpeed; //Constant data member

static long totalCarsBuilt; //Static data member

public:

Car () : speed(0), minimumSpeed(0) { } //constructor

~ Car ( ) { } //Destructor

};

#endif

C++ Source Code File

//////////////////////////////////Car.cpp/////////////////////////////////

#include "Car.h"

long Car::totalCarsBuilt = 0; //Static data member initialization

C++ Main Function

/////////////////////////////////main.cpp//////////////////////////////////

#include "car.h"

int main ()

{

Car car1; //Default constructor

return 0;

}

  1. Minimum C++ Code Generation Scripts for Data Members

To generate the C++ class declaration with data member declarations, we used script to generate the Car.h file and to generate the Car.cpp file. We created the main.cpp manually. The two scripts are shown below.

Script to Generate the C++ Declaration with Data Members

////////////////////TRUNCATE_EIGHT$CLASS_NAME.h file//////////////////

#ifndef __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

#define __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

CLASS_USER1

CLASS_USER2

class CLASS_NAME[NO_RETURN NO_REPEAT: NO_REPEAT public BASE_CLASS ,DELETE_LAST_SYMBOL]

{ [CPP_ATTRIBUTE_STATIC CPP_ATTRIBUTE_CONSTANT ATTRIBUTE_TYPE ATTRIBUTE_NAME$; //data member]

public:

CLASS_NAME ()

SELECT_WHEN LOGICAL_NOT ATTRIBUTE_IS_STATIC [NO_RETURN NO_REPEAT: ATTRIBUTE_NAME(ATTRIBUTE_INITIAL_VALUE),DELETE_LAST_SYMBOL]

{

}

[ CPP_OPERATION_VIRTUAL CPP_OPERATION_STATIC OPERATION_RETURN_TYPE OPERATION_NAME (CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT CPP_OPERATION_PURE_VIRTUAL;

]

~ CLASS_NAME ( ) { } //Destructor

};

#endif


Script to Generate the C++ Function Definitions - .cpp File

//////////////////////////TRUNCATE_EIGHT$CLASS_NAME.cpp file////////////////////////////////////

#include "TRUNCATE_EIGHT$CLASS_NAME.h"

SELECT_WHEN ATTRIBUTE_IS_STATIC

[ATTRIBUTE_TYPE CLASS_NAME$::$ATTRIBUTE_NAME = ATTRIBUTE_INITIAL_VALUE$; //Static data member initialization]

[

OPERATION_RETURN_TYPE CLASS_NAME::OPERATION_NAME(CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT

{

OPERATION_CODE

}

]

  1. Enhanced C++ Code for Data Members, Accessor Functions, and Operators

To code attributes and their accessor functions in C++, create non-static and static data members and accessor functions as shown in the diagrams below. Key aspects of the class declaration are shown on the left. This information class diagram shows that a class declaration should have a class name, static data members, static data member accessor functions, non-static data members, non-static data member accessor functions, a constructor, function members, and a destructor. The class diagram on the right shows sample C++ identifiers that are also in the code listings.

const Symbolic Name const int INITIAL_NUMBER = 1;

Figure Class Diagram with Data Members and Accessor Functions

Key aspects of coding a class with non-static and static data members and accessor functions are:

- define a default constructor to initialize an object with default data member values in the initializer list, e.g. Car ():gasQuantity (0),minGasQuantity (0) { } ,

- define a constant attribute as a C++ const data member, e.g. const int minGasQuantity; A const data member must be initialized in the initializer list. Set accessor functions are not permitted for const data members.

- define a symbolic constant as a C++ const outside the class declaration, e.g. const int INITIAL_NUMBER = 1;

- define get assessor functions to get the data member values, e.g. int getgasQuantity () const {return gasQuantity;},

- define set assessor functions to set data member values, e.g. void setgasQuantity (float agasQuantity) { gasQuantity = agasQuantity; },

- declare a static data member for a class attribute, e.g. static long totalCarsBuilt;

- define static get assessor functions for static data members, e.g. static long getTotalCarsBuilt () {return totalCarsBuilt; },

- define static set assessor functions for static data members, e.g. static void setTotalCarsBuilt (long atotalCarsBuilt) {totalCarsBuilt = atotalCarsBuilt; },

- define a default destructor to deinitialize the object, ~Car () { },

- initialize static data member outside the class declaration, e.g. long Car::totalCarsBuilt = 0; A static data member may not be initialized in the default constructor or constructor with arguments.

- define a main (test) function to create an object and access non-static and static data members.

The complete C++ code listing is below.

Listing C++ Code Listing for Non-Static and Static Data Members and Accessor Function

C++ Class Declaration - Header File

// Class: Car //ANSI C++

#ifndef __CAR_H //Required for Car class

#define __CAR_H

#ifndef __IOSTREAM_H //Required for cin and cout

#include <iostream.h>

#endif

const int INITIAL_NUMBER = 1; //Symbolic constant

class Car

{ float gasQuantity; //Non-static data member

const float minGasQuantity; //Constant data member

static int totalCarsBuilt; //Static data member

public:

//Default constructor alternative to compiler provided default constructor

Car ();

//Constructor with arguments

Car ( float agasQuantity, float aminGasQuantity ) ;

//Copy Constructor

Car (const Car& aCar );

//Operator= Assignment Operator

Car& operator= (const Car& aCar);

//Operator== Equality Operator

int operator== (const Car& aCar) const;

//Operator<< for cout

friend ostream& operator<< (ostream& os, const Car& aCar);

//Operator>> for cin

friend istream& operator>> (istream& is, Car& aCar);

//Get accessor function for non-static attribute data member

float getgasQuantity() const

{ return gasQuantity;

}

//Set accessor function for non-static attribute data member

void setgasQuantity (const float agasQuantity)

{ gasQuantity = agasQuantity;

}

//Get accessor function for static attribute data member

static int gettotalCarsBuilt()

{ return totalCarsBuilt;

}

//Set accessor function for static attribute data member

static void settotalCarsBuilt ( const int atotalCarsBuilt)

{ totalCarsBuilt = atotalCarsBuilt;

}

//Get accessor function for constant attribute data member

float getminGasQuantity()

{ return minGasQuantity;

}

~ Car ( ) { } //Destructor

};

#endif

C++ Source Code File

//////////////////////.cpp file//////////////////////////////////////////////

#include "Car.h"

int Car::totalCarsBuilt = 0; //Static data member initialization

// Functions for class Car

//Default constructor alternative to compiler provided default constructor

Car::Car () : gasQuantity(0), minGasQuantity(0)

{

}

//Constructor with arguments

Car::Car ( float agasQuantity, float aminGasQuantity )

: minGasQuantity (aminGasQuantity)

{ gasQuantity = agasQuantity; //Initialization of attributes

}

//Copy constructor alternative to compiler provided default copy constructor

Car::Car (const Car& aCar ) : minGasQuantity (aCar.minGasQuantity)

{int i = 0;

gasQuantity = aCar.gasQuantity;

}

//Operator= Assignment Operator alternative to compiler provided operator=

Car& Car::operator= (const Car& aCar)

{ if (this == &aCar) return *this;

gasQuantity = aCar.gasQuantity;

return *this;

}

//Operator== Equality Operator

int Car::operator== (const Car& aCar) const

{ return (

(gasQuantity == aCar.gasQuantity) //Equality check for attribute data members

);

}

//Operator<< extraction for cout

ostream& operator<< (ostream& os, const Car& aCar)

{ os << "Object Attribute Values - Class Car" << endl;

os << "gasQuantity: " << aCar.gasQuantity << endl;

os << "minGasQuantity: " << aCar.minGasQuantity << endl;

os << "totalCarsBuilt: " << aCar.totalCarsBuilt << endl;

return os;

}

//Operator>> insertion for cin

istream& operator>> (istream& is, Car& aCar)

{ cout << "\nEnter Object Attribute Values or 0 - Class Car";

cout << "\nEnter gasQuantity : " << endl;

is >> aCar.gasQuantity;

return is;

}

C++ Main Function

/////////////////////////////////main.cpp/////////////////////////////////

#include "car.h"

#include <iostream.h>

int main ()

{ Car car1; //invokes the default constructor

Car car2 (10.0, 0); //invokes the constructor with arguments

car1.setgasQuantity (20.0); //invokes the set assessor function

Car::settotalCarsBuilt (1000);//invokes the set assessor function for

//static member

cout << car1;

return 0;

}

///////////////////////////Sample Output///////////////////////////////

Object Attribute Values - Class Car

gaaQuantity: 20

minGasQuantity: 0

totalCarsBuilt: 1000

  1. Modeling Attributes for Quality Software

How we model attributes can affect the quality of the resulting software. Our goal is to create high quality software. Correctly identifying and specifying attributes can contribute to creating high quality software that is correct, reliable, extendible, and reusable. For example, specifying correct constraints such as minimum and maximum attribute values supports correctness and reliability.

The two software quality techniques most applicable to attributes are encapsulation and strong cohesion. We can support encapsulation (information hiding) by declaring attributes as private. This may prevent corrupting an attribute with an illegal value. We can support strong cohesion by identifying attributes that are related together in a class. There should be no unneeded or out-of-place attributes. This is also a guideline in relational data base management systems. There, a normalization rule to avoid data redundancy states that each field of a table should represent a fact about the key, the whole key, and nothing but the key. The object-oriented version of this rule for strong cohesion is that each attribute value should represent a fact about the object, the whole object, and nothing but the object. We can check for strong cohesion by examining each attribute in a class to ensure that it describes an object of the class. For example, the attribute "current national debt" is an out-of place attribute in a customer class.

  1. Summary

To model classes and objects, attributes and operations must be identified and described. An attribute is a characteristic or property of an object. An operation is an action or set of steps to accomplish something. Attributes and operations are graphically shown on the class diagram. They are described in the attribute specification form and operation specification form. A CASE tool is useful to create class diagrams and specification forms. A CASE tool may generate source code for the declaration of attributes and operations in the class declaration. A CASE tool may generate fill-in code templates which must be updated with code statements to accomplish the purpose of each operation.

buy cialis cialisfunsurforg cialisfunsurforg onlinehtml site cialis and back pain cialis levitra vs combine viagra and cialis allowed black buy casino cialis diet gambling health jack phentermine poker tag viagra xhtml canada over the counter cialis viagra cialis generic viagra cialis viagra levitra prices women take cialis drug buy cialis tadalafil cialis drinking alcohol cialis online usa levitra vs cialis vs viagra brand name cialis cheapest soft cialis cialis get viagra cialis viagra taking cialis with viagra buy cialis where cialis drugs cialis over dose lowest price generic cialis buy cialis generic ciales web site marketing cialis interaction precautions cialis western open add cialis link new buying generic cialis cialis free cialis suggest url valium detox buy cialis pharmacy cialis experience cialis pills online cialis buy cialis dream pharmaceutical cialis and oral sex cialis lawyer columbus compare viagra cialis levitra viagra cialis levitra buy cialis shop tadalafil cialis fast heart rate cialis online pharmacy online pharmacy cialis seychelles buy cialis ebay find tadalafil cheap cialis cialis injury attorney cincinnati cialis uk similar drugs for cialis buy cialis online submit=buy cialis online cialis dose it work cialis no prescription needed generic cialis muncie indiana buy cialis genericf hostingcom link cialis cheap no prescription cialis injury attorney cleveland cialis versus viagra 20mg cialis canada cialis deals cialis forum cialis free consultation cialis sample price viagra cialis levitra buy cialis link onlineinttc cialis class action lawsuit cialis levitra combine cialis and levitra viagra allowed black buy casino cialis diet gambling jack low online order phentermine poker tag viagra xhtml can cialis and viagra be taken together cialis free sample coupon cialis soft tab online consultation purchase cialis buy cialis online us cialis commercial cialis line differences viagra cialis levitra allowed black casino cialis diet gambling health jack phentermine poker tag viagra xhtml can i get cialis in canada cialis free samples cialis samples sale without prescription cialis in detroit area buy cialis cialis drug prescription cialis on second attempt generic viagra cialis levitra best cialis price canadian perscription of cialis cialis free trial cialis site suggest samples of viagra cialis levitra buy cialis now cialis cheap cialis injury lawyer ohio cialis viagra vs valium buying online buy discount cialis cialis effects side cialis online discount cialis soft allowed black buy casino cialis diet gambling jack online order phentermine poker tag viagra xhtml by cialis comment post posted cialis for sale on line cialis prescription las posas de ciales buy canada cialis cheap generic cialis cialis generic price cialis soft tab prescription cialis on line buy cialis online viagra cialis compare levitra cialis link online suggest discount generic cialis . buy tadalafil cialis cialis for sale cialis open western lowest cialis levitra prices buy cialis dosage effects online side warning cheap cialis generic cialis free sample cialis soft tab online consultation usa side effects of cialis buy cialis link suggest cialis attorney columbus cialis information pamphlet cialis stories viagra cialis generica buy cialis viagra cialis compared to viagra cialis new viagra dangers of taking cialis allowed cialis tag viagra xhtml canada cialis cialis for woman cialis overnight hypertension treatment using cialis buy cheap cialis canadian cialis cialis for women cialis price order cialis submit=order cialis buy cialis in the uk cheapest cialis generic cialis generic cialis sale review cialis levitra viagra buy cialis link onlinenew pharminfo cialis and liver disease cialis how to avoid backache cialis soft tabs penis pump plus cialis buy cialis online cialis comparison levitra viagra cialis icos lily online cialis tadalafil swflash 1.cab buy cialis online dreampharmaceuticals cialis co drug eli impotence lilly cialis julilatiwaveprohostingcom link onlinehtml cialis samples submit=cialis samples mixing cialis and viagra buy cialis without prescription cheap cialis submit=cheap cialis cialis female view cialis review lawsuits involving blindness caused by cialis buy cialis generic online canada cialis line cialis female opinion cialis online submit=cialis online generic cialis submit=generic cialis buy cialis link onlinenettc can you mix cialis and viagra cialis fda approval cialis online buy generic cialis 20 mg best price cialis buy viagra cialis levitra cialis erectile dysfunction cialis official website erection does not go down after taking cialis black casino cialis diet followup gambling health jack phentermine poker post viagra cialis 20mg cialis generic link suggest cialis woman sitemap2 add cialis link buy generic cialis cialis dosage cialis melt packs buy generic cialis online