...
Persistence is the term used for storing (application) state in between sessions, in our case model instances represented by objects structures (graphs), and covers file and database storage, including SQL, object and NoSQL databases. The logic of files and databases are so different that it is easier to treat them separately. A file is essentially a sequence or array of bytes, which often encode characters, and serialisation is the term used for generating this byte (or character) sequence from an object structure. The opposite process, de-serialisation, is the process of reconstructing the object structure from the byte stream.
...
Resources
EMF uses a(n instance of the) Resource (class) as the container of the object graph and scope of serialisation. The object graph will mainly consist of EObjects, since this is the base superclass of all modelled data, hence we'll use EObjects as a synonym for graph of instances of an Ecore model. if You Thus, you serialise the EObjects contained in a Resource to an OutputStream (e.g. a FileOutputStream) with its save method, and de-serialise from an InputStream (e.g. a ByteArrayInputStream) into a Resource with its load method, which then will contain the re-constructed object structure EObjects. The Resource class is abstract, and it's the Resource subclass you use that implements the serialisation logic which determines the format of the byte or character sequence. E.g. the XMIResource class supports a generic format named XML Metadata Interchange (XMI), which is an XML-based model format standardised by the Object Management Group (OMG), so if you want your EObjects serialised as XMI, you use an XMIResource as the container of your EObjects. You can implement your own custom format by making your own Resource subclass, e.g. to load support existing legacy formats or a format designed to be easier to read and write for humans (e.g. a DSL). The (structure of) EObjects within a Resource is often self-contained, but cross-links between Resources, are supported, and this must be handled by the serialisation and de-serialisation mechanism. EMF uses a dual technique based on URIs: 1) a URI is used to identify a Resource , e.g. "file:/Users/hal/resource2.xmi" and 2) a fragment is used to identify an EObject within a Resource. The fragment is computed by the target Resource's getURIFragment(EObject) method and is typically a path-like string like "/orgUnits/0/workers/2", and can be used alone to serialise links within a Resource.Together this gives URIs like "file:/Users/hal/resource2.xmi#/orgUnits/0/workers/2" where "#" is used as separator according to the URI standard. A Resource is identified by a URI, which typically matches the source of the byte stream from which it was loaded, e.g. a URL or filesystem path. The URI is important for supporting so-called cross-links, which is when an EObject in one Resource refers to an EObject in another Resource (illustrated in the figure to the right). When serialising such links, the first Resource, must encode a reference to the EObject in the other Resource. The URI will be used to refer to the Resource, and then a reference to the EObject within the Resource is appended as the URI's so-called fragment, giving something like "file:/Users/hal/resource2.xmi#/path/to/object". The fragment is the part after the #, and the actual format of the fragment is decided by the target Resource's getURIFragment method (which has a default implementation which can be overridden). When loading a Resource with a cross-link, the object reference is resolved and the target Resource is loaded, too, The fragment is useful on its own, as it can be used to serialise links within a Resource, too. When loading a Resource with a cross-link, the base URI is resolved and the target Resource loaded, before looking up the target EObject using its getEObject(String). | Det circles in Resource 1 and 2 are instances of subclasses of EObject, where the classes typically are generated from your Ecore model. The arrows from circles in Resource 1 to Resource 2 are cross-links. From http://www.informit.com/articles/article.aspx?p=1323360&seqNum=5 |
ResourceSets
so in practice you may end up with many Resources, each containing part of a large object graph. To have a place to put all these Resources, you use a ResourceSet, as shown in the figure.
Summarised: A ResourceSet contains a set of linked Resources and a Resource contains an object structure. A Resource is identified by a URI and objects within a Resource by a URI with a fragment
.Det circles in Resource 1 and 2 are instances of subclasses of EObject, where the classes typically are generated from your Ecore model
.
The arrows from circles in Resource 1 to Resource 2 are cross-links.From http://www.informit.com/articles/article.aspx?p=1323360&seqNum=5The Resource.Factory class
Since a Resource implements important logic for handling serialisation, it is important to use the right subclass as a container for your model instance, to ensure the correct format is used. Although you may use several format, e.g. XMI for file storage and JSON for REST, the format and hence Resource subclass is usually the same for all instances of a model.
...