ISIS-903: TranslationService, LocaleProvider, TrString class, also: - deprecated a bunch of old *Event files in the applib, for wrapper factory only.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/67e234b8 Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/67e234b8 Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/67e234b8 Branch: refs/heads/master Commit: 67e234b84230d62ab99ba935c288966ac6ada9dd Parents: faf70c0 Author: Dan Haywood <[email protected]> Authored: Fri Feb 13 16:51:44 2015 +0000 Committer: Dan Haywood <[email protected]> Committed: Wed Feb 18 14:07:29 2015 +0000 ---------------------------------------------------------------------- .../apache/isis/applib/events/AccessEvent.java | 5 +- .../isis/applib/events/ActionArgumentEvent.java | 5 +- .../applib/events/ActionInvocationEvent.java | 5 +- .../applib/events/ActionUsabilityEvent.java | 5 +- .../applib/events/ActionVisibilityEvent.java | 5 +- .../applib/events/CollectionAccessEvent.java | 5 +- .../applib/events/CollectionAddToEvent.java | 5 +- .../applib/events/CollectionMethodEvent.java | 6 +- .../events/CollectionRemoveFromEvent.java | 5 +- .../applib/events/CollectionUsabilityEvent.java | 5 +- .../events/CollectionVisibilityEvent.java | 5 +- .../isis/applib/events/InteractionEvent.java | 5 +- .../isis/applib/events/ObjectTitleEvent.java | 5 +- .../isis/applib/events/ObjectValidityEvent.java | 5 +- .../applib/events/ObjectVisibilityEvent.java | 5 +- .../isis/applib/events/ParseValueEvent.java | 5 +- .../isis/applib/events/PropertyAccessEvent.java | 5 +- .../isis/applib/events/PropertyModifyEvent.java | 5 +- .../applib/events/PropertyUsabilityEvent.java | 5 +- .../applib/events/PropertyVisibilityEvent.java | 5 +- .../isis/applib/events/ProposedHolderEvent.java | 5 +- .../isis/applib/events/UsabilityEvent.java | 5 +- .../isis/applib/events/ValidityEvent.java | 5 +- .../isis/applib/events/VisibilityEvent.java | 5 +- .../i18n/TranslatableMessagesService.java | 96 ++++++++ .../services/i18n/TranslatableString.java | 240 +++++++++++++++++++ .../services/i18n/TranslationService.java | 44 ++++ .../applib/services/locale/LocaleProvider.java | 29 +++ .../isis/applib/services/i18n/TrStringTest.java | 123 ++++++++++ .../facets/all/i18n/I18nFacetFactory.java | 167 +++++++++++++ .../cssclassfa/CssClassFaFacetAbstract.java | 16 +- .../services/ServicesInjectorDefault.java | 36 +-- .../services/i18n/LocaleProviderDefault.java | 36 +++ .../i18n/TranslationServiceLogging.java | 72 ++++++ .../specloader/ObjectReflectorDefault.java | 28 ++- .../dflt/ProgrammingModelFacetsJava5.java | 13 +- .../services/ServicesInstallerFallback.java | 52 ++++ ...InstallerFromConfigurationAndAnnotation.java | 10 + .../src/main/webapp/WEB-INF/isis.properties | 13 - 39 files changed, 1017 insertions(+), 79 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/AccessEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/AccessEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/AccessEvent.java index dd0f168..c4034ab 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/AccessEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/AccessEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents an access (reading) of a property, collection or title. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an access (reading) of a property, collection or title. * * <p> * Analogous to {@link ValidityEvent} (which corresponds to modifying a property @@ -33,7 +33,10 @@ import org.apache.isis.applib.Identifier; * @see UsabilityEvent * @see VisibilityEvent * @see ValidityEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public abstract class AccessEvent extends InteractionEvent { /** http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java index 7f1f5b0..e497e8d 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a particular argument for an action is valid + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a particular argument for an action is valid * or not. * * <p> @@ -31,7 +31,10 @@ import org.apache.isis.applib.Identifier; * * <p> * Called once per argument, and before {@link ActionInvocationEvent}. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ActionArgumentEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ActionInvocationEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ActionInvocationEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ActionInvocationEvent.java index 6b97f95..d23022b 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ActionInvocationEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ActionInvocationEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a particular argument for an action is valid + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a particular argument for an action is valid * or not. * * <p> @@ -31,7 +31,10 @@ import org.apache.isis.applib.Identifier; * * <p> * Called after each of the {@link ActionArgumentEvent}s. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ActionInvocationEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ActionUsabilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ActionUsabilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ActionUsabilityEvent.java index 0e51e6c..772ab3e 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ActionUsabilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ActionUsabilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether an action is usable or has been disabled. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether an action is usable or has been disabled. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * action is disabled; otherwise action is enabled. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ActionUsabilityEvent extends UsabilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ActionVisibilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ActionVisibilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ActionVisibilityEvent.java index 1307f38..9e1199a 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ActionVisibilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ActionVisibilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether an action is visible or has been hidden. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether an action is visible or has been hidden. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * action is invisible; otherwise action is visible. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ActionVisibilityEvent extends VisibilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAccessEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAccessEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAccessEvent.java index e182e49..f3e5aab 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAccessEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAccessEvent.java @@ -22,14 +22,17 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents an access (reading) of a collection. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an access (reading) of a collection. * * <p> * Analogous to {@link CollectionAddToEvent} or * {@link CollectionRemoveFromEvent}, however the {@link #getReason()} will * always be <tt>null</tt>. (If access is not allowed then a vetoing * {@link CollectionVisibilityEvent} would have been fired). + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionAccessEvent extends AccessEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAddToEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAddToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAddToEvent.java index a940bc4..3de08ce 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAddToEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionAddToEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a particular object to be added to a + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a particular object to be added to a * collection is valid or not. * * <p> @@ -30,7 +30,10 @@ import org.apache.isis.applib.Identifier; * object is invalid; otherwise the object is valid. * * @see CollectionRemoveFromEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionAddToEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionMethodEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionMethodEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionMethodEvent.java index 93d50eb..be57bb1 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionMethodEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionMethodEvent.java @@ -22,9 +22,11 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents an interaction with a collection object itself. - * + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an interaction with a collection object itself. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionMethodEvent extends AccessEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionRemoveFromEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionRemoveFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionRemoveFromEvent.java index 909227c..d1372aa 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionRemoveFromEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionRemoveFromEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a particular object to be removed from a + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a particular object to be removed from a * collection is valid or not. * * <p> @@ -30,7 +30,10 @@ import org.apache.isis.applib.Identifier; * object is invalid; otherwise the object is valid. * * @see CollectionAddToEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionRemoveFromEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionUsabilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionUsabilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionUsabilityEvent.java index cff56b7..1b0fe6d 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionUsabilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionUsabilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a collection is usable or has been disabled. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a collection is usable or has been disabled. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * collection is disabled; otherwise collection is enabled. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionUsabilityEvent extends UsabilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/CollectionVisibilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionVisibilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionVisibilityEvent.java index f7965ae..cb0dabc 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/CollectionVisibilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/CollectionVisibilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a collection is visible or has been hidden. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a collection is visible or has been hidden. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * collection is invisible; otherwise collection is visible. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class CollectionVisibilityEvent extends VisibilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java index 7b2b4c5..7905d6d 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java @@ -25,13 +25,16 @@ import java.util.List; import org.apache.isis.applib.Identifier; /** - * Represents an interaction with a domain object or a particular feature + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an interaction with a domain object or a particular feature * (property, collection, action) of a domain object. * * <p> * Many of the interactions are checks for {@link VisibilityEvent visibility}, * {@link UsabilityEvent usability} and {@link ValidityEvent validity}. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public abstract class InteractionEvent extends EventObject { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java index c4e19c2..b25f855 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents an access (reading) of an object's title. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an access (reading) of an object's title. * * <p> * The {@link #getReason()} will always be <tt>null</tt>; access is always * allowed. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ObjectTitleEvent extends AccessEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java index 0266196..0068b1c 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java @@ -22,14 +22,17 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether the current values of the + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether the current values of the * properties/collections of an object are valid (for example, prior to saving * that object). * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * object is invalid, otherwise ok. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ObjectValidityEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ObjectVisibilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectVisibilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectVisibilityEvent.java index 883b968..59ca9db 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ObjectVisibilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ObjectVisibilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether an object is visible or has been hidden. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether an object is visible or has been hidden. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * object is invisible; otherwise action is visible. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ObjectVisibilityEvent extends VisibilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java index 36566b1..3bafcaa 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java @@ -22,13 +22,16 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether the proposed values of the value type is + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether the proposed values of the value type is * valid. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * proposed value is invalid, otherwise the new value is acceptable. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class ParseValueEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java index 090f949..06d9f8c 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java @@ -22,13 +22,16 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents an access (reading) of a property. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents an access (reading) of a property. * * <p> * Analogous to {@link PropertyModifyEvent}, however the {@link #getReason()} * will always be <tt>null</tt>. (If access is not allowed then a * {@link PropertyVisibilityEvent} would have been fired). + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class PropertyAccessEvent extends AccessEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java index 33be17e..51ef377 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java @@ -22,13 +22,16 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a particular value for a property is valid + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a particular value for a property is valid * or not. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * value is invalid; otherwise the value is valid. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class PropertyModifyEvent extends ValidityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java index a4a94d2..f4a8593 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a property is usable or has been disabled. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a property is usable or has been disabled. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * property is disabled; otherwise property is enabled. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class PropertyUsabilityEvent extends UsabilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java index c8b72e4..a0b538d 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java @@ -22,12 +22,15 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check as to whether a property is visible or has been hidden. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check as to whether a property is visible or has been hidden. * * <p> * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the * property is invisible; otherwise property is visible. + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public class PropertyVisibilityEvent extends VisibilityEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java index 5358bbb..292cc72 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java @@ -20,10 +20,13 @@ package org.apache.isis.applib.events; /** - * Makes it easier to process different events that hold a single proposed + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> makes it easier to process different events that hold a single proposed * argument (such as {@link CollectionAddToEvent} and * {@link PropertyModifyEvent}). + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public interface ProposedHolderEvent { Object getProposed(); http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java index 7792bdd..0e6e6b6 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check to determine whether a member of an object is usable or + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check to determine whether a member of an object is usable or * has been disabled. * * <p> @@ -32,7 +32,10 @@ import org.apache.isis.applib.Identifier; * @see AccessEvent * @see VisibilityEvent * @see ValidityEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public abstract class UsabilityEvent extends InteractionEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java index d452400..a50ad88 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check to determine whether a proposed change is valid. + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check to determine whether a proposed change is valid. * * <p> * Multiple subclasses, including: @@ -41,7 +41,10 @@ import org.apache.isis.applib.Identifier; * @see AccessEvent * @see VisibilityEvent * @see UsabilityEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public abstract class ValidityEvent extends InteractionEvent implements ProposedHolderEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java index a306b02..06908e6 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java +++ b/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java @@ -22,7 +22,7 @@ package org.apache.isis.applib.events; import org.apache.isis.applib.Identifier; /** - * Represents a check to determine whether a member of an object is visible or + * <i>Supported only by {@link org.apache.isis.applib.services.wrapper.WrapperFactory} service, </i> represents a check to determine whether a member of an object is visible or * has been hidden. * * <p> @@ -32,7 +32,10 @@ import org.apache.isis.applib.Identifier; * @see AccessEvent * @see UsabilityEvent * @see ValidityEvent + * + * @deprecated - superceded by <code>domainEvent</code> support ({@link org.apache.isis.applib.services.eventbus.PropertyDomainEvent}, {@link org.apache.isis.applib.IsisApplibModule.CollectionDomainEvent}, {@link org.apache.isis.applib.services.eventbus.ActionDomainEvent}). */ +@Deprecated public abstract class VisibilityEvent extends InteractionEvent { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableMessagesService.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableMessagesService.java b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableMessagesService.java new file mode 100644 index 0000000..63b6fad --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableMessagesService.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.applib.services.i18n; + +import java.util.Collection; +import java.util.Map; +import java.util.Properties; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import org.apache.isis.applib.annotation.Action; +import org.apache.isis.applib.annotation.ActionLayout; +import org.apache.isis.applib.annotation.DomainService; +import org.apache.isis.applib.annotation.DomainServiceLayout; +import org.apache.isis.applib.annotation.NatureOfService; +import org.apache.isis.applib.annotation.ParameterLayout; +import org.apache.isis.applib.annotation.Programmatic; +import org.apache.isis.applib.annotation.SemanticsOf; +import org.apache.isis.applib.value.Clob; + +@DomainService( + nature = NatureOfService.VIEW_MENU_ONLY +) +@DomainServiceLayout( + menuBar = DomainServiceLayout.MenuBar.SECONDARY, + named = "Prototyping" +) +public class TranslatableMessagesService { + + @Programmatic + @PostConstruct + public void init(final Map<String,String> config) { + final Properties props = new Properties(); + for (final String key : config.keySet()) { + props.put(key, config.get(key)); + } + props.list(System.out); + } + + @Programmatic + @PreDestroy + public void shutdown() { + + } + + + @Action( + semantics = SemanticsOf.SAFE + ) + @ActionLayout( + cssClassFa = "fa-download" + ) + public Clob downloadPotFile( + @ParameterLayout(named = ".pot file name") + final String potFileName) { + final Map<String, Collection<String>> messages = translationService.messages(); + final StringBuilder buf = new StringBuilder(); + for (String message : messages.keySet()) { + final Collection<String> contexts = messages.get(message); + for (String context : contexts) { + buf.append("#: ").append(context).append("\n"); + } + buf.append("msgid: \"").append(message).append("\"\n"); + buf.append("msgstr: \"\"\n"); + buf.append("\n\n\n"); + } + return new Clob(potFileName, "text/plain", buf.toString()); + } + + public String default0DownloadPotFile() { + return "myapp.pot"; + } + + // ////////////////////////////////////// + + + @Inject + private TranslationService translationService; + +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java new file mode 100644 index 0000000..75b1a6e --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.applib.services.i18n; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.google.common.collect.Lists; + +public final class TranslatableString { + + //region > tr, trn (factory methods) + + /** + * A translatable string supporting both singular and plural forms. + * + * @param pattern - pattern for all (singular and plural) form, with <code>${xxx}</code> placeholders + * @param paramArgs - parameter/argument pairs (string and object, string and object, ...) + */ + public static TranslatableString tr( + final String pattern, + final Object... paramArgs) { + return new TranslatableString(Type.TR, pattern, null, 1, asMap(paramArgs)); + } + + /** + * A translatable string supporting both singular and plural forms. + * + * @param singularPattern - pattern for the singular form, with <code>${xxx}</code> placeholders + * @param pluralPattern - pattern for the singular form, with <code>${xxx}</code> placeholders + * @param number - whether to use singular or plural form when rendering + * @param paramArgs - parameter/argument pairs (string and object, string and object, ...) + */ + public static TranslatableString trn( + final String singularPattern, + final String pluralPattern, + final int number, + final Object... paramArgs) { + return new TranslatableString(Type.TRN, singularPattern, pluralPattern, number, asMap(paramArgs)); + } + + /** + * Converts a list of objects [a, 1, b, 2] into a map {a -> 1; b -> 2} + */ + private static Map<String, Object> asMap(final Object[] paramArgs) { + final HashMap<String, Object> map = new HashMap<String, Object>(); + boolean param = true; + String paramStr = null; + for (final Object paramArg : paramArgs) { + if (param) { + if (paramArg instanceof String) { + paramStr = (String) paramArg; + } else { + throw new IllegalArgumentException("Parameter must be a string"); + } + } else { + final Object arg = paramArg; + map.put(paramStr, arg); + paramStr = null; + } + param = !param; + } + if (paramStr != null) { + throw new IllegalArgumentException("Must have equal number of parameters and arguments"); + } + return map; + } + //endregion + + + private final Type type; + private final String singularPattern; + private final String pluralPattern; + private final int number; + private final Map<String, Object> argumentsByParameterName; + + private enum Type { + /** + * No plurals + */ + TR { + @Override + public String toString(final TranslatableString trString) { + return "tr: " + trString.singularPattern; + } + }, + /** + * With plurals + */ + TRN { + @Override + public String toString(final TranslatableString trString) { + return "trn: " + trString.pluralPattern; + } + }; + + public abstract String toString(final TranslatableString trString); + } + + private TranslatableString( + final Type type, + final String singularPattern, + final String pluralPattern, + final int number, + final Map<String, Object> argumentsByParameterName) { + + this.type = type; + this.singularPattern = singularPattern; + this.pluralPattern = pluralPattern; + this.number = number; + this.argumentsByParameterName = argumentsByParameterName; + } + + /** + * The pattern (or the singular pattern if {@link #isPluralForm()} is <code>true</code>). + */ + String getSingularPattern() { + return singularPattern; + } + + /** + * The plural pattern (but will be <code>null</code> if {@link #isPluralForm()} is <code>false</code>). + */ + String getPluralPattern() { + return pluralPattern; + } + + boolean isPluralForm() { + return type == Type.TRN; + } + + /** + * The arguments; excluded from {@link #equals(Object)} comparison. + */ + Map<String, Object> getArgumentsByParameterName() { + return argumentsByParameterName; + } + + //region > equals, hashCode + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final TranslatableString that = (TranslatableString) o; + + if (pluralPattern != null ? !pluralPattern.equals(that.pluralPattern) : that.pluralPattern != null) + return false; + if (singularPattern != null ? !singularPattern.equals(that.singularPattern) : that.singularPattern != null) + return false; + if (type != that.type) return false; + + return true; + } + + @Override + public int hashCode() { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + (singularPattern != null ? singularPattern.hashCode() : 0); + result = 31 * result + (pluralPattern != null ? pluralPattern.hashCode() : 0); + return result; + } + + //endregion + + + //region > translate + + public String translate(final TranslationService translationService, final String context, final Locale locale) { + final String translatedText = translationService.translate(context, getText(), locale); + return translated(translatedText); + } + + /** + * The text to be translated; depends on whether {@link #isPluralForm()} and whether to be translated. + * + * <p> + * May or may not hold placeholders. + * </p> + */ + String getText() { + return !isPluralForm() || number == 1 ? getSingularPattern() : getPluralPattern(); + } + + String translated(final String translatedText) { + return format(translatedText, argumentsByParameterName); + } + + static String format(String format, Map<String, Object> values) + { + StringBuilder formatter = new StringBuilder(format); + List<Object> valueList = Lists.newArrayList(); + + Matcher matcher = Pattern.compile("\\{(\\w+)}").matcher(format); + + while (matcher.find()) + { + String key = matcher.group(1); + + String formatKey = String.format("{%s}", key); + int index = formatter.indexOf(formatKey); + + if (index != -1) + { + formatter.replace(index, index + formatKey.length(), "%s"); + valueList.add(values.get(key)); + } + } + + return String.format(formatter.toString(), valueList.toArray()); + } + + //endregion + + + @Override + public String toString() { + return type.toString(this); + } +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslationService.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslationService.java b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslationService.java new file mode 100644 index 0000000..6204cdd --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslationService.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.applib.services.i18n; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; +import org.apache.isis.applib.annotation.Programmatic; + +public interface TranslationService { + + @Programmatic + public String translate(final String context, final String originalText, final Locale targetLocale); + + /** + * Returns the set of messages encountered and cached by the service (the key of the map) along with a set of + * context strings (the value of the map) + * + * <p> + * The intention is that an implementation running in prototype mode should retain all requests to + * {@link #translate(String, String, java.util.Locale)}, such that they can be translated and used by the + * same implementation in non-prototype mode. + * </p> + */ + @Programmatic + public Map<String, Collection<String>> messages(); + +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java b/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java new file mode 100644 index 0000000..5a34285 --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.applib.services.locale; + +import java.util.Locale; +import org.apache.isis.applib.annotation.Programmatic; + +public interface LocaleProvider { + + @Programmatic + Locale getLocale(); + +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/applib/src/test/java/org/apache/isis/applib/services/i18n/TrStringTest.java ---------------------------------------------------------------------- diff --git a/core/applib/src/test/java/org/apache/isis/applib/services/i18n/TrStringTest.java b/core/applib/src/test/java/org/apache/isis/applib/services/i18n/TrStringTest.java new file mode 100644 index 0000000..552f9e1 --- /dev/null +++ b/core/applib/src/test/java/org/apache/isis/applib/services/i18n/TrStringTest.java @@ -0,0 +1,123 @@ +package org.apache.isis.applib.services.i18n; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class TrStringTest { + + public static class GetText extends TrStringTest { + + @Test + public void singularForm() throws Exception { + final TranslatableString ts = TranslatableString.tr("No, you can't do that!"); + + assertThat(ts.getText(), is("No, you can't do that!")); + } + + @Test + public void pluralFormOne() throws Exception { + final TranslatableString ts = TranslatableString.trn("You can't do that because there is a dependent object", "You can't do that because there are dependent objects", 1); + + assertThat(ts.getText(), is("You can't do that because there is a dependent object")); + } + + @Test + public void pluralFormTwo() throws Exception { + final TranslatableString ts = TranslatableString.trn("You can't do that because there is a dependent object", "You can't do that because there are dependent objects", 2); + + assertThat(ts.getText(), is("You can't do that because there are dependent objects")); + } + + } + + public static class Translated extends TrStringTest { + + @Test + public void singularForm() throws Exception { + final TranslatableString ts = TranslatableString.tr("My name is {lastName}, {firstName} {lastName}.", "lastName", "Bond", "firstName", "James"); + + assertThat(ts.translated("Iche heisse {lastName}, {firstName} {lastName}."), is("Iche heisse Bond, James Bond.")); + } + + @Test + public void pluralFormOne() throws Exception { + final TranslatableString ts = TranslatableString.trn( + "My name is {lastName}, {firstName} {lastName}.", + "My name is {firstName} {lastName}.", + 1, + "lastName", "Bond", "firstName", "James"); + + assertThat(ts.translated("Iche heisse {lastName}, {firstName} {lastName}."), is("Iche heisse Bond, James Bond.")); + } + } + + public static class Translate extends TrStringTest { + + @Rule + public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES); + + private TranslationService echoTranslationService; + + private String originalTextToTranslate; + + @Before + public void setUp() throws Exception { + echoTranslationService = new TranslationService() { + @Override + public String translate(final String context, final String originalText, final Locale targetLocale) { + originalTextToTranslate = originalText; + return originalText; + } + @Override + public Map<String, Collection<String>> messages() { + return null; + } + }; + } + + @Test + public void singularForm() throws Exception { + final TranslatableString ts = TranslatableString.tr("My name is {lastName}, {firstName} {lastName}.", "lastName", "Bond", "firstName", "James"); + + assertThat(ts.translate(echoTranslationService, null, null), is("My name is Bond, James Bond.")); + assertThat(originalTextToTranslate, is("My name is {lastName}, {firstName} {lastName}.")); + } + + @Test + public void pluralFormOne() throws Exception { + final TranslatableString ts = TranslatableString.trn( + "My name is {lastName}, {firstName} {lastName}.", + "My name is {firstName} {lastName}.", + 1, + "lastName", "Bond", "firstName", "James"); + + assertThat(ts.translate(echoTranslationService, null, null), is("My name is Bond, James Bond.")); + assertThat(originalTextToTranslate, is("My name is {lastName}, {firstName} {lastName}.")); + } + + @Test + public void pluralFormTwo() throws Exception { + final TranslatableString ts = TranslatableString.trn( + "My name is {lastName}, {firstName} {lastName}.", + "My name is {firstName} {lastName}.", + 2, + "lastName", "Bond", "firstName", "James"); + + assertThat(ts.translate(echoTranslationService, null, null), is("My name is James Bond.")); + assertThat(originalTextToTranslate, is("My name is {firstName} {lastName}.")); + } + + } + + + + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java new file mode 100644 index 0000000..6761b04 --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.core.metamodel.facets.all.i18n; + + +import java.util.Locale; +import java.util.Objects; +import com.google.common.base.Strings; +import org.apache.isis.applib.services.i18n.TranslationService; +import org.apache.isis.applib.services.locale.LocaleProvider; +import org.apache.isis.core.metamodel.facetapi.FacetHolder; +import org.apache.isis.core.metamodel.facetapi.FacetUtil; +import org.apache.isis.core.metamodel.facetapi.FeatureType; +import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder; +import org.apache.isis.core.metamodel.facetdecorator.i18n.internal.DescribedAsFacetWrapI18n; +import org.apache.isis.core.metamodel.facetdecorator.i18n.internal.NamedFacetWrapI18n; +import org.apache.isis.core.metamodel.facets.ContributeeMemberFacetFactory; +import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; +import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet; +import org.apache.isis.core.metamodel.facets.all.named.NamedFacet; +import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector; +import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware; + +public class I18nFacetFactory extends FacetFactoryAbstract implements ContributeeMemberFacetFactory, ServicesInjectorAware { + + private ServicesInjector servicesInjector; + + private TranslationService translationService; + private LocaleProvider localeProvider; + + public I18nFacetFactory() { + super(FeatureType.EVERYTHING); + } + + @Override + public void process(final ProcessClassContext processClassContext) { + final FacetHolder facetHolder = processClassContext.getFacetHolder(); + if(facetHolder instanceof IdentifiedHolder) { + final IdentifiedHolder holder = (IdentifiedHolder) facetHolder; + final String context = holder.getIdentifier().toClassIdentityString(); + translateName(holder, context); + translateDescription(holder, context); + } + } + + @Override + public void process(final ProcessMethodContext processMethodContext) { + final IdentifiedHolder holder = processMethodContext.getFacetHolder(); + + final String context = holder.getIdentifier().toClassAndNameIdentityString(); + translateName(holder, context); + translateDescription(holder, context); + } + + @Override + public void processParams(final ProcessParameterContext processParameterContext) { + final IdentifiedHolder holder = processParameterContext.getFacetHolder(); + + final String context = holder.getIdentifier().toFullIdentityString(); + translateName(holder, context); + translateDescription(holder, context); + } + + @Override + public void process(final ProcessContributeeMemberContext processMemberContext) { + final IdentifiedHolder holder = processMemberContext.getFacetHolder(); + + final String context = holder.getIdentifier().toClassAndNameIdentityString(); + translateName(holder, context); + translateDescription(holder, context); + } + + // ////////////////////////////////////// + + void translateName(final IdentifiedHolder facetHolder, final String context) { + final NamedFacet facet = facetHolder.getFacet(NamedFacet.class); + if(facet == null) { + // not expected... + return; + } + final String originalText = facet.value(); + if (isNullOrEmptyWhenTrimmed(originalText)) { + // not expected... + return; + } + + final TranslationService translationService = lookupTranslationService(); + final LocaleProvider localeProvider = lookupLocaleProvider(); + + final Locale locale = localeProvider.getLocale(); + final String translatedText = translationService.translate(context, originalText, locale); + if(!Objects.equals(originalText, translatedText)) { + FacetUtil.addFacet(new NamedFacetWrapI18n(translatedText, facetHolder)); + } + } + + void translateDescription(final FacetHolder facetHolder, final String context) { + + final IdentifiedHolder holder = (IdentifiedHolder) facetHolder; + final DescribedAsFacet facet = facetHolder.getFacet(DescribedAsFacet.class); + if(facet == null) { + return; + } + final String originalText = facet.value(); + if (isNullOrEmptyWhenTrimmed(originalText)) { + return; + } + + final TranslationService translationService = lookupTranslationService(); + final LocaleProvider localeProvider = lookupLocaleProvider(); + + final Locale locale = localeProvider.getLocale(); + final String translatedText = translationService.translate(context, originalText, locale); + if(!Objects.equals(originalText, translatedText)) { + FacetUtil.addFacet(new DescribedAsFacetWrapI18n(translatedText, holder)); + } + } + + private boolean isNullOrEmptyWhenTrimmed(final String originalText) { + return originalText == null || Strings.isNullOrEmpty(originalText.trim()); + } + + // ////////////////////////////////////// + + /** + * Looks up from {@link org.apache.isis.core.metamodel.runtimecontext.ServicesInjector}, otherwise defaults to + * {@link org.apache.isis.core.metamodel.services.i18n.LocaleProviderDefault}. + */ + LocaleProvider lookupLocaleProvider() { + if(localeProvider == null) { + localeProvider = servicesInjector.lookupService(LocaleProvider.class); + } + return localeProvider; + } + + /** + * Looks up from {@link org.apache.isis.core.metamodel.runtimecontext.ServicesInjector}, otherwise defaults to + * {@link org.apache.isis.core.metamodel.services.i18n.TranslationServiceLogging}. + */ + TranslationService lookupTranslationService() { + if(translationService == null) { + translationService = servicesInjector.lookupService(TranslationService.class); + } + return translationService; + } + + @Override + public void setServicesInjector(final ServicesInjector servicesInjector) { + this.servicesInjector = servicesInjector; + } +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/cssclassfa/CssClassFaFacetAbstract.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/cssclassfa/CssClassFaFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/cssclassfa/CssClassFaFacetAbstract.java index 99fba5f..963b860 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/cssclassfa/CssClassFaFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/cssclassfa/CssClassFaFacetAbstract.java @@ -51,17 +51,23 @@ public class CssClassFaFacetAbstract extends SingleStringValueFacetAbstract impl * @param value The original CSS classes defined with {@literal @}{@link org.apache.isis.applib.annotation.CssClassFa CssClassFa} * @return The original CSS classes plus <em>fa</em> and <em>fa-fw</em> if not already provided */ - static String sanitize(String value) { - Iterable<String> classes = Splitter.on(WHITESPACE).split(value); - Set<String> cssClassesSet = Sets.newLinkedHashSet(); + static String sanitize(final String value) { + final Iterable<String> classes = Splitter.on(WHITESPACE).split(value); + final Set<String> cssClassesSet = Sets.newLinkedHashSet(); cssClassesSet.add("fa"); cssClassesSet.add("fa-fw"); - for (String cssClass : classes) { - cssClassesSet.add(cssClass); + for (final String cssClass : classes) { + cssClassesSet.add(faPrefix(cssClass)); } return Joiner.on(' ').join(cssClassesSet).trim(); } + private static String faPrefix(final String cssClass) { + return cssClass.startsWith("fa-") + ? cssClass + : "fa-" + cssClass; + } + public static Class<? extends Facet> type() { return CssClassFaFacet.class; } http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java index da67329..409f8c5 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java @@ -71,7 +71,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati * </p> * @param injectorMethodEvaluator */ - public ServicesInjectorDefault(InjectorMethodEvaluator injectorMethodEvaluator) { + public ServicesInjectorDefault(final InjectorMethodEvaluator injectorMethodEvaluator) { this.injectorMethodEvaluator = injectorMethodEvaluator != null ? injectorMethodEvaluator : new InjectorMethodEvaluatorDefault(); } @@ -187,7 +187,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati final List<Field> fields = Arrays.asList(cls.getDeclaredFields()); final Iterable<Field> injectFields = Iterables.filter(fields, new Predicate<Field>() { @Override - public boolean apply(Field input) { + public boolean apply(final Field input) { final Inject annotation = input.getAnnotation(javax.inject.Inject.class); return annotation != null; } @@ -204,10 +204,10 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati } } - private void autowire(Object object, Field field, List<Object> services) { + private void autowire(final Object object, final Field field, final List<Object> services) { for (final Object service : services) { final Class<?> serviceClass = service.getClass(); - boolean canInject = isInjectorFieldFor(field, serviceClass); + final boolean canInject = isInjectorFieldFor(field, serviceClass); if(canInject) { field.setAccessible(true); invokeInjectorField(field, object, service); @@ -219,7 +219,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati private void autowireViaPrefixedMethods(final Object object, final List<Object> services, final Class<?> cls, final String prefix) { final List<Method> methods = Arrays.asList(cls.getMethods()); final Iterable<Method> prefixedMethods = Iterables.filter(methods, new Predicate<Method>(){ - public boolean apply(Method method) { + public boolean apply(final Method method) { final String methodName = method.getName(); return methodName.startsWith(prefix); } @@ -230,10 +230,10 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati } } - private void autowire(Object object, Method prefixedMethod, List<Object> services) { + private void autowire(final Object object, final Method prefixedMethod, final List<Object> services) { for (final Object service : services) { final Class<?> serviceClass = service.getClass(); - boolean isInjectorMethod = injectorMethodEvaluator.isInjectorMethodFor(prefixedMethod, serviceClass); + final boolean isInjectorMethod = injectorMethodEvaluator.isInjectorMethodFor(prefixedMethod, serviceClass); if(isInjectorMethod) { prefixedMethod.setAccessible(true); invokeInjectorMethod(prefixedMethod, object, service); @@ -271,9 +271,9 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati private static void invokeInjectorField(final Field field, final Object target, final Object parameter) { try { field.set(target, parameter); - } catch (IllegalArgumentException e) { + } catch (final IllegalArgumentException e) { throw new MetaModelException(e); - } catch (IllegalAccessException e) { + } catch (final IllegalAccessException e) { throw new MetaModelException(String.format("Cannot access the %s field in %s", field.getName(), target.getClass().getName())); } if (LOG.isDebugEnabled()) { @@ -299,38 +299,38 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati //region > lookupService, lookupServices @Override - public <T> T lookupService(Class<T> serviceClass) { - List<T> services = lookupServices(serviceClass); + public <T> T lookupService(final Class<T> serviceClass) { + final List<T> services = lookupServices(serviceClass); return !services.isEmpty() ? services.get(0) : null; } @SuppressWarnings("unchecked") @Override - public <T> List<T> lookupServices(Class<T> serviceClass) { + public <T> List<T> lookupServices(final Class<T> serviceClass) { locateAndCache(serviceClass); return (List<T>) servicesByType.get(serviceClass); }; - private void locateAndCache(Class<?> serviceClass) { + private void locateAndCache(final Class<?> serviceClass) { if(servicesByType.containsKey(serviceClass)) { return; } - List<Object> matchingServices = Lists.newArrayList(); + final List<Object> matchingServices = Lists.newArrayList(); addAssignableTo(serviceClass, services, matchingServices); servicesByType.put(serviceClass, matchingServices); } - private static void addAssignableTo(Class<?> type, List<Object> candidates, List<Object> filteredServicesAndContainer) { - Iterable<Object> filteredServices = Iterables.filter(candidates, ofType(type)); + private static void addAssignableTo(final Class<?> type, final List<Object> candidates, final List<Object> filteredServicesAndContainer) { + final Iterable<Object> filteredServices = Iterables.filter(candidates, ofType(type)); filteredServicesAndContainer.addAll(Lists.newArrayList(filteredServices)); } private static final Predicate<Object> ofType(final Class<?> cls) { return new Predicate<Object>() { @Override - public boolean apply(Object input) { + public boolean apply(final Object input) { return cls.isAssignableFrom(input.getClass()); } }; @@ -343,7 +343,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati private InjectorMethodEvaluator injectorMethodEvaluator; @Override - public void setSpecificationLookup(SpecificationLoader specificationLookup) { + public void setSpecificationLookup(final SpecificationLoader specificationLookup) { injectorMethodEvaluator = specificationLookup; } http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java new file mode 100644 index 0000000..4b7ec49 --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.core.metamodel.services.i18n; + + +import java.util.Locale; +import org.apache.isis.applib.annotation.Programmatic; +import org.apache.isis.applib.services.locale.LocaleProvider; + +/** + * Not annotated with @DomainService, but is registered as a fallback by <tt>ServicesInstallerFallback</tt>. + */ +public class LocaleProviderDefault implements LocaleProvider { + + @Programmatic + @Override + public Locale getLocale() { + return Locale.getDefault(); + } +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/TranslationServiceLogging.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/TranslationServiceLogging.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/TranslationServiceLogging.java new file mode 100644 index 0000000..e4f8467 --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/TranslationServiceLogging.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.core.metamodel.services.i18n; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; +import java.util.NavigableSet; +import com.google.common.collect.TreeMultimap; +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.isis.applib.annotation.Programmatic; +import org.apache.isis.applib.services.i18n.TranslationService; + +/** + * Not annotated with @DomainService, but is registered as a fallback by <tt>ServicesInstallerFallback</tt>. + */ +public class TranslationServiceLogging implements TranslationService { + + public static Logger LOG = LoggerFactory.getLogger(TranslationServiceLogging.class); + + private final TreeMultimap<String, String> messages = TreeMultimap.create(); + + public TranslationServiceLogging() { + + LOG.info(""); + LOG.info(""); + LOG.info(""); + LOG.info("################################################################################"); + LOG.info("#"); + LOG.info("# " + LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss")); + LOG.info("#"); + LOG.info("################################################################################"); + LOG.info(""); + LOG.info(""); + + } + + @Override + @Programmatic + public String translate(final String context, final String originalText, final Locale targetLocale) { + + final NavigableSet<String> contexts = messages.get(originalText); + final boolean added = contexts.add(context); + if(added) { + LOG.info(String.format("%s_%s: %s", targetLocale.getISO3Country(), targetLocale.getISO3Language(), originalText)); + } + return originalText; + } + + @Programmatic + public Map<String, Collection<String>> messages() { + return messages.asMap(); + } +} http://git-wip-us.apache.org/repos/asf/isis/blob/67e234b8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java index ce25255..a27a1bf 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java @@ -490,25 +490,19 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App } public ObjectSpecification introspectIfRequired(final ObjectSpecification spec) { + final ObjectSpecificationAbstract specSpi = (ObjectSpecificationAbstract)spec; final IntrospectionState introspectionState = specSpi.getIntrospectionState(); + // REVIEW: can't remember why this is done in multiple passes, could it be simplified? if (introspectionState == IntrospectionState.NOT_INTROSPECTED) { + specSpi.setIntrospectionState(IntrospectionState.BEING_INTROSPECTED); - - specSpi.introspectTypeHierarchyAndMembers(); - facetDecoratorSet.decorate(spec); - specSpi.updateFromFacetValues(); - - specSpi.setIntrospectionState(IntrospectionState.INTROSPECTED); + introspect(specSpi); + } else if (introspectionState == IntrospectionState.BEING_INTROSPECTED) { - // nothing to do - specSpi.introspectTypeHierarchyAndMembers(); - facetDecoratorSet.decorate(spec); - specSpi.updateFromFacetValues(); - - specSpi.setIntrospectionState(IntrospectionState.INTROSPECTED); + introspect(specSpi); } else if (introspectionState == IntrospectionState.INTROSPECTED) { // nothing to do @@ -516,6 +510,13 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App return spec; } + private void introspect(final ObjectSpecificationAbstract specSpi) { + specSpi.introspectTypeHierarchyAndMembers(); + facetDecoratorSet.decorate(specSpi); + specSpi.updateFromFacetValues(); + specSpi.setIntrospectionState(IntrospectionState.INTROSPECTED); + } + @Override public ObjectSpecification lookupBySpecId(ObjectSpecId objectSpecId) { return getCache().getByObjectType(objectSpecId); @@ -628,7 +629,8 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App return o.getClass(); } }); - return Collections.unmodifiableList(serviceClasses); + // take a copy, to allow eg I18nFacetFactory to add in default implementations of missing services. + return Collections.unmodifiableList(Lists.newArrayList(serviceClasses)); } @Override
