Annotations are removed by Faktor-IPS Code Generator - code-generation

I need to annotate some methods which are generated by Faktor-IPS. The most common case is the #Override-annotation, because I have additional interfaces or a base class I implement:
* Gibt den Wert des Attributs beschreibung zurueck.
*
* #generated
*/
#IpsAttribute(name = "beschreibung", kind = AttributeKind.CHANGEABLE, valueSetKind = ValueSetKind.AllValues)
#Override // <- manually added
public String getBeschreibung() {
return beschreibung;
}
Problem is, that the additional annotation is removed by the code generator of Faktor-IPS.
I know about the special tags to use in the class-comment ( "#implements a.b.c.MyInterface" ) to keep the class implement the interface a.b.c.MyInterface - is there something similar for annotations, especially on generated methods?

Faktor-IPS uses the JMerge tool created by the Eclipse EMF project to combine generated and handwritten code. There is a (German) description of the ways you can control how the code is merged at https://www.faktorzehn.org/de/en/dokumentation/manuelle-anpassungen-des-generieten-codes/.
To keep additional annotations while still letting the code generator update the rest of the code, add the Javadoc tag (inside the Javadoc, not an annotation, although also beginning with '#') '#customizedAnnotations ADDED'.
If you have certain annotations that you want to add in many places, that workaround is too much work, so Faktor-IPS allows you to define a list of annotations that will never be removed in the .ipsproject generator setting 'retainAnnotations': just add 'Override' there and any '#Override' annotation you manually place won't be removed by the generator.

Related

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

Joomla 3.1.5 Saving tags to ucm_content and contentitem_tag_map

I have spent days on this one so I have put my hand up. I am implementing tags in my own component and have followed Elin's instructions on the Joomla site to the letter (27 July 2013). I can get the new tags to save in the TAGS table correctly, but not the UCM or TAG MAP tables as all the standard components do.
I have traced the code all the way through, and compared to the com_contacts, and cannot for the life of me see any difference in my component.
Where should I be looking for where the code updates the other two tables? I know this will end in an embarrassing answer but I am happy to look foolish.
My table does not have meta fields, but I have manually fudged the metadata array in the $data array. Any help is appreciated.
Instructions:http://docs.joomla.org/J3.1:Using_Tags_in_an_Extension
After many days of extra frustration I discovered that for my component I had to include the archived information into my table class, that is not supposed to be required any more.
Add a property
/**
* Indicator that the tags have been changed
*
* #var JHelperTags
* #since 3.1
*/
protected $tagsHelper = null;
This property helps to manage change in tags.
Modify your constructor
Follow this example to modify your consructor which provides substantial reduction in duplicate code.
$this->tagsHelper = new JHelperTags();
$this->tagsHelper->typeAlias = 'com_contact.contact';
Modify your store() method
Management of tagging and associated data is largely handled through the store() method. This provides maximum flexibility for the handling of tags across many extensions.
If you don't have a store() method you will need to add one. The assumption is that tables will inherit from JTable.
The handling involves preStoreProcess(), a call to the parent store() method, and then a postStoreProcess().
$this->tagsHelper->preStoreProcess($this);
$result = parent::store($updateNulls);
return $result && $this->tagsHelper->postStoreProcess($this);

How to teach SpecFlow to add additional NUnit attributes to my test class

SpecFlow is great - and it helps us very much to do proper integration testing.
One thing I was wondering is whether there's a way to tell SpecFlow to add additional NUnit attributes to the test class it creates in the feature code-behind file.
Right now, my test class gets generated something like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.8.1.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Some action description here")]
public partial class MySampleFeature
{
......
}
Is there any way in SpecFlow to tell it to add an additional NUnit attribute to define the category of the test - like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.8.1.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Some action description here")]
[NUnit.Framework.Category("LongRunningTests")] <== add this "Category" attribute
public partial class MySampleFeature
{
......
}
Adding this manually to the generated code-behind is wasteful - next time SpecFlow re-generates that code-behind, I have to remember doing it again (and chances are, I'll forget).
And if that capability is not yet present in SpecFlow - how to petition for this to be added? :-)
In fact the NUnit.Framework.Category attribute is already supported if you use tags (look for the tags section) on your feature or scenarios. So if you write
#LongRunningTests
Feature: MySampleFeature
it will generate the proper Category attribute.
However if you want to have additional custom attributes you need to write a custom generator provider with implementing the IUnitTestGeneratorProvider interface and register with the unitTestProvider's generatorProvider attribute in your config's specflow section.
You can find the source of the built in implementations at github.
To add to #nemesv's good answer, once you've added:
#LongRunningTests
Feature: MySampleFeature
To execute from the console, do this:
nunit3-console.exe myTests.dll --where "cat==LongRunningTests"

CM+MEF: registering MEF exports from external assemblies

this post ideally continues my other post on MEF plugins, but my first post was too full of comments and this sample is more complete. Here I summarize my updated scenario, with all my findings up to this point. Hope this can be useful to other CM newbies like me.
You can download a full repro sample scenario: it's an almost do-nothing dumb skeleton for a CM + MEF plugins-based application:
VS2010 repro solution (updated)
This is a minimal stripped down solution representing my issues with CM+MEF.
There are 3 projects:
the main UI (CmRepro).
a core DLL shared among all the addins (AddinCore), with a couple of interfaces and custom attributes used for MEF metadata.
a sample addin DLL (AlphaAddin), with a view and a viewmodel implementing the interfaces.
The core contains 2 interfaces representing a viewmodel and its view, and 2 attributes to be used for decorating the viewmodels and the views. The viewmodel interface describes a class which should compose a greeting message from some person name, so it exposes a couple of properties and a method for this. The view interface just exposes a property returning its DataContext cast to the viewmodel interface.
The sample addin has an implementation for a viewmodel and a view; both are MEF-exports, decorated by the corresponding attribute. In the real-world solution several properties of these attributes are used for filtering; here I just have a dummy Language property which should allow for other plugins for different languages.
The main UI has a MEF bootstrapper which adds code for retrieving MEF exports from an Addins folder. I modified this code to include exports from MEF directories and get a better understanding of some MEF exceptions, but still I cannot figure out how to properly "register" them with CM.
The main viewmodel has 2 methods: one (A) uses a MEF catalog to retrieve a viewmodel and its view, bind them and show them into a window. Another (B) uses the same catalog to get a viewmodel, and then a CM window manager to locate, create, bind and show the corresponding view according to CM naming conventions. These methods represent two alternative ways I should deal with in my real-world code, i.e. instantiating some crucial objects "by myself" just using MEF but then let them work for CM, or letting CM (with a MEF-bootstrapper) do most of the work starting from a viewmodel.
Anyway, it seems that in both cases I am missing something as for registration with CM. Issues:
(A) how do I wire up VM+V for CM so that the conventions for databinding etc are applied? At this time I can build my MEF parts together, but CM ignores them as it was not used to instantiate none of them.
I answer to myself here:
ViewModelBinder.Bind(viewmodel, (UserControl)view, null);
(B) how do I register the exports from MEF in CM so that the CM window manager can find the view? Currently it does not manage to locate the view from the viewmodel.
Addition (21 jun)
I try to explain better for whom cannot access the repro solution. I use a "standard" MEF bootstrapper, changing the Configure override like:
_container = new CompositionContainer(
new AggregateCatalog(AssemblySource.Instance.Select(
x => new AssemblyCatalog(x)).OfType()
.Union(GetAddinDirectoryCatalogs())));
this creates a MEF composition container which aggregates the catalog from AssemblySource, with CM types like event aggregator or window manager, with a catalog from several addin directories, which contain exports for both V and VM's.
In my sample main viewmodel I create a new VM from a plugin, found in the host application directory among others, and I'd like a CM window manager to locate, instantiate and show its view in a dialog, e.g.:
viewmodel = GetMyViewModelFromAddin();
windowmanager.ShowDialog(viewmodel);
CM anyway cannot locate the view. AFAIK, naming conventions are honored: both V and VM are in the same addin assembly, marked as MEF exports, named like SomethingViewModel / SomethingView. Anyway, as Leaf pointed out in his clarification, AssemblySource.Instance is a static IObservableCollection collection of assemblies and I have not added my addins to it. But this is right the point: I would not like to add all of them in advance, because this means loading ALL the addins without yet knowing which (if any) will be ever used. A robust plugin system is the reason for using MEF, after all. I'm new to CM and not sure if it is possible (and where) to find an extension point for CM in this scenario. The window manager does not call my bootstrapper implementation at all, clearly because there is nothing to be instantiated by IoC, as no match was found in assembly source Instance. So, it seems I'm stuck here, the only solution being loading in advance all the assemblies in the Instance, but this seems defeating the whole purpose of using MEF.
The plugin-based application I'm developing loads tons of V+VM CM "pairs" representing user interface widgets, which in turn often use a window manager to popup other V+VM's pairs as dialogs. I can bypass instantiation by CM and use MEF to retrieve V+VM for each widget, but still I'm facing the same view location issue for each widget requiring a window manager. The other alternative (workaround) I can see is avoding the use of window manager and implement my own mechanism for the purpose of showing dialogs from widgets, but this makes feel me a little wrong about CM...:). Usually when I find myself writing much more code than expected I am inclined to think I'm not using the tool in the right way. Any idea?
Caliburn.Micro goes through 3 stages to find a view from a viewmodel instance.
Does text transforms to transform view type name to viewmodel type name. There are a set of standard conventions for these transformations, e.g. SomeNamespace.ViewModels.CustomerViewModel might map to SomeNamespace.Views.CustomerView.
With the view type name(s), Caliburn.Micro then uses AssemblySource.Instance (a static IObservableCollection<Assembly> collection of assemblies) to find the first matching Type.
Caliburn.Micro attempts to create an instance of that Type via one of the IoC.GetInstance() methods (which delegate to your bootstrapper and hence MEF).
I'm guessing (your file share site is blocked here) that the problem with resolving views from viewmodels is due to the second step and the AssemblySource.Instance collection not containing your dynamic assembly.
One solution might be to add each dynamically loaded addin's assembly to AssemblySource.Instance when they are loaded, or if you know all assemblies at startup then you can override the Bootstrapper.SelectAssemblies method to return list of assemblies you expect to contain views and viewmodels.
Update to show how you could pull assemblies from MEF loaded parts
If you are using DirectoryCatalog to load your parts from other assemblies then you could find the assemblies used like this:
var directoryCatalog = new DirectoryCatalog(#"./");
AssemblySource.Instance.AddRange(
directoryCatalog.Parts
.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
.Where(assembly => !AssemblySource.Instance.Contains(assembly)));
If your addins folder changes during the runtime of the application then you would have to DirectoryCatalog.Refresh() the catalog and run the code to add any new assemblies to AssemblySource.Instance
I found a workaround. It's not that pretty, but it allows CM and its window manager to work. I summarize here my findings, hope this will help others or let someone point me to a better solution.
Given that (a) I do not want to load ALL the assemblies including all their dependencies in my plugins folder, to avoid polluting my app domain with unused stuff; and that (b) the only available CM extension point for this seems SelectAssemblies, my goal is add my assemblies there, but only the plugin assemblies requiring to be registered with CM.
So I started looking for a way of loading all the DLL's into a temporary app domain, scan them for some aspect marking them as plugins, and then load into the current app domain only the plugin ones, passing them to SelectAssemblies. This is far from being the optimal solution, as I cannot use a general purpose scanning way like MEF, and I feel I'm duplicating the effort, but at least it's a working solution.
First, to provide at least a way for loading only the plugins, I decorate my plugin assemblies requiring CM registration with a custom attribute marking them as plugins, and further enumerate their types looking for the ones which should be later used by MEF.
The attribute is as simple as:
[AttributeUsage(AttributeTargets.Assembly)]
public class AssemblyRegisteredWithCMAttribute : Attribute {}
I then found this very good piece of code for scanning assemblies into another temporary AppDomain:
http://sachabarber.net/?p=560
I had to modify it a bit, because it was failing when loading assemblies with dependencies, and it was scanning the assemblies types while in my case I just need to check for the attribute.
Here is my code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace CmRepro
{
///
/// Separate AppDomain assembly loader.
///
/// Modified from http://sachabarber.net/?p=560 .
public class SeparateAppDomainAssemblyLoader
{
///
/// Loads an assembly into a new AppDomain returning the names of the files
/// containing assemblies marked with the assembly attribute name matching
/// the specified name. The new AppDomain is then Unloaded.
///
/// list of files to load
/// assemblies directory
/// matching attribute name
/// list of found namespaces
/// null files, assembly directory or matching attribute
public List LoadAssemblies(string[] aFiles, string sAssemblyDirectory, string sMatchingAttribute)
{
if (aFiles == null) throw new ArgumentNullException("aFiles");
if (sAssemblyDirectory == null) throw new ArgumentNullException("sAssemblyDirectory");
if (sMatchingAttribute == null) throw new ArgumentNullException("sMatchingAttribute");
List<String> namespaces = new List<String>();
AppDomain childDomain = BuildChildDomain(AppDomain.CurrentDomain);
try
{
Type loaderType = typeof(AssemblyLoader);
if (loaderType.Assembly != null)
{
AssemblyLoader loader = (AssemblyLoader)childDomain.
CreateInstanceFrom(
loaderType.Assembly.Location,
loaderType.FullName).Unwrap();
namespaces = loader.LoadAssemblies(aFiles, sAssemblyDirectory, sMatchingAttribute);
} //eif
return namespaces;
}
finally
{
AppDomain.Unload(childDomain);
}
}
/// <summary>
/// Creates a new AppDomain based on the parent AppDomains
/// Evidence and AppDomainSetup.
/// </summary>
/// <param name="parentDomain">The parent AppDomain</param>
/// <returns>A newly created AppDomain</returns>
private AppDomain BuildChildDomain(AppDomain parentDomain)
{
Evidence evidence = new Evidence(parentDomain.Evidence);
AppDomainSetup setup = parentDomain.SetupInformation;
return AppDomain.CreateDomain("DiscoveryRegion", evidence, setup);
}
/// <summary>
/// Remotable AssemblyLoader, this class inherits from <c>MarshalByRefObject</c>
/// to allow the CLR to marshall this object by reference across AppDomain boundaries.
/// </summary>
private class AssemblyLoader : MarshalByRefObject
{
private string _sRootAsmDir;
/// <summary>
/// ReflectionOnlyLoad of single Assembly based on the assemblyPath parameter.
/// </summary>
/// <param name="aFiles">files names</param>
/// <param name="sAssemblyDirectory">assemblies directory</param>
/// <param name="sMatchingAttribute">matching attribute name</param>
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
internal List<string> LoadAssemblies(string[] aFiles, string sAssemblyDirectory, string sMatchingAttribute)
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += OnReflectionOnlyAssemblyResolve;
_sRootAsmDir = sAssemblyDirectory;
List<string> aAssemblies = new List<String>();
try
{
sMatchingAttribute = "." + sMatchingAttribute;
foreach (string sFile in aFiles)
Assembly.ReflectionOnlyLoadFrom(sFile);
aAssemblies.AddRange(from asm in AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
let attrs = CustomAttributeData.GetCustomAttributes(asm)
where attrs.Any(a => a.ToString().Contains(sMatchingAttribute))
select asm.FullName);
return aAssemblies;
}
catch (FileNotFoundException)
{
/* Continue loading assemblies even if an assembly
* can not be loaded in the new AppDomain. */
return aAssemblies;
}
}
private Assembly OnReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs e)
{
// http://blogs.msdn.com/b/junfeng/archive/2004/08/24/219691.aspx
System.Diagnostics.Debug.WriteLine(e.Name);
AssemblyName name = new AssemblyName(e.Name);
string sAsmToCheck = Path.GetDirectoryName(_sRootAsmDir) + "\\" + name.Name + ".dll";
return File.Exists(sAsmToCheck)
? Assembly.ReflectionOnlyLoadFrom(sAsmToCheck)
: Assembly.ReflectionOnlyLoad(e.Name);
}
}
}
}
Now in my bootstrapper I override the SelectAssemblies method as follows:
...
protected override IEnumerable SelectAssemblies()
{
string sAddinPath = GetAbsolutePath(ADDIN_PATH);
FileCheckList list = new FileCheckList(sAddinPath);
// check only DLL files which were added or changed since last check
SeparateAppDomainAssemblyLoader loader = new SeparateAppDomainAssemblyLoader();
List<string> aAssembliesToRegister = loader.LoadAssemblies(list.GetFiles(null),
sAddinPath, "AssemblyRegisteredWithCM");
string[] aFilesToRegister = (from s in aAssembliesToRegister
select Path.Combine(sAddinPath, s.Substring(0, s.IndexOf(',')) + ".dll")).ToArray();
// update checklist
foreach (string sFile in aFilesToRegister) list.SetCheck(sFile, true);
list.UncheckAllNull();
list.Save();
// register required files
return (new[]
{
Assembly.GetExecutingAssembly(),
}).Union((from s in list.GetFiles(true)
select Assembly.LoadFrom(s))).ToArray();
}
...
As you can see, I am calling the loader not for all the DLL's in my addins path, but only for the ones which a cached files checklist tells me have been added or modified in that folder since the last full scan. This should speed up things a bit and does not require the checklist file to exist: if not found it will be recreated at startup by scanning all the files, if found only added or changed files will be scanned again (I use a CRC to detect changes). So I get the addins folder, create a files checklist for that folder, get from it a list of new or changed files, and pass it to the assemblies loader. This returns only the names of the DLL files which should be registered (i.e. the ones containing assemblies marked with my attribute); I then update the checklist for the next startup, and register only the required files. This way I can let my addin VM's use window managers and correctly locate the view for each required viewmodel. Somewhat ugly, but working. Thanks again to Leaf, who explained me the working of CM.

Custom tags with Doxygen

I am trying to figure out if there is a way to create a custom tag using Doxygen. I did find the ALIAS configuration file option but that does not do exactly what I need. Basically in my code I want to be able to write something like
/// \req Requirement #322 - blah blah
And then have Doxygen create a list like it does for \bug and \todo commands for lines that have this custom tag. Is this possible with Doxygen?
The generalization of \bug and \todo is \xrefitem.
The solution I suggest is:
in Doxyfile:
ALIASES += "req=\xrefitem req \"Requirement\" \"Requirements\" "
in documented code:
/// \req #42 - The system shall work in any situation
Thanks mouviciel! I have adopted your solution and extended it for my purposes.
The text below goes into my Doxyfile:
ALIASES += req{1}="\ref SRTX_\1 \"SRTX-\1\" "
ALIASES += satisfy{1}="\xrefitem satisfy \"Satisfies requirement\" \"Requirement Implementation\" \1"
ALIASES += verify{1}="\xrefitem verify \"Verifies requirement\" \"Requirement Verification\" \1"
Where SRTX is the name of my project and is used as a prefix to requirements.
Then I create a file called Requirements.dox that provides a link between the requirement id and a URL for the requirement in my requirements management tool (an issue tracker in my case).
/**
#page Requirements
#section Build1
#anchor SRTX_1113
SRTX-1113
#anchor SRTX_1114
SRTX-1114
*/
One could also put the text of the requirement in the anchor tag if you didn't need to link to an external source.
In my code I have:
/**
* This is the basic executive that schedules processes.
* #satisfy{#req{1114}}
*/
class Scheduler: public Process
{
...
}
And in my tests I put:
/**
* Provide a number of tests for process scheduling.
* #verify{#req{1114}}
*/
class Scheduler_ut : public CppUnit::TestFixture
{
...
}
This gives me related pages for Requirements, Requirements Implementation, and Requirements Verification. It also provides Satisfies requirement and Verifies requirements sections in the class description (or function -- wherever you put the tag).
Combining the two answers above, you can have a single clean requirement tag that will build a cross-reference table, and, also provide a direct link to the requirement repo in your docs:
Doxygen CONFIG file:
ALIASES = "requirement{1}=#xrefitem requirement \"Requirements\" \"Requirements Traceability\" \1"
Source code:
#requirement{REQ-123} Brief textual summary of this requirement item
This will render in the documentation as:
Requirements:
REQ-123 Brief textual summary of this requirement item