lipido's idea is good, but unfortunatelly the proposed solution has an apparently minor but significant flaw and does not cover your third requirement: role could exist and not affected to any user-doc relation. Modelled as an association class, Role can only exist as a link instance between a User and a Document objects. In this solution a Role can not be defined as an independent instance! In addition, it does not permit reuse of roles.
Here you have two solutions that fix this problem. You should chose among them according to additional conditions (see the notes):
- All 3 concepts (User, Document, Role) exist independent of each other and can be freely and independenty created and queried
- A new concept of "Access" models the fact than a User has a Role (or several roles) in context of a specific Document. There are two ways to model Access, depending on if it should have some more own attributes (see diagrams). Access as an independent class permit reuse of Roles. In both solutions an Access has exactly 1 Document, 1 User and 1 or more Roles.
- User can have 1 or more Roles with each Document he has Access to
- All possible queries are possible - getAllUsers, getAllDocuments, gettAllRoles, getUsersRoles(Document), getRoles(User, Document) and similar.
UPDATE (after the comments)
Here is an object diagram that explains the run-time structure of object (it is based in the second class diagram, the one with association class rather than n-ry association):
Please see the notes in the comments. Not that Access instance is both a class and an association instance (link). That's why it always has a single instance of both associated classes and in this case only one Role. Each User can have on the other hand Access to many Documents (0..) and each Document can be Accessed by 0 or more Users (0..).