Search code examples
oceanpetrel

Structured archive with multiple domain objects that inherit from common class


I'm writing an Ocean plugin for Petrel and need to persist some custom domain objects, and everything seems to point to using a structured archive data source. I've created a common class to hold a lot of the standard domain object stuff (droid, name, color, image, comments, history, etc), to avoid rewriting it for every domain object I create. The Ocean development guide only has simple examples of classes with no inheritance, but given that everything has a version number, I foresee a potential problem when the base class version is different than the version of inherited-class-1 which is different than inherited-class-2, and then I update something in the base class.

Is it possible to use a structured archive with the common base class? Are there any special considerations for versioning, or anything else I need to be aware of?

ETA: A simple class diagram showing the relationships and some stuff I've tried

public abstract class ClassA
                    |
       -----------------------------------
       |                                 |
public class ClassB : ClassA       public classC : ClassA


public class ClassD
{
    private List<ClassA> _myClassAObjects;
}

All classes are marked Archivable, and in ClassD, _myClassAObjects is marked Archived. Everything saves OK, but when I load, I get an InvalidCastException, as it tries to cast the List<ClassB> to a List<ClassA>. The casting should work, since ClassB inherits from ClassA, should it not?


Solution

  • Got an answer from Schlumberger. It is possible, by doing something like this:

    [Archivable]
    public abstract class Abstract CDO
    {
    
        [ArchivableContextInject]
        protected StructuredArchiveDataSource DataSourceCore;
    
        [Archived(Name = "Name")]
        private string _name;
    
        private AbstractCDO _parent;
    
        [Archived(Name="ParentDroid")]
        private Droid _parentDroid;
    
        [Archived(Name = "Droid")]
        protected Droid DroidCore
        {
            get { return _droid; }
            set
            {
                if (_droid != value)
                {
                    DataSourceCore.IsDirty = true;
                    _droid = value;
                }
            }
        }
    
        public Droid ParentDroid
        {
            get { return _parentDroid; }
            set
            {
                if (_parentDroid != value)
                {
                    DataSourceCore.IsDirty = true;
                    _parentDroid = value;
                }
            }
        }
    
        public AbstractCDO Parent
        {
            get { return _parent; }
            set
            {
                if (_parent != value)
                {
                    DataSourceCore.IsDirty = true;
                    _parent = value;
                    _parentDroid = _parent.Droid;
                }
            }
        }
    
        protected AbstractCDO(string name)
        {
            _name = name;
            DataSourceCore = Factory.Get();
            _droid = DataSourceCore.GenerateDroid();
            DataSourceCore.AddItem(_droid, this);
        }
    
    }
    
    [Archivable]
    public abstract class AbstractCDOCollection : AbstractCDO, IObservableElementList
    {
    
        [Archived]
        private List<AbstractCDO> _children;
    
        protected AbstractCDO(string name) : base(name) { }
    
        public List<AbstractCDO> Children
        {
            get { return _children; }
        }
    
    }
    
    [Archivable]
    public class ConcreteObject : AbstractCDO
    {
    
        public ConcreteObject(string name) : base(name)
        {
            // other stuff
        }
    
    }
    

    The DataSource property needs to be protected since the injection had a bug which was fixed in Petrel 2013.3 / 2014.1.