Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: disregard Deleted Objects

Fedora Repository Views

...

But the angle one views the repository might also affect the number of entries seen. The above, recursive approach will always lead to one entry per data object. The remedy for this is to mark some classes as Entries for a certain view angle. This means that to compute the records for a given view angle, the view of all objects of a class that is an Entry should be computed. This is the view of the repository.

Fedora Implementation 

This section describes how the above could be implemented in Fedora. 

...

Code Block
languagejava
Set<Object> visitedObjects;
 
List<Object> CalculateView(Object o) {
	List<Objects> view = new List<Objects>();
 
	if (visitedObjects.contain(o){
		return view;
	}


	visitedObjects.add(o);
 	if (o.isDeleted){
		return view;
	}
	ContentModel c = o.getContentModel();
	List<Relation> view-rels = c.getViewRelations();
	List<Relation> object-rels = o.getRelations();
 
	for (Relation r : object-rels){
		if (view-rels.contain(r)){
			view.addAll(CalculateView(r.getObject());
		}
	}
 
	List<Relation> view-invrels = c.getInverseViewRelations();
	List<Relation> object-invrels = o.getInverseRelations();
	for (Relation r : object-invrels){
		if (view-invrels.contain(r)){
			view.addAll(CalculateView(r.getSubject());
		}
	}
 
	return view;
}

...

  • When finding the annotated relations for a given view angle for a data object, get the list from each of the content models, merge it to one list and remove the duplicates. These are the view relations of this object. Do the same with the inverse relations.
  • If a content model marks an object as an Entry for a given view angle, the object is an entry. It does not matter if it has other content models that does not mark it as an entry. An object can of course be an entry for several view angles.   

Update Tracking

This document describes how the backend services should use to view to detect changes in records.

Changing an object and marking the view as updated

Whenever one of the components of a View is changed, the whole View count as updated. As such, any services that subscribe to the View in any way need to be notified. If there is a search index for the Views, and one is updated, its state in the index must be recomputed.

The problem arrives when trying to do this. The View system is designed to ease the computing of a View when knowing the Entry object. The reverse is finding the Views, ie. the Entry objects, that have this data object in their View. Rather than encoding this information in the model, we chose to keep an external record of all the views.

The external record will be SQL based, or something similar. It will have two tables.

The first table, ENTRIES, will have these columns

  • entryPid: This is the pid of the entry object
  • viewAngle: This is the viewangle
  • state: This is the fedora object state
  • dateForChange: This is the timestamp when this row was created

EntryPid, viewAngle and State will form an unique key.

To explain the reasoning: Each Entry Object can be an entry object for multiple viewAngles. If the object state is changed, the old entry should remain. As such, each entry object can result in many rows.

The second table, OBJECTS, will have these columns

  • objectPid: The pid of this object
  • entryPid: The pid of the entry object that includes this object
  • viewAngle: The name of the view angle by which the entry object includes this object

There are a fixed number of operations that can be done on objects in doms. For each of these, this is what should be done on the index as a result

...

Each of these operations will be elaborated below

Object State Changed

When the object state changes, we will have to mark all ENTRIES containing this object in it's new state as changed, ie. with a new timestamp. If the object does not previously exist, this will do nothing, as it is not referred in the ENTRIES table.

If the object that changed is itself an Entry object, update/insert it into the ENTRIES. As each Entry Object will per definition include itself in it's view, also add to object to the OBJECTS table.

Code Block
languagejava
void objectStateModified(String pid, Date date, String state) {
 
	//Find the DomsObject rows that regard this object.
	//There will be one per entry/viewAngle combination
	List<DomsObject> results = OBJECTS.list(objectPid=pid);


	//Find all Entries that include this object
	//If the object does not previously exist, this list will be empty
	for (DomsObject result : results) {
    	if (!result.getEntryPid().equals(pid)) {
        	//Mark them as updated
	        updateEntry(result.getEntryPid(),
    	                      state,
        	                  result.getViewAngle(),
            	              date);
	    }
	}


	// Find view Info for this object
	List<ViewInfo> viewInfoList = fedora.getViewInfo(pid, date);
	for (ViewInfo viewInfo : viewInfoList) {
    	//If it is an entry object, set it in the ENTRIES table
	    if (viewInfo.isEntry()) {
    	    updateEntry(pid, state, viewInfo.getViewAngle(), date);
	        updateDomsObjects(pid, pid, viewInfo.getViewAngle());
    	}
	}
}

// Update the Entries table regarding a change
void updateEntry(String entryPid, String state, String viewAngle, Date date) {
    //Find the Entry objects that fulfill these restrictions
    List<Entry> results = ENTRIES.list(entrypid,state,viewangle)

    //There might be no Entry, but if we are here, we know that an entry should exist, so create it.
    if (results.size() == 0) {
		ENTRIES.insert(new Entry(entryPid, viewAngle, state, date));
    } else {
        for (Entry result : results) {
	        //Is this entry older than the current change?
            if (result.getDateForChange().getTime() < date.getTime()) {
                result.setDateForChange(date);
                result.setEntryPid(entryPid);
                result.setState(state);
                result.setViewAngle(viewAngle);
            }
            //Save the entry
            ENTRIES.update(result);
        }
    }
}
 
void updateDomsObjects(String objectPid, String entryPid, String viewAngle) {
	list<DomsObject> results = OBJECTS.list(objectPid,entryPid,viewAngle)
    if (results.size() == 0) {
        OBJECTS.insert(new DomsObject(objectPid, entryPid, viewAngle));
    }
}

Object Relations Changed

 An object's relations changed. This could change which objects are in which entry's views. 

We find all the Entries that contain this object by listing OBJECTS.

For each of these, we recalculate the view bundle and update the relevant rows in OBJECTS and ENTRIES.

Each row in OBJECTS specify that an object is contained in a named view for a specific entry object.

Then we update the ENTRIES table to mark that the view is changed. 

 

Code Block
void objectRelationsChanged(String pid, Date date) {

    //This can change the structure of the views and we must therefore recaculate the views

    //if a current entry object use this object, we will need to recalculate the view of that object

    //This method will only be called on objects that already exist. Objects cannot change type once created.
    //ObjectModified() creates an Entry row, if the object is an entry object. As such, there will always be
    // the correct Entry entries when this method is called, and these should just be recalculated

    List<DomsObject> results = OBJECTS.list(objectPid=pid);

    //we now have a list of all the entries that include this object.

    for (DomsObject result : results) {

        //get the ViewBundle from fedora
        ViewBundle bundle = fedora.calcViewBundle(result.getEntryPid(), result.getViewAngle(), date);

        //First, remove all the objects in this bundle from the table
        removeNotListedFromDomsObjects(bundle.getContained(), result.getEntryPid(), result.getViewAngle());

        //Add all the objects from the bundle to the objects Table.
        for (String objectPid : bundle.getContained()) {
            updateDomsObjects(objectPid, bundle.getEntry(), bundle.getViewAngle());
        }

        updateEntry(bundle.getEntry(), STATE_INPROGRESS, bundle.getViewAngle(), date);

    }
}


void removeNotListedFromDomsObjects(List<String> objectPid, String entryPid, String viewAngle) {

    List<DomsObject> results = OBJECTS.list(entryPid,viewAngle);

    for (DomsObject result : results) {
        if (!objectPid.contains(result.getObjectPid())) {
            OBJECTS.delete(result);
        }
    }
}

 

With these two functions, the rest of the events can be modelled as from them

Object Changed

This is the same as Object State Changed, if the state did not really change. If the state is not changed, this method will just update timestamps in ENTRIES.

Object Created

An object that is created will not, per default, be part of any views, except any where it is the entry object, as these are defined through relations, and a newly created object will not reference any other objects.

As such, it is the same as Object State Changed.

Object Deleted

The Object was purged from DOMS.

Find the object as an entrypid in ENTRIES (if it is not an entry, it will not be there).

if is an entry 

    Mark is as deleted with the new date.

    Find all the rows in OBJECTS which refer to this entrypid and viewangles, and remove them. 

Remove the object from OBJECTS

 

...