Download CDET The Consistent Document Engineering Toolkit User Manual

Transcript
CDET
The Consistent Document Engineering Toolkit
User Manual
www.unibw.de/inf2/CDET
Jan Scheffczyk
[email protected]
September 6, 2005
Contents
1 Introduction
1.1 What Can You Use CDET for? . . .
1.2 What is CDET not Meant for? . . .
1.3 System Requirements & Installation
1.4 This Manual . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 Working with CDET
2
3
3
4
4
5
3 CDET System Architecture
12
4 What You need to Input into CDET?
4.1 CDET Project Description . . . . . . . . . . . . . . . . . . . . . . .
4.2 Consistency Rules . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
14
17
23
5 Technical Details
5.1 Project Description XML Syntax
5.2 Language XML Syntax . . . . . .
5.3 Rule XML Syntax . . . . . . . .
5.4 Repository Interface . . . . . . .
32
32
33
37
41
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6 Future Work
A The
A.1
A.2
A.3
42
CDET Prelude
Prelude Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prelude Predicates . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prelude Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
B DTDs
B.1 Project Description DTD consistencycheck.dtd
B.2 Rules DTD rules.dtd . . . . . . . . . . . . . . . .
B.3 Language DTD language.dtd . . . . . . . . . . .
B.4 Report DTD report.dtd . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
43
43
43
44
47
47
49
53
59
C GNU General Public License
68
Bibliography
73
2
Abstract
When a group of authors collaboratively edits interrelated documents, semantic
inconsistencies occur almost immediately. Current document management systems (short DMS) provide useful mechanisms such as document locking and version control, but often lack consistency management facilities. At best, semantic
consistency is “defined” via informal guidelines, which do not support automatic
consistency checks.
The Consistent Document Engineering Toolkit (short CDET) aims at overcoming these shortcomings. It is a result of my research at the Universit¨at der
Bundeswehr M¨
unchen since 2002. CDET complements DMS or revision control
systems (short RCS) by consistency management. The overall goal of the CDET
is to provide a means by which you can formalize semantic consistency requirements (such as business rules), check your documents for consistency automatically, and derive repairs for inconsistencies. The crucial point is, however, to
tolerate inconsistencies, which are commonly considered a “natural” consequence
of multi-author environments.
Chapter 1
Introduction
Larger bodies of writing, such as books, technical documentations, or software
specifications, contain many interrelated heterogeneous documents. Typically, a
whole team of authors is responsible for producing and maintaining these documents. In supporting a multi-author environment, document management systems (DMS) and revision control systems (RCS1 ) store documents in repositories.
On the one hand, DMS/RCS provide fundamental management facilities, e.g.,
version management, access control, or deployment management. On the other
hand, DMS/RCS fail to manage semantic domain-specific consistency requirements. Usually, authors aim to produce an overall consistent work, i.e., certain
relations between the documents are maintained. These relations are, however,
mostly implicit and vague, e.g., “Links within documents should have a valid target.” What does “valid” mean? Why do we say “should”? Does it mean that the
rule does not need to hold always? In order to achieve consistency, authors have
to spend plenty of time re-reading and revising their own and related documents.
Worse, each check-in to the DMS/RCS potentially violates consistency. Larger
companies define guidelines and policies for writing; but still a human reviewer
is needed to maintain them. What prevents automatic consistency checks is that
guidelines are implicit or at best informal.
CDET implements a formal quality control approach that is built on top of
informal document engineering processes.2 We call this kind of quality control
“semi-formal consistency management.” CDET introduces explicit formal consistency rules to capture informal quality requirements. It does not require any
adaptations to editing practices of authors. CDET smoothly integrates consistency
management into (almost) arbitrary DMS/RCS without requiring adaptations to
document engineering processes. This is in sharp contrast to entirely formal consistency management approaches, which provide strong means for consistency management but severely hinder your work by requiring a specific document model or
format.
By “consistency checking” I mean to determine how the repository conforms
to the rules. This is in contrast to classic logic, where “consistency checking”
1
By RCS I mean an arbitrary revision control system and not the specific tool with the same
name.
2
By “document engineering process” I mean the act of editing interrelated documents in a
targeted way — similar to software engineering; see, e.g., www.documentengineering.org.
2
1.1 What Can You Use CDET for?
3
means to determine whether a set of formulae has a model, i.e., all formulae can
be fulfilled at once. Essentially, CDET is a sophisticated model checker, where
the DMS/RCS provides the model. We call a violation of a consistency rule
inconsistency. We can resolve an inconsistency by applying a repair to some
documents in the repository.
Consistency rules can express intra- and inter-document requirements regardless of the document model and the document format used. Strong rules must
be adhered to, whereas weak rules may be violated. Rules can restrict how documents evolve in time — hence, CDET supports temporal logic. From consistency
rules, CDET generates
• S-DAGs (S uggestion carrying D irected Acyclic Graphs), which visualize inconsistencies and repair actions for individual rules; and
• one repair collection, containing alternative repair sets, which each contains
repairs that together resolve all inconsistencies for all your rules.
1.1
What Can You Use CDET for?
Of course, you can use CDET for maintaining semantic consistency requirements
in a tolerant way during your document engineering projects. Besides pure consistency management, there are some other application areas:
• You can use temporal consistency rules for supervising and enforcing development processes.
• You can categorize documents on how they conform to some consistency
rules.
• You can even burn your CPU by CDET.
1.2
What is CDET not Meant for?
At date, CDET is in a very preliminary state — I consider it α software. Interfaces
to DMS/RCS are quite stable — so CDET should not corrupt your data. However,
I would not recommend CDET for mission critical tasks in high budgeted enterprise
projects. Sure, I am confident this changes in the near future. CDET is not
meant to ensure data integrity, locking, or to implement access rights; this should
be implemented by the DMS/RCS you are using. CDET does not take off the
responsibility to think about semantic consistency — in fact, it strongly encourages
such thoughts. Worse, you cannot use CDET for cooking coffee (except by using
the heat produced by your CPU) or carrying out your garbage . . .
4
1.3
Introduction
System Requirements & Installation
CDET has been tested on two Debian Linux boxes; it should run on other Linux/Unix boxes as well, may be you need to modify some paths. If you were
successful in running CDET, please let me know. CDET should be portable to
Windows without major efforts; however, I did not come around to that already.
For running CDET, you need the Glasgow Haskell Compiler (GHC) version 6.4 or
above, autoconf, and a DMS/RCS, including the headers of their support libraries.
Currently, CDET supports DARCS [Rou05], subversion [CSFP04], and the normal
file system.
For installing CDET, just grab the tar ball and unpack it. In the src subdirectory you should invoke
autoconf
which creates the configure script. For compiling CDET with file system support
only, simply type
./configure
for darcs support add the option --enable-darcs=<darcs_dir> (where <darcs_dir>
is the directory of your darcs sources); for subversion support add the option
--enable-svn. By typing
./configure --help
you can see a list of all available options. The configure script shows a short
summary of the CDET compile options. Now a simple
make
should compile CDET. By
make install
you copy CDET into your /usr/local/bin directory.
1.4
This Manual
From here, this manual proceeds as follows. In Chapter 2 you get to know CDET
from the author perspective by a small example. Chapter 3 shows details about
CDET’s system architecture. Chapter 4 is directed to the people who formalize
consistency requirements; here, you learn what you should provide CDET with
in order to get meaningful output. Chapter 5 includes a detailed description of
CDET’s syntax in a rather technical manner. Finally, in Chapter 6 lists some todo
items for future works. If you think some of these tasks is well suited to you or
you have other suggestions, please let me know — I will be happy to hear.
This is a manual only. Explaining formal details and algorithms behind CDET
is out of scope. You might want to look up such details in the research papers around CDET [SBRS03a, SBRS03b, SBRS04b, SSBS04, SBRS04c, SBRS04a,
SBBS05]. Notice that report generation as described in [SBRS03a, SBRS03b,
SBRS04b, SSBS04] is slightly out of date, though the general ideas still hold. If
you prefer the whole story as one large volume, see my PhD thesis [Sch04].
Chapter 2
Working with CDET
In this chapter you learn how to use the command line interface of CDET. Currently, there is no GUI support; so some of the interactive features are still not
accessible. This chapter is meant for authors, who do not need to know the formal
details about rules etc. Chapter 3 introduces the rˆole model of CDET.
For illustration, we assume a (ridiculously simple) toy example, which is also
used in some of my papers.
Example 2.1 Suppose you archive manuals over a long period of time. Documents (and manuals) reference manuals through keys (see Fig. 2.1). Since names
and kinds of manuals may change over time, you need key resolvers mapping keys
to their semantics, i.e., manual kind and name. Multiple key resolvers may exist.
Their actual names are hidden from authors. To ensure consistency, we require
that (two-step) links to manuals are valid (φ1 ) and names and kinds of manuals
are invariant over time (φ2 ). A link to a key k is valid if k is defined in a key
resolver and this definition points to an existing manual of the correct kind.
Fig. 2.1 also shows a repository that contains a plain text document doc1.txt
and three XML documents: a key resolver keys.xml, and two manuals man1.xml
and man2.xml. The check-in at state 2 causes three inconsistencies: (1) the reference to kaA3 violates φ1 because the kind of man1.xml is different from the kind
of kaA3’s key definition; (2) the reference to kaA2 violates φ1 because the key
key
documents
kind+
key resolvers
name
key
manuals
State 1 doc1.txt ...as shown in manual kaA3 ...
keys.xml <kDef key="kaA3"
kId="man1.xml"
kKind="technical M."/>
man1.xml <man kind="technical M."> ...
man2.xml <man kind="field M."> ...
State 2 doc1.txt ...as shown in kaA3 and kaA2 ...
man1.xml <man kind="field M."> ...
Figure 2.1: Example repository
5
6
Working with CDET
resolver does not contain a definition for kaA2; (3) the state transition violates φ2
because the kind of man1.xml has changed.
2
Suppose, we have already formalized the rules φ1 and φ2 as consistency rules.
Then do a
cdet --compile example_project.xml
in order to compile and optimize our rules, where example_project.xml contains
the project description of our example document engineering project.1 Rule compilation includes type checking; thus, it may fail if your rules include type errors.
Technically speaking, rule compilation creates some Haskell files and compiles
them via GHC. Finally, a new project-specific binary is compiled, say cdetExProj
for example. For large projects, compilation via GHC may take some time; so be
prepared to have some coffee at hand. You have to recompile the rules whenever
you change them.
After compilation, you can check your repository for consistency. Either you
can do this offline by issuing2
cdetExProj --check example_project.xml
or by including the above line in a so-called pre-commit hook script, in order to
check consistency online at each check-in. Using DARCS, you issue
darcs setpref test "cdetExProj --check example_project.xml"
at the command line (make sure you are in your DARCS repository). Of course,
you can edit the preferences file of your DARCS repository directly, see the DARCS
manual [Rou05] for further instructions. Currently, for subversion some strange
problems with the transaction mechanism currently prevent online consistency
checking.
Notice that during consistency checking in online mode, the repository is locked;
during consistency checking in offline mode, the repository is free for check-ins.
Consistency checking generates an S-DAG for each consistency rule. You can
“display” the S-DAGs on the text console doing a
cdetExProj --show example_project.xml [<repository state>]
The optional argument <repository state> can be used to display the S-DAGs
for this repository state only. For example, cdetExProj --show example_project.xml 2
displays the S-DAGs for the second repository state.
S-DAGs visualize inconsistencies and possible repair actions. The structure of
an S-DAG resembles that of a consistency rule. Nodes represent logical connectives
or atomic formulae; edges target the subformulae of a connective. We find inner
∃ universal quantifiers ,
∀ conjunctions ,
∧ and
nodes for existential quantifiers ,
∨ Leafs represent predicates, i.e., atomic formulae.
disjunctions .
Edges below quantifier nodes carry bindings of variables to values. A predicate
node occurs as a leaf only. It contains an atomic formula φ responsible for an
inconsistency and the truth value of φ.
∀ represents inconsistencies reFrom the user perspective, a universal node sulting from failure prone document content, where each edge blames a value for
∃
inconsistencies represented by the edge’s target S-DAG. An existential node 1
For each project, you need a project description, which imports the consistency rules and
sets some options.
2
Don’t worry about the path to the actual repository — it is included in the project description.
7
t 2
S−DAG for
rule φ 1
x {dId = doc1.txt, dState = 2}
k kaA2
d
k kaA3
= kaA3, kId = man1.xml,
{key
{
kKind = technical M.
False: k = key(d)
{
d
m
m
*
{k [kaA2
kaA3] 1},
{d.key [kaA3
kaA2] 5}
{
= kaA3, kId = man1.xml,{
{key
kKind = technical M.
= man1.xml, dState = 2,
{
{dId
kind = field M.
False: kind(m) = kKind(d)
Abandoned
{{m.kind [field M.
t2 2
S−DAG for
rule φ 2
technical M.] 2}}
t1 1
Abandoned
m2
*
m1
= man1.xml, dState = 1,
{
{dId
kind = technical M.
m2
= man1.xml, dState = 2,
{
{dId
kind = field M.
Abandoned
False: kind(m 1 ) = kind(m 2 )
{{m2.kind [field M.
technical M.] 2}}
Figure 2.2: Example S-DAGs
represents an inconsistency resulting from missing document content. This content could be either really missing or it could be regarded as missing because one
∧ and universal
of the edges carries defective content. Below conjunction nodes ∀ each S-DAG must be repaired. In contrast, it is sufficient to repair only
nodes ∨ and existential node ,
∃ respectively.
one S-DAG below a disjunction node At state 2 CDET generates the S-DAGs shown in Fig. 2.2. In the leaves
you find atomic formulae responsible for inconsistencies. At the edges below
quantifier nodes you find values blamed for inconsistencies. Let us read the SDAG for φ1 from its root to the leaves. At the second repository state (t 7→ 2)
you have an inconsistent document doc1.txt in your repository (x 7→ {dId =
doc1.txt, dState = 2}). Notice that CDET identifies a document by its name
dId and check-in state dState. The document doc1.txt contains two inconsistent
key references (k 7→ kaA2 and k 7→ kaA3). Let us first follow the left hand edge.
The key reference to kaA2 is inconsistent because the repository does not include
an appropriate key definition. You only have a key definition for the key kaA3
(d 7→ {key 7→ kaA3, . . .}). The left hand leaf indicates that the referenced key k is
different from the defined key key(d), which is due to the above bindings. Next,
we follow the right hand edge for k’s universal node. Here CDET finds a matching
key definition, which is the same as above. There is also a manual man1.xml in
the repository that looks promising (m 7→ {dId = man1.xml, dState = 2, . . .}).
This manual causes, however, an inconsistency because its kind (kind(m)) is different from the kind of the key definition (kKind(d)). This is indicated by the
Working with CDET
8
t 2
KEEP
S−DAG for
rule φ 1
Chg
x {dId = doc1.txt, dState = 2}
Del {dId = doc1.txt, dState = 2}
k kaA3 Del kaA3
kaA3 k kaA2
= kaA3, kId = man1.xml,
{key
{
kKind = technical M.
Chg key = kaA2, kId = man1.xml,
{kKind = technical M.
{
d
False: k = key(d)
{
= kaA3, kId = man1.xml,{
{key
kKind = technical M.
d
m
= man1.xml, dState = 2,
{
{dId
kind = field M.
Chg dId=man1.xml, dState = 2,
{ kind = technical M.
{
m
*
{k [kaA2
kaA3] 1},
{d.key [kaA3
kaA2] 5}
{
False: kind(m) = kKind(d)
Abandoned
{{m.kind [field M.
S−DAG for
rule φ 2
t2 2
t1 1
KEEP
KEEP
m1
Abandoned
m2
*
Abandoned
m2
technical M.] 2}}
= man1.xml, dState = 1,
{
{dId
kind = technical M.
KEEP
dId = man1.xml, dState = 2,
kind = field M.
Chg dId=man1.xml, dState = 2,
kind = technical M.
{
{
{
{
False: kind(m 1 ) = kind(m 2 )
{{m2.kind [field M.
technical M.] 2}}
Figure 2.3: Example augmented S-DAGs
right hand leaf. Sure, the repository contains a second manual man2.xml, which
would, however, cause more efforts for repair! S-DAGs will contain repairs that
impose minimal changes to the repository and preserve check-ins if possible. CDET
denotes S-DAGs that are not worth repairing by a special leaf Abandoned .
The S-DAG in Fig. 2.2 lacks concrete repair actions, i.e., to add, change,
or delete document content. In order to support interactive repair, CDET can
augment S-DAGs by repair actions after consistency checking. Simply issue
cdetExProj --augment example_project.xml [<repository state>]
at the command line. By the optional argument <repository state> you can
choose the repository state for which the S-DAGs should be augmented. If this
argument is not given, augmented S-DAGs contain repairs for all repository states.
During S-DAG augmentation, the repository is not accessed (and, therefore, not
locked).
Fig. 2.3 shows the augmented S-DAGs for the repository state 2; you can
view them by another cdetExProj --show example_project.xml. In addition,
cdetExProj --augment generates quite nice SVG pictures, which you can view
with your favorite WWW browser, and a structured XML output of the S-DAGs.
The name of the SVG picture is φ1 _SDAG.xml.svg for rule φ1 and φ2 _SDAG.xml.svg
for rule φ2 , respectively. You find these files in a directory given in the project
description file. Fig. 2.4 shows the generated SVG files. They look a bit different
from the ideal S-DAGs because currently, CDET’s implementation does not use
9
Figure 2.4: Example generated SVG files
Working with CDET
10
sophisitcated graph drawing algorithms. I expect this to change in the near future. In the SVG graphics each node is identified by a unique number that may
be referenced. In the S-DAG for φ1 you find the lower right leaf labeled Ref -> 6
— its incoming edge actually points to the node labeled by the number 6, which
you find on the left hand side. For efficiency reasons, S-DAGs are not fully shared.
In an augmented S-DAG, quantifier edges carry repair actions marked grey. An
action proposes to either add a value to (Add), or change a value within (Chg), or
delete a value from the sphere of this quantifier (Del). An action KEEP indicates
that the value must not be changed. For our example, CDET proposes to change
the key reference kaA2 to kaA3 or to delete the document doc1.txt. From an
augmented S-DAG you can choose repair actions interactively. CDET applies a
chosen repair action to an S-DAG. Since CDET’s current implementation lacks a
graphical user interface, this feature is not available at date, i.e., it is implemented
but you cannot access it.
Notice that, still, it is unclear which repair actions in an S-DAG must be applied
together in order to resolve all inconsistencies. You can instruct CDET to generate
the repair collection for both consistency rules, thus:
cdetExProj --derive example_project.xml [<repository state>]
By the optional argument <repository state> you can choose the repository
state for which the repair collection should be derived. But notice that the augmented S-DAGs must include this state, otherwise you will get an empty repair
collection. If this argument is not given, the repair collection will contain repairs
that derive all inconsistencies at all repository states (which is probably not what
you want).3 During repair derivation, the repository is not accessed (and, therefore, not locked). In contrast to S-DAG augmentation, you will notice that repair
derivation can take a long time because of the combinatorial explosion of repair
alternatives. CDET tries to reduce them but it cannot succeed in all cases.
The repair collection contains alternative repair sets, each including repairs that
are necessary and sufficient to repair all inconsistencies in the repository. CDET
guarantees that repairs within each set do not contradict each other and altogether
resolve the inconsistencies. Repairs may, however, introduce new inconsistencies.
Fig. 2.5 shows some repairs derived from our example S-DAGs at state 2. The
first component of a repair constitutes its sphere, the second component denotes
the proposed action. For example, the repair repk affects the variable k in the
rule φ1 . The repair proposes to change the key kaA2 into kaA3 in the document
doc1.txt at repository state 2. The repair resolves one inconsistency for a high
priority rule, may violate rule φ1 , and costs 1.4
The repair collection below shows how the repairs in Fig. 2.5 are best combined
in order to resolve all inconsistencies at state 2.


1.) {repk , repm,m2 }




2.) {repd , repm,m2 }


 3.) {repkaA2 , repm,m2 } 
4.) {repdoc1 , repm2 }
3
4
Also derivation will need plenty of time.
Repairs are rated by a simple cost model, based on natural numbers.
11
repk
= Rep {φ1 (k)}
refs(x)
{t 7→ 2, x 7→ {dId = doc1.txt, dState = 2}}
Chg kaA2
kaA3
Rate {1 (high)} {φ1 } 1
repd
= Rep {φ1 (d)}
concatMap(t, kDefs, repResDs(t))
{t 7→ 2}
Chg {key = kaA3, . . .}.key
kaA2
Rate {1 (high)} {φ1 } 5
repkaA2 = Rep {φ1 (k)}
refs(x)
{t 7→ 2, x 7→ {dId = doc1.txt, dState = 2}}
Del kaA2
Rate {1 (high)} {φ1 } 0
repdoc1 = Rep {φ1 (k)}
repDs(t)
{t 7→ 2}
Del {dId = doc1.txt, dState = 2}
Rate {3 (high)} {φ1 } 0
repm2
= Rep {φ2 (m2 )}
repManDs(t2 )
Chg {dId = man1.xml, . . .}.kind
Rate {1 (medium)} {φ1 , φ2 } 2
{t2 7→ 2}
technical M.
repManDs(t)
{t 7→ 2}
repm,m2 = Rep {φ1 (m), φ2 (m2 )}
Chg {dId = man1.xml, . . .}.kind
technical M.
Rate {2 (medium), 1 (medium)} {φ1 , φ2 } 2
Figure 2.5: Repairs generated for the rules φ1 and φ2
The collection implies a preference between the repair sets. In the example, you
change a document rather than deleting it. Changing a text document is preferred
to changing a key definition within a key resolver. In addition, you prefer deleting
some content within a document to deleting a whole document. Of course, you
can define your own preferences.
Chapter 3
CDET System Architecture
Fig. 3.1 illustrates the architecture of CDET. CDET distinguishes four rˆoles: authors, the project manager, the rule designer, and the language designer.
Authors use the DMS/RCS as usual, except if you formalize strong rules (see
below).
For specific projects, the project manager chooses consistency rules. In addition, he defines the ordering metrics for sorting the repair collection and global
options like the repository and the repository type, e.g., DARCS or subversion.
The rule designer formalizes consistency rules and hints, using a variant of
predicate logic. Rules define what consistency means — they reflect wishes from
an “administrator” perspective. CDET distinguishes between strong rules, which
must be adhered to, and weak rules, which may be violated. Hints guide repair
generation. In addition, the rule designer creates templates for documents. These
will be DTDs or Schemas, if XML is used as document format.
At a consistency check, CDET generates an S-DAG for each consistency rule.
CDET augments S-DAGs at request. From an augmented S-DAG authors can
choose repairs and apply them to the documents in the repository. Alternatively,
CDET can derive one ordered repair collection from all S-DAGs. The metrics for
sorting the collection is defined by the project manager.
Consistency rules use functions and predicates from domain-specific languages.
This makes the rules independent of concrete document formats, which can be
changed without affecting rules. During compilation, CDET checks consistency
rules for well-typedness w.r.t. the functions and predicates used. For convenience,
CDET provides a basic language Prelude, which defines fundamental functions,
predicates, and types.
In user-defined languages a language designer defines domain-specific functions, predicates, and types. The semantics of functions and predicates is defined
in Haskell [PJ03] — a statically typed purely functional programming language.
Haskell provides access to other libraries via a foreign function interface [C+ 03].
Such libraries offer sophisticated functionality, e.g., for parsing documents or
heuristics for semantic content analysis. Formal document types (usually corresponding to document templates) can be expressed by record or variant types.
This makes CDET independent of any particular document format and facilitates
12
13
access
external libs
(XPath, heuristics, ...)
Haskell
annotated
predicate logic
implemented
language
functions
types
predicates
language
designer
partly
derived
formalized
use & type check
consistency
rules & hints
document
rule templates
designer
project
manager
choose
project
templates
cdet −−compile
project
rules & hints
instance of
documents
author
choose
& apply
check in
consistency
check
cdetPrj
−−check
check out
repository
(managed by DMS/RCS)
S−DAGs
1.) repair set
2.) repair set
...
cdetPrj −−derive
augmented
S−DAGs
cdetPrj −−augment
Figure 3.1: CDET System Architecture (ovals mark fixed components; rectangles
mark customizable components)
heterogeneous repositories. If XML is used as document format, document types
and parser functions can be derived from DTDs, e.g., via HaXml [WR99].1
1
CDET uses an adapted version of HaXml that handles PackedStrings instead of normal
Strings.
Chapter 4
What You need to Input into
CDET?
In this chapter we explore the means you need for managing consistency for our
example, namely a project description, the consistency rules, and a language.
CDET’s current implementation uses XML for the concrete syntax. Also, you have
to edit these XML files by yourself; I plan, however, to develop some graphical
tools for this purpose. Using a DTD-aware XML editor (like emacs) already
alleviates editing XML files. This chapter is not meant for authors; they are not
confronted by the formal issues described here. This chapter is meant for rule
designers and language designers, who are experts in first-order logic and Haskell,
respectively. Due to the early prototype implementation, some things will appear
a bit complicated to you. I am sure that this will change in the future as CDET
evolves.
For our example project, suppose you have the following directory structure:
darcs/
dtd/
out/
haskell/
xml/
4.1
contains the DARCS repository you use for managing documents
contains two DTDs:
manual.dtd for manuals, resolver.dtd for key resolvers
here you will find the output of CDET (S-DAGs and repairs)
is your temporal directory for CDET; here the project-specific
binary is placed after compilation. Also the directory contains
a subdirectory cache
contains three XML files (project description, rules, language)
CDET Project Description
Let us first review the project manager ’s task. CDET uses the project description
as the entry point to your project; each project should have its own project description. For clarity, I do not recommend sharing project descriptions across projects
(in contrast to rules and languages). For our example, we use the following project
description file ManualsCheck.xml (located in the subdirectory xml/):
14
4.1 CDET Project Description
15
<consistencycheck name="Manuals"
reportdtd="../../../src/dtd/report.dtd"
tmpdir="../haskell/"
outputdir="../out/"
repositorybase="../darcs/"
repositorytype="darcs">
<performance usecache="true"
fastprelude="true"
incremental="true"
filterrules="true"
optimizerules="true"/>
<repair partialResolution="false" maxsets="10">
<metrics><![CDATA[
-- sum metrics
repairMetrics rs1 rs2
= sum (map rat rs1) >= sum (map rat rs2)
where rat rep = changeRat rep
+ offendsRat rep
+ costRat rep
-- punish deletion
changeRat rep = case change rep of
ActDelete v -> if isDocVal v ||
isDocListVal v
then -15 else -10
_ -> 0
-- punish offending rules
offendsRat rep = - (length (offends (rating rep)))
-- costs of a repair
costRat rep = case repaircost (rating rep) of
Just c -> -c
Nothing -> 0
]]></metrics>
</repair>
<!-- here are the CDET sources -->
<cdetdir path="../../../src"/>
<!-- import these rules -->
<importrules path="ManualsRules.xml"/>
</consistencycheck>
Let us take a closer look at the XML elements above:
<consistencycheck name="Manuals"
reportdtd="../../../src/dtd/report.dtd"
tmpdir="../haskell/"
outputdir="../out/"
repositorybase="../darcs/"
repositorytype="darcs">
First, we say that our project is called Manuals. The DTD for the consistency report produced by CDET can be found in the directory ../../../src/dtd/ and is
called report.dtd. You can use relative or absolute paths as you like. The temporal directory for CDET is ../haskell/. Here CDET also places the project-specific
16
What You need to Input into CDET?
binary after a successful cdet --compile; you may, however, copy the projectspecific binary whereever you like. CDET places its generated XML files in the
directory ../out/. There you will find (after appropriate commands) for each rule
φ its S-DAG structure (file name φ_SDAG.xml), the corresponding SVG file (file
name φ_SDAG.xml.svg), and the overall repairs (file name overallRepairs.xml).
The darcs repository holding our project documents is located in the directory
../darcs/.
<performance usecache="true"
fastprelude="true"
incremental="true"
filterrules="true"
optimizerules="true"/>
Above, you find performance options. I recommend to turn all performance options on, i.e., true. For our project, we use the internal caches of CDET (for
each function or predicate you can specify whether it should be cached). By
fastprelude you tell CDET to evaluate Prelude functions and predicates internally. The basic language Prelude contains large part of Haskell’s Prelude, see
App. A. We use incremental evaluation and only check those rules that might
be touched by a check-in. In addition, we let CDET optimize our rules, which
essentially means to push quantifiers into the rules.
<repair partialResolution="false" maxsets="10">
<metrics><![CDATA[
-- sum metrics
repairMetrics rs1 rs2
= sum (map rat rs1) >= sum (map rat rs2)
where rat rep = changeRat rep
+ offendsRat rep
+ costRat rep
-- punish deletion
changeRat rep = case change rep of
ActDelete v -> if isDocVal v ||
isDocListVal v
then -15 else -10
_ -> 0
-- punish offending rules
offendsRat rep = - (length (offends (rating rep)))
-- costs of a repair
costRat rep = case repaircost (rating rep) of
Just c -> -c
Nothing -> 0
]]></metrics>
</repair>
Above, we have specified options for repair generation. We turn off partial inconsistency resolution, which essentially means to generate a smaller repair collection.
The repair collection will contain at most 10 alternative repair sets. In the metric
element you find the Haskell code of the metric used to sort the repair collection.1
The above metric counts potentially violated rules (negatively) and subtracts the
repair cost, where deleting document content is punished by subtracting 10 and
1
Notice the use of <![CDATA[ in order to avoid XML parsing errors in the Haskell code.
4.2 Consistency Rules
17
deleting a document is punished by subtracting 15. In general, the punishment
of deletion should be greater than the cost of the most expensive hint. In fact,
deleting content (or even a whole document) is a fall-back solution that should be
considered only if no other repair is possible.
Technically, a metric is a Haskell function
repairMetrics :: [Repair] -> [Repair] -> Bool
that indicates whether we prefer the first list of repairs over the second list (for
simplicity, a repair list represents one alternative repair set). For defining metrics
you can use the following Haskell data types:
data Repair = Repair {vars :: [(Id,VSym)],
(rule identifiers and)
(variables x therein to repair)
ident :: (Id,Int), (unique identifier for a repair)
(original rule, unique number (for this rule))
domain :: Term,
(the term identifying the domain of x)
assign :: [(VSym,Value)],
(variable assignment for the domain)
change :: RepairAction, (the actual repair action)
rating :: Rating}
(rating for the repair)
data RepairAction =
ActDel Value
(delete value)
| ActChange Value Value
(change value from to)
| ActChangeField Value FSym Value
(change a field in a value)
| ActAdd Value
(insert value)
| ActChangeSuchThat PSym [Value] Bool
(we do not know how to set the value)
data Rating = Rating {offends :: [Id],
(possibly impacted rules)
resolves :: [(Int,Int)],
(how many inconsistencies resolved at which importance level)
repaircost :: Maybe Cost}
(repair costs)
In addition, isDocVal :: Value -> Bool determines whether a value is a document; isDocListVal :: Value -> Bool determines whether a value is a list
containing documents.
<!-- here are the CDET sources -->
<cdetdir path="../../../src"/>
<!-- import these rules -->
<importrules path="ManualsRules.xml"/>
Finally, we tell CDET about its own sources and import some rule sets. You can
specify as many rule sets as you like. ManualsRules.xml is also located in the
xml/ subdirectory and contains our example consistency rules.
4.2
Consistency Rules
We now go deeper into the formalization of consistency rules — the rule designer ’s
task. First, we explain how rules are formalized using the syntax of predicate logic.
Second, we show our example rules in CDET’s XML syntax.
18
What You need to Input into CDET?
φ1 Always links must be valid : At each state t, we have for all documents x at t,
that for all their referenced keys k there exists a key definition d (in one of the
resolvers) for k and there exists a manual m with name and kind as defined by d.
∀ tKEEP ∈ repStates • ∀ x ∈ repDs(t) • ∀ k ∈ refs(x) •
∃ d ∈ concatMap(kDefs, repResDs(t))
• ∃ m ∈ repManDs(t)
•
{k ; key(d) False 1 },
k = key(d)
{d.key ; k False 5}
∧
dId(m) = kId(d)
{{m.dId ; kId(d) False 3}}
∧
kind(m) = kKind(d)
{{m.kind ; kKind(d) False 2}}
φ2 Names and kinds of manuals are invariant over time: At all states t1 we have
for all manuals m1 at t1 that at all future states t2 there exists a manual m2 that
has the same name and the same kind as m1 .
KEEP
∀ tKEEP
∈ repStates • ∀ t2
∈ repStates •
1
¬
(t
≤
t
)
∨
1
2


∀ mKEEP
∈ repManDs(t1 ) • ∃ m2 ∈ repManDs(t2 ) •
1
 dId(m1 ) = dId(m2 )
{{m2 .dId ; dId(m1 ) False 3}} 


∧

kind(m1 ) = kind(m2 ) {{m2 .kind ; kind(m1 ) False 2}}
Figure 4.1: Example rules φ1 and φ2 with hints
Consistency rules are statements about repository states.2 The rule designer
formalizes consistency rules in a variant of temporal logic, based on the logic
proposed in [AHV96]. Instead of temporal operators like since or until, explicit
quantification over repository states is used in rules. Consistency rules mostly
correspond to standard first-order formulae, where the domain of a quantifier is
described by a term. As usual, rules use functions and predicates, which are
defined in languages (see Sect. 4.3).
For our example we define two rules as shown in Fig. 4.1. For clarity, we deal
with hint annotations (given in curly braces) later in this section.
Rule φ1 first quantifies over all repository states, provided by repStates;
repDs(t) returns the current documents for a state t. For each document x, the
variable k comprises the referenced keys, computed via refs(x). Key definitions in
the resolvers are determined with the help of the higher-order function concatMap.
It applies kDefs to each key resolver, computed by repResDs(t). Applied to a key
resolver, kDefs returns a list of key definitions, which are finally concatenated.
Thus, d ranges over the key definitions from all key resolvers; we require that
the referenced key k equals the key defined by d. The variable m ranges over all
manuals at the state t, computed by repManDs(t). The name of the manual m
must equal the name d points to, and the kind of m must equal the kind d points
to. Rule φ2 twice quantifies over time because two different versions of a manual
have to be related: the old version at state t1 and the new version at state t2 .
Repair generation requires domain-specific guidance because CDET supports
arbitrary predicates. For example, if an atomic formula p(x, y) is violated, CDET
2
A state represents a repository snapshot at a given time.
4.2 Consistency Rules
19
cannot anticipate how to change x and y in order to fulfill p(x, y). Therefore,
rule designers may annotate an atomic formula by a collection of hints, containing
alternative hint sets. Within a hint set, all hints are evaluated simultaneously.
Formally, a hint x ; e b c proposes to change the variable x to the term e if the
atomic formula evaluates to the truth value b; the repair imposes the cost c. If
the type of x is a record type, the hint x.f ; e b c proposes to change the field f
of x.
In order to repair a violated atomic formula k = key(d) in rule φ1 , the hints in
Fig. 4.1 propose to either change k to key(d) or change the field key of d to k. The
former repair imposes a cost of 1; the latter repair costs 5. We consider changing a
key definition more expensive because this might cause new inconsistencies regarding other referenced keys. In fact, the latter repair will be preferred if changing a
single key definition resolves multiple inconsistencies that could alternatively be
resolved by changing multiple manuals; in the above case changing a single key
definition is cheaper than changing six manuals. Notice that in φ1 the manuals
are “blamed” for inconsistent manual identifiers and kinds; the hints affect the
variable m only. A quantifier annotation tKEEP prevents S-DAG generation from
considering any repairs for the variable t. Of course, we cannot change repository
states, nor can we change old manual versions m1 .
Let us now formalize rule φ1 in CDET’s concrete XML syntax. Recall that for
our example we imported the rules from the file ManualsRules.xml, which starts
as follows:
<rules>
<importlanguage path="../../prelude/RulePrelude.xml"/>
<importlanguage path="ManualsLanguage.xml"/>
For formalizing rules, we use two languages: The predefined language Prelude
(defined in the file RulePrelude.xml) contains useful basic types, functions, and
predicates like Document, concatMap, and = (see App. A). The domain-specific
language in ManualsLanguage.xml contains some types and functions, specific for
our example project, e.g., a document type and a parser function for manuals.
<rule id="phi1" date="2004-08-16">
<meta weight="70" weak="true">
<desc>The two-step links to manuals are valid</desc>
</meta>
A rule starts with some meta data, e.g., its name (here phi1) and its definition
date (here 16 August 2004). We also assign the weight 70 to φ1 and tell CDET
that our example rule may be violated (weak="true"). If we prohibited violations,
CDET would not permit any check-ins to the repository that violate φ1 .
The actual formula begins with the tag <formula>. Let us now express the
quantifier cascade for the variables t, x, k, d, and m
∀ tKEEP ∈ repStates • ∀ x ∈ repDs(t) • ∀ k ∈ refs(x) •
∃ d ∈ concatMap(kDefs, repResDs(t)) • ∃ m ∈ repManDs(t) •
in XML:
20
What You need to Input into CDET?
<formula>
<forall action="keep" id="t">
<term>
<fapply id="repStates"/>
</term>
<formula>
<forall id="x">
<term>
<fapply id="repDs">
<term>
<var id="t"/>
</term>
</fapply>
</term>
<formula>
<forall id="k">
<term>
<fapply id="refs">
<term>
<var id="x"/>
</term>
</fapply>
</term>
<formula>
<exists id="d">
<term>
<fapply id="concatMap">
<term>
<sym id="kDefs"/>
</term>
<term>
<fapply id="repResDs">
<term>
<var id="t"/>
</term>
</fapply>
</term>
</fapply>
</term>
<formula>
<exists id="m">
<term>
<fapply id="repManDs">
<term>
<var id="t"/>
</term>
</fapply>
</term>
We express universal quantification by forall and existential quantification by
exists. Both elements carry the mandatory attribute id denoting the quanti-
4.2 Consistency Rules
21
fied variable and the optional attribute action denoting a quantifier annotation.
Immediately after the quantification tag we use the element term to denote the
quantifier sphere term. There fapply denotes the application of a function to
argument terms and var denotes a variable. Both elements carry the mandatory
attribute id denoting the function name and variable name, respectively. By sym
we denote an un-applied function that serves as a parameter to a higher-order
functions, e.g., <sym id="kDefs"/>. The subformula of a quantification is introduced by another formula element.
Let us concentrate on the three-way conjunction below the existential quantifier
for m:
k = key(d)
∧
dId(m) = kId(d)
∧
kind(m) = kKind(d)
{k ; key(d) False 1 },
{d.key ; k False 5}
{{m.dId ; kId(d) False 3}}
{{m.kind ; kKind(d) False 2}}
In CDET’s XML syntax we use and for conjunctions and or for disjunctions, where
both tags can carry arbitrarily many subformulae:
<formula>
<and>
<formula>
<papply id="==">
<term>
<var id="k"/>
</term>
<term>
<fapply id="key">
<term>
<var id="d"/>
</term>
</fapply>
</term>
<hintalternative>
<set condition="false" id="d" field="key" repaircost="5">
<term><var id="k"/></term>
</set>
</hintalternative>
<hintalternative>
<set condition="false" id="k" repaircost="1">
<term><fapply id="key">
<term><var id="d"/></term>
</fapply>
</term>
</set>
</hintalternative>
</papply>
</formula>
<formula>
<papply id="==">
<term>
22
What You need to Input into CDET?
<fapply id="dId">
<term>
<var id="m"/>
</term>
</fapply>
</term>
<term>
<fapply id="kId">
<term>
<var id="d"/>
</term>
</fapply>
</term>
<hintalternative>
<set condition="false" id="m" field="dId" repaircost="3">
<term><fapply id="kId">
<term><var id="d"/></term>
</fapply></term>
</set>
</hintalternative>
</papply>
</formula>
<formula>
<papply id="==">
<term>
<fapply id="kind">
<term>
<var id="m"/>
</term>
</fapply>
</term>
<term>
<fapply id="kKind">
<term>
<var id="d"/>
</term>
</fapply>
</term>
<hintalternative>
<set condition="false" id="m" field="kind" repaircost="2">
<term><fapply id="kKind">
<term><var id="d"/></term>
</fapply></term>
</set>
</hintalternative>
</papply>
</formula>
</and>
</formula>
Predicate application via papply corresponds to function application. A predicate application can carry alternative hint sets hintalternative, each of which
may include arbitrarily many hints (element set). Within the element set, the
4.3 Languages
23
attribute condition denotes the truth value of the predicate application that
should be inverted; id denotes the variable to change; field denotes the record
field to change (if appropriate); repaircost denotes the cost for repair. The set
element carries an arbitrary term that calculates the new value for the variable
(attribute id above).
Finally, we close all open tags:
</and>
</formula>
</exists>
</formula>
</exists>
</formula>
</forall>
</formula>
</forall>
</formula>
</forall>
</formula>
<actions/>
</rule>
<!-- rule phi2 omitted for brevity -->
</rules>
4.3
Languages
Our example rules use some symbols that are not defined yet, e.g., the symbol
“=” or the symbol “repStates.” These symbols are defined in languages. For
convenience, CDET provides the predefined language Prelude, which defines many
useful types and symbols (see App A).3 Therefore, you only need to define a
few symbols and types for specific projects. In this section we first review our
example language in a formal abstract syntax. Second, we explore the concrete
XML syntax, which again will be a bit more verbose.
For our example we define the language ManualsLanguage, which contains
symbols and types as shown in Fig. 4.2. ManualsLanguage imports the predefined language Prelude, the relevant part of which is also shown in Fig. 4.2. For
simplicity, our formalism neglects import relations between languages. We let <
denote an explicit subtype relation between record types; a record type may have
multiple supertypes.
The variant list type [α] is declared as usual in functional programming [MTH90,
PJ03]; the variant constructors are [] (empty list) and (:) (add an element to the
front of a list). The record type Document stands for a formal document, carrying
a name (of type String) and a check-in state (of type State). That way we distinguish different document versions. CDET requires that each document type is
a subtype of Document. This is important for efficient consistency checking. The
record type ResD resembles the key resolver structure (see Fig. 2.1 on pg. 5). ResD
inherits all record labels from its supertype Document. Our notion of subtyping
3
Roughly, Prelude defines large part of Haskell’s Prelude, hence the name.
24
What You need to Input into CDET?
Extract from language Prelude (predefined)
Type definitions
String
[α]
=
[] | (:) α×[α]
Document = Document {dId : String, dState : State}
Predicate symbol definitions
=
: ∀α.α×α → Bool
≤
: ∀α.α×α → Bool
<
: ∀α.α×α → Bool
Function symbol definitions
concatMap : ∀α, β.(α → [β])×[α] → [β]
repStates : [State]
strings
Haskell like lists
documents
equality
less than or equal
less than
Haskell like concatMap
all repository states
Language ManualsLanguage, defined by the language designer (imports Prelude)
Type definitions
ManD < {Document} = Man {kind : String} manual documents
ResD < {Document} = Res {kDefs : [KDef]} key resolver documents
KDef
= KDef {key : String, kId : String, kKind : String}
key definitions
Function symbol definitions
repDs
: State → [Document] get all documents in the repository
repManDs
: State → [ManD]
get all manual documents
repResDs
: State → [ResD]
get all resolver documents
refs
: Document → [String] keys referenced in a document
Figure 4.2: Example types and symbols (the operator : separates a symbol from
its type, → separates the argument types of a function type or predicate type from
the result type, × separates argument types)
resembles XML Schema subtyping via extension and restriction [W3C01]. Record
and variant type definitions induce new function symbols (labels and constructors,
respectively). For example, ResD induces kDefs : ResD → [Item].
We regard predicate symbols as function symbols with a boolean result type,
denoted by Bool. Function symbols starting with rep provide access to documents
within the repository at a given state. For a document d, refs(d) returns all
referenced keys. concatMap(f, xs) applies the function f to each member of the
list xs and concatenates the result lists. Record labels can serve as parameter
for concatMap, e.g., in concatMap(kDefs, repResDs(t)). In addition, we have to
define the semantics of the symbols in our new ManualsLanguage; still no one
tells CDET what the symbols really do. For semantics definition, CDET employs
Haskell.
Let us define our ManualsLanguage in CDET’s concrete XML syntax. Recall that we have imported the file ManualsLanguage.xml in our rule definition.
ManualsLanguage.xml starts as follows:
<language id="ManualsLanguage">
<importlanguage path="../../prelude/RulePrelude.xml" qualifiedAs="P"/>
<importparser dtd="../dtd/manual.dtd" qualifiedAs="Man"/>
<importparser dtd="../dtd/resolver.dtd" qualifiedAs="Res"/>
4.3 Languages
25
Above, we import the basic language Prelude such that we can define our new
symbols and types in terms of functions and types defined in Prelude. In addition,
we generate two parsers for manuals and resolver documents from their DTDs.
CDET uses an HaXml [WR99] adaptation for generating appropriate Haskell types
and parsers. Unfortunately, these Haskell types do not exactly correspond to the
Haskell types generated by CDET, because HaXml lacks support for subtyping.
Thus, there will be still some work to do; but at least you do not have to struggle
with lexing and parsing issues . . . We import the generated parsers qualified in
order to avoid naming conflicts.
Next, we define our three new record types
Type definitions
ManD < {Document} = Man {kind : String} manual documents
ResD < {Document} = Res {kDefs : [KDef]} key resolver documents
KDef
= KDef {key : String, kId : String, kKind : String}
key definitions
in XML
<typedefs>
<typedef id="ManD">
<desc>Manual document</desc>
<record rcon="ManD">
<supers>
<gtype>
<tapply tcref="Document"/>
</gtype>
</supers>
<label id="kind" key="false">
<gtype>
<tapply tcref="PString"/>
</gtype>
</label>
</record>
</typedef>
<typedef id="ResD">
<desc>Resolver document</desc>
<record rcon="ResD">
<supers>
<gtype>
<tapply tcref="Document"/>
</gtype>
</supers>
<label id="kDefs" key="false">
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="KDef">
</tapply>
</gtype>
</tapply>
</gtype>
</label>
What You need to Input into CDET?
26
</record>
</typedef>
<typedef id="KDef">
<desc>Key definition</desc>
<record rcon="KDef">
<supers/>
<label id="key" key="true">
<gtype>
<tapply tcref="PString"/>
</gtype>
</label>
<label id="kId" key="true">
<gtype>
<tapply tcref="PString"/>
</gtype>
</label>
<label id="kKind" key="true">
<gtype>
<tapply tcref="PString"/>
</gtype>
</label>
</record>
</typedef>
</typedefs>
For a record type we specify a record constructor, which may be different from the
type constructor (as in Haskell). The supertypes of a record type are given by the
supers element. The element gtype denotes a ground type (i.e., a non-function
type); tapply denotes the application of a type constructor to ground types. For
example,
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="KDef">
</tapply>
</gtype>
</tapply>
</gtype>
means to apply the type constructor [] to the type KDef, which we would write
[] KDef or, more commonly, [KDef] in Haskell. After the record’s supertypes,
we specify the record labels. The label element carries an optional key attribute.
CDET compares record values by inspecting their key labels only. So, by specifying only a few key labels, you can speed up comparisons (and thus consistency
checking) significantly. But you must guarantee that records are distinguishable
by their key labels only, otherwise you get rather strange results! For document
types (i.e., subtypes of Document) it is safe to make all record labels non key labels
because the repository guarantees that given a repository state and a document
name, we find at most one document in the repository.
You might wonder about the type PString. For efficiency reasons CDET
uses an array based String type, in contrast to Haskell (where Strings are lists
of Characters). Internally, CDET uses the FastPacketString library from the
DARCS [Rou05] distribution.
4.3 Languages
27
Since we do not define new predicate symbols, we include
<predsymdefs/>
and go on with the definition of our first function symbol
repDs : State → [Document] get all documents in the repository
in XML:
<funsymdefs>
<funsymdef id="repDs">
<desc>Documents in the repository</desc>
<meta>
<docdep regex="./*.xml"/>
<docdep regex="./*.txt"/>
<cachemeta cached="true" reftrans="true">
<argdep num="0"/>
</cachemeta>
</meta>
<funtype>
<type>
<gtype>
<state/>
</gtype>
</type>
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="Document"/>
</gtype>
</tapply>
</gtype>
</funtype>
<code>
repDs repo t = ds
where ds=repDocs "./*.xml" t repo ++
repDocs "./*.txt" t repo
</code>
</funsymdef>
Above, we have defined the new function symbol repDs, which accesses the documents ending with *.xml or *.txt. The symbol is referentially transparent and
CDET should cache the symbol results in order to improve performance. In addition, the symbol result depends on its first argument (CDET starts counting by
zero) only. Referential transparency and annotations of accessed documents are
essential for efficient consistency checking. I plan to implement some syntactic
analysis that automatically retrieves these information out of the symbol’s source
code: for the moment, however, you have to provide these annotations by your
own.
After the symbol metadata we define the symbol type. Above, we say that
the argument type is State; the result type is a list of documents. The funtype
element denotes a function type consisting of some argument types and a result
type. The type element comprises both function types and ground types (element
What You need to Input into CDET?
28
gtype). A function type must always result in a ground type in order to ensure
the first-order properties of CDET’s logic.
Finally, we define the semantics of the symbol repDs by giving its Haskell source
code. The first argument of each function and predicate is the repository (which
is an abstract Haskell data type). Notice that this argument is implicit, i.e., it is
not part of the type declaration. Above, we simply retrieve some documents from
the repository with help of the repository access function
repDocs :: String -> State -> Repository -> [Document]
The first argument denotes a regular file pattern as you know it from your dayto-day work with files. Essentially, a regular file pattern is a regular expression
where the dot (“.”) is not escaped explicitly.
That was easy, wasn’t it. Let us look at the function repManDs, which should
return the manuals
repManDs : State → [ManD] get all manual documents
In CDET’s XML syntax we write:
<funsymdef id="repManDs">
<desc>Manuals in the repository</desc>
<meta>
<docdep regex="./man*.xml"/>
<cachemeta cached="true" reftrans="true">
<argdep num="0"/>
</cachemeta>
</meta>
<funtype>
<type>
<gtype>
<state/>
</gtype>
</type>
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="ManD"/>
</gtype>
</tapply>
</gtype>
</funtype>
<code>
repManDs repo t
= map (\ d -> mkMan d $ fromJust’ (err d) $ fromJust’ (err d) $
parseDoc d repo readXml) ds
where err d = "repManDs: internal error reading xml " ++ show d
ds=repDocs "./man*.xml" t repo
mkMan :: Document -> Man.Man -> ManD
mkMan d (Man.Man attrs _)
= ManD {manD_dId = document_dId d,
manD_dState = document_dState d,
manD_kind = Man.manKind attrs}
fromJust’ err (Just a) = a
4.3 Languages
29
fromJust’ err Nothing = error err
</code>
</funsymdef>
The Haskell source above looks a bit more complicated because we have to parse
manuals. Their names and check-in states are not sufficient; we need their structure. For accessing documents in the repository, you can use the repository access
function
parseDoc :: Document -> Repository -> (String -> a) -> Maybe a
It gets the document to parse, the repository, and a parser function as arguments.4
parseDoc retrieves the document from the repository and applies the parser function to its content (given as String). The parser function should convert the
document content into some data structure, which is returned if the document
exists. For convenience, CDET provides a standard parser for XML documents,
which is generated by HaXml automatically. Recall that we told CDET to do this
for manuals and key resolvers in the language header! Technically, CDET’s HaXml
generates an instance for the type class XmlContent, which provides the function
readXml :: (XmlContent a) => String -> Maybe a.
Unfortunately, Haskell and HaXml both lack subtyping support, such that
the types generated by HaXml and by CDET, respectively, are not compatible.5
HaXml generates the following types for manuals from the DTD manuals.dtd
(you can view them in the generated Haskell module haskell/DTD_manual.hs):6
data Man = Man Man_Attrs PackedString
deriving (Eq,Show)
data Man_Attrs = Man_Attrs
{ manKind :: PackedString
} deriving (Eq,Show)
CDET generates the following type for manuals from our language definition (you
can view them in the generated Haskell module haskell/ManualsLanguageTypes.hs):
data ManD = ManD {
manD_dId :: PString,
manD_dState :: State,
manD_kind :: PString}
deriving (Eq, Ord)
In Haskell CDET’s general document type looks as follows:
data Document = Document {
document_dId :: PString,
document_dState :: State}
deriving (Eq, Ord)
For bridging these types, we have defined the helper function mkMan above. I
admit that this is the most complex task in the work with CDET. But you have
to do this only once.
Let us risk a look at the definition of the function repResDs:
repResDs : State → [ResD] get all resolver documents
Here we have to bridge the following HaXml types (you can find them in the file
haskell/DTD_resolver.hs):
4
You might ask at what repository state the document is accessed — its the check-in state of
the document given as first argument.
5
I plan to overcome this severe shortcoming by a HaXml extension that supports a subset of
XML Schema and subtypes.
6
Notice that PString is just a type synonym for PackedString.
30
What You need to Input into CDET?
newtype Res = Res [KDef] deriving (Eq,Show)
data KDef = KDef KDef_Attrs Descr
deriving (Eq,Show)
data KDef_Attrs = KDef_Attrs
{ kDefKey :: PackedString
, kDefKId :: PackedString
, kDefKKind :: PackedString
} deriving (Eq,Show)
newtype Descr = Descr PackedString deriving (Eq,Show)
to the CDET types (also in haskell/ManualsLanguageTypes.hs)
data ResD = ResD {
resD_dId :: PString,
resD_dState :: State,
resD_kDefs :: [KDef]}
deriving (Eq, Ord)
data KDef = KDef {
kDef_kId :: PString,
kDef_kKind :: PString,
kDef_key :: PString}
deriving (Eq, Ord)
We do this by the function mkResD below.
<funsymdef id="repResDs">
<desc>resolver documents in the repository</desc>
<meta>
<docdep regex="./key*.xml"/>
<cachemeta cached="true" reftrans="true">
<argdep num="0"/>
</cachemeta>
</meta>
<funtype>
<type>
<gtype>
<state/>
</gtype>
</type>
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="ResD"/>
</gtype>
</tapply>
</gtype>
</funtype>
<code>
repResDs repo t
= map (\ d -> mkResD d $ fromJust’ (err d) $ fromJust’ (err d) $
parseDoc d repo readXml) ds
where err d = "repResD: internl error reading xml" ++ show d
ds=repDocs "./key*.xml" t repo
mkResD :: Document -> Res.Res -> ResD
mkResD d (Res.Res kdefs)
= ResD {resD_dId = document_dId d,
resD_dState = document_dState d,
4.3 Languages
31
resD_kDefs = map mkKDef kdefs}
mkKDef (Res.KDef attrs _)
= KDef {kDef_key = Res.kDefKey attrs,
kDef_kId = Res.kDefKId attrs,
kDef_kKind = Res.kDefKKind attrs}
</code>
</funsymdef>
What is left is the function refs, which scans an arbitrary document for referenced
keys.
refs : Document → [String] keys referenced in a document
Below, we tell CDET that a key begins with the letters kaA and is separated from
other text by white spaces. Sure, you can imagine more complex definitions than
the one below:
<funsymdef id="refs">
<desc>Key references inside a document.</desc>
<meta>
<docargdep num="0"/>
<cachemeta cached="true" reftrans="true">
<argdep num="0"/>
</cachemeta>
</meta>
<funtype>
<type>
<gtype>
<tapply tcref="Document"/>
</gtype>
</type>
<gtype>
<tapply tcref="[]">
<gtype>
<tapply tcref="PString"/>
</gtype>
</tapply>
</gtype>
</funtype>
<code>
refs repo d = fromJust’ (err d) (parseDoc d repo getRefs)
where err d = "refs: internal error reading document " ++ show d
getRefs :: String -> [PString]
getRefs content = map packString $ filter isKeyRef (words content)
isKeyRef w = keyprefix == (take 3 w)
keyprefix = "kaA"
</code>
</funsymdef>
</funsymdefs>
</language>
That’s it, you have defined your first CDET language.
Sure, defining languages suffers from poor tool support. In the future, I will
particularly focus on the gap between HaXml and CDET’s subtypes. When this
gap is closed, language definition will be almost as easy as rule formalization.
Chapter 5
Technical Details
In this chapter we take a deep technical look at the XML syntax of CDET, i.e., the
project description syntax, the language definition syntax, and the rule definition
syntax. For the S-DAG XML syntax and the repair collection syntax see the report
DTD in App. B.4. The syntax descriptions below directly correspond to XML
elements. Finally, in Sect. 5.4 we present CDET’s generic repository interface.
We present the grammars in “DTD tree style.” You find the child elements of
an element e below e and slightly indented. An element may be annotated by ?
(element is optional), * (element may appear arbitrarily often), + (element must
appear at least once), ++ (element must appear at least twice). If not otherwise
noted, the order of subelements is significant. An element description may be
omitted if the element was described before or will be described below.
5.1
Project Description XML Syntax
• consistencycheck
The configuration of your project
Required attributes: name (the name of your project), tmpdir (the temporal directory for CDET), outputdir (the output directory for CDET),
reportdtd (the DTD for consistency reports), repositorybase (the base
directory of your repository), repositorytype (your DMS/RCS, currently
supported are dir, darcs, and subversion)
– performance
Performance options
Required attributes: usecache (use CDET’s internal caches?), fastprelude
(use internal computation for Prelude functions?), incremental (check
consistency incrementally?), filterrules (only check rules influenced
by a check-in?), optimizerules (rewrite rules for faster consistency
checking?)
– repair
Options for repair
Required attributes: partialResolution (should we permit partial inconsistency resolution?)
Optional attributes: maxsets (maximum number of alternative repair
sets)
32
5.2 Language XML Syntax
33
∗ metrics?
The metrics for sorting the repair sets. Here you
can place a Haskell implementation of the function
repairMetrics :: [Repair] -> [Repair] -> Bool
– cdetdir
The CDET source directory.
Required attributes: path (the directory path)
– includedir*
Extra include directories needed to compile your
project, e.g., directories from which you import parsers or auxiliary
Haskell modules.
Required attributes: path (the directory path)
– importrules+
One or more rule sets for your project. Against
the rules from these files your repository will be checked for consistency.
Required attributes: path (the rule definition file)
5.2
Language XML Syntax
language
A user defined language, needed by some rules. A language defines types, predicate symbols, and function symbols.
Required attributes: id (the name of the language, use a unique name, different
from any other language, project description, or rule set)
Implied attributes: qualifiedPrelude (import Prelude qualified with this name),
qualifiedChar (import Char qualified with this name), qualifiedRatio (import Ratio qualified with this name), qualifiedComplex (import Complex qualified with this name), qualifiedNumeric (import Numeric qualified with this
name), qualifiedIx (import Ix qualified with this name), qualifiedList (import List qualified with this name), qualifiedMaybe (import Maybe qualified
with this name), qualifiedRandom (import Random qualified with this name),
qualifiedTime (import Time qualified with this name)
By default, the Haskell Prelude is imported unqualified; the other Haskell modules are imported fully qualified.
• desc?
A comprehensive description for your language.
• importlanguage*
Import another language such that you can use
symbols of the imported language for symbol definition.
Required attributes: path (the XML file holding the imported language)
Optional attributes: qualifiedAs (qualified import with a given name)
• importmodule*
Import an auxiliary Haskell module.
Required attributes: module (the name of the Haskell module)
Optional attributes: qualifiedAs (qualified import with a given name)
• importparser*
Generate and import a parser for a given DTD. The
parser will be generated by HaXml.
Required attributes: dtd (the name of the DTD for which the Parser should
be generated)
Optional attributes: qualifiedAs (qualified import with a given name)
34
Technical Details
• importforeign*
Import a foreign function, say from a C library (currently, only C is supported)
Required attributes: call (calling convention, currently ccall only), header
(the C header file), foreign (the name of the foreign function), haskell (the
name of the corresponding Haskell function)
The following subelements specify the type of the Haskell function. You
need extra XML elements for this in order to prevent XML parsing errors.
– fargtype*
Argument types of the imported function’s Haskell
side.
Required attributes: id (the argument type name)
– frestype
The result type of the imported function’s Haskell side.
Required attributes: id (the result type name)
• typedefs
The type definitions of the language. You may define as
many types as you want. Notice, however, that their names must be unique.
– typedef*
A type definition, which can be either atomic, record,
or variant.
Required attributes: id (the type constructor name)
∗ desc?
A comprehensive description of the type.
One of the following type definitions is permitted:
∗ atomic
An atomic type like Int or Char.
∗ record
A record type like Document.
Required attributes: rcon (the record constructor, not to be confused with the record type constructor although often the same)
· tvar*
Type variables (arguments) for the record type.
Required attributes: id (the type variable name)
· supers?
Supertypes of the defined type. You can specify
multiple supertypes by the subelement
gtype*
(see below)
Any type variables in a gtype element must be arguments of
the record type (tvar above).
· label*
The labels of the record type. Here you specify
the record type’s ingredients.
Required attributes: id (the name of the label)
Optional attributes: key (is the label a key label?). For testing
equality, key labels are considered only! If the attribute is
omitted, CDET assumes (for safety reasons) that the label is a
key label.
By the subelement
gtype
you specify the label’s type (see below).
∗ variant
A variant type like Bool.
· tvar*
Type variables (arguments) for the variant type.
Required attributes: id (the type variable name)
5.2 Language XML Syntax
35
· subs?
Subtypes of the defined variant type. You can
specify multiple subtypes by the subelement
gtype*
(see below)
Any type variables in a gtype element must be arguments of
the variant type (tvar above).
· vcon*
The variant data constructors.
Required attributes: id (the variant constructor name)
If the variant constructor has type arguments, you can specify
them by the subelement
gtype*
Again, any type variables in a gtype element must be arguments of the variant type (tvar above).
• predsymdefs
Predicate symbol definitions. You can define as many
predicate symbols as you want. Notice, however, that their names must be
unique.
– predsymdef*
A predicate symbol definition.
Required attributes: id (the predicate symbol name)
∗ desc?
A comprehensive description of the predicate symbol.
∗ meta?
Predicate symbol metadata.
Optional attributes: calcStates (does the symbol calculate over
repository states?) If the attribute is not given, CDET is optimistic
and assumes that the symbol does not calculate over repository
states.
· docdep*
Document dependencies.
Required attributes: regex: List here a pattern of files, the
predicate symbol directly accesses via a repository access function. I hope to calculate these patterns in the future.
· docargdep*
Argument dependencies of a symbol.
Required attributes: num: Give here the argument number, responsible for document access. I hope to calculate these numbers in the future.
· cachemeta
Additional metadata to influence caching behavior.
Required attributes: cached (should the symbol be cached?),
reftrans (is the symbol referentially transparent, i.e., does it
not use repStates or repHead?)
In general, Haskell guarantees referential transparency of each
symbol. The repository access functions repStates or repHead
can, however, change their result between consistency checks.
By the subelement
argdep*
you specify the argument numbers, the result of the predicate
symbol depends on. Usually, these are all argument numbers,
but sometimes not.
36
Technical Details
∗ predtype
The predicate type. You need to specify the argument types only because each predicate has a boolean result type.
· type*
low).
Argument types of the predicate symbol (see be-
∗ code
Finally, the Haskell code of the predicate symbol’s implementation. The first parameter of each symbol is the repository
(type Repository). Otherwise you could not access the repository.
Then follow the parameters as specified by the predicate symbol’s
type above. Don’t forget to enclose the code by a CDATA section in
order to avoid XML parsing errors.
• funsymdefs
Function symbol definitions. You can define as many
function symbols as you want. Notice, however, that their names must be
unique.
– funsymdef*
A function symbol definition.
Required attributes: id (the function symbol name)
∗ desc?
A comprehensive description of the function symbol.
∗ meta?
Function symbol metadata (see above).
∗ funtype
The function symbol’s type, consisting of (general)
argument types and a ground result type.
· type*
Argument types, which can be either ground types
(gtype) or function types (funtype). This supports the definition of higher-order functions, which result in a non-function
type. This restriction is necessary to keep CDET’s logic first
order.
One of the following subelements is supported.
gtype
(ground type)
funtype
(function type)
· gtype
A ground type, i.e., a non-function type. Here,
the ground type is the result type of a function symbol.
A ground type can be either a type application (tapply), a type
variable (tvar), the supertype of all types (top), or the repository state type (state). Hence one of the following subelements is permitted:
tapply
(type constructor application)
The attribute tcref specifies the type constructor to apply.
The subelement
gtype*
specifies the argument types.
tvar
(type variable) The attribute id specifies the
type variable name.
top
(the supertype of all types)
state
(the repository state type)
∗ code
Finally, the Haskell code of the function symbol’s implementation. The first parameter of each symbol is the repository
5.3 Rule XML Syntax
37
(type Repository). Otherwise you could not access the repository.
Then follow the parameters as specified by the function symbol’s
type above. Don’t forget to enclose the code by a CDATA section in
order to avoid XML parsing errors.
5.3
Rule XML Syntax
rules
A user defined rule set. Here you define what consistency means.
You can import this rule set in a project description.
• importlanguage+
Import at least one language, the symbols of which
you use in your rules.
Required attributes: path (the XML file holding the imported language)
• importrule*
Import other rule sets. This implies that whenever this
rule set is used by a project, all other imported rule sets are used, too.
Required attributes: path (the XML file holding the imported rule set)
• rule*
A consistency rule.
Required attributes: id (the rule name, must be unique), date (the date of
the last rule modification)
– meta
Rule metadata.
Required attributes: weight (importance level of the rule), weak (may
the rule be violated?)
∗ desc?
A comprehensive description for this rule.
∗ docdeps?
Document dependencies. By these document dependencies you can override the dependencies calculated by CDET.
Sometimes the calculated dependencies are too pessimistic and you
know better. The more restrictive the document dependencies are
the more consistency checking is accelerated.
· docdep*
Document dependencies.
Required attributes: regex (pattern of files, the rule accesses)
– formula
The actual predicate logic formula, described below.
The formula element contains the predicate logic part of a rule, which is rather
standard. It consists of the following subelements.
• desc?
A comprehensive description of the formula. Here I plan to
include some automatic translation of the formula into natural language.
The formula itself may be one of the following (like in classic predicate logic):
• papply
An atomic formula, i.e., predicate symbol application to some
argument terms.
Required attributes: id: The predicate symbol to apply. Make sure that the
symbol is defined in a language imported by this rule set.
38
Technical Details
– term*
Argument terms of the predicate symbol application.
Make sure that the result types of the argument terms “fit” to the predicate symbol’s type (modulo polymorphism and subtyping of course).
CDET’s type checker will assist you in this.
A term consists of a comprehensive description and the actual term.
∗ desc?
A comprehensive description of the term. Here I plan
to include some automatic translation into natural language.
CDET’s notion of terms is a bit more expressive than in classic predicate logic. CDET supports variables, function symbol application,
function symbols as such, record construction, variant deconstruction, and explicitly typed terms (to guide type inference). A term
may be one of the following:
∗ var
A variable. Make sure that you only reference variables
that are bound by a quantifier; else you get a type error. CDET
supports closed formulae only.
∗ fapply
A function symbol application.
Required attributes: id: The function symbol to apply. Make sure
that the symbol is defined in a language imported by this rule set.
· term*
Argument terms of the function symbol application. Make sure that the result types of the argument terms
“fit” to the function symbol’s type (modulo polymorphism and
subtyping of course). CDET’s type checker will assist you in
this.
∗ sym
A function symbol as argument of a higher-order function.
Required attributes: id: The function symbol’s name. Make sure
that the symbol is defined in a language imported by this rule set.
∗ rec
A record construction.
Required attributes: id: The record data constructor, not to be
confused with the record type constructor. Make sure that the
record data constructor is defined in a language imported by this
rule set (and that it constructs the correct record type of course).
· label*
Label bindings for the record construction. Make
sure that you bind all labels of the record including those of
the record’s supertypes.
Required attributes: id: The record label’s name. Make sure
that the name is part of the record type and that you bind it
only once in a record construction.
The label is bound to a term, which you specify by the subelement
term
∗ case
A variant deconstruction.
Optional attributes: tcref: You may want to specify the variant
type constructor in case you construct variant supertypes without
adding new variant data constructors. Then CDET’s type checker
may need some guidance.
5.3 Rule XML Syntax
39
· term
The variant term to be deconstructed, i.e., the
case scrutinee.
· binding*
Bindings of each alternative variant data constructor (including those of the subtypes) to a function symbol,
which will be applied to the variant data constructor’s arguments.
Required attributes: id (the variant constructor, unique in the
case construct); sym (the function symbol that should be applied to the variant constructor’s arguments)
∗ typed
An explicitly typed term. Explicit typing may guide
type inference, which is, however, only seldom necessary.
· term
· type
The actual term.
It’s type annotation.
– hintalternative*
An alternative hint set. You can guide repair
generation by giving hints that tell CDET about how the truth values
of atomic formulae can be inverted.
∗ set*
A hint inside a hint set. All hints in a hint set are
executed simultaneously. Essentially, a hint tells CDET about how
a variable should be changed in order to invert the truth value of
the atomic formula at hand.
Required attributes: id (the variable to which the hint applies)
Optional attributes: condition: The truth value of the atomic formula responsible for executing the hint; this truth value should be
inverted. If the attribute is not given, CDET will execute the hint
on either truth value.
varcondition: Should the hint be executed if the variable is new
(content has changed since the last check-in) or old (content remained constant since the last check-in)? If the attribute is not
given, CDET will execute the hint always.
field: If the variable’s type is a record type you can specify the
record label to be changed. If the attribute is not given the hint
applies to the full value of the variable.
repaircost: You can specify the cost of the hint, in order to get
the cheapest repairs only. If the attribute is not given, nothing is
assumed about the cost — hence you might get more repair alternatives.
By the subelement
term
you tell CDET how the variable (or the field) should be changed.
Make sure that the term’s type corresponds to the variable’s type
(or the field’s type if given). Otherwise, you get a type error.
• or
Classical disjunction.
– formula++
two).
The disjunction’s subformulae (you need at least
40
Technical Details
• and
Classical conjunction.
– formula++
two).
• not
Classical negation.
– formula
• implies
The conjunction’s subformulae (you need at least
The negated subformula.
Classical implication.
– formula
The first argument formula of the implication (the one
that implies something).
– formula
The second argument formula of the implication (the
one that is implied).
• forall
Universal quantification.
Required attributes: id: The quantified variable. Make sure that within a
rule you quantify at most once over a variable. For clarity and simplicity,
CDET does not support multiple quantification over the same variable. Of
course in different rules you can “reuse” variables.
Optional attributes: action: Here you can specify a preferred repair action
for the quantified variable. The following actions are supported: delete
(only derive repairs to delete something), change (only derive repairs to
change something), keep (don’t derive any repairs for this variable).
keepdomain: Cache the quantifier domain (the values over which the quantifier iterates). Use this feature with caution since quantifier domains may
become really large.
– term
A term that tells CDET where the values of the bound
variable come from. Over all these values the quantifier iterates. Make
sure that the type of the term is a list [τ ]; then the quantified variable
has the type τ .
– formula
The argument formula; here the quantified variable is
“in scope” and may be referenced in terms.
• exists
Existential quantification (attributes and subelements are similar to those of universal quantification).
Required attributes: id: The quantified variable.
Optional attributes: action: Here you can specify a preferred repair action for the quantified variable. The following actions are supported: add
(only derive repairs to add something), change (only derive repairs to change
something), keep (don’t derive any repairs for this variable).
keepdomain: Cache the quantifier domain.
– term
A term that tells CDET where the values of the bound
variable come from.
– formula
The argument formula of the existential quantification;
here the quantified variable is “in scope.”
5.4 Repository Interface
5.4
41
Repository Interface
In this section you learn details about CDET’s generic interface to the repository of
an arbitrary DMS/RCS. As already mentioned, CDET only makes few assumptions
about the underlying DMS/RCS. The interface consists of five Haskell functions,
which you can use for implementing functions and predicates (the abstract Haskell
data type Repository represents the repository itself):
• repStates :: Repository -> [State] returns all states of a given repository.
• repHead :: Repository -> State returns the current repository state.
• repDocs :: Repository -> State -> String -> [Document] returns
the documents in the repository that are current at a given state and match
a regular expression. For example, repDocs repo 2 "*.xml" returns all
XML documents current at state 2 in the repository repo. Notice that the
returned documents only include the name and the last modification state
(up to the given state).
data Document = Document
{document_dId :: PString,
document_dState :: State}
The content of the document has to be parsed by the function parseDoc
described below.
• repDirs :: Repository -> State -> String -> [Folder] behaves like
repDocs but returns directories instead. Similar to documents, directories
include the name and the last modification state only.
data Folder
= Folder
{folder_fId :: PString,
folder_fState :: State}
• parseDoc :: Repository -> Document -> (String -> a) -> Maybe a
accesses a given document in the repository. The third parameter is a function that parses the document content and converts it into an appropriate
Haskell data structure. For XML documents, such parser functions can be
generated [WR99]. If the given document does not exist in the repository,
parseDoc returns Nothing.
Chapter 6
Future Work
As you might have noticed, CDET is far from being a mature product. Indeed,
CDET is in a very preliminary state. Here are just some directions for future work:
• Support type definition by a subset of XML Schema and derive parsers
automatically in a HaXml like manner.
• Improve incremental consistency checking for XML documents, provided
that the DMS/RCS supports XML patches.1 .
• Implement some graphical tools for rule formalization, language definition,
and S-DAG playing.
• Improve repairs by data mining approaches.
• Translate rules and repairs into natural language.
You feel that you could help in some of the above points? You want to add
something? You have an interesting document engineering project and want to apply CDET? Then feel free to contact me, e.g., by email [email protected].
1
see www.unibw.de/inf2/OO VCS/
42
Appendix A
The CDET Prelude
Here we list the basic CDET language Prelude, which includes large part of the Haskell prelude, helper functions from the FastPackedString library from the DARCS distribution,
and some basic repository access functions.
A.1
Prelude Types
For convenience we use infix notation where appropriate. Notice that in CDET’s XML
syntax you have to use prefix notation instead.
Haskell like Int
Haskell like Char
PackedString from DARCS
Haskell like Float
Haskell like Maybe
Haskell like Bool
Haskell like 2 tuples
Haskell like 3 tuples
tuples up to 7 tuples
[] | α : [α]
Haskell like lists
dId : PString,
Document Document
Documents (name and check-in state)
dState : State
Int
Char
PString
Float
Maybe α
Bool
(α, β)
(α, β, γ)
...
[α]
A.2
atomic
atomic
atomic
atomic
Just α | Nothing
True | False
(α, β)
(α, β, γ)
Prelude Predicates
Notice that in Haskell equality and inequality require the type class Eq. In contrast,
CDET lets GHC derive instances for the type class Eq for each type, such that equality
and inequality are fully polymorphic. The same holds for class members of the Haskell
type class Ord.
==
: α × α → Bool
fullEq : α × α → Bool
/=
: α × α → Bool
<
: α × α → Bool
<=
: α × α → Bool
>
: α × α → Bool
>=
: α × α → Bool
all
: (α → Bool) × [α] → Bool
any
: (α → Bool) × [α] → Bool
equality (key fields only)
full structural equality
inequality (key fields only)
less than
less than or equal
greater than
greater than or equal
Haskell like all
Haskell like any
43
The CDET Prelude
44
elem
: α × [α] → Bool
elemS : Char × PString → Bool
notElem : α × [α] → Bool
even
: Int → Bool
odd
: Int → Bool
null
: [α] → Bool
nullS : PString → Bool
and
: [Bool] → Bool
or
: [Bool] → Bool
A.3
Haskell like elem
elem for packed Strings
Haskell like notElem
Haskell like even
Haskell like odd
Haskell like null
null for packed Strings
Haskell like and
Haskell like or
Prelude Functions
Notice that CDET does not support constant values in formulae, such that we provide
some numerical constants as function symbols with no parameter. Notice further that
due to lack of type classes, CDET distinguishes functions for number calculations w.r.t.
their type Int or Float.
const0
: Int
const1
: Int
const2
: Int
id
:α→α
succInt : Int → Int
predInt : Int → Int
+Int
: Int × Int → Int
−Int
: Int × Int → Int
∗Int
: Int × Int → Int
/Int
: Int × Int → Int
absInt
: Int × Int → Int
mod
: Int × Int → Int
divMod
: Int × Int → (Int, Int)
succFloat : Float → Float
predFloat : Float → Float
+Float
: Float × Float → Float
−Float
: Float × Float → Float
∗Float
: Float × Float → Float
/Float
: Float × Float → Float
absFloat : Float × Float → Float
round
: Float → Int
floor
: Float → Int
ceiling : Float → Int
mkFloat : Int → Float
maximum : [α] → α
minimum : [α] → α
++
: [α] × [α] → [α]
appendS : PString × PString → PString
head
: [α] → α
headS
: PString → Char
last
: [α] → α
tail
: [α] → [α]
tailS
: PString → PString
0
1
2
Haskell like id
Haskell like succ for Int
Haskell like pred for Int
Haskell like + for Int
Haskell like - for Int
Haskell like * for Int
Haskell like div for Int
Haskell like abs for Int
Haskell like mod
Haskell like divMod
Haskell like succ for Float
Haskell like pred for Float
Haskell like + for Float
Haskell like - for Float
Haskell like * for Float
Haskell like / for Float
Haskell like abs for Float
Haskell like round
Haskell like floor
Haskell like ceiling
Convert an Int into a Float
Haskell like maximum
Haskell like minimum
Haskell like ++
++ for packed Strings
Haskell like head
head for packed Strings
Haskell like last
Haskell like tail
tail for packed Strings
A.3 Prelude Functions
init
: [α] → [α]
take
: Int × [α] → [α]
takeS
: Int × PString → PString
drop
: Int × [α] → [α]
dropS
: Int × PString → PString
reverse
: [α] → [α]
reverseS
: PString → PString
diff
: [α] × [α] → [α]
length
: [α] → Int
lengthS
: PString → Int
lookup
: α × [(α, β)] → Maybe β
!!
: [α] × Int → α
indexS
: PString × Int → Char
map
: (α → β) × [α] → [β]
concatMap
: (α → [β]) × [α] → [β]
foldl
: (α × β → α) × α × [β] → α
foldlS
: (α × Char → α) × α × PString → α
foldr
: (α × β → β) × β × [α] → β
foldrS
: (Char × β → β) × β × PString → β
filter
: (α → Bool) × [α] → [α]
filterElem
: [β] × (α → β) × [α] → [α]
filterNotElem : [β] × (α → β) × [α] → [α]
takeWhile
: (α → Bool) × [α] → [α]
takeWhileS
: (Char → Bool) × PString → PString
dropWhile
: (α → Bool) × [α] → [α]
dropWhileS
: (Char → Bool) × PString → PString
productInt
: [Int] → Int
sumInt
: [Int] → Int
productFloat : [Float] → Float
sumFloat
: [Float] → Float
splitAt
: Int × [α] → ([α], [α])
splitAtS
: Int × PString → (PString, PString)
span
: (α → Bool) × [α] → ([α], [α])
spanS
: (Char → Bool) × PString
:
→ (PString, PString)
break
: (α → Bool) × [α] → ([α], [α])
breakS
: (Char → Bool) × PString
:
→ (PString, PString)
fst
: (α, β) → α
snd
: (α, β) → β
maybe
: β × (α → β) × Maybe α → β
catMaybes
: [Maybe α] → [α]
zip
: [α] × [β] → [(α, β)]
zipWith
: (α × β → γ) × [α] × [β] → [γ]
unzip
: [(α, β)] → ([α], [β])
words
: [Char] → [[Char]]
lines
: [Char] → [[Char]]
wordsS
: PString → [PString]
linesS
: PString → [PString]
unwords
: [[Char]] → [Char]
45
Haskell like init
Haskell like take
take for packed Strings
Haskell like drop
drop for packed Strings
Haskell like reverse
reverse for packed Strings
Haskell like \ \
Haskell like length
length for packed Strings
Haskell like lookup
Haskell like !!
!! for packed Strings
Haskell like map
Haskell like concatMap
Haskell like foldl
foldl for packed Strings
Haskell like foldr
foldr for packed Strings
Haskell like filter
advanced filter
advanced negative filter
Haskell like takeWhile
takeWhile for packed Strings
Haskell like dropWhile
dropWhile for packed Strings
Haskell like product for Int
Haskell like sum for Int
Haskell like product for Float
Haskell like sum for Float
Haskell like splitAt
splitAt for packed Strings
Haskell like span
span for packed Strings
Haskell like break
break for packed Strings
Haskell like fst
Haskell like snd
Haskell like maybe
Haskell like catMaybes
Haskell like zip
Haskell like zipWith
Haskell like unzip
Haskell like words
Haskell like lines
words for packed String
lines for packed String
Haskell like unwords
The CDET Prelude
46
unlines : [[Char]] → [Char]
unwordsS : [PString] → PString
unlinesS : [PString] → PString
concat
: [[α]] → [α]
concatS : [PString] → PString
nilS
: PString
repStates : [State]
repHead : State
repInit : State
next
: State → State
prev
: State → State
prevState : State → State
Haskell like unlines
unwords for packed String
unlines for packed String
Haskell like concat
concat for packed Strings
empty packed String
all repository states
repository head state
initial repository state
next repository state
previous repository state
total version of prev
Appendix B
DTDs
Here you find the complete DTDs of CDET.
B.1
Project Description DTD consistencycheck.dtd
<!-- top level configuration element -->
<!ELEMENT consistencycheck (performance,repair,cdetdir,includedir*,importrules+)>
<!-- name: a name for your project -->
<!-- tmpdir: directory where temporal files can be stored -->
<!-- outputdir: directory where the generated XML files are stored -->
<!-- reportdtd: where is the DTD for the consistency report -->
<!-- repositorybase: base directory of your repository -->
<!-- repositoryconfig: optional configuration file for some repository types -->
<!-currently this is necessary for subversion only -->
<!-other repositories ignore this value -->
<!-- repositorytype: type of the repository (dir | darcs | subversion | cas) -->
<!ATTLIST consistencycheck
name CDATA #REQUIRED
tmpdir CDATA #REQUIRED
outputdir CDATA #REQUIRED
reportdtd CDATA #REQUIRED
repositorybase CDATA #REQUIRED
repositoryconfig CDATA #IMPLIED
repositorytype (dir | darcs | subversion | cas) #REQUIRED>
<!-- some performance tuning -->
<!-- you _should_ turn on everything -->
<!ELEMENT performance EMPTY>
<!-- usecache: should we use caches? -->
<!-- fastprelude: functions from Haskell’s Prelude
be evaluated internally? -->
<!-- incremental: generate S-DAGs incrementally? -->
<!-- filterrules: only check rules influenced by a check-in? -->
<!-- optimizerules: rewrite rules for optimum performance? -->
<!ATTLIST performance
47
48
DTDs
usecache (true | false) #REQUIRED
fastprelude (true | false) #REQUIRED
incremental (true | false) #REQUIRED
filterrules (true | false) #REQUIRED
optimizerules (true | false) #REQUIRED>
<!-- influence repair generation -->
<!ELEMENT repair (metrics?)>
<!-- maxalts: not supported at the moment! -->
<!-- partialResolution: support partial inconsistency resolution? -->
<!-- maxsets: maximum alternative repair sets in the repair collection -->
<!ATTLIST repair
maxalts CDATA #IMPLIED
partialResolution (true | false) #REQUIRED
maxsets CDATA #IMPLIED>
<!ELEMENT metrics (#PCDATA)>
<!-- user defined preference metrics to sort repair sets -->
<!-- function to be defined:
repairMetrics :: [Repair] -> [Repair] -> Bool -->
<!-- Types to be used: -->
<!-- data Repair = Repair {vars :: [(Id,VSym)], (rule identifiers and)
<!-(variables x therein to repair)
<!-ident :: (Id,Int), -->
<!-(unique identifier for a repair)
<!-(original rule, unique number (for this rule))
<!-domain :: Term,
(the term identifying the domain of x)
<!-assign :: [(VSym,Value)],
(variable assignment for the domain)
<!-(cannot contain x)
<!-change :: RepairAction,
(the actual repair action)
<!-rating :: Rating}
(rating for the repair)
<!-- data RepairAction = -->
<!-ActDel Value
(delete value)
<!-| ActChange Value Value
(change value from to)
<!-| ActChangeField Value FSym Value (change a field in a value)
<!-| ActInsert Value
(insert value)
<!-| ActChangeSuchThat PSym [Value] Bool -->
<!-(we do not know how to set the value)
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
<!-- data Rating = Rating {offends :: [Id], (possibly impacted rules) -->
<!-resolves :: [(Int,Int)], -->
<!-(how many incons. resolved at which importance level) -->
<!-repaircost :: Maybe Cost
(repair costs)} -->
<!-- directory for the CDET sources for rule and language compilation -->
<!-- this is the parent directory of the "CDET" directory -->
<!ELEMENT cdetdir EMPTY>
B.2 Rules DTD rules.dtd
<!ATTLIST cdetdir
path CDATA #REQUIRED>
<!-- include cirectories needed for rule and language compilation -->
<!ELEMENT includedir EMPTY>
<!ATTLIST includedir
path CDATA #REQUIRED>
<!-- rulesets against which the repository should be checked -->
<!ELEMENT importrules EMPTY>
<!ATTLIST importrules
path CDATA #REQUIRED>
B.2
Rules DTD rules.dtd
<!-- top level ruleset element -->
<!ELEMENT rules (importlanguage+,importrule*,rule*)>
<!-- import a language -->
<!ELEMENT importlanguage EMPTY>
<!-- path to the XML file holding the language definition -->
<!ATTLIST importlanguage
path CDATA #REQUIRED>
<!-- import another ruleset -->
<!ELEMENT importrule EMPTY>
<!-- path to the XML file holding the ruleset definition -->
<!ATTLIST importrule
path CDATA #REQUIRED>
<!-- consistency rule -->
<!ELEMENT rule (meta,formula,actions)>
<!-- date: creation date of the rule -->
<!-if a rule is newer than the last runtime then
it might have been changed -->
<!-- id: rule identifier -->
<!ATTLIST rule
date CDATA #REQUIRED
id ID #REQUIRED> <!-- rule name -->
<!-- rule metadata -->
<!ELEMENT meta (desc?,precon*,docdeps?)>
<!-- weight: rule weight (importance) 0 .. 100 -->
<!-- weak: may a rule be violated? -->
<!ATTLIST meta
weight CDATA "0"
weak (true | false) #REQUIRED>
49
50
DTDs
<!-- consistency rule description -->
<!ELEMENT desc (#PCDATA)>
<!-- rule precondition: this rule must be satisfied in order to check -->
<!-- the current rule (not supported at the moment) -->
<!ELEMENT precon EMPTY>
<!ATTLIST precon
id CDATA #REQUIRED>
<!-- document dependencies of a rule -->
<!-- not given: dont know (determined by CDET) -->
<!-- given: these are the documents the rule really depends on -->
<!ELEMENT docdeps (docdep*)>
<!ELEMENT docdep EMPTY>
<!-- regex: regular expression of the dependent documents -->
<!ATTLIST docdep
regex CDATA #REQUIRED>
<!-- first order formula with description -->
<!ELEMENT formula
(desc?,(papply | or | and | not | implies | forall | exists))>
<!-- applied predicate (atomic formula) plus hint collection -->
<!ELEMENT papply (term*,hintalternative*)>
<!-- id: predicate symbol -->
<!ATTLIST papply
id CDATA #REQUIRED>
<!-- alternative hint set -->
<!ELEMENT hintalternative (set*)>
<!-- hint -->
<!ELEMENT set (term)>
<!-- condition: predicate result causing to execute the hint -->
<!-- id: variable to set -->
<!-- varcondition: set variable only if it is marked new / old -->
<!-- field: record field to set -->
<!-- repaircost: cost imposed by executing the corresponding repair -->
<!ATTLIST set
condition (true | false) #IMPLIED
id CDATA #REQUIRED
varcondition (new | old) #IMPLIED
field CDATA #IMPLIED
repaircost CDATA #IMPLIED>
<!-- disjunction -->
<!ELEMENT or (formula,formula+)>
<!-- conjunction -->
B.2 Rules DTD rules.dtd
51
<!ELEMENT and (formula,formula+)>
<!-- implication -->
<!ELEMENT implies (formula,formula)>
<!-- negation -->
<!ELEMENT not (formula)>
<!-- universal quantification with sphere term -->
<!ELEMENT forall (term,formula)>
<!-- id: quantified variable -->
<!-- action: hint for quantifier -->
<!-- keepdomain: also cache the quantifier sphere (may be expensive!) -->
<!ATTLIST forall
id CDATA #REQUIRED
action (delete | add | change | keep) #IMPLIED
keepdomain (true | false) #IMPLIED>
<!-- existential quantification with sphere term -->
<!ELEMENT exists (term,formula)>
<!-- id: quantified variable -->
<!-- action: hint for quantifier -->
<!-- keepdomain: also cache the quantifier sphere (may be expensive!) -->
<!ATTLIST exists
id CDATA #REQUIRED
action (delete | add | change | keep) #IMPLIED
keepdomain (true | false) #IMPLIED> <!-- quantified variable -->
<!-- TERMS -->
<!-- term with description -->
<!ELEMENT term (desc?,(var | fapply | sym | rec | case | typed))>
<!-- variable -->
<!ELEMENT var EMPTY>
<!-- id: variable name -->
<!ATTLIST var
id CDATA #REQUIRED>
<!-- applied function symbol -->
<!ELEMENT fapply (term*)>
<!-- id: function symbol name -->
<!ATTLIST fapply
id CDATA #REQUIRED>
<!-- function symbol e.g. as argument for higher order functions -->
<!ELEMENT sym EMPTY>
<!-- id: function symbol name -->
52
DTDs
<!ATTLIST sym
id CDATA #REQUIRED>
<!-- record construction -->
<!ELEMENT rec (label)*>
<!-- id: record constructor name -->
<!ATTLIST rec
id CDATA #REQUIRED>
<!-- record label -->
<!ELEMENT label (term)>
<!-- id: label name (unique for this record) -->
<!ATTLIST label
id CDATA #REQUIRED>
<!-- variant deconstruction -->
<!ELEMENT case (term,binding*)>
<!-- tcref: variant constructor (type constructor) -->
<!ATTLIST case
tcref CDATA #IMPLIED>
<!-- binding inside case: id -> sym -->
<!ELEMENT binding EMPTY>
<!-- id: variant constructor -->
<!-- sym: function symbol to be applied to constructor arguments -->
<!ATTLIST binding
id CDATA #REQUIRED
sym CDATA #REQUIRED>
<!-- explicitly typed term -->
<!ELEMENT typed (term,type)>
<!-- user defined action what should be done with the report -->
<!-- not supported at the moment -->
<!ELEMENT actions (mailreport*, mailrepair*,mailsummary?)>
<!-- Mail the report to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailreport (recipient+)>
<!ATTLIST mailreport
currentonly (true | false) #REQUIRED
explain
(true | false) #REQUIRED
format
(xml | latex) #REQUIRED
attachDocs (true | false) #REQUIRED>
<!-- Mail the repair suggestions to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailrepair (recipient+)>
B.3 Language DTD language.dtd
<!ATTLIST mailrepair
currentonly
explain
format
attachDocs
(true | false) #REQUIRED
(true | false) #REQUIRED
(xml | latex) #REQUIRED
(true | false) #REQUIRED>
<!-- Mail a comprehensive summary to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailsummary (recipient+)>
<!ELEMENT recipient EMPTY>
<!ATTLIST recipient
mailto CDATA #REQUIRED>
<!-- TYPES -->
<!-- type: ground or function type -->
<!ELEMENT type (gtype | funtype)>
<!-- groundtype -->
<!ELEMENT gtype (tapply | tvar | top | state)>
<!-- type application -->
<!ELEMENT tapply (gtype*)>
<!-- tcref: type constructor to be applied -->
<!ATTLIST tapply
tcref CDATA #REQUIRED>
<!-- type variable -->
<!ELEMENT tvar EMPTY>
<!-- id: type variable name -->
<!ATTLIST tvar
id CDATA #REQUIRED>
<!-- supertype of all other types -->
<!ELEMENT top EMPTY>
<!-- repository state -->
<!ELEMENT state EMPTY>
<!-- function type -->
<!ELEMENT funtype (type*,gtype)>
B.3
Language DTD language.dtd
<!-- top level language element -->
<!ELEMENT language (desc?,importlanguage*,importmodule*,importparser*,
importforeign*,typedefs, predsymdefs, funsymdefs)>
<!-- id: language name -->
53
54
DTDs
<!-- qualifiedPrelude: import Haskell’s Prelude qualified as -->
<!-- qualifiedXMLTypes: import HaXml types qualified as (you should do that)-->
<!-- qualifiedChar: import Haskell’s Char module qualified as -->
<!-- qualifiedRatio: import Haskell’s Ratio module qualified as -->
<!-- qualifiedComplex: import Haskell’s Complex module qualified as -->
<!-- qualifiedNumeric: import Haskell’s Numeric module qualified as -->
<!-- qualifiedIx: import Haskell’s Ix module qualified as -->
<!-- qualifiedList: import Haskell’s List module qualified as -->
<!-- qualifiedMaybe: import Haskell’s Maybe module qualified as -->
<!-- qualifiedRandom: import Haskell’s Random module qualified as -->
<!-- qualifiedTime: import Haskell’s Time module qualified as -->
<!-- by default we import Prelude unqualified and -->
<!-all other modules fully qualified -->
<!ATTLIST language
id CDATA #REQUIRED
qualifiedPrelude CDATA #IMPLIED
qualifiedXMLTypes CDATA #IMPLIED
qualifiedChar CDATA #IMPLIED
qualifiedRatio CDATA #IMPLIED
qualifiedComplex CDATA #IMPLIED
qualifiedNumeric CDATA #IMPLIED
qualifiedIx CDATA #IMPLIED
qualifiedList CDATA #IMPLIED
qualifiedMaybe CDATA #IMPLIED
qualifiedRandom CDATA #IMPLIED
qualifiedTime CDATA #IMPLIED>
<!-- import other languages -->
<!ELEMENT importlanguage EMPTY>
<!-- path: path to the XML file holding he language -->
<!-- qualifiedAs: import qualified (default: unqualified import) -->
<!ATTLIST importlanguage
path CDATA #REQUIRED
qualifiedAs CDATA #IMPLIED>
<!-- import an XML parser automatically generated by HaXml for a DTD -->
<!ELEMENT importparser EMPTY>
<!-- dtd: path to the DTD -->
<!-- qualifiedAs: import name (necessary to avoid naming conflicts) -->
<!ATTLIST importparser
dtd CDATA #REQUIRED
qualifiedAs CDATA #REQUIRED>
<!-- import another Haskell module -->
<!ELEMENT importmodule EMPTY>
<!-- module: path to the Haskell module -->
<!-- qualifiedAs: import qualified (default: unqualified import) -->
<!ATTLIST importmodule
module CDATA #REQUIRED
qualifiedAs CDATA #IMPLIED>
B.3 Language DTD language.dtd
<!-- import a foreign function -->
<!-- currently only C is supported by GHC -->
<!ELEMENT importforeign (fargtype*,frestype)>
<!-- call: calling convention (currently ccall only) -->
<!-- header: the C header file (implies object file to link) -->
<!-- foreign: the name of the foreign function -->
<!-- haskell: the name of the corresponding haskell function -->
<!ATTLIST importforeign
call (ccall | cplusplus | dotnet | jvm | stdcall) #REQUIRED
header CDATA #REQUIRED
foreign CDATA #REQUIRED
haskell CDATA #REQUIRED>
<!-- an argument type of the corresponding haskell function -->
<!-- use an extra element here
to avoid XML parsing errors for Haskell’s arrow -->
<!ELEMENT fargtype EMPTY>
<!-- id: name of the argument type -->
<!ATTLIST fargtype
id CDATA #REQUIRED>
<!-- the result type of the corresponding haskell function -->
<!ELEMENT frestype EMPTY>
<!-- id: name of the result type -->
<!ATTLIST frestype
id CDATA #REQUIRED>
<!-- SYMBOL DEFINITIONS -->
<!-- function symbol definitions -->
<!ELEMENT funsymdefs (funsymdef)*>
<!-- function symbol definition -->
<!ELEMENT funsymdef (desc?,meta?,funtype,code)>
<!-- id: function symbol name -->
<!ATTLIST funsymdef
id CDATA #REQUIRED>
<!-- predicate symbol defintions -->
<!ELEMENT predsymdefs (predsymdef)*>
<!-- predicate symbol definition -->
<!ELEMENT predsymdef (desc?,meta?,predtype,code)>
<!-- id: predicate symbol name -->
<!ATTLIST predsymdef
id CDATA #REQUIRED>
55
56
DTDs
<!-- implementation of symbols (Haskell source code) -->
<!ELEMENT code (#PCDATA)>
<!-- SYMBOL METADATA for function and predicate symbols -->
<!-- description -->
<!ELEMENT desc (#PCDATA)>
<!-- detailed metadata -->
<!ELEMENT meta (docdep*,strdep*,docargdep*,cachemeta)>
<!-- calcStates: does the symbol calculate over repository states? -->
<!ATTLIST meta
calcStates (true | false) #IMPLIED>
<!-- document dependencies of the symbol -->
<!ELEMENT docdep EMPTY>
<!-- regex: regular expression of documents the result depends on -->
<!ATTLIST docdep
regex CDATA #REQUIRED>
<!-- string dependencies of the symbol -->
<!ELEMENT strdep EMPTY>
<!-- regex: regular expression of strings the may symbol result in -->
<!ATTLIST strdep
regex CDATA #REQUIRED>
<!-- document argument dependencies of the symbol -->
<!ELEMENT docargdep EMPTY>
<!-- num: argument number responsible for document access -->
<!ATTLIST docargdep
num CDATA #REQUIRED>
<!-- cache metadata for a symbol -->
<!ELEMENT cachemeta (argdep*,property*)>
<!-- cached: should the symbol be cached? -->
<!-- reftrans: is the symbol referentially transparent? -->
<!ATTLIST cachemeta
cached (true | false) #REQUIRED
reftrans (true | false) #REQUIRED>
<!-- argument dependencies of the symbol -->
<!ELEMENT argdep EMPTY>
<!-- num: argument number responsible for symbol result -->
<!ATTLIST argdep
num CDATA #REQUIRED>
<!-- symbol properties (not supported at the moment) -->
B.3 Language DTD language.dtd
57
<!ELEMENT property (simprop | fungenprop| predgenprop)>
<!-- simple property -->
<!ELEMENT simprop EMPTY>
<!-- prop: simple property: transitive, symmetric, antisymmetric,
asymmetric, reflexive, irreflexive -->
<!ATTLIST simprop
prop (trans | sym | antisym | asym | refl | irrefl) #REQUIRED>
<!-- generic properties for function symbols (currently not supported) -->
<!-- pre results imply post result -->
<!-- something similar to ghc rule pragmas -->
<!ELEMENT fungenprop (fpre*,fpost)>
<!-- pre-result: arguments and function result (all simple variables) -->
<!ELEMENT fpre (arg*)>
<!-- res: result variable -->
<!ATTLIST fpre
res CDATA #REQUIRED>
<!ELEMENT arg EMPTY>
<!-- arg: argument variable -->
<!ATTLIST arg
id CDATA #REQUIRED>
<!-- post result: arguments and function result -->
<!ELEMENT fpost (arg*)>
<!ATTLIST fpost
res CDATA #REQUIRED>
<!-- generic properties for predicate symbols -->
<!-- pre results imply post result -->
<!-- something similar to ghc rule pragmas -->
<!ELEMENT predgenprop (ppre*,ppost)>
<!ELEMENT ppre (arg*)>
<!ATTLIST ppre
res (true | false) #REQUIRED>
<!ELEMENT ppost (arg*)>
<!ATTLIST ppost
res (true | false) #REQUIRED>
<!-- TYPE DEFINITIONS -->
<!-- type definitions -->
<!ELEMENT typedefs (typedef)*>
<!-- type definition: atomic, record, variant -->
58
DTDs
<!ELEMENT typedef (desc?,(atomic|record|variant))>
<!-- id: type (constructor) name -->
<!ATTLIST typedef
id CDATA #REQUIRED>
<!-- atomic type like Int, Char -->
<!ELEMENT atomic EMPTY>
<!-- record type: argument type variables, super types, labels -->
<!-- only! argument tyvars can be used in definition -->
<!ELEMENT record (tvar*,supers?,label*)>
<!-- rcon: record constructor -->
<!ATTLIST record
rcon CDATA #REQUIRED>
<!-- super types of a record -->
<!ELEMENT supers (gtype*)>
<!-- record label -->
<!ELEMENT label (gtype)>
<!-- id: label name -->
<!-- key: the label belongs to the key of a record -->
<!-- records can be identified by _only_ looking at their key labels -->
<!-- only key labels are used for value comparison and in repairs -->
<!ATTLIST label
key (true | false) #IMPLIED
id CDATA #REQUIRED>
<!-- variant type: argument types, subtypes, constructors -->
<!ELEMENT variant (tvar*,subs?,vcon*)>
<!-- subtypes of a variant -->
<!ELEMENT subs (gtype)*>
<!-- variant constructor -->
<!ELEMENT vcon (gtype)*>
<!-- id: variant constructor name -->
<!ATTLIST vcon
id CDATA #REQUIRED>
<!-- TYPES -->
<!-- type: ground or function type -->
<!ELEMENT type (gtype | funtype)>
<!-- groundtype -->
<!ELEMENT gtype (tapply | tvar | top | state)>
B.4 Report DTD report.dtd
59
<!-- type application -->
<!ELEMENT tapply (gtype*)>
<!-- tcref: type constructor to be applied -->
<!ATTLIST tapply
tcref CDATA #REQUIRED>
<!-- type variable -->
<!ELEMENT tvar EMPTY>
<!-- id: type variable name -->
<!ATTLIST tvar
id CDATA #REQUIRED>
<!-- supertype of all other types -->
<!ELEMENT top EMPTY>
<!-- repository state -->
<!ELEMENT state EMPTY>
<!-- function type -->
<!ELEMENT funtype (type*,gtype)>
<!-- predicate type -->
<!ELEMENT predtype (type)*>
B.4
Report DTD report.dtd
<!-- CONSISTENCY REPORTS -->
<!-- rule evaluations (for each rule its report) -->
<!ELEMENT evaluations (evaluation*,repairs?)>
<!ELEMENT evaluation (rule,report)>
<!-- reports (description + S-DAG) -->
<!ELEMENT report (desc?,sdag)>
<!-- truth: report’s boolean truth value -->
<!ATTLIST report
truth (true | false) #REQUIRED><!-- report’s truth value -->
<!-- S-DAG -->
<!ELEMENT sdag (leaf | allofnq | oneofnq | allofq | oneofq | abandoned | ref)>
<!-- predicate leaf -->
<!ELEMENT leaf (desc?,suggestalternative*)>
<!-- psym: predicate symbol -->
<!-- cons: is psym responsible for an inconsistency? -->
<!-- result: boolean result of psym -->
60
DTDs
<!ATTLIST leaf
id CDATA #REQUIRED
psym CDATA #REQUIRED
cons (consistent | inconsistent) #REQUIRED
result (true | false) #REQUIRED>
<!-- alternative predicate suggestions set -->
<!ELEMENT suggestalternative (suggest*)>
<!-- predicate suggestion -->
<!ELEMENT suggest (sugsetsuchthat | sugdontknow | sugset | sugcontradict)>
<!-- set the value of a variable to the specified value -->
<!ELEMENT sugset (value)>
<!-- var: variable to set -->
<!-- field: field in the variable to set -->
<!-- cost: repair cost -->
<!ATTLIST sugset
var CDATA #REQUIRED
field CDATA #IMPLIED
cost CDATA #IMPLIED>
<!-- set a variable such that the specified predicate holds or not -->
<!ELEMENT sugsetsuchthat (value*)>
<!-- var: variable to set -->
<!-- bool: targeted boolean value -->
<!ATTLIST sugsetsuchthat
var CDATA #REQUIRED
bool (true | false) #REQUIRED>
<!-- don’t know how to change the variable -->
<!ELEMENT sugdontknow EMPTY>
<!-- var: variable to set -->
<!-- bool: targeted boolean value -->
<!ATTLIST sugdontknow
var CDATA #REQUIRED
bool (true | false) #REQUIRED>
<!-- contradicting suggestions, e.g. set x to 1 and keep x -->
<!ELEMENT sugcontradict (suggest*)>
<!-- S-DAG conjunction node -->
<!ELEMENT allofnq (sdag*)>
<!ATTLIST allofnq
id CDATA #REQUIRED>
<!-- S-DAG disjunction node -->
<!ELEMENT oneofnq (sdag*)>
<!ATTLIST oneofnq
id CDATA #REQUIRED>
B.4 Report DTD report.dtd
61
<!-- S-DAG universal node -->
<!ELEMENT allofq (domain?,quantedge*)>
<!-- id: quantified variable -->
<!ATTLIST allofq
var CDATA #REQUIRED
id CDATA #REQUIRED>
<!-- S-DAG existential node -->
<!ELEMENT oneofq (domain?,quantedge*)>
<!-- id: quantified variable -->
<!ATTLIST oneofq
var CDATA #REQUIRED
id CDATA #REQUIRED>
<!-- domain of a quantifier node -->
<!ELEMENT domain (value*)>
<!-- repair action -->
<!ELEMENT repairaction (delete | add | change | changesuchthat | keep)>
<!-- delete a value -->
<!ELEMENT delete (value)>
<!-- add a value -->
<!ELEMENT add (value)>
<!-- change a value (from, to) -->
<!ELEMENT change (value,value)>
<!-- field: change this field -->
<!ATTLIST change
field CDATA #IMPLIED>
<!-- change free variables of the corresponding formula such that -->
<!-- the predicate symbol applied to the given values results in ... -->
<!ELEMENT changesuchthat (value*)>
<!-- psym: predicate symbol which should be applied to the values -->
<!-- bool: requested boolean result -->
<!ATTLIST changesuchthat
psym CDATA #REQUIRED
bool (true | false) #REQUIRED>
<!-- do nothing -->
<!ELEMENT keep EMPTY>
<!-- edge below a quantifier node
(bound values, repair actions, target S-DAG) -->
<!ELEMENT quantedge (value*,repairaction*,sdag)>
62
DTDs
<!-- an abandoned S-DAG which we do not want to repair -->
<!ELEMENT abandoned EMPTY>
<!-- a reference to another S-DAG node -->
<!ELEMENT ref EMPTY>
<!ATTLIST ref
targetID CDATA #REQUIRED>
<!-- REPAIR collection -->
<!ELEMENT repairs (repairalt*)>
<!-- alternative repair set in the repair collection -->
<!ELEMENT repairalt (repair*)>
<!-- repair -->
<!ELEMENT repair (concerns*,term,assign*,repairaction,rating)>
<!-- rules for which a repair resolves inconsistencies -->
<!ELEMENT concerns EMPTY>
<!-- rule: rule identifier -->
<!-- var: variable inside the rule -->
<!ATTLIST concerns
rule CDATA #REQUIRED
var CDATA #REQUIRED>
<!-- repair context -->
<!ELEMENT assign (value)>
<!-- var: variable to which a value is assigned -->
<!ATTLIST assign
var CDATA #REQUIRED>
<!-- rating of a repair -->
<!ELEMENT rating (resolves*,offends*)>
<!-- cost: repair cost -->
<!ATTLIST rating
cost CDATA #IMPLIED>
<!-- how many inconsistencies does a rule resolve -->
<!ELEMENT resolves EMPTY>
<!-- ruleprio: priority of the rule for which inconsistencies are resolved -->
<!-- inconsistencies: number of inconsistencies resolved -->
<!ATTLIST resolves
ruleprio CDATA #REQUIRED
inconsistencies CDATA #REQUIRED>
<!-- rules that might be violated by apoplying a repair -->
<!-- rule: rule identifier of a possibly violated rule -->
<!ELEMENT offends EMPTY>
<!ATTLIST offends
B.4 Report DTD report.dtd
rule CDATA #REQUIRED>
<!-- VALUES -->
<!ELEMENT value (vat | vrec | vvar | vfun | vundefined)>
<!-- atomic value -->
<!ELEMENT vat (#PCDATA)>
<!-- record value -->
<!ELEMENT vrec (vlabel*)>
<!-- id: record constructor -->
<!ATTLIST vrec
id CDATA #REQUIRED>
<!-- record value label -->
<!ELEMENT vlabel (value)>
<!-- id: label name -->
<!ATTLIST vlabel
id CDATA #REQUIRED>
<!-- variant value -->
<!ELEMENT vvar (value*)>
<!-- id: variant constructor name -->
<!ATTLIST vvar
id CDATA #REQUIRED>
<!-- function value -->
<!ELEMENT vfun EMPTY>
<!-- id: name of the function -->
<!ATTLIST vfun
id CDATA #REQUIRED>
<!-- undefined value -->
<!ELEMENT vundefined EMPTY>
<!-- consistency rule -->
<!ELEMENT rule (meta,formula,actions)>
<!-- date: creation date of the rule -->
<!-if a rule is newer than the last runtime then
it might have been changed -->
<!-- id: rule identifier -->
<!ATTLIST rule
date CDATA #REQUIRED
id ID #REQUIRED> <!-- rule name -->
<!-- rule metadata -->
<!ELEMENT meta (desc?,precon*,docdeps?)>
63
64
DTDs
<!-- weight: rule weight (importance) 0 .. 100 -->
<!-- weak: may a rule be violated? -->
<!ATTLIST meta
weight CDATA "0"
weak (true | false) #REQUIRED>
<!-- consistency rule description -->
<!ELEMENT desc (#PCDATA)>
<!-- rule precondition: this rule must be satisfied in order to check -->
<!-- the current rule (not supported at the moment) -->
<!ELEMENT precon EMPTY>
<!ATTLIST precon
id CDATA #REQUIRED>
<!-- document dependencies of a rule -->
<!-- not given: dont know (determined by CDET) -->
<!-- given: these are the documents the rule really depends on -->
<!ELEMENT docdeps (docdep*)>
<!ELEMENT docdep EMPTY>
<!-- regex: regular expression of the dependent documents -->
<!ATTLIST docdep
regex CDATA #REQUIRED>
<!-- first order formula with description -->
<!ELEMENT formula
(desc?,(papply | or | and | not | implies | forall | exists))>
<!-- applied predicate (atomic formula) plus hint collection -->
<!ELEMENT papply (term*,hintalternative*)>
<!-- id: predicate symbol -->
<!ATTLIST papply
id CDATA #REQUIRED>
<!-- alternative hint set -->
<!ELEMENT hintalternative (set*)>
<!-- hint -->
<!ELEMENT set (term)>
<!-- condition: predicate result causing to execute the hint -->
<!-- id: variable to set -->
<!-- varcondition: set variable only if it is marked new / old -->
<!-- field: record field to set -->
<!-- repaircost: cost imposed by executing the corresponding repair -->
<!ATTLIST set
condition (true | false) #IMPLIED
id CDATA #REQUIRED
varcondition (new | old) #IMPLIED
B.4 Report DTD report.dtd
65
field CDATA #IMPLIED
repaircost CDATA #IMPLIED>
<!-- disjunction -->
<!ELEMENT or (formula,formula+)>
<!-- conjunction -->
<!ELEMENT and (formula,formula+)>
<!-- implication -->
<!ELEMENT implies (formula,formula)>
<!-- negation -->
<!ELEMENT not (formula)>
<!-- universal quantification with sphere term -->
<!ELEMENT forall (term,formula)>
<!-- id: quantified variable -->
<!-- action: hint for quantifier -->
<!-- keepdomain: also cache the quantifier sphere (may be expensive!) -->
<!ATTLIST forall
id CDATA #REQUIRED
action (delete | add | change | keep) #IMPLIED
keepdomain (true | false) #IMPLIED>
<!-- existential quantification with sphere term -->
<!ELEMENT exists (term,formula)>
<!-- id: quantified variable -->
<!-- action: hint for quantifier -->
<!-- keepdomain: also cache the quantifier sphere (may be expensive!) -->
<!ATTLIST exists
id CDATA #REQUIRED
action (delete | add | change | keep) #IMPLIED
keepdomain (true | false) #IMPLIED> <!-- quantified variable -->
<!-- TERMS -->
<!-- term with description -->
<!ELEMENT term (desc?,(var | fapply | sym | rec | case | typed))>
<!-- variable -->
<!ELEMENT var EMPTY>
<!-- id: variable name -->
<!ATTLIST var
id CDATA #REQUIRED>
<!-- applied function symbol -->
<!ELEMENT fapply (term*)>
<!-- id: function symbol name -->
66
DTDs
<!ATTLIST fapply
id CDATA #REQUIRED>
<!-- function symbol e.g. as argument for higher order functions -->
<!ELEMENT sym EMPTY>
<!-- id: function symbol name -->
<!ATTLIST sym
id CDATA #REQUIRED>
<!-- record construction -->
<!ELEMENT rec (label)*>
<!-- id: record constructor name -->
<!ATTLIST rec
id CDATA #REQUIRED>
<!-- record label -->
<!ELEMENT label (term)>
<!-- id: label name (unique for this record) -->
<!ATTLIST label
id CDATA #REQUIRED>
<!-- variant deconstruction -->
<!ELEMENT case (term,binding*)>
<!-- tcref: variant constructor (type constructor) -->
<!ATTLIST case
tcref CDATA #IMPLIED>
<!-- binding inside case: id -> sym -->
<!ELEMENT binding EMPTY>
<!-- id: variant constructor -->
<!-- sym: function symbol to be applied to constructor arguments -->
<!ATTLIST binding
id CDATA #REQUIRED
sym CDATA #REQUIRED>
<!-- explicitly typed term -->
<!ELEMENT typed (term,type)>
<!-- user defined action what should be done with the report -->
<!-- not supported at the moment -->
<!ELEMENT actions (mailreport*, mailrepair*,mailsummary?)>
<!-- Mail the report to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailreport (recipient+)>
<!ATTLIST mailreport
currentonly (true | false) #REQUIRED
B.4 Report DTD report.dtd
explain
format
attachDocs
(true | false) #REQUIRED
(xml | latex) #REQUIRED
(true | false) #REQUIRED>
<!-- Mail the repair suggestions to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailrepair (recipient+)>
<!ATTLIST mailrepair
currentonly (true | false) #REQUIRED
explain
(true | false) #REQUIRED
format
(xml | latex) #REQUIRED
attachDocs (true | false) #REQUIRED>
<!-- Mail a comprehensive summary to some recipients -->
<!-- not supported at the moment -->
<!ELEMENT mailsummary (recipient+)>
<!ELEMENT recipient EMPTY>
<!ATTLIST recipient
mailto CDATA #REQUIRED>
<!-- TYPES -->
<!-- type: ground or function type -->
<!ELEMENT type (gtype | funtype)>
<!-- groundtype -->
<!ELEMENT gtype (tapply | tvar | top | state)>
<!-- type application -->
<!ELEMENT tapply (gtype*)>
<!-- tcref: type constructor to be applied -->
<!ATTLIST tapply
tcref CDATA #REQUIRED>
<!-- type variable -->
<!ELEMENT tvar EMPTY>
<!-- id: type variable name -->
<!ATTLIST tvar
id CDATA #REQUIRED>
<!-- supertype of all other types -->
<!ELEMENT top EMPTY>
<!-- repository state -->
<!ELEMENT state EMPTY>
<!-- function type -->
<!ELEMENT funtype (type*,gtype)>
67
Appendix C
GNU General Public License
Version 2, June 1991
c 1989, 1991 Free Software Foundation, Inc.
Copyright 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change
it. By contrast, the GNU General Public License is intended to guarantee your freedom
to share and change free software—to make sure the software is free for all its users.
This General Public License applies to most of the Free Software Foundation’s software
and to any other program whose authors commit to using it. (Some other Free Software
Foundation software is covered by the GNU Library General Public License instead.) You
can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute copies
of free software (and charge for this service if you wish), that you receive source code or
can get it if you want it, that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you
these rights or to ask you to surrender the rights. These restrictions translate to certain
responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee,
you must give the recipients all the rights that you have. You must make sure that they,
too, receive or can get the source code. And you must show them these terms so they
know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this
license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author’s protection and ours, we want to make certain that everyone
understands that there is no warranty for this free software. If the software is modified
by someone else and passed on, we want its recipients to know that what they have is
not the original, so that any problems introduced by others will not reflect on the original
authors’ reputations.
Finally, any free program is threatened constantly by software patents. We wish to
avoid the danger that redistributors of a free program will individually obtain patent
68
69
licenses, in effect making the program proprietary. To prevent this, we have made it clear
that any patent must be licensed for everyone’s free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING,
DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed
by the copyright holder saying it may be distributed under the terms of this General
Public License. The “Program”, below, refers to any such program or work, and
a “work based on the Program” means either the Program or any derivative work
under copyright law: that is to say, a work containing the Program or a portion of
it, either verbatim or with modifications and/or translated into another language.
(Hereinafter, translation is included without limitation in the term “modification”.)
Each licensee is addressed as “you”.
Activities other than copying, distribution and modification are not covered by this
License; they are outside its scope. The act of running the Program is not restricted,
and the output from the Program is covered only if its contents constitute a work
based on the Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program’s source code as
you receive it, in any medium, provided that you conspicuously and appropriately
publish on each copy an appropriate copyright notice and disclaimer of warranty;
keep intact all the notices that refer to this License and to the absence of any
warranty; and give any other recipients of the Program a copy of this License along
with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at
your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus
forming a work based on the Program, and copy and distribute such modifications
or work under the terms of Section 1 above, provided that you also meet all of these
conditions:
(a) You must cause the modified files to carry prominent notices stating that you
changed the files and the date of any change.
(b) You must cause any work that you distribute or publish, that in whole or
in part contains or is derived from the Program or any part thereof, to be
licensed as a whole at no charge to all third parties under the terms of this
License.
(c) If the modified program normally reads commands interactively when run,
you must cause it, when started running for such interactive use in the most
ordinary way, to print or display an announcement including an appropriate
copyright notice and a notice that there is no warranty (or else, saying that
you provide a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this License.
(Exception: if the Program itself is interactive but does not normally print
such an announcement, your work based on the Program is not required to
print an announcement.)
70
GNU General Public License
These requirements apply to the modified work as a whole. If identifiable sections
of that work are not derived from the Program, and can be reasonably considered
independent and separate works in themselves, then this License, and its terms, do
not apply to those sections when you distribute them as separate works. But when
you distribute the same sections as part of a whole which is a work based on the
Program, the distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to each and
every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to control
the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with
the Program (or with a work based on the Program) on a volume of a storage or
distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section
2) in object code or executable form under the terms of Sections 1 and 2 above
provided that you also do one of the following:
(a) Accompany it with the complete corresponding machine-readable source code,
which must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange; or,
(b) Accompany it with a written offer, valid for at least three years, to give any
third party, for a charge no more than your cost of physically performing
source distribution, a complete machine-readable copy of the corresponding
source code, to be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange; or,
(c) Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or
executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source
code for all modules it contains, plus any associated interface definition files, plus
the scripts used to control compilation and installation of the executable. However,
as a special exception, the source code distributed need not include anything that is
normally distributed (in either source or binary form) with the major components
(compiler, kernel, and so on) of the operating system on which the executable runs,
unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from
a designated place, then offering equivalent access to copy the source code from the
same place counts as distribution of the source code, even though third parties are
not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense or
distribute the Program is void, and will automatically terminate your rights under
this License. However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such parties remain
in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or
71
its derivative works. These actions are prohibited by law if you do not accept this
License. Therefore, by modifying or distributing the Program (or any work based
on the Program), you indicate your acceptance of this License to do so, and all its
terms and conditions for copying, distributing or modifying the Program or works
based on it.
6. Each time you redistribute the Program (or any work based on the Program),
the recipient automatically receives a license from the original licensor to copy,
distribute or modify the Program subject to these terms and conditions. You may
not impose any further restrictions on the recipients’ exercise of the rights granted
herein. You are not responsible for enforcing compliance by third parties to this
License.
7. If, as a consequence of a court judgment or allegation of patent infringement or
for any other reason (not limited to patent issues), conditions are imposed on you
(whether by court order, agreement or otherwise) that contradict the conditions
of this License, they do not excuse you from the conditions of this License. If you
cannot distribute so as to satisfy simultaneously your obligations under this License
and any other pertinent obligations, then as a consequence you may not distribute
the Program at all. For example, if a patent license would not permit royalty-free
redistribution of the Program by all those who receive copies directly or indirectly
through you, then the only way you could satisfy both it and this License would be
to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply and the section as a
whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the
sole purpose of protecting the integrity of the free software distribution system,
which is implemented by public license practices. Many people have made generous
contributions to the wide range of software distributed through that system in
reliance on consistent application of that system; it is up to the author/donor to
decide if he or she is willing to distribute software through any other system and a
licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries
either by patents or by copyrighted interfaces, the original copyright holder who
places the Program under this License may add an explicit geographical distribution
limitation excluding those countries, so that distribution is permitted only in or
among countries not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the
General Public License from time to time. Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems or
concerns.
Each version is given a distinguishing version number. If the Program specifies a
version number of this License which applies to it and “any later version”, you have
the option of following the terms and conditions either of that version or of any
later version published by the Free Software Foundation. If the Program does not
specify a version number of this License, you may choose any version ever published
by the Free Software Foundation.
72
GNU General Public License
10. If you wish to incorporate parts of the Program into other free programs whose
distribution conditions are different, write to the author to ask for permission. For
software which is copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our decision will be
guided by the two goals of preserving the free status of all derivatives of our free
software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING
THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO
IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED
OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Bibliography
[AHV96]
S. Abiteboul, L. Herr, and J. Van den Bussche. Temporal versus firstorder logic to query temporal databases. In ACM Symp. on Principles
of Database Systems, pages 49–57, Montreal, Canada, 1996. ACM
Press.
[C+ 03]
M. Chakravarty et al. The Haskell Foreign Function Interface 1.0
(Addendum to the Haskell 98 Report), 2003.
see www.cse.unsw.edu.au/˜chak/haskell/ffi/.
[CSFP04]
B. Collins-Sussman, B. W. Fitzpatrick, and C. M. Pilato. Version
Control with Subversion. O’Reilly and Associates, 2004.
[MTH90]
R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML.
MIT Press, 1990.
[PJ03]
S. L. Peyton-Jones. Haskell 98 Language and Libraries: The Revised
Report. Cambridge University Press, 2003.
[Rou05]
D. Roundy. DARCS: David’s advanced revision control system, 2005.
see www.darcs.net.
[SBBS05]
J. Scheffczyk, U. M. Borghoff, A. Birk, and J. Siedersleben. Pragmatic
consistency management in industrial requirements specifications. In
Proc. of the 3rd IEEE Int. Conf. on Software Engineering and Formal
Methods, page to appear, Koblenz, Germany, 2005. IEEE CS Press.
[SBRS03a] J. Scheffczyk, U. M. Borghoff, P. R¨odig, and L. Schmitz. Consistent
document engineering. In Proc. of the 2003 ACM Symp. on Document
Engineering, pages 140–149, Grenoble, France, 2003. ACM Press.
[SBRS03b] J. Scheffczyk, U. M. Borghoff, P. R¨odig, and L. Schmitz. Efficient (in) consistency management for heterogeneous repositories. In Proc. of
the 4th Int. Conf. on Software Engineering, Artificial Intelligence, Networking, and Parallel/Distributed Computing, pages 370–377, L¨
ubeck,
Germany, 2003. ACIS.
[SBRS04a] J. Scheffczyk, U. M. Borghoff, P. R¨odig, and L. Schmitz. Managing
inconsistent repositories via prioritized repair actions. In Proc. of the
2004 ACM Symp. on Document Engineering, pages 137–146, Milwaukee, WI, 2004. ACM Press.
73
74
BIBLIOGRAPHY
[SBRS04b] J. Scheffczyk, U. M. Borghoff, P. R¨odig, and L. Schmitz. Towards efficient consistency management for informal applications. Int. Journal
of Computer & Information Science, 5(2):109–121, 2004.
[SBRS04c] J. Scheffczyk, Uwe M. Borghoff, P. R¨odig, and L. Schmitz. S-DAGs:
Towards efficient document repair generation. In Proc. of the 2nd
Int. Conf. on Computing, Communications and Control Technologies,
volume 2, pages 308–313, Austin, TX, 2004. University of Texas at
Austin.
[Sch04]
J. Scheffczyk. Consistent Document Engineering. PhD thesis, Universit¨at der Bundeswehr M¨
unchen, 2004. see www.unibw.de/inf2/CDET.
[SSBS04]
J. Scheffczyk, C. Stutz, U. M. Borghoff, and J. Siedersleben. Formale
Konsistenzsicherung in informellen Software-Spezifikationen. Informatik Forschung und Entwicklung, 19(1):17–29, 2004.
[W3C01]
World Wide Web Consortium W3C. XML Schema part 0: Primer.
W3C Recommendation, 2001. see www.w3.org/TR/xmlschema-0/.
[WR99]
M. Wallace and C. Runciman. Haskell and XML: Generic combinators
or type-based translation? In Proc. of the 4th ACM SIGPLAN Int.
Conf. on Functional Programming, pages 148–159, Paris, France, 1999.
ACM Press.