Navigator for SubViews

I am creating a Vaadin app, which include some Views and some Sub-Views:

(1)In the UI level, there are (normal) views, for example:
LoginView, MainView, UserRegisterView, SystemErrorView, and so on…
I manage these views with Navigator.
Let’s call it Navigator-A.
In this part, there is no problem.

(2)In the MainView, I have a menu bar, which will switch SubViews to display,
and a Panel, which will be the ViewDisplayer for SubViews.
When user click menu buttons in the menu bar, the top level views will not be switched.
Only a SubView correspond to the clicked menu button will be displayed in the Panel, as a part of MainView.

I manage these SubViews with Navigator, too.
Let’s call it Navigator-B.
Navigator for SubViews works just fine, It can switch SubViews, and display SubViews in the Panel.

Here is the problem:
(=A=) The navigator property of the current UI instance is set to Navigator-B.
And in the method UI.doInit:

        Navigator navigator = getNavigator();
        if (navigator != null) {
            // Kickstart navigation if a navigator was attached in init()

These code will execute on the Navigator-B(Navigator for SubViews),
but not Navigator-A(Navigator for top Views)

(=B=) The uriFragment is going wrong:
For example, let’s say
The view name for MainView is “main”,
and view name for SubViewA is “subA”, view name for SubViewB is “subB”.

When I switch to MainView->SubViewA, uriFragment should be “main/subA”,
and for MainView->SubViewB, it should be “main/subB”

But the current implement of Navigator class simplly retrieve the whole uriFragment, and process it as the state string of one view.
It do not distinguish which part of the uriFragment is the state string for parent View, and which part is for SubView.

To solve these problem, I create 2 class:

public class SubViewNavigator extends Navigator {
    public static final SubViewNavigator build(final SingleComponentContainer container, final String parentViewName) {
        // !!! To fix the problem (A) !!!
        Navigator oldNavigator = UI.getCurrent().getNavigator();

        try {
            return new SubViewNavigator(container, parentViewName);
        } finally {
            // !!! To fix the problem (A) !!!

    // =========================================================================

    public SubViewNavigator(final ComponentContainer container, final String parentViewName) {
        this(new ComponentContainerViewDisplay(container), parentViewName);

    public SubViewNavigator(final SingleComponentContainer container, final String parentViewName) {
        this(new SingleComponentContainerViewDisplay(container), parentViewName);

    public SubViewNavigator(final ViewDisplay display, final String parentViewName) {
        this(new SubViewUriFragmentManager(Page.getCurrent(), parentViewName), display);

    public SubViewNavigator(final NavigationStateManager stateManager, final ViewDisplay display) {
        super(UI.getCurrent(), stateManager, display);
public class SubViewUriFragmentManager extends UriFragmentManager {
    private static final long serialVersionUID = -3213234745768639487L;

    private String parentViewName;

    public SubViewUriFragmentManager(final Page page, final String parentViewName) {
        this.parentViewName = parentViewName;

    public void setState(final String state) {
        // !!! To fix the problem (B) !!!
        String fullState = this.parentViewName + "/" + state;


    public String getState() {
        // !!! To fix the problem (B) !!!
        String state = super.getState();

        state = StringUtils.removeStart(state, this.parentViewName + "/");

        return state;

Now I am using (normal) Navigator class for top level (normal) views, and the new SubViewNavigator class for SubViews.
It works just fine.

How do you think about this SubViewNavigator and SubViewUriFragmentManager.
Am I doing it right?