SMILA/Project Concepts/ID Concept

From Eclipsepedia

Jump to: navigation, search

Contents

Description

The purpose of an ID is to identify an object in the system. What is an object in EILF?

  • simple case: a single document
  • what about compounds?
    • archive files, e.g. ZIPs
    • Big documents that should be indexed by page or by section
  • EILF objects have a life cycle
    • creation in crawler or agent
    • enrichment, splitting, merging (possible?) during processing in EILF
    • persisting in storages (possibly in different states of procesing) or indexes (usually at the end, but also possibly multiple times).
    • process is repeated, when object source changes (index update) -> new object must have same object ID.
    • using the ID it must be possible to refer to the source object.


These are the associated JIRA tasks:

Discussion

Technical proposal

Definition of concepts:

  • data source: a single location providing access to a colletion of data. (web server, file system, database, CMS, ...). Data is read from a data source using crawler/agents. A data source must have an unique source ID within EILF to refer to it without having to deal with the technical details of access.
  • source object: entity in data source. A crawler/agent can create multiple EILF objects from a single object source (e.g. by extracting files from a ZIP archive). A source object can be identified with respect to its data source using a relatively simple key (URL, path, primary key, ...)
  • record: an entity representing a complete source object or a part of an source object to be processed by EILF.
    • Can be split into multiple records.
    • Multiple records referring to different parts of the same source object can be merged again? Could be useful to split really large documents, process them section by section and merge the results again.
    • Can be written to storages or indexes.
    • Can be read from a storage in order to redo the rest of the processing (e.g. to

rebuild an index after ontology changes).


Record ID design

A Record ID must contain and it must be able to extract:

  • data source ID
  • key of source object in data source, relative to the definitions of the data source

These must be provided by the crawler/agent.

Source objects can have multiple key values, e.g. in database tables with a primary key consisting of multiple columns.

During processing, the record ID may be can be enhanced:

  • Part specification after splitting a compound
    • Element: part of a container, e.g. path in archive (what about recursion: part of part of part...), attachment index in mails, etc. The element is identified by another key which is relative to the container element.
    • Fragment: identified by page number, section number, section name, etc.

If merging is supported, multiple records belonging to the same source object can be merged into a single record. The merged ID must reflect this.

Do we want to pack all this into a single ID string (URL, whatever)? All kinds of quoting problems may arise (remember that the source object key could be a complex URL itself already). Thus, we probably want to use a structured ID object. Something like this:

<eilf:Record>
    <eilf:ID>
        <eilf:Source><!-- String: ID of data source --></eilf:Source>
        <eilf:Key><!-- String: key of source object wrt. data source --></eilf:Key>
 
        <!-- the elemements above are mandatory, the following is optional -->
 
        <eilf:Element>
            <eilf:Key><!-- String: path in archive, attachment index --></eilf:Key>
            <!-- eilf:Element can repeated for recursive archives -->
        </eilf:Element>
 
        <eilf:Fragment><!-- page number, section name/number --></eilf:Fragment>
        <!-- maybe repeated e.g. for for books: Part, Chapter, Section, Subsection ... -->
    </eilf:ID>
 
    <!-- other metadata and non-binary content -->
 
</eilf:Record>

For a source object with multiple key values it must be distinguishable which key value belongs to which key "column". Therefore eilf:Key can be optionally annotated with a name attribute:

<eilf:Record>
    <eilf:ID>
        <eilf:Source><!-- String: ID of data source --></eilf:Source>
        <eilf:Key name="column1"><!-- key value in named column --></eilf:Key>
        <eilf:Key name="column2"><!-- key value in named column --></eilf:Key>
        ...
    </eilf:ID>
</eilf:Record>

Because eilf:Element uses the eilf:Key element to identify the element inside a compound, it would be technically possible to support compounds that need multiple key values to identify an element. We cannot think of an actual use case currently, though (-;

In Java:

public interface ID extends Serializable
{
    String getSource();
    Key getKey(); 
 
    List<Key> getElements();
    List<String> getFragments();
 
    ID createElementID(String elementName);
    ID createElementID(Key elementKey);
    ID createFragmentID(String framentName);
 
    ID mergeWith(Collection<ID> otherParts);
}
public interface Key extends Serializable
{
    static final String NONAME = "__eilf:unnamedkey__";
 
    Iterator<String> getKeyNames();
    String getKey(String name);
    String getKey(); // shortcut for getKey(NONAME)
}
public interface IDFactory
{
    ID createID(String source, Key key);
    Key createKey(Map<String, String> keyValues);
 
    // convenience methods:
    ID createID(String source, String key);
    ID createID(String source, Map<String, String> keyValues);
    Key createKey(String key);
}

IDs should be usable as hash keys:

  • IDs are unchangeable objects
  • Provide appropriate hashcode() implementation


Examples

Assume a file system data source named "share", referring to a shared directory on a file server (e.g. "\\fileserv\share"). It looks like this:

\\fileserv\share
    |- PDF
    |   \- big.pdf
    \- Archive
        \- oldstuff.zip
        \- PDF
            \- old.pdf
            \- another.zip
                \- another.pdf

"big.pdf" initially gets this ID:

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>PDF/big.pdf</eilf:Key>
</eilf:ID>

After splitting it by pages, the following ID refers to the first page of the document:

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>PDF/big.pdf</eilf:Key>
    <eilf:Fragment>0</eilf:Fragment> <!-- or start counting at 1? -->
</eilf:ID>

Similar for the ZIP: It starts as:

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>Archive/oldstuff.zip</eilf:Key>
</eilf:ID>

When it is expanded, the contained file is referred to as

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>Archive/oldstuff.zip</eilf:Key>
    <eilf:Element>
        <eilf:Key>PDF/old.pdf</eilf:Key>
    </eilf:Element>
</eilf:ID>

which it turn can be splitted to pages to become:

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>Archive/oldstuff.zip</eilf:Key>
    <eilf:Element>
        <eilf:Key>PDF/old.pdf</eilf:Key>
    </eilf:Element>
    <eilf:Fragment>0</eilf:Fragment>
</eilf:ID>

And finally, the first page of the PDF in the recursive.zip would have this ID:

<eilf:ID>
    <eilf:Source>share</eilf:Source>
    <eilf:Key>Archive/oldstuff.zip</eilf:Key>
    <eilf:Element>
        <eilf:Key>another.zip</eilf:Key>
        <eilf:Element>
            <eilf:Key>another.pdf</eilf:Key>
        </eilf:Element>
    </eilf:Element>
    <eilf:Fragment>0</eilf:Fragment>
</eilf:ID>

Similar, for a mail server as a data source "mail" we could have the following ID to refer to an attachment of a mail in folder INBOX. In this case, the Element name is the index of the Mime Message part in the message in this case.

<eilf:ID>
    <eilf:Source>mail</eilf:Source>
    <eilf:Key>INBOX/42</eilf:Key>
    <eilf:Element>
      <eilf:Key>2</eilf:Key>
    </eilf:Element>
</eilf:ID>

A row in a database table with a primary key consisting of columns x and y would be identitified like this:

<eilf:ID>
    <eilf:Source>db</eilf:Source>
    <eilf:Key name="x">0815</eilf:Key>
    <eilf:Key name="y">4711</eilf:Key>
</eilf:ID>