How to implement custom internationalization with gwt? - gwt

I want to make custom internationalization for my gwt app. What does this means? Imagine that my app must be internationalized for men and women. (id=men, id=women).
is it possible to make two different .properties files like
MyAppMessages_men_en.properties
MyAppMessages_women_en.properties
MyAppMessages_men_fr.properties
MyAppMessages_men_fr.properties
etc...
and my app host page will be accessed like this for example http://blabla/MyAppHostPage.html?locale=en&id=men
and this must load english version for men.
Thanks.

How about using fictional locale identifiers such as en_US_Men and en_US_Women and so forth for other locales?
(note that you should include a country whenever you include a variant of a locale)
Otherwise, I'd suggest using an abstract factory for your Messages and switch the concrete implementation using deferred binding on a distinct property (men vs. women):
interface MyAppMessagesFactory { MyAppMessages create(); }
class MyAppMessagesFactory_Men implements MyAppMessagesFactory {
#Override
public MyAppMessages create() { return GWT.create(MyAppMessages_Men.class); }
}
class MyAppMessagesFactory_Women implements MyAppMessagesFactory {
#Override
public MyAppMessages create() { return GWT.create(MyAppMessages_Women.class); }
}
You'd then have your MyAppMessages_Men_en.properties and MyAppMessages_Women_en.properties.

Related

PostSharp C# - How to Implement All Fields Required

PostSharp contracts make it easy to label individual fields as Required. But I want a class attribute that makes all of the class fields required. I'm guessing I would have to implement a custom aspect to support this.
It seems like it would be a common need for anyone passing around data containers. Can anyone direct me to some code that implements a custom "AllFieldsRequired" aspect in PostSharp?
You can implement PostSharp.Aspects.IAspectProvider:
public class AllFieldsRequiredAttribute : TypeLevelAspect, IAspectProvider
{
IEnumerable<AspectInstance> IAspectProvider.ProvideAspects(object targetElement)
{
Type type = (Type)targetElement;
return type.GetFields().Select(
m => new AspectInstance(m, new ObjectConstruction(typeof(RequiredAttribute))));
}
}
[AllFieldsRequired]
public class Foo
{
public string Bar;
public object Baz;
}

use GwtCreateResource to provide text programatically

I would like my uiBinder to use a ClientBundle which will provide some runtime customized labels. Kind of a TextResource but not from a text file !
I tried with GwtCreateResource but from the DevGuide it seems like it's not possible. Am I right ? (create() and name() are the only methods available)
What I would like to achieve is something like this:
client bundle:
public interface MyWidgetResources extends ClientBundle {
GwtCreateResource<WidgetLabels> labels();
#Source("lol.css")
CssResource style();
}
labels class:
public final class MyWidgetLabels {
public String title() {
return load("mywidget-title");
}
public String banner() {
return load("mywidget-banner");
}
private String load(String key) {
// load from external..
}
}
uiBinder:
<ui:with type="com.package.MyWidgetResources" field="res"/>
<gwt:SimplePanel>
<gwt:Label text="{res.labels.title}"></gwt:Label>
<gwt:Label text="{res.labels.banner}"></gwt:Label>
</gwt:SimplePanel>
My code looks like this already but res.label.title does not work because GwtCreateResource can only serve as class instantiator (res.labels.create().title()).
Is there a solution for me ? Maybe with a custom ResourceGenerator ?
As long as MyWidgetLabels can be created by GWT.create, you can put anything you want into that type, and you can make it behave however you'd like. You will need the create reference in your uibinder as you suggested at the end of the post to actually build the object, so your lines will look about like this:
<gwt:Label text="{res.labels.create.title}"></gwt:Label>
Each . separated piece (except the first, which is a ui:field/#UiField) is a no-arg method to be called - you declared labels() in MyWidgetResources, create() already existed in GwtCreateResource, and you created title() in your own MyWidgetLabels type.
Since that first piece is a ui:field/#UiField, you could have another that references res.labels.create as something like labels so that later you could instead say:
<gwt:Label text="{labels.title}"></gwt:Label>
Finally, yes, you could build your own ResourceGenerator which would enable you to do whatever you wanted to emit the type in question, as long as you extended the ResourcePrototype type and had a getName() method.

Using Gin to Inject Multiple Views

I'm attempting to put together a multi-project application, wherein one of the sub-projects has multiple views for a single presenter. I am using Gin to inject views into my presenters.
The sub-project contains the presenter and the 2 different views. I have 2 separate gin modules, each binding one of the views to the view interface.
As per Thomas Broyer's suggestion on the answer to this post, my Ginjectors are wrapped in a "holder" class that calls the GWT.create on the particular ginjector. The appropriate holder is configured in the gwt.xml file using a replace-with statement.
When I run my project in Dev Mode, I see the alternate view appear as I expect it to. However, when I compile the project, I still only get the default view. Also, only 6 permutations (I would expect more on account of the replace-with logic), and I do not get the view I expect in the different scenarios.
Here is some code to illustrate.
Subproject.gwt.xml contains this:
<replace-with class="com.example.GinjectorDesktopHolder">
<when-type-is class="com.example.GinjectorHolder" />
</replace-with>
<replace-with class="com.example.GinjectorTabletHolder">
<when-type-is class="com.example.GinjectorHolder" />
<when-property-is name="formfactor" value="tablet" />
</replace-with>
The "formfactor" variable is defined in a gwt.xml copied verbatim from GWT's mobilewebapp sample project.
The Holder classes look like this:
public abstract class GinjectorHolder {
public abstract Ginjector getGinjector();
}
public class GinjectorTabletHolder extends GinjectorHolder {
#Override
public Ginjector getGinjector() {
return GWT.create(GinjectorTablet.class);
}
}
public class GinjectorDesktopHolder extends GinjectorHolder {
#Override
public Ginjector getGinjector() {
return GWT.create(GinjectorDesktop.class);
}
}
My Ginjectors look like this:
public interface MyGinjector {
MyView getView();
EventBus getEventBus();
}
#GinModules({ModuleDesktop.class})
public interface GinjectorDesktop extends Ginjector, MyGinjector {}
#GinModules({ModuleTablet.class})
public interface GinjectorTablet extends Ginjector, MyGinjector {}
My modules look like this:
public class ModuleDesktop extends AbstractGinModule {
#Override
protected void configure() {
bind(MyPresenter.View.class).to(DesktopView.class);
}
}
public class ModuleTablet extends AbstractGinModule {
#Override
protected void configure() {
bind(MyPresenter.View.class).to(TabletView.class);
}
}
And finally, in my presenter proxy, basically the entry point into this particular sub-project, I have this line:
GinjectorHolder holder = GWT.create(GinjectorHolder.class);
MyGinjector ginjector = holder.getGinjector();
As mentioned earlier, when I run in Dev Mode and put in breakpoints, I can see the appropriate GinjectorHolder is created. The FormFactor.gwt.xml (linked above) provides a switch for using a URL param to switch to the context you'd like to see. So I can do formfactor=tablet in the URL and the Tablet Ginjector Holder is created.
As mentioned in the comments, removing the line
<collapse-property name="formfactor" values="*"/>
leads to the expected increase in the number of permutations.
Still, it's mysterious, why this is necessary, because usually it should be possible to collapse any properties you like - it just means, that each browser has to download more code, but should still get everything it needs. Could be a bug.
First of all instead of mapping view to viewimpl you can bind it to viewprovider, and then based on user-agent values you can return the appropriate instance to bind to.

Is it possible to find all classes annotated with #MyAnnotation using a GWT GeneratorContext?

While creating classes using Generators, it's possible to discover all subclasses of a type. You can find this technique for example in the GWT Showcase source (see full code):
JClassType cwType = null;
try {
cwType = context.getTypeOracle().getType(ContentWidget.class.getName());
} catch (NotFoundException e) {
logger.log(TreeLogger.ERROR, "Cannot find ContentWidget class", e);
throw new UnableToCompleteException();
}
JClassType[] types = cwType.getSubtypes();
I would like to do something similar, but instead of extending a class (or implementing an interface)
public class SomeWidget extends ContentWidget { ... }
, could I also do this by annotating Widgets?
#MyAnnotation(...)
public class SomeWidget extends Widget { ... }
And then finding all Widgets that are annotated with #MyAnnotation? I couldn't find a method like JAnnotationType.getAnnotatedTypes(), but maybe I'm just blind?
Note: I was able to make it work with the Google Reflections library, using reflections.getTypesAnnotatedWith(SomeAnnotation.class), but I'd prefer using the GeneratorContext instead, especially because this works a lot better when reloading the app in DevMode.
Yes - easiest way is to iterate through all types, and check them for the annotation. You might have other rules too (is public, is non-abstract) that should also be done at that time.
for (JClassType type : oracle.getTypes()) {
MyAnnotation annotation = type.getAnnotation(MyAnnotation.class);
if (annotation != null && ...) {
// handle this type
}
}
The TypeOracle instance can be obtained from the GeneratorContext using context.getTypeOracle().
Note that this will only give you access to types on the source path. That is, only types currently available based on the modules being inherited and <source> tags in use.

Dependecy injection of arguments known at runtime?

I've been using IoC container's for quite some time but today I've found some "pattern" appearing in code over and over again. To give you some background I am now working on web application basically used for data analysis. There is a set of features there, that requires user to pick up what we call QueryTypeContex at the very beginning. Once this query type is chosen other steps may be taken but that all are performed in this specific QueryTypeContex. In the gui the QueryTypeContex pick up is represented as opening new tab with other controls.
When user is working with given QueryTypeContex all ajax calls to the server include QueryTypeId that identifies users choice and is used to build QueryTypeContex on the server which then is used for various data retrieval and manipulation.
What I've found is that many of our controllers (we use asp.net mvc) that are constructed with Ioc container have one thing in common. There is an action method that looks somewhat like this:
public class AttributeController : Controller
{
public AttributeController(IUsefulService usefulService)
{
_usefulservice = usefulService;
}
ActionResult GetAttributes(QueryTypeContex context)
{
var dataDto = _usefulService.Manipulate(context, currentUser);
return JSon(dataDto);
}
...
}
In order to bind QueryTypeContex to action argument we use custom model binder that pulls some information from database. Once the service gets QueryTypeContex as argument it passes it or its properties down to its collaborators in method arguments for instance data access layer. And so there is a factory class that looks like this
public interface IDateValueFactory
{
DateValue CurrentYear(QueryTypeContex context);
DateValue RollingMonth(int numberOfMonths, QueryTypeContex context);
DateValue RollingQuareter(int numberOfQuarters, QueryTypeContex context);
}
public class DateValueFactory : IDateValueFactory
{
public DateValueFactory(IDateValueDb dateValueDb)
{
_dateValueDb = dateValueDb;
}
public DateValue CurrentYear(QueryTypeContext context)
{
var currentYear = _dateValueDb.GetCurrentYear(context.Id);
return new DateValue(DateValueType.CurrentYear, currentYear, context);
}
public DateValue RollingMonth(int numberOfMonths, QueryTypeContex context)
{
return new DateValue(DateValueType.RollingMonth, numberOfMonths, context);
}
...
}
As you see all of these methods get QueryTypeContex as a parameter more importantly they all get the very same instance of QueryTypeContex during their short life (one web request). So I started to wonder if I could refactor this so that whenever many service class methods require QueryTypeContex as arguments it would be injected via constructor instead of passing the same value over an over again. For example:
public interface IDateValueFactory
{
DateValue CurrentYear();
DateValue RollingMonth(int numberOfMonths);
DateValue RollingQuareter(int numberOfQuarters);
}
public class DateValueFactory : IDateValueFactory
{
public DateValueFactory(IDateValueDb dateValueDb, QueryTypeContext context)
{
_dateValueDb = dateValueDb;
_context = context;
}
public DateValue CurrentYear()
{
var currentYear = _dateValueDb.GetCurrentYear(_context.Id);
return new DateValue(DateValueType.CurrentYear, currentYear, _context);
}
public DateValue RollingMonth(int numberOfMonths)
{
return new DateValue(DateValueType.RollingMonth, numberOfMonths, _context);
}
...
}
And now the real question:
Is this a good idea to to this sort of thing or it violates some design principles i should adhere to ?
In order to inject QueryTypeContex instance, builded using information from http request I thought about embedding the QueryTypeId in the uris so it would be available in the RouteData on the server. Then before the controller is constructed I could pull it out, build the QueryTypeContex, create nested IoC container for that request and inject it into the container. Then whenever some class would need QueryTypeContex to perform its job it would simply declare it as constructor argument.
Anything you can meaningfully push to the constructor as dependencies, you should. Dependencies wired up with constructor injection are implementation details, whereas method parameters are part of your model's API.
It's much easier to refactor dependencies wired through constructors than to change an API, so for maintainability reasons you should prefer as few method parameters as possible.