The standard User-Role or User-Group pattern is typically implemented as three tables; User, Group, and an associative table User_Group. OWL (Ontology Web Language) is particularly suited to modeling this pattern, and, with a little help from an inferencing engine, can make some obvious yet valuable inferences for us. In many organizations it’s easier to model roles as a set of interrelated nodes such that membership in one conveys membership in a broader group. In this diagram Mark is declared as having a “marketing” role, however, he’s also an employee, and the graph makes that clear. If we were using the standard RDBMS approach mentioned above we’d have to enumerate each group and assert his membership to each one in the associative table.

users and roles
Before we continue let’s go ahead and plan the types of questions we’ll need to ask our graph. First, for any given user we’ll want to ask if they are members of a particular role. Before allowing someone to check in code for instance, the security mechanism may ask “is user a member of the developer role?”. Another obvious question is the reverse. Given a particular role the program might need to know the set of user to which it is assigned. ”Which users have the ‘biz’ role?”. Starting with these two questions we are now able to plan an approach to finding answers. For the first question we might start with the the given user and traverse the graph through each role to which they are assigned until we encounter the role we are looking for. Note that this traversal must also visit sub-roles. If the role isn’t found when all links are exhausted we reply that the user is not given that role. Answering membership for a given role would require us to follow the edges in reverse. But as humans we look at this graph and with a glance can determine that Summer is indeed an employee. OWL, with it’s ability to infer new information from information we give it regarding relationships in our graph, can do something similar. It can assert the obvious for us, and remove the necessity of graph traversals to answer simple questions. Step 1 in creating an OWL ontology is defining your relationships. Relationships rule in semantic web programming. Classes are important, however, they are not primary as in OOP.

hasRole with range of Role
:hasRole a owl:ObjectProperty, owl:TransitiveProperty; rdfs:range :Role .
This small snippet of OWL (in n3 format) declares a property “hasRole”. It also declares that anything on the right side (the object) of this relationship is of type “Role”. Note that we’re not restricting the range. We aren’t saying everything in the range of this property must be a “Role”. We are saying that anything which is the object of this relationship can be inferred as being a “Role”. We have also declared this property to be transitive. If a-hasRole>b and b-hasRole>c then a-hasRole>c. We’ve accounted for relating people to roles, now we need a way to relate roles to each other

:parentRole a owl:ObjectProperty; rdfs:domain :Role; rdfs:subPropertyOf :hasRole .
The parentRole declaration is similar in that it’s range is also of type “Role”. But in this case we also know that the domain (the left side of a relationship) is a role as well. Anything with an outgoing parentRole relationship is inferred as a “Role”. More importantly, parentRole is declared as being a subprperty of “hasRole”. Adding the resulting inferences to those gained from the fact that “hasRole” is transitive results in the new fact (among several others) that Mark has the role of employee (and biz).
Now we know which roles are applicable to a given user, we still need an easy answer to which individuals are members of a given role. That’s an easy fact to infer given what we already know. All that’s left to do is assert one more property and how it relates to other properties in the graph:
:hasMember a owl:ObjectProperty; owl:inverseOf :hasRole .
“hasMember” is declared as being the inverse of the “hasRole” property. The result will be an edge going in the opposite direction for every occurance of “hasRole”. Taking into consideration the fact that “hasRole” has already benefited from transitive inference and you may see that we’ll get a direction assertion per member of the role group.

@prefix : <#> . @prefix owl: . @prefix owl2xml: . @prefix rdf: . @prefix rdfs: . @prefix roles: . @prefix xsd: .<> a owl:Ontology .:Role a owl:Class . :User a owl:Class; rdfs:subClassOf owl:Thing . :hasMember a owl:ObjectProperty; owl:inverseOf :hasRole . :hasRole a owl:ObjectProperty, owl:TransitiveProperty; rdfs:range :Role . :marko a owl:Thing; roles:hasRole :role_sysadmin . :parentRole a owl:ObjectProperty; rdfs:domain :Role; rdfs:subPropertyOf :hasRole . :role_developer a owl:Thing; roles:parentRole :role_employee . :role_employee a owl:Thing . :role_sysadmin a owl:Thing; roles:parentRole :role_employee . :sebastian a owl:Thing; roles:hasRole :role_developer .owl:Thing a owl:Class .