How can you properly model Nested/Sub Classes in UML? - class-diagram

I've been playing around with UML
My primary background is that of a sysadmin, not as a programmer.
In order to get a better understanding of class models I've been trying to do map out the xmdomain.cfg file the xen hypervisor in UML (you can find the man page at http://linux.die.net/man/5/xmdomain.cfg)
So after working it out i get a basic start like this (note, this is attributes only, not actions)
xenDomU:[
- kernelImage
- initialRamdisk
- allocatedMemory
- rootDevice
- nicAmount
- domuName
]
The following situation has been a real pain in the ass
"disk" and "vif" can both occur multiple times in a domu config file. ("disk" can occur 1 to infinite times and "vif" 0 to infinite times) essentially they are classes themselves
disk:[
- backendDevice
- frontendDevice
- deviceAccessMode
]
virtualNetworkInterface:[
- networkBridgeDevice
- interfaceIP
- macAddress
- interfaceName
]
In addition, "domain shutdown options" are really 3 values but it's actually best summorized as a single attribute, but then you get the same situation as above.
shutdownOptions{
- onShutdown
- onReboot
- onCrash
}
So after that, you end up with something that really doesn't seem like valid UML to me.
xenDomU:[
kernelImage
initialRamdisk
allocatedMemory
rootDevice
nicAmount
disk:[
backendDevice
frontendDevice
deviceAccessMode
]
domuName
virtualNetworkInterface:[
networkBridgeDevice
interfaceIP
macAddress
interfaceName
]
shutdownOptions{
onShutdown
onReboot
onCrash
}
]
I'm sure there are "better" ways to do this, but this is what seems like the most natural to me.
Could someone please enlighten me and show the right way to do this.

I didn't understand why couldn't you have Disk and VIF as regular classes and create associations.
As far as I know, UML doesn't support nested classes. However in some cases you can associate package with classes you wanted to be nested with the class you want to nest into.

For the shutdownOptions, you want to make it an enumeration, instead of a class. You need to declare an attribute of that type in the class for objects that will have one of those options.
Even though classes do allow nested classifiers (UML 2.3, 9.3.1), I agree with Gabriel that Disk and VIF should be standalone classes in the same package, with your main class declaring aggregations of Disks and VIFs. Nested classes are interesting when you want to hide that nested classifier from the outside world, which is rarely the case.
Or in the TextUML notation (which generated the diagram above):
package xen;
class XenDomU
attribute domuName : String;
attribute kernelImage : any;
attribute initialRamdisk : any;
attribute allocatedMemory : any;
attribute rootDevice : any;
attribute nicAmount : any;
attribute shutdownMode : ShutdownOptions;
composition disks : Disk[*];
composition interfaces : VirtualNetworkInterface[*];
end;
class Disk
attribute backendDevice : any;
attribute frontendDevice : any;
attribute deviceAccessMode : any;
end;
class VirtualNetworkInterface
attribute networkBridgeDevice : any;
attribute interfaceIP : any;
attribute macAddress : any;
attribute interfaceName : any;
end;
enumeration ShutdownOptions
onShutdown,
onReboot,
onCrash
end;
end.

Related

Using Orika in place of Spring Data Commons

There are several Spring Data projects like Neo4j that use the Spring Data Commons to build up a PersistentEntity/PeristentProperty (basically type info plus property geters and setters) and EntityConverter to roll from a native store to Java. This is what the SDN (Spring Data Neo4j) does plus it bundling BeanWrapper converters to make sure that certain property types are allowed for the Neo4j data structure.
Basically Java beans are stamped with a #NodeEntity annotation and the beans is decomposed on writes into nodes (think a bean with only simple properties) interlinked by relationship objects.
Wondering if I can do the same with Orika? Means identifying classes via an annotation and processing each property when complex recursively. For example:
#NodeEntity
class Software {
String name;
....
Organisation organisation;
....
}
#NodeEntity
class Organisation {
String name;
}
Should be rolled into 2 nodes each containing the property name and a relationship object (denotes Organisation as a member of Software).
Here is an example of an Orika ClassMapBuilder supporting custom annotations, I think you can adapt it to meet your needs.
Gist : AnnotationClassMapBuilder
For Node (or DBObject of MongoDB) you can use a custom property resolver, take a look at:
http://orika-mapper.github.com/orika-docs/advanced-mappings.html (ElementPropertyResolver)
Edit
Orika build mappers by class-map which are actually, just a collection of property-pair, property can be any thing which has name, type and setter or/and getter.
You can automatically create for each attribute in your beans an equivalent in Neo4J side, and let Orika build the mapper.
For example you can create a Person(name)->PrintStream mapper,
in which you create for each person's property (name) an equivalent that print data (System.out)
Example
final Builder name = new Property.Builder()
.name("name")
.type(String.class.getName())
.setter("append(\"My name : \").append(%s).append('\\n')");
factory.classMap(Person.class, PrintStream.class).fieldMap("name", name, false).add().register();
factory.getMapperFacade().map(person, System.out); // This print to default output stream, My name : xxxx

traverse an ontology using dotnetrdf

I have created an ontology using protege. Now I want to write a code to traverse ontology using dotNetRDF. By mean of traverse is displaying all classes, sub-classes etc.
I am using following code but it is giving exception **
The Namespace URI for the given Prefix 'owl' is not known by the
in-scope NamespaceMapper
OntologyGraph g = new OntologyGraph();
FileLoader.Load(g, "humanontordf.owl");
OntologyClass classOfClasses = g.CreateOntologyClass(g.CreateUriNode("owl:Class"));
//This iterates over the things that are a class
foreach (OntologyResource r in classOfClasses.Instances)
{
//Do what you want with the class
Console.WriteLine(r.ToString());
}
This code is base on answer given here (http://answers.semanticweb.com/questions/19984/dotnetrdf-list-all-ontology-classes)
Can anyone let me know what am I missing in above code? any good URL for tutorial on dotNetRDF?
The error message refers to the following part of your code:
g.CreateUriNode("owl:Class")
This uses a prefixed name as a shortcut for the full URI which requires the owl prefix to be defined in your graph.
If you are getting this then your RDF file does not include this, you can define this like so:
g.NamespaceMap.AddNamespace("prefix", new Uri("http://some/namespace/"));
I guess an OntologyGraph should really define the OWL namespace automatically, I'll add this in the next release.

Document serialization with Doctrine MongoDB ODM

I'm trying to code a class handling serialization of documents by reading their metadata. I got inspired by this implementation for entities with Doctrine ORM and modified it to match how Doctrine ODM handles documents. Unfortunatly something is not working correctly as one document is never serialized more than once even if it is refered a 2nd time thus resulting on incomplete serialization.
For example, it outputs this (in json) for a user1 (see User document) that belongs to some place1 (see Place document). Then it outputs the place and the users belonging to it where we should see the user1 again but we don't :
{
id: "505cac0d6803fa1e15000004",
login: "user1",
places: [
{
id: "505cac0d6803fa1e15000005",
code: "place1",
users: [
{
id: "505c862c6803fa6812000000",
login: "user2"
}
]
}
]
}
I guess it could be related to something preventing circular references but is there a way around it ?
Also, i'm using this in a ZF2 application, would there be a better way to implement this using the ZF2 Serializer ?
Thanks for your help.
I have a serializer already written for DoctrineODM. You can find it in http://github.com/superdweebie/DoctrineExtensions - look in lib/Sds/DoctrineExtensions/Serializer.
If you are are using zf2, then you might also like http://github.com/superdweebie/DoctrineExtensionsModule, which configures DoctrineExtensions for use in zf2.
To use the Module, install it with composer, as you would any other module. Then add the following to your zf2 config:
'sds' => [
'doctrineExtensions' => [
'extensionConfigs' => [
'Sds\DoctrineExtensions\Serializer' => null,
),
),
),
To get the serializer use:
$serializer = $serivceLocator->get('Sds\DoctrineExtensions\Serializer');
To use the serializer:
$array = $serializer->toArray($document)
$json = $serializer->toJson($document)
$document = $serializer->fromArray($array)
$document = $serializer->fromJson($json)
There are also some extra annotations available to control serialization, if you want to use them:
#Sds\Setter - specify a non standard setter for a property
#Sds\Getter - specify a non standard getter fora property
#Sds\Serializer(#Sds\Ignore) - ignore a property when serializing
It's all still a work in progress, so any comments/improvements would be much appreciated. As you come across issues with these libs, just log them on github and they will get addressed promptly.
Finally a note on serializing embedded documents and referenced documents - embedded documents should be serialized with their parent, while referenced documents should not. This reflects the way data is saved in the db. It also means circular references are not a problem.
Update
I've pushed updates to Sds/DoctrineExtensions/Serializer so that it can now handle references properly. The following three (five) methods have been updated:
toArray/toJson
fromArray/fromJson
applySerializeMetadataToArray
The first two are self explainitory - the last is to allow serialization rules to be applied without having to hydrate db results into documents.
By default references will be serialized to an array like this:
[$ref: 'CollectionName/DocumentId']
The $ref style of referencing is what Mongo uses internally, so it seemed appropriate. The format of the reference is given with the expectation it could be used as a URL to a REST API.
The default behaviour can be overridden by defineing an alternative ReferenceSerializer like this:
/**
* #ODM\ReferenceMany(targetDocument="MyTargetDocument")
* #Sds\Serializer(#Sds\ReferenceSerializer('MyAlternativeSerializer'))
*/
protected $myDocumentProperty;
One alternate ReferenceSerializer is already included with the lib. It is the eager serializer - it will serialize references as if they were embedded documents. It can be used like this:
/**
* #ODM\ReferenceMany(targetDocument="MyTargetDocument")
* #Sds\Serializer(#Sds\ReferenceSerializer('Sds\DoctrineExtensions\Serializer\Reference\Eager'))
*/
protected $myDocumentProperty;
Or an alternate shorthand annotation is provided:
/**
* #ODM\ReferenceMany(targetDocument="MyTargetDocument")
* #Sds\Serializer(#Sds\Eager))
*/
protected $myDocumentProperty;
Alternate ReferenceSerializers must implement Sds\DoctrineExtensions\Serializer\Reference\ReferenceSerializerInterface
Also, I cleaned up the ignore annotation, so the following annotations can be added to properties to give more fine grained control of serialization:
#Sds\Serializer(#Sds\Ignore('ignore_when_serializing'))
#Sds\Serializer(#Sds\Ignore('ignore_when_unserializing'))
#Sds\Serializer(#Sds\Ignore('ignore_always'))
#Sds\Serializer(#Sds\Ignore('ignore_never'))
For example, put #Sds\Serializer(#Sds\Ignore('ignore_when_serializing')) on an email property - it means that the email can be sent upto the server for update, but can never be serialized down to the client for security.
And lastly, if you hadn't noticed, sds annotations support inheritance and overriding, so they play nice with complex document structures.
Another very simple, framework independent way to transforming Doctrine ODM Document to Array or JSON - http://ajaxray.com/blog/converting-doctrine-mongodb-document-tojson-or-toarray
This solution gives you a Trait that provides toArray() and toJSON() functions for your ODM Documents. After useing the trait in your Document, you can do -
<?php
// Assuming in a Symfony2 Controller
// If you're not, then make your DocmentManager as you want
$dm = $this->get('doctrine_mongodb')->getManager();
$report = $dm->getRepository('YourCoreBundle:Report')->find($id);
// Will return simple PHP array
$docArray = $report->toArray();
// Will return JSON string
$docJSON = $report->toJSON();
BTW, it will work only on PHP 5.4 and above.

RavenDB does not set all the properties on store

I have a really weird scenario where I try to store domain events (I'm trying to learn CQRS and RavenDB at the same time). The basic structure of the documents I try to store are:
public interface IDomainEvent { ... }
public abstract class BaseDomainEvent : IDomainEvent { ... }
public class DomainEventA : BaseDomainEvent { ... }
public class DomainEventB : BaseDomainEvent { ... }
Given that I want to store DomainEventA and DomainEventB in the same collection in RavenDB and I have managed to do so. But the problem is that in the collection I am missing the properties of DomainEventB, and not all properties are set even though I have checked that the properties are set before I commit the transaction where I store the objects. The following gist shows a working example of what I want to do: https://gist.github.com/2830093, and the test code that fails me is found in this test: https://github.com/mastoj/TJ.CQRS/blob/ravenfail/TJ.CQRS.RavenEvent.Tests/RavenEventStoreTests.cs that is using this RavenDB code: https://github.com/mastoj/TJ.CQRS/blob/ravenfail/TJ.CQRS.RavenEvent/RavenEventStore.cs.
I really can't get my head around this one.
EDIT 1: I can add that in the failing scenario the metadata of the stored object says it is one type but the properties for that type is not stored.
I planned to delete or vote for close but I think more than me might experience this problem at some point. I found the solution in my case and it was that the objects I added to RavenDB had a faulty equals method so RavenDB thought that all my objects were the same one. When I added one more property to check in the equals method everything start working as expected.

Entity Framework 4.1 Dynamically retrieve mapped column name

I am trying to construct an SQL statement dynamically.
My context is created dynamically, using reflection finding classes deriving from EntityTypeConfiguration and adding them to DbModelBuilder.Configuration.
My EntityTypeConfiguration classes specify HasColumnName to map the Entity property name to db table column name, which I need to construct my SQL statement.
namespace MyDomain {
public class TestEntityConfig : EntityTypeConfiguration<TestEntity>{
Property("Name").HasColumnName("dbName");
}
}
From What I have researched, it seems I can get access to this information through MetadataWorkspace, which I can get to through ObjectContext.
I have managed to retrieve the the entity I am interested in with MetadataWorkspace.GetItem("MyDomain.TestEntity",DataSpace.OSpace), which gives me access to Properties, but none of the properties, of Properties, give me the name of the mapped db column, as specified with HasColumnName.
Also I am not clear what DataSpace.OSpace is and why my model is constructed in this space.
If Anyone can shed some light on this I would be grateful
UPDATE
Further to #Ladislav's comments. I discovered I can get the information as follows
For the class properties
ctx.MetadataWorkspace.GetItem<ClrEntityType>("MyDomain.TestEntity", DataSpace.OSpace)).Members
For the table properties
ctx.MetadataWorkspace.GetItem<EntityType>("CodeFirstDatabaseSchema.TestEntity",SSpace).Members
So given that I only know the type MyDomain.TestEntity and Memeber "Name". How would I go about to get "dbName". Can I always assume that my mapped class will be created in CodeFirstDatabaseSchema, om order to dynamically construct the identity to retrieve it from SSpace and how would I get to the correct Member in SSpace. Can I do something like
var memIndex = ctx.MetadataWorkspace.GetItem<ClrEntityType>("MyDomain.TestEntity", DataSpace.OSpace)).Members["Name"].Index;
var dbName = ctx.MetadataWorkspace.GetItem<EntityType>("CodeFirstDatabaseSchema.TestEntity",SSpace).Members[memIndex];
MetadataWorkspace contanis several containers specified by DataSpace. Interesting for you are:
CSpace - description of conceptual model (this should contain properties)
CSSpace - mapping of conceptual model to storage model (this should contain how classes / properties are mapped to tables / columns)