SADL V2 Quick Reference Guide

Last revised 07/27/2015

(or What can I say in SADL?)


Every Model Must Have a Name!

(And it must be the first non-comment in the file.)

    uri "http://sadl.imp/shapes_top".

Since the URI can be long and not easy for people to remember, an "alias" can be provided, which can then be used as a "prefix" in prefixed QName references in models.

    uri "http://sadl.imp/shapes_top" alias top.

The model's version can be specified if desired:

    uri "http://sadl.imp/shapes_top"  alias top version"1.0".

When using a source code control system such as CVS, the version information can be specified so that it will be automatically updated. Using appropriate, system-dependent tags within the version string, on might provide a version which, after check-in to the system, expands to something like this:

    uri "http://sadl.imp/shapes_top"  alias top version "$Revision: 1.7 $ Last modified on $Date: 2015/07/27 14:27:36 $".

Note that key word expansion in SVN may need to be enabled (see

A Model Can Import Other Models

This is accomplished with the "import" keyword:

    import "http://sadl.imp/shapes_top".

It is possible to import by imported model SADL file name instead of the imported model URI:

    import "shapes-top.sadl".

The SADL file reference will be converted to a URI by the SADL editor. While it is recommended to provide global aliases in the model URI, it is possible to provide a local alias, which will be used as an XML QName prefix within the importing model only:

    import "shapes-top.sadl" as top.

The alias becomes the prefix used to specify a concept from that namespace explicitly using the syntax <prefix>:<concept>, e.g.,


(See also Importing OWL Models into SADL.)

Defining Concepts/Classes/Sets/Categories

A class can be defined as a top-level class, meaning that no more general concept is defined in this model or any model it imports to which members of this class also belong.

Shape is a top-level class.

or, if you prefer:

Shape is a class.

A class can also be defined as a subset or refinement of an existing class.

Circle is a type of Shape.

Since a class is a set, the set operations union and intersection are useful in defining other sets. In SADL we use curley brackets to indicate that what is between the brackets defines a new set or class. Intersection is indicated "and" and union is indicated by "or". For example, the following statement creates the intersection of the Person and Female classes and names the intersection Woman.

Woman is a type of {Person and Female}.

As an example of a union:

Refreshment is a type of {Food or Drink}.

A class definition may include an enumeration of all of the instances (individuals) that belong to the class.

Season is a top-level class, must be one of{Spring, Summer, Fall, Winter}.

It is also possible to define a set of subclasses with a single statement.

{MalePerson, FemalePerson} are types of Person.

A comma is this case is interpreted as an "or" (union). The above statement is equivalent to

{MalePerson or FemalePerson} is a type of Person.

In the later statement, the "{MalePerson or FemalePerson}" is an explicitly defined class, albeit without a specified name, so the singular for of subclassing (is a type of) is used. The statement before is a convenient shorthand which is less formal and more English-like.

Defining Properties

A property may be defined by giving it a name and identifying the class(es) of things that can have this property (the domain). The definition may also include the kinds of values that the property can have (the range).

    area describes Shape has values of type float.    // This is a data property--the range is the primitive type xsd:float

    teaches describes Professor has values of type Student.    // This is an object property--the range is the defined class Student

A property may also be defined by identifying an existing property of which this property is a subset and adding some additional defining information.

    surfaceArea describes Shape-3D is a type of area.

An alternative wording for defining a property is also available.

    relationship of Professor to Student is teaches.

Note that class and property definitions can be combined.

    Shape is a top-level class, described by area with a single value of type float.

    Circle is a type of Shape, described by radius with a single value of type float.

    Teacher is a top-level class, described by  teaches with  values of type Student.

In SADL, the phrase "with a single value of" means that the property has a maximum cardinality restriction of one on the domain class. This is different from declaring a property to be a functional property ("<property> has a single value."). You may also restrict the property to a single value for a specific class using an explicit maximum cardinality restriction, discussed in the next section.

Refining Class Definitions

The definition of a class may be refined, or made more precise, in several ways.

    teaches of Professor has at least one value of type College_Student.     // any instance of Professor must have at least one value of teaches from the range class College_Student

    teaches of Professor has at least one value of type {Fulltime_Student or Parttime_Student}.    // that is, at least one value from the union of , so the value could be from either range class

    teaches of Professor has at least one value each of types {Fulltime_Student, Parttime_Student}.    // that is, at least one of each of the range classes. This is equivalent to two separate statements, "teaches of Professor has a least one value of type Fulltime_Strudent." and "teaches of Professor has at least one value of type Parttime_Student."

    teaches of Professor only has values of type College_Student.     // any instance of Professor cannot have any values of teaches from any class except College_Student (although it may have no values)

    teaches of Professor has at least 1 value. // min cardinality--an instance of Professor must have at least one value of the property teaches

    teaches of Professor has at least 1 value of type College_Student.    // min qualified cardinality--an instance of Professor must have at least one value of the property teaches from the College_Student class

    teaches of Professor has at most 500 values. // max cardinality--an instance of Professor cannot have more than 500 values of the property teaches

    teaches of Professor has exactly 30 values. // cardinality --an instance of Professor must have exactly 30 values of the property teaches; no more and no less

    rating of Professor must be one of {Excellent, Good, Average, Poor}.     // any instance of Professor cannot have any values of rating that is not either Excellent, Good, Average, or Poor

    gender of Person must be one of {"Male", "Female"}.    // Note: this differs from the above in that the property is a data property and the values are literals, not individuals

    rating of GoodProfessor always has value Good.  // Note: this will only have an effect if an OWL DL reasoner is involved, e.g., Jena OWL_MEM_RULE_INF

    a Person is a Professor only if teaches has at least 1value.     // necessary and sufficient condition: if an instance of Person has at least one value of teaches, then it is also an instance of  Professor

    a Professor is a College_Professor only if teaches has value College_Student.     // necessary and sufficient condition: if an instance of Professor has a value of teaches which is an instance of
                                                                                                                                                        //  College_Student, then it is also an instance of College_Professor

Defining Individuals (Instances)

An individual may be defined simply by giving it a name and a type.

    Jane is a Student.

An existing individual may be further described.

    Jane has age 19 .  // a space is required between 19 and the ending period so that it doesn't appear to be a decimal point.

Alternately, additional information may be given as part of the original definition.

    Jane is a Student, has age 19 .

In fact, multiple pieces of information can be given.

    Jane is a Student, has age 19, has gender Female.

As would be the case in a natural language, one can say things about instances in SADL without giving everything a name. For example:

        A Birth, has birthMother Martha, has child George,
where (a Location, has lattitude38.186111, has longitude-76.930556, has description "Pope's Creek Estate near present-day Colonial Beach, Virginia, USA),

This says that there is an unnamed instance of the class Birth with the specified properties. In fact, one of those properties is "where", which has an unnamed but well-described instance of Location as its value.


Annotations in OWL are properties that are usually ignored by reasoners. SADL supports two common annotations. An rdfs:label is called an "alias" in SADL and an rdfs:comment is called a "note". Annotations can be added to the ontology (to the model itself) or to any concept in the model. Note that with respect to the ontology, "alias" is used both for the XML namespace prefix and as the annotation keyword. The former must follow the model URI, is not within parentheses, and takes an unquoted ID as its value. The latter is embedded within parentheses and takes a quoted string or set of comma-separated quoted strings, as value(s). Here are some examples.

uri "http://sadl.imp/shapes_top" alias top
version "$Revision: 1.7 $ Last modified on $Date: 2015/07/27 14:27:36 $"
    (alias "The root model for the shapes ontologies")
note "This model captures concepts that are common to all types of shapes").

Shape (note "A geometric object of any dimensionality") is a top-level class,
described by area with values of type float.

LengthUnits is a top-level class, must be one of
Millimeter (alias "mm"), Centimeter (alias "cm"), Inch (alias "in", "\""),
Meter (alias "m"), Foot (alias "ft"), Mile (alias "mile"), Kilometer (alias "km")

Note that an rdfs:comment, rdfs:label, and rdfs:seeAlso annotation properties can also be specified using "comment", "label", or "seeAlso", respectively, as one would any other property. These and other annotation properties are colored in green but are not bold like normal properties.

Shape has comment "A Shape is any geometric object.".

area has comment "Sub-properties can be used for different kinds of area".

Note also that user-defined annotation properties are supported, e.g., "ofInterestTo" in this example:

Rock is a top-level class,
described by color with values of type string,
described by hardness with values of type Hardness.

Hardness is a top-level class, must be one of {Hard, Soft}.

PatronType is a top-level class, must be one of {Expert, Novice, Everyone}.

ofInterestTo is a type of annotation.

color has ofInterestTo Everyone .

hardness has ofInterestTo Expert.

Annotation properties do not have a domain or range.

Defining Rules

A rule has three parts: given, if, and then. The given and the if are really both part of the rule premise, but some people may find rules more understandable if certain constraints are labeled as given. Each of these three parts of a rule may contain rule elements. The elements of the premise establish a pattern to be matched in the instance data. If the pattern is matched, then the conditions of the conclusion (then) are imposed on each matching data. Here is a simple rule.

    Rule AreaOfRectangle
given        x is any Rectangle
area of x= height of x* width of x.

    Rule R2
given x is a Person
if x has age <= 12
then x is a Child.

    Rule R1b: if x is a Person with age <= 12 then x is a Child.

In these rules, "x" is a variable--a placeholder that ties the rule elements together. A variable cannot be used in a rule conclusion unless it has been "bound" or defined in the rule premise. In the rule premises, a variable cannot be used in the right-hand side of an assignment (=) unless it has already been defined in a previous element.

One of the subtleties of rule writing is the various kinds of negation that one might wish to express. SWRL and Jena Rules do not support "strong negation" (see "Strong negation" in, but some forms of negation are supported and may be useful.

SADL Extensions to Support Model Validation and Testing

There are several non-OWL constructs that can be used in a SADL file used for testing purposes. They are as follows.


It is possible to ask a question of a model in SADL with the syntax "Ask:" in front of a SPARQL query. The query can be in one of two forms. First, SADL provides a query language similar to the rule language useful for queries that are not too complex. Second, a quoted SPARQL query of any valid content can be specified.

An Ask using SADL query syntax will look something like this:

Ask: age of John.

Ask: a child of a Birth with mother Mary.

Ask: select x, y where y is the latitude of the location of x.

An Ask using a quoted SPARQL query must be of the form:

        Ask: "select ?x ?y where {?x <someProperty> ?o . ?o <someOtherProperty> ?y}" .

A SPARQL "construct" query will display the resulting graph as a 3-column table with each returned triple, subject, predicate, and object, forming one row in the table. In addition, if GraphViz has is installed on the computer where the SADL-IDE is running and if the path to the GraphViz "bin" folder is set in the SADL-IDE preferences, the returned graph will be rendered as a visual graph.


It is sometimes desirable to get a specific explanation of why a statement exist (or doesn't exist) in the inferred model. The Explain keyword provides this capability. There are two forms of Explain.

  1. Explain followed by a statement of a triple or set of triples:
    Explain: MyCircle has area 38.48 .
    Explain: George is a Person.
    Explain: George is a Person with age 23 .
    George is a Person with age 23, has friend Sam.
    Explain: George has age x.

  2. Explain followed by the keyword "Rule" followed by the name of a rule in the current model or its imports:
    Explain: Rule Friends.

It can be difficult to determine why a rule isn't firing. The second form of Explain provides help in diagnosing this problem by translating the graph pattern of the rule premises (most built-ins are ignored at present) into a SPARQL query and executing the query to see if the rule premises have matches in the model graph. Rule Explain starts with the first premise and adds premises until all premises are included or until there are no matches in the data graph. This information can be very informative in terms of identifying why the rule is not firing.

If the statement in the first form of Explain does not find a match in the model's data, an attempt will be made to find one or more rules that have conclusions that appear to be able to conclude the desired statement. The rule(s) are then processed in the same way as a Rule Explain to see if the premises of the rule are matched in the data.


The "Expr:" command provides an easy way to test an expression for use in Rule or Query.

    Expr: x is a Man with age > 21 .

The expression is parsed and any parsing errors are shown. In addition, the translation of the expression is shown in the console window.


The Print keyword has a couple of flavors. Most commonly, it allows comments to be placed in the test output for easier readability of test results in the console window:

Print: "The following explanation should include only one statement.".

Print may also be used to save inferred models to a file for examination in debugging a set of models. In this case Print is followed by one of two keywords:

Print: Model.           // Print the entire inferred model to an OWL file in the Temp subfolder

Print: Deductions // Print only the deductions model to an OWL file in the Temp subfolder


In SADL, placing the prefix "Test:" in front of a statement about an individual will cause the information to be compared to what is known rather than being assigned. The actual testing occurs when the "Test" action is chosen from the "SADL Actions" popup menu on a file. For example, running tests on a file containing this line:

    Test: MyRect is a Shape, has width 4.5, has area 15.75 .

will cause three tests to be performed. (1) Verify that MyRect is of type Shape. (2) Verify that MyRect has width 4.5. (3) Verify that MyRect has area 15.75. The last makes the most sense as a test since the area is computed using a rule and we may want to validate that the rule is giving the expected answer.

An alternate form of test compares the results of a SPARQL query with a specified set of results. This is particularly useful when the model contains blank nodes created during the course of inference as there is no way to explicitly specify the blank node in a statement but a query allows the blank node to be identified by its relationship to other nodes in the model graph. The query is of the same form as the Ask (see above) and the comparison values can be:

  1. a single value

  2. a set of values

  3. a list of sets of values

Sets of values are enclosed in square brackets and may be separated by space or by a comma. Lists are designated by curly brackets and list elements can be separated by space or by a comma.

Comparisons can be one of the following types:

  1. values are the same, specified as "is" or "=="

  2. values are not the same, specified by "is not" or "!="

  3. values are only those given, specified by "is only"

  4. no values are present, specified by "is not known"

To illustrate, consider the following example model and set of tests, all of which will pass.

Person is a top-level class, described by name with values of type string,
describedby age with values of type int,
describedby spouse with a single value of type Person.

Tom is a Person, has name"Tom Dunham", has age35, has spouse Betty.
isa Person, has name"Betty Dunham", has spouse Tom.

Test: "select ?s where {<Tom> <spouse> ?s}" is Betty.

Test: (select s where Tom has spouse s) is Betty.

Test: "select ?p ?yrs where {?p <rdf:type> <Person> . ?p <age> ?yrs}" == { [ Tom35 ] } .

Test: (select p, yrs where p is a Person and p has age yrs) == {[Tom, 35]}.

Test: "select ?p ?n where {?p <rdf:type> <Person> . ?p <name> ?n}" == { [ Tom, "Tom Dunham"] [ Betty, "Betty Dunham"] }.

Test: (select p, n where p is a Person and p has name n) == {[Tom, "Tom Dunham"][Betty, "Betty Dunham"]}.

Test: "select ?s where {<Tom> <spouse> ?s}" is only Betty.

Test: (select s where spouse of Tom is s) is only Betty.

Test: "select ?y where {<Tom> <age> ?y}" is not40 .

Test: (select y where age of Tom is y) is not 40 .

Test: "select ?y where {<Betty> <age> ?y}" is not known.

Test: (select y where age of Betty is y) is not known.

It is also possible to specify suites of tests in a file with the file extension ".test". Each line in the file is of the form:

    Test: "file:///shapes-test.sadl" .

Note that when the query returns a single variable, an abbreviated syntax is supported which drops the select and where keywords to simplify:

Test: spouse of Tom is Betty.

Test: spouse of Tom is only Betty.

Test: age of Tom is not 40 .

Test: age of Betty is not known.

Test: the age of the spouse of Betty is 35 .

Note that when comparing a scalar value to a vector of values, the test passes if the test of the scalar value against each of the vector values passes. The vector must be one-dimensional, i.e., a table with a single column and multiple rows.

SADL Extensions to Support Data Input, Output


The Read command allows instance data for a test scenario to be read in from a file. The source data file can be in OWL (RDF) format as shown in this example.  This statement reads data from the "shapes-test.owl" file in the "OwlModels" subfolder.


The input data can be in other formats provided there is a DataImporter available supporting the format of the input data. A DataImporter implementation will require some kind of mapping specification, which is the argument of the "using" keyword. For example, if there is a comma-separated-value importer, one might read CSV data using a mapping template file which provides a mapping from the tabular data, which is semantically incomplete, to the full graph model of RDF triples (see DataImporter).


This command reads data from the "Rectangles.csv" file in the "CsvImport" folder using the maping file "Rectangles.tmpl" in the same folder.


The Write command is used to output the results of one or more other commands to a file. The optional "data" keyword following the "Write:" indicates whether only the data but none of the other output is to be included in the output. The data is the actual content returned by a query.


This command outputs the ResultSet data (only) for the specified Ask cmd to the specified output file.


This command constructs an RDF graph and writes it to the specified .owl file.

Cleaning a SADL Project

SADL files in an Eclipse Resource Project are also saved as OWL files and (accompanying rule files for Jena Rules) whenever a SADL file that does not contain errors is saved. It may be desirable to regenerate the OWL files for a Eclipse project for a variety of reasons. If the project has been given a SADL Nature, this can be done by selecting "Clean" on the "Project" title bar menu and selecting the project. (A project is given a SADL nature by right-clicking on the project name and selecting "Enable SADL Builder".) Cleaning will cause all project OWL files to be deleted. If "Build Automatically" is checked, the OWL files will then be regenerated. If not, they can be regenerated by selecting "Build Project" on the project context menu (right click on the project name in the navigator pane) or by invoking "Build Project" from the "Project" title bar menu. You may wish to uncheck "Build Automatically" so that each file change does not cause a build to occur.

When a Rule Doesn't Fire

It can be difficult to determine why a rule isn't firing. Help is provided for diagnosing this problem by translating the graph pattern of the rule premises (built-ins ignored for now) into a SPARQL query and executing the query to see if the rule premises have matches in the model graph. If not, the last premise is dropped and the process is repeated until matches are found or there are no more premises. This information can be very informative in terms of identifying why the rule was not firing. Generally the last premise dropped (the first premise dropped in premise order) is what is not matching. There are three ways to exercise this functionality:

  1. An ask statement in the model will cause a rule's premises to be checked. The rule is specified by name:
    : RuleMyRuleWhichIsNotWorking .
    which means evaluate the premises of the named rule
  2. A query in the Run Query dialog of the special form "Rule MyRuleWhichIsNotWorking"
  3. The Check Rule Premises SADL Action which will ask for the rule name

SADL Custom Built-ins for Jena

Built-ins are a set of Java classes (at least for Jena and Pellet) that allow a rule to access some additional processing capability. A built-in might appear in a rule premise and thereby ultimately return either true (yes, this part of the premise matches) or false, or it might appear in the conclusion and thereby provide an effect of rule firing. Both Jena Rules and SWRL use built-in functions. However, Jena makes it relatively easy to supply additional built-in functions. While Jena comes with a number of built-ins, see "Builtin Primitives" at, SADL provides several additional built-in functions that have been found to be useful. Note that additional built-ins must be made known to Jena (their implementing class specified) in the "" file and the implementing code must be included on the Java classpath.