{"id":69,"date":"2012-06-26T05:27:11","date_gmt":"2012-06-26T03:27:11","guid":{"rendered":"https:\/\/nikostotz.de\/blog\/?p=69"},"modified":"2012-06-26T05:52:44","modified_gmt":"2012-06-26T03:52:44","slug":"parallel-type-trees-generic-attribute-vs-generic-accessor-method","status":"publish","type":"post","link":"https:\/\/www.nikostotz.de\/blog\/parallel-type-trees-generic-attribute-vs-generic-accessor-method\/","title":{"rendered":"Parallel Type Trees: Generic Attribute vs. Generic Accessor Method"},"content":{"rendered":"<p class=\"abstract\">\nWhen working with <a href=\"http:\/\/www.eclipse.org\/modeling\/emf\/\">ecore<\/a> models, we often encounter super\/subtype relations on both the container and the member side. We want to easily access both the <em>generic<\/em> and the <em>specific<\/em> container members. Intuitively, we used different approaches to fulfill this requirement. This article explores some implementation possibilities and examines their advantages, drawbacks and performance implications.\n<\/p>\n<h2>Scenario<\/h2>\n<p>\nAs example, we&#8217;ll use an <code class=\"codecolorer text default\"><span class=\"text\">AbstractLibrary<\/span><\/code> containing many <code class=\"codecolorer text default\"><span class=\"text\">AbstractEntry<\/span><\/code>s. We have a specialized <code class=\"codecolorer text default\"><span class=\"text\">BookLibrary<\/span><\/code> containing <code class=\"codecolorer text default\"><span class=\"text\">Book<\/span><\/code>s and a specialized <code class=\"codecolorer text default\"><span class=\"text\">MovieLibrary<\/span><\/code> containing <code class=\"codecolorer text default\"><span class=\"text\">Movie<\/span><\/code>s and its subtypes <code class=\"codecolorer text default\"><span class=\"text\">SciFi<\/span><\/code>s and <code class=\"codecolorer text default\"><span class=\"text\">Comedy<\/span><\/code>s. Both <code class=\"codecolorer text default\"><span class=\"text\">AbstractLibrary<\/span><\/code> and <code class=\"codecolorer text default\"><span class=\"text\">AbstractEntry<\/span><\/code> are considered <em>generic<\/em>, while all other types are considered <em>specific<\/em>.\n<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-94\" title=\"Parallel Type Trees Overview\" src=\"https:\/\/nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/overview.png\" alt=\"\" width=\"453\" height=\"385\" \/><\/p>\n<h2>Situation<\/h2>\n<p>\nTypical tasks when working with models include verification and generation. We might want to assure every library has at least some content, or generate an XML descriptor for any entry in any library. In both cases, we&#8217;re not interested in the specific type of library or entry. At the same time, we might want to check all books to have an author, or generate different descriptors for science fiction movies and comedies.\n<\/p>\n<p>\nTherefore, we would need a list of generic entries in any library, and specific typed lists it specific libraries. Unfortunately, ecore prohibits overriding attributes. This limitation is not that important for single references, as we can easily define getter\/setter to cast the return\/parameter type as required. It gets much more complicated on multi-valued references.\n<\/p>\n<h2>Requirements<\/h2>\n<p>\nOn multi-valued references (aka lists), we want to<\/p>\n<ul>\n<li><code class=\"codecolorer text default\"><span class=\"text\">get<\/span><\/code> the members of the list,<\/li>\n<li><code class=\"codecolorer text default\"><span class=\"text\">add<\/span><\/code> single values, and<\/li>\n<li><code class=\"codecolorer text default\"><span class=\"text\">addAll<\/span><\/code> multiple values at once.<\/li>\n<\/ul>\n<p>for both<\/p>\n<ul>\n<li><em>generic<\/em> and<\/li>\n<li><em>specific<\/em><\/li>\n<\/ul>\n<p>types, including type-safety checks at compile-time. We also want to avoid type casts in the code using our model.\n<\/p>\n<h2>Implementation approaches<\/h2>\n<p>\nLuckily, another trait of ecore makes up for the lack of reference overriding: All member access happens through getter\/setter methods (as required for JavaBeans). We can leverage this trait to implement an API that <em>feels<\/em> almost like overriding generic reference types. The basic idea: We replace the missing generic or specific getter by an operation, exposing the same signature as we&#8217;d get by the emulated reference. There are two ways to go: Adding generic accessor methods (i. e. holding typed references in the specific containers) or using a generic reference (i. e. adding specific accessor methods to the specific containers).\n<\/p>\n<h3>Generic Accessor Methods<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAccessorMethods.png\" alt=\"\" title=\"Generic Accessor Methods\" width=\"421\" height=\"286\" class=\"aligncenter size-full wp-image-105\" srcset=\"https:\/\/www.nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAccessorMethods.png 421w, https:\/\/www.nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAccessorMethods-300x203.png 300w\" sizes=\"auto, (max-width: 421px) 100vw, 421px\" \/><\/p>\n<h4>Model<\/h4>\n<p>\n<code class=\"codecolorer text default\"><span class=\"text\">BookLibrary<\/span><\/code> holds a <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"nu0\">0<\/span>..<span class=\"sy0\">*<\/span><\/span><\/code> reference to <code class=\"codecolorer text default\"><span class=\"text\">Book<\/span><\/code> (<code class=\"codecolorer text default\"><span class=\"text\">MovieLibrary<\/span><\/code> accordingly). We want to have an additional method <code class=\"codecolorer java5 default\"><span class=\"java5\">getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> for accessing generic entries, so we add this method to <code class=\"codecolorer text default\"><span class=\"text\">AbstractLibrary<\/span><\/code>. In order to avoid superfluous type casts, we need to use a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Generics_in_Java#Type_Wildcards\">generic type wildcard with upper bound<\/a> as return type. Entering such a type in the ecore tree editor is quite tricky:<\/p>\n<ol>\n<li>Open the ecore file.<\/li>\n<li>Make sure menu entry <em>Sample Ecore Editor | Show Generics<\/em> is checked.<\/li>\n<li>If the generic method does not exist yet, create it by right-clicking on the <tt>EClass<\/tt>, selecting <em>New Child | EOperation<\/em>.<\/li>\n<li>Open the Properties View for the generic method.<\/li>\n<li>Make sure the generic method has an appropriate <tt>Name<\/tt> (&#8220;getEntries&#8221; in our case).<\/li>\n<li>If the generic method already has a return type (<tt>EType<\/tt> in Properties View), remove it by selecting the empty first row in the drop-down list. Otherwise the context menu entry in the next step will be greyed out. Check also the <tt>lowerBound<\/tt> to be <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"nu0\">0<\/span><\/span><\/code> and the <tt>upperBound<\/tt> to be <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"nu0\">1<\/span><\/span><\/code>.<\/li>\n<li>Right-click on the generic method in the editor tree, select <em>New Child | EGeneric Return Type<\/em>.<\/li>\n<li>In the Properties View of our newly added <em>EGeneric Return Type<\/em>, select <code class=\"codecolorer java5 default\"><span class=\"java5\">EEList<span class=\"sy0\">&lt;<\/span>E<span class=\"sy0\">&gt;<\/span><\/span><\/code> for <tt>EClassifier<\/tt>.<\/li>\n<li>The <em>EGeneric Return Type<\/em> in the editor tree now has a new child. Right-click this child, select <em>Add Child | EGeneric Upper Bound Type<\/em>.<\/li>\n<li>The formerly unspecified generic type in the tree editor changes from <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"sy0\">&lt;?&gt;<\/span><\/span><\/code> to <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"sy0\">&lt;?<\/span> <span class=\"kw2\">extends<\/span> <span class=\"sy0\">?&gt;<\/span><\/span><\/code>. In the Properties View of the newly added <em>EGeneric Upper Bound Type<\/em>, set <tt>EClassifier<\/tt> to the generic type (<code class=\"codecolorer text default\"><span class=\"text\">AbstractEntry<\/span><\/code> in our case).<\/li>\n<\/ol>\n<p>Finally, we should arrive at the following picture:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericEReturnType.png\" alt=\"\" title=\"Generic EReturn Type\" width=\"300\" height=\"88\" class=\"aligncenter size-full wp-image-115\" \/>\n<\/p>\n<h4>Implementation<\/h4>\n<p>\nWe&#8217;ll implement the method in both <code class=\"codecolorer text default\"><span class=\"text\">BookLibraryImpl<\/span><\/code> and <code class=\"codecolorer text default\"><span class=\"text\">MovieLibraryImpl<\/span><\/code> rather than <code class=\"codecolorer text default\"><span class=\"text\">AbstractLibraryImpl<\/span><\/code>. The code snippets below contain lots of code created by EcoreGen, we add only our implementation of <code class=\"codecolorer java5 default\"><span class=\"java5\">getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>:<\/p>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericAccessorMethods.<span class=\"me1\">BookLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> BookLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;?<\/span> <span class=\"kw2\">extends<\/span> AbstractEntry<span class=\"sy0\">&gt;<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ ...<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* The cached value of the '{@link #getBooks() &lt;em&gt;Books&lt;\/em&gt;}' containment reference list.<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* @see #getBooks()<br \/>\n&nbsp; &nbsp; &nbsp;* @generated<br \/>\n&nbsp; &nbsp; &nbsp;* @ordered<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">protected<\/span> EList<span class=\"sy0\">&lt;<\/span><span class=\"kw17\">Book<\/span><span class=\"sy0\">&gt;<\/span> books<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ ...<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* @generated<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span><span class=\"kw17\">Book<\/span><span class=\"sy0\">&gt;<\/span> getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>books == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; books = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span><span class=\"kw17\">Book<\/span><span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw17\">Book<\/span>.<span class=\"kw2\">class<\/span>, <span class=\"kw2\">this<\/span>, GenericAccessorMethodsPackage.<span class=\"me1\">BOOK_LIBRARY__BOOKS<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> books<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ BookLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericAccessorMethods.<span class=\"me1\">MovieLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> MovieLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;?<\/span> <span class=\"kw2\">extends<\/span> AbstractEntry<span class=\"sy0\">&gt;<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> getMovies<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ ...<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* The cached value of the '{@link #getMovies() &lt;em&gt;Movies&lt;\/em&gt;}' containment reference list.<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* @see #getMovies()<br \/>\n&nbsp; &nbsp; &nbsp;* @generated<br \/>\n&nbsp; &nbsp; &nbsp;* @ordered<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">protected<\/span> EList<span class=\"sy0\">&lt;<\/span>Movie<span class=\"sy0\">&gt;<\/span> movies<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ ...<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* @generated<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span>Movie<span class=\"sy0\">&gt;<\/span> getMovies<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>movies == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; movies = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span>Movie<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span>Movie.<span class=\"kw2\">class<\/span>, <span class=\"kw2\">this<\/span>, GenericAccessorMethodsPackage.<span class=\"me1\">MOVIE_LIBRARY__MOVIES<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> movies<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ MovieLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<\/p>\n<h3>Generic Attributes<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAttributes.png\" alt=\"\" title=\"Generic Attributes\" width=\"421\" height=\"284\" class=\"aligncenter size-full wp-image-121\" srcset=\"https:\/\/www.nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAttributes.png 421w, https:\/\/www.nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAttributes-300x202.png 300w\" sizes=\"auto, (max-width: 421px) 100vw, 421px\" \/><\/p>\n<h4>Model<\/h4>\n<p>\n<code class=\"codecolorer java5 default\"><span class=\"java5\">AbstractLibrary<\/span><\/code> holds a <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"nu0\">0<\/span>..<span class=\"sy0\">*<\/span><\/span><\/code> reference to <code class=\"codecolorer java5 default\"><span class=\"java5\">AbstractEntry<\/span><\/code>. We add a method <code class=\"codecolorer java5 default\"><span class=\"java5\">getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> with return <tt>EType<\/tt> <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"kw17\">Book<\/span><\/span><\/code>, <tt>Lower Bound<\/tt> <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"nu0\">0<\/span><\/span><\/code> and <tt>Upper Bound<\/tt> <code class=\"codecolorer java5 default\"><span class=\"java5\">-<span class=\"nu0\">1<\/span><\/span><\/code> to <code class=\"codecolorer java5 default\"><span class=\"java5\">BookLibrary<\/span><\/code> (<code class=\"codecolorer java5 default\"><span class=\"java5\">MovieLibrary<\/span><\/code> accordingly). We don&#8217;t need any generics in this case.\n<\/p>\n<h4>Implementation<\/h4>\n<p>The original implementation approach (dubbed <em>genericAttributes<\/em>) included a serious amount of dynamic casting. This proved to be problematic, especially performance-wise. A second implementation (<em>genericUnitypeAttributes<\/em>) performed better.\n<\/p>\n<h5>Generic Attributes<\/h5>\n<p>\nWe wrap the generic entries into an <code class=\"codecolorer java5 default\"><span class=\"java5\">UnmodifiableEList<\/span><\/code> in order to keep the interface contract of <code class=\"codecolorer java5 default\"><span class=\"java5\">java.<span class=\"me1\">lang<\/span>.<span class=\"kw166\">List<\/span><\/span><\/code> (<code class=\"codecolorer java5 default\"><span class=\"java5\">add<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> must fail if nothing was added). The second method included below, <code class=\"codecolorer java5 default\"><span class=\"java5\">getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>, is a copy of the code generated into <code class=\"codecolorer java5 default\"><span class=\"java5\">AbstractLibraryImpl<\/span><\/code>, with the type (marked in line 19) set to our <em>specific<\/em> type. This prevents adding illegal types to the collection.\n<\/p>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericAttributes.<span class=\"me1\">BookLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> BookLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* <\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* @generated NOT<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span><span class=\"kw17\">Book<\/span><span class=\"sy0\">&gt;<\/span> getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> <span class=\"kw2\">new<\/span> UnmodifiableEList<span class=\"sy0\">&lt;<\/span><span class=\"kw17\">Book<\/span><span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span>getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">size<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>, getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span class=\"me1\">toArray<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* @generated NOT<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>entries == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; entries = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span><br \/>\n<span class=\"xtra ln-xtra\">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw17\">Book<\/span>.<span class=\"kw2\">class<\/span>,<br \/><\/span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">this<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GenericAttributesPackage.<span class=\"me1\">ABSTRACT_LIBRARY__ENTRIES<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> entries<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ BookLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericAttributes.<span class=\"me1\">MovieLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> MovieLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* <\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* @generated NOT<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span>Movie<span class=\"sy0\">&gt;<\/span> getMovies<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> <span class=\"kw2\">new<\/span> UnmodifiableEList<span class=\"sy0\">&lt;<\/span>Movie<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span>getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">size<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>, getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span class=\"me1\">toArray<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;* @generated NOT<\/span><br \/>\n<span class=\"co3\">&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>entries == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; entries = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span><br \/>\n<span class=\"xtra ln-xtra\">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Movie.<span class=\"kw2\">class<\/span>,<br \/><\/span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">this<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GenericAttributesPackage.<span class=\"me1\">ABSTRACT_LIBRARY__ENTRIES<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> entries<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ MovieLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<h5>Generic Unitype<a href=\"#1\" id=\"ref1\"><sup>[1]<\/sup><\/a> Attributes<\/h5>\n<p>\nPerformance tests on the different implementations showed the dynamic casting used in the Generic Attributes implementation to be very expensive. It was introduced to satisfy generics casting limitations of Java. However, we can avoid these casts by <em>exploiting<\/em> the limitations of Java&#8217;s generics implementation (and some <code class=\"codecolorer java5 default\"><span class=\"java5\">@<span class=\"kw21\">SuppressWarnings<\/span><\/span><\/code> annotations already used by EcoreGen). The magic happens by removing all generic types from the manually implemented methods<a href=\"#2\" id=\"ref2\"><sup>[2]<\/sup><\/a>. The <code class=\"codecolorer java5 default\"><span class=\"java5\">getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> implementation is the same as for Generic Attributes, except the removed generic type information on the return type and the <code class=\"codecolorer java5 default\"><span class=\"java5\">@<span class=\"kw21\">SuppressWarnings<\/span><\/span><\/code> annotation. The specific getter implementation is as simple as humanly possible.\n<\/p>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericUnitypeAttributes.<span class=\"me1\">BookLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> BookLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* <br \/>\n&nbsp; &nbsp; &nbsp;* @generated NOT<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">SuppressWarnings<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> <span class=\"st0\">&quot;rawtypes&quot;<\/span>, <span class=\"st0\">&quot;unchecked&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* @generated NOT<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">SuppressWarnings<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> <span class=\"st0\">&quot;rawtypes&quot;<\/span>, <span class=\"st0\">&quot;unchecked&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>entries == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; entries = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw17\">Book<\/span>.<span class=\"kw2\">class<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">this<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GenericUnitypeAttributesPackage.<span class=\"me1\">ABSTRACT_LIBRARY__ENTRIES<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> entries<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ BookLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<div class=\"codecolorer-container java5 default\" style=\"overflow:auto;white-space:nowrap;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/><\/div><\/td><td><div class=\"java5 codecolorer\"><span class=\"kw2\">public<\/span> <span class=\"kw2\">class<\/span> genericUnitypeAttributes.<span class=\"me1\">MovieLibraryImpl<\/span> <span class=\"kw2\">extends<\/span> AbstractLibraryImpl <span class=\"kw2\">implements<\/span> MovieLibrary <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* &lt;!-- begin-user-doc --&gt; &lt;!-- end-user-doc --&gt;<br \/>\n&nbsp; &nbsp; &nbsp;* <br \/>\n&nbsp; &nbsp; &nbsp;* @generated NOT<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">SuppressWarnings<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> <span class=\"st0\">&quot;rawtypes&quot;<\/span>, <span class=\"st0\">&quot;unchecked&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList getMovies<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* @generated NOT<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">SuppressWarnings<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> <span class=\"st0\">&quot;rawtypes&quot;<\/span>, <span class=\"st0\">&quot;unchecked&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; @<span class=\"kw21\">Override<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">public<\/span> EList getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>entries == <span class=\"kw4\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; entries = <span class=\"kw2\">new<\/span> EObjectContainmentEList<span class=\"sy0\">&lt;<\/span>AbstractEntry<span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Movie.<span class=\"kw2\">class<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">this<\/span>,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GenericUnitypeAttributesPackage.<span class=\"me1\">ABSTRACT_LIBRARY__ENTRIES<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">return<\/span> entries<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span> <span class=\"co1\">\/\/ MovieLibraryImpl<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<h2>Evaluation<\/h2>\n<p>\nEvaluation of the different implementation approaches focuses on three aspects:<\/p>\n<ul>\n<li><strong>Contract conformance:<\/strong> We want to keep the contracts intact, i. e. adding <code class=\"codecolorer java5 default\"><span class=\"java5\">Movie<\/span><\/code>s into a <code class=\"codecolorer java5 default\"><span class=\"java5\">BookLibrary<\/span><\/code> should be prohibited.<\/li>\n<li><strong>Type safety:<\/strong> As one major reason for the whole endeavor is improving development productivity, we want to keep the type checks of the compiler as good as possible.<\/li>\n<li><strong>Performance:<\/strong> Increased development productivity should not lead to worse run-time performance.<\/li>\n<\/ul>\n<h3>Contract conformance and type safety<\/h3>\n<p>\nThe following table summarizes the evaluation of contract conformance and type safety. We evaluate <em>generic<\/em> and <em>specific<\/em> access for each implementation approach. In each case, we check getter, adding one valid\/invalid type and multiple valid\/invalid types.\n<\/p>\n<p>\n<em>Valid<\/em> denotes types that should be usable in the context (i. e. <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"kw17\">Book<\/span><\/span><\/code> for <code class=\"codecolorer java5 default\"><span class=\"java5\">BookLibrary<\/span><\/code>; <code class=\"codecolorer java5 default\"><span class=\"java5\">Movie<\/span><\/code>, <code class=\"codecolorer java5 default\"><span class=\"java5\">SciFi<\/span><\/code> and <code class=\"codecolorer java5 default\"><span class=\"java5\">Comedy<\/span><\/code> for <code class=\"codecolorer java5 default\"><span class=\"java5\">MovieLibrary<\/span><\/code>), while <em>invalid<\/em> stands for incompatible types (i. e. <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"kw17\">Book<\/span><\/span><\/code> for <code class=\"codecolorer java5 default\"><span class=\"java5\">MovieLibrary<\/span><\/code>; <code class=\"codecolorer java5 default\"><span class=\"java5\">Movie<\/span><\/code> and subtypes for <code class=\"codecolorer java5 default\"><span class=\"java5\">BookLibrary<\/span><\/code>).\n<\/p>\n<p>\n<strong>Contract conformance<\/strong> is displayed by the leading symbol: \u2713 shows the contract to be fulfilled, \u2715 failed to fulfill the contract; \u25cb are edge cases. The evaluation is done based on the context: For adding an invalid type, the contract is fulfilled (marked with \u2713) if the operation fails.\n<\/p>\n<p>\n<strong>Type safety<\/strong> is shown as second part of each cell:<\/p>\n<ul>\n<li>for <code class=\"codecolorer java5 default\"><span class=\"java5\">get<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>, the return type is coded with <tt>G<\/tt> for <em>generic<\/em> type and <tt>S<\/tt> for <em>specific<\/em> type.<\/li>\n<li>for <code class=\"codecolorer java5 default\"><span class=\"java5\">add<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>, we note down the type of error reporting.<\/li>\n<\/ul>\n<table>\n<colgroup>\n<col \/>\n<col class=\"table-column-odd\" span=\"2\" \/>\n<col class=\"table-column-even\" span=\"2\" \/>\n<col class=\"table-column-odd\" span=\"2\" \/> <\/colgroup>\n<tr>\n<th class=\"corner\"><\/th>\n<th class=\"table-column-odd\" colspan=\"2\">genericAccessorMethods<\/th>\n<th class=\"table-column-even\" colspan=\"2\">genericAttributes<\/th>\n<th class=\"table-column-odd\" colspan=\"2\">genericUnitypeAttributes<\/th>\n<\/tr>\n<tr>\n<th class=\"corner\"><\/th>\n<th class=\"table-column-odd subheader\">generic<\/th>\n<th class=\"table-column-odd subheader\">specific<\/th>\n<th class=\"table-column-even subheader\">generic<\/th>\n<th class=\"table-column-even subheader\">specific<\/th>\n<th class=\"table-column-odd subheader\">generic<\/th>\n<th class=\"table-column-odd subheader\">specific<\/th>\n<\/tr>\n<tr>\n<th>get()<\/th>\n<td>\u2713 \u200b<em>[? extends G]<\/em><\/td>\n<td>\u2713 <em>[S]<\/em><\/td>\n<td>\u2713 <em>[G]<\/em><\/td>\n<td>\u2713 <em>[S]<\/em><\/td>\n<td>\u2713 <em>[G]<\/em><\/td>\n<td>\u2713 <em>[S]<\/em><\/td>\n<\/tr>\n<tr>\n<th>add() <em>[validType]<\/em><\/th>\n<td>\u2715 (compiler)<a href=\"#A\" id=\"refA\"><sup>[A]<\/sup><\/a><\/td>\n<td>\u2713<\/td>\n<td>\u2713<\/td>\n<td>\u25cb (Unsupported\u200bOperation\u200bException<a href=\"#B\" id=\"refB\"><sup>[B]<\/sup><\/a>)<\/td>\n<td>\u2713<\/td>\n<td>\u2713<\/td>\n<\/tr>\n<tr>\n<th>add() <em>[invalidType]<\/em><\/th>\n<td>\u2715 (compiler)<a href=\"#A\" id=\"refA\"><sup>[A]<\/sup><\/a><\/td>\n<td>\u2713 (compiler)<\/td>\n<td>\u2713 (Array\u200bStore\u200bException)<\/td>\n<td>\u2713 (compiler)<\/td>\n<td>\u2713 (Array\u200bStore\u200bException)<\/td>\n<td>\u2713 (compiler)<\/td>\n<\/tr>\n<tr>\n<th>addAll() <em>[validType]<\/em><\/th>\n<td>\u2715 (compiler)<a href=\"#A\" id=\"refA\"><sup>[A]<\/sup><\/a><\/td>\n<td>\u2713<\/td>\n<td>\u2713<\/td>\n<td>\u25cb (Unsupported\u200bOperation\u200bException<a href=\"#B\" id=\"refB\"><sup>[B]<\/sup><\/a>)<\/td>\n<td>\u2713<\/td>\n<td>\u2713<\/td>\n<\/tr>\n<tr>\n<th>addAll() <em>[invalidType]<\/em><\/th>\n<td>\u2715 (compiler)<a href=\"#A\" id=\"refA\"><sup>[A]<\/sup><\/a><\/td>\n<td>\u2713 (compiler)<\/td>\n<td>\u2713 (Array\u200bStore\u200bException)<\/td>\n<td>\u2713 (compiler)<\/td>\n<td>\u2713 (Array\u200bStore\u200bException)<\/td>\n<td>\u2713 (compiler)<\/td>\n<\/tr>\n<\/table>\n<p>\n<a href=\"#refA\" id=\"A\">[A]:<\/a> The compiler flags any parameter type as invalid generic type; This case needs more research. This article will be updated.\n<\/p>\n<p>\n<a href=\"#refB\" id=\"B\">[B]:<\/a> <code class=\"codecolorer java5 default\"><span class=\"java5\">java.<span class=\"me1\">util<\/span>.<span class=\"kw46\">Collection<\/span>.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> is optional, therefore throwing an <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"kw21\">UnsupportedOperationException<\/span><\/span><\/code> fulfills the contract. However, the ecore user would expect the operation call to succeed, thus we evaluated this as edge case.\n<\/p>\n<p>\nAdding invalid types to specific type collections (e. g. <code class=\"codecolorer java5 default\"><span class=\"java5\">bookLibrary.<span class=\"me1\">getBooks<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">new<\/span> Movie<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/span><\/code>) was correctly flagged as a compiler error in all cases. For both Generic Attributes implementations, adding invalid types to generic type collections (e. g. <code class=\"codecolorer java5 default\"><span class=\"java5\">bookLibrary.<span class=\"me1\">getEntries<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">new<\/span> Movie<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/span><\/code>) was correctly flagged as Exception (there is no way to detect this at compile-time).\n<\/p>\n<h3>Performance<\/h3>\n<p>\nWe evaluate the same categories as for contract conformance and type safety (<em>generic<\/em> and <em>specific<\/em> access for each implementation approach). Evaluation is done by counting the number of elements in the collection.<a href=\"#3\" id=\"ref3\"><sup>[3]<\/sup><\/a>\n<\/p>\n<ul>\n<li><em>statistics<\/em> denotes a plain call to <code class=\"codecolorer java5 default\"><span class=\"java5\">getEntries<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">size<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code> (for <em>generic<\/em>) and accordingly <code class=\"codecolorer java5 default\"><span class=\"java5\">getBooks<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">size<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>.<\/li>\n<li><em>instanceof<\/em> uses the &#8220;inverted&#8221; getter and checks for the required type in <code class=\"codecolorer java5 default\"><span class=\"java5\"><span class=\"kw2\">instanceof<\/span><\/span><\/code> cascades in a very safe, but slow way.<\/li>\n<li><em>dispatch<\/em> uses <a href=\"http:\/\/www.eclipse.org\/xtend\/\">Xtend<\/a> to dispatch on a higher level than <em>instanceof<\/em>.<\/li>\n<\/ul>\n<p>\n+ shows very good performance below measurement precision. \u2212 is set for considerably worse performance, which may still be acceptable. \u2212\u2212 denotes very poor performance, only usable in a limited set of use cases.\n<\/p>\n<table>\n<colgroup>\n<col \/>\n<col class=\"table-column-odd\" span=\"2\" \/>\n<col class=\"table-column-even\" span=\"2\" \/>\n<col class=\"table-column-odd\" span=\"2\" \/>\n <\/colgroup>\n<tr>\n<th class=\"corner\"><\/th>\n<th class=\"table-column-odd\" colspan=\"2\">genericAccessorMethods<\/th>\n<th class=\"table-column-even\" colspan=\"2\">genericAttributes<\/th>\n<th class=\"table-column-odd\" colspan=\"2\">genericUnitypeAttributes<\/th>\n<\/tr>\n<tr>\n<th class=\"corner\"><\/th>\n<th class=\"table-column-odd subheader\">generic<\/th>\n<th class=\"table-column-odd subheader\">specific<\/th>\n<th class=\"table-column-even subheader\">generic<\/th>\n<th class=\"table-column-even subheader\">specific<\/th>\n<th class=\"table-column-odd subheader\">generic<\/th>\n<th class=\"table-column-odd subheader\">specific<\/th>\n<\/tr>\n<tr>\n<th>statistics<\/th>\n<td>+<\/td>\n<td>+<\/td>\n<td>+<\/td>\n<td>\u2212<\/td>\n<td>+<\/td>\n<td>+<\/td>\n<\/tr>\n<tr>\n<th>instanceof<\/th>\n<td>+<\/td>\n<td>\u2212\u2212<\/td>\n<td>\u2212<\/td>\n<td>\u2212\u2212<\/td>\n<td>+<\/td>\n<td>\u2212\u2212<\/td>\n<\/tr>\n<tr>\n<th>dispatch<\/th>\n<td>+<\/td>\n<td>+<\/td>\n<td>\u2212<\/td>\n<td>\u2212<\/td>\n<td>+<\/td>\n<td>+<\/td>\n<\/tr>\n<\/table>\n<h2>Conclusion<\/h2>\n<p>\nGeneric Unitype Attributes provided the best results for all of contract conformance, type safety, and performance. Additionally, the straightforward implementation can easily be reused.\n<\/p>\n<p>\nAs any emulation, this one has its drawbacks. The most obvious one are the &#8220;non-standard&#8221; access techniques for member collections, which might confuse some ecore based tools. For both Generic Attribute implementations this effect is manageable, as the &#8220;magic&#8221; happens on Java level. However, the Generic Accessor Method implementation uses advanced ecore generics functionality and needs to adjust the <tt>upperBound<\/tt> of a collection reference to 1, effectively &#8220;disguising&#8221; the reference&#8217;s collection nature.\n<\/p>\n<h2>Resources<\/h2>\n<p>\nAll code used for this article is available for <a href='https:\/\/nikostotz.de\/blog\/wp-content\/uploads\/2012\/06\/genericAttributesVsGenericMethods.zip'>download<\/a>. Some remarks:\n<\/p>\n<ul>\n<li>The code was tested under MacOS X 1.7, Eclipse 4.2RC1<\/li>\n<li>The code contains compile errors (see <a href=\"#A\">[A]<\/a>), but all tests should run successfully.<\/li>\n<\/ul>\n<h2>Acknowledgment<\/h2>\n<p>\nI would like to thank my colleague <a href=\"http:\/\/christiandietrich.wordpress.com\/\">Christian Dietrich<\/a> for intensive discussion and help on this post.\n<\/p>\n<h2>Footnotes<\/h2>\n<p>\n<a href=\"#ref1\" id=\"1\">[1]:<\/a> The name has been chosen from the original idea to limit this implementation to one type (&#8220;uni type&#8221;). As it turned out, this limitation doesn&#8217;t apply.\n<\/p>\n<p>\n<a href=\"#ref2\" id=\"2\">[2]:<\/a> The compiler removes generic type information anyways, so we don&#8217;t introduce an error.\n<\/p>\n<p>\n<a href=\"#ref3\" id=\"3\">[3]:<\/a> Evaluating <code class=\"codecolorer java5 default\"><span class=\"java5\">add<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>-performance requires future research.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When working with ecore models, we often encounter super\/subtype relations on both the container and the member side. We want to easily access both the generic and the specific container members. Intuitively, we used different approaches to fulfill this requirement. This article explores some implementation possibilities and examines their advantages, drawbacks and performance implications. Scenario [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-69","post","type-post","status-publish","format-standard","hentry","category-emf"],"_links":{"self":[{"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/posts\/69","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/comments?post=69"}],"version-history":[{"count":62,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/posts\/69\/revisions"}],"predecessor-version":[{"id":149,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/posts\/69\/revisions\/149"}],"wp:attachment":[{"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/media?parent=69"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/categories?post=69"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nikostotz.de\/blog\/wp-json\/wp\/v2\/tags?post=69"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}