org.jabylon.rest.ui.wicket.config.SettingsPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.jabylon.rest.ui.wicket.config.SettingsPanel.java

Source

/**
 * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
/**
 *
 */
package org.jabylon.rest.ui.wicket.config;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.authorization.UnauthorizedInstantiationException;
import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.string.StringValue;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.jabylon.common.resolver.URIResolver;
import org.jabylon.common.util.AttachablePreferences;
import org.jabylon.common.util.DelegatingPreferences;
import org.jabylon.common.util.PreferencesUtil;
import org.jabylon.common.util.config.DynamicConfigUtil;
import org.jabylon.properties.PropertiesPackage;
import org.jabylon.properties.Resolvable;
import org.jabylon.rest.ui.model.AttachableModel;
import org.jabylon.rest.ui.model.AttachableWritableModel;
import org.jabylon.rest.ui.security.CDOAuthenticatedSession;
import org.jabylon.rest.ui.security.LoginPage;
import org.jabylon.rest.ui.util.WicketUtil;
import org.jabylon.rest.ui.wicket.components.ClientSideTabbedPanel;
import org.jabylon.security.CommonPermissions;
import org.jabylon.users.User;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ArrayListMultimap;

/**
 * @author jutzig.dev@googlemail.com
 *
 */
public class SettingsPanel<T extends CDOObject> extends GenericPanel<T> {

    public static final String QUERY_PARAM_NAMESPACE = "namespace";

    private static final long serialVersionUID = 1L;

    public static final String QUERY_PARAM_CREATE = "create";

    private static final Logger logger = LoggerFactory.getLogger(SettingsPage.class);

    private List<ConfigSection<?>> allSections;

    @Inject
    private URIResolver resolver;

    @SuppressWarnings("unchecked")
    public SettingsPanel(String id, IModel<T> model, PageParameters pageParameters) {
        super(id, model);
        EClass eclass = getEClassToCreate(pageParameters);
        if (eclass != null) {
            setModel(new AttachableWritableModel<T>(eclass, getModel()));
        }

        T modelObject = getModelObject();
        boolean isNew = modelObject.cdoState() == CDOState.NEW || modelObject.cdoState() == CDOState.TRANSIENT;
        final Preferences preferences = isNew ? new AttachablePreferences()
                : new DelegatingPreferences(PreferencesUtil.scopeFor(modelObject));

        final List<ITab> extensions = loadTabExtensions(preferences);

        // submit section

        @SuppressWarnings({ "rawtypes" })
        Form form = new Form("form", getModel()) {

            private static final long serialVersionUID = 1L;
            String oldName;

            @Override
            protected void beforeUpdateFormComponentModels() {
                super.beforeUpdateFormComponentModels();
                IModel model = getModel();
                if (model != null && model.getObject() instanceof Resolvable) {
                    //store the original project name in case it gets changed
                    Resolvable resolvable = (Resolvable) model.getObject();
                    oldName = resolvable.getName();
                }
            }

            @Override
            protected void onSubmit() {
                Preferences prefs = preferences;
                IModel<T> model = SettingsPanel.this.getModel();
                CDOObject object = model.getObject();
                CDOView cdoView;
                if (model instanceof AttachableModel) {
                    // it's a new object that needs attaching
                    AttachableModel<CDOObject> attachable = (AttachableModel) model;
                    attachable.attach();
                    CDOObject parent = (CDOObject) attachable.getObject().eContainer();
                    cdoView = parent.cdoView();
                } else
                    cdoView = object.cdoView();
                if (cdoView instanceof CDOTransaction) {
                    CDOTransaction transaction = (CDOTransaction) cdoView;

                    if (prefs instanceof AttachablePreferences) {
                        // the prefs are not in the tree yet
                        Preferences targetPrefs = PreferencesUtil.scopeFor(object);
                        try {
                            PreferencesUtil.cloneNode(prefs, targetPrefs);
                            prefs = targetPrefs;
                        } catch (BackingStoreException e) {
                            error("Some settings could not be saved: " + e.getMessage());
                            logger.error("Failed to attach preferences to target path", e);
                        }
                    }
                    if (oldName != null && !oldName
                            .equals(model.getObject().eGet(PropertiesPackage.Literals.RESOLVABLE__NAME))) {
                        renameResolvable(oldName, model);

                        prefs = PreferencesUtil.renamePreferenceNode(preferences,
                                (String) model.getObject().eGet(PropertiesPackage.Literals.RESOLVABLE__NAME));
                    }
                    commit(prefs, object, transaction);
                    // model.detach();
                } else
                    throw new IllegalStateException("not a transaction");
                super.onSubmit();
            }

            protected void commit(final Preferences preferences, CDOObject object, CDOTransaction transaction) {

                for (ConfigSection<?> section : allSections) {
                    section.commit(getModel(), preferences);
                }
                try {
                    transaction.commit();

                    URI uri = resolver.getURI(object);
                    setResponsePage(SettingsPage.class, WicketUtil.buildPageParametersFor(uri));

                    preferences.flush();
                    getSession().success(getString("save.success.feedback.message"));
                } catch (CommitException e) {
                    getSession().error(e.getMessage());
                    logger.error("failed to commit configuration for " + object, e);
                } catch (BackingStoreException e) {
                    getSession().error(e.getMessage());
                    logger.error("failed to commit configuration for " + object, e);
                } finally {
                    // transaction.close();
                }
            }
        };

        ClientSideTabbedPanel<ITab> tabContainer = new ClientSideTabbedPanel<ITab>("tabs", extensions, false,
                "settings/" + model.getObject().getClass().getSimpleName()) {

            private static final long serialVersionUID = 1L;

            @Override
            public boolean isVisible() {
                boolean visible = super.isVisible();
                List<ITab> tabContents = extensions;
                for (ITab component : tabContents) {
                    if (component.isVisible())
                        return visible;
                }
                CDOAuthenticatedSession session = (CDOAuthenticatedSession) CDOAuthenticatedSession.get();
                User user = session.getUser();
                if (user == null || CommonPermissions.USER_ANONYMOUS.equals(user.getName()))
                    // user is not logged in, give him the chance
                    throw new RestartResponseAtInterceptPageException(LoginPage.class);
                // if no tab is visible, the user has no permission to be here
                throw new UnauthorizedInstantiationException(SettingsPanel.class);
            }

        };
        form.add(tabContainer);
        // form.add(new CustomFeedbackPanel("feedback"));

        Button submitButton = new Button("submit", new StringResourceModel("submit.button.label", this, null));
        form.add(submitButton);
        // Button cancelButton = new Button("cancel-button",
        // Model.of("Cancel"));
        // form.add(cancelButton);

        add(form);

    }

    /**
     * called when the name of a resolvable changes
     * @param oldName
     * @param model
     */
    @SuppressWarnings("rawtypes")
    protected void renameResolvable(String oldName, IModel<T> model) {
        T object = model.getObject();
        if (object instanceof Resolvable) {
            Resolvable r = (Resolvable) object;
            logger.info("Renaming {} {} to {}", r.getClass().getSimpleName(), oldName, r.getName());
            URI absoluteFilePath = r.absoluteFilePath();
            String fileString = absoluteFilePath.toFileString();
            if (!fileString.startsWith("/") || fileString.startsWith("\\")) {
                fileString = "/" + fileString;
            }
            File targetFile = new File(fileString);
            File sourceFile = new File(targetFile.getParentFile(), oldName);
            sourceFile.renameTo(targetFile);
        }

    }

    private EClass getEClassToCreate(PageParameters pageParameters) {
        StringValue value = pageParameters.get(QUERY_PARAM_CREATE);
        if (value != null && !value.isEmpty()) {
            String namespace = pageParameters.get(QUERY_PARAM_NAMESPACE).toString(PropertiesPackage.eNS_URI);
            EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(namespace);
            if (ePackage != null) {
                EClassifier eClassifier = ePackage.getEClassifier(value.toString());
                if (eClassifier instanceof EClass) {
                    EClass eclass = (EClass) eClassifier;
                    return eclass;
                }
            }
        }
        return null;

    }

    @SuppressWarnings({ "unused", "unchecked", "rawtypes" })
    private List<ITab> loadTabExtensions(Preferences preferences) {

        List<IConfigurationElement> configurationElements = DynamicConfigUtil.getConfigTabs();
        ArrayListMultimap<String, ConfigSection<?>> sections = ArrayListMultimap
                .create(configurationElements.size(), 5);
        allSections = new ArrayList<ConfigSection<?>>();
        List<IConfigurationElement> elements = DynamicConfigUtil.getApplicableElements(getModelObject());
        for (IConfigurationElement element : elements) {
            String id = element.getAttribute("tab");
            ConfigSection<?> extension;
            try {
                extension = (ConfigSection<?>) element.createExecutableExtension("section");
                sections.put(id, extension);
            } catch (CoreException e) {
                logger.error("Failed to create executable extension: " + element, e);
            }
        }
        List<ITab> extensions = new ArrayList<ITab>();
        T modelObject = getModelObject();
        for (IConfigurationElement element : configurationElements) {
            String name = element.getAttribute("name");
            String id = element.getAttribute("tabID");
            List<ConfigSection<?>> tabSections = sections.removeAll(id);
            ConfigTab tab = new ConfigTab(name, tabSections, getModel(), preferences);
            allSections.addAll(tabSections);
            if (tab.isVisible())
                extensions.add(tab);
        }
        if (!sections.isEmpty()) {
            logger.warn("Unmapped config sections left {}", sections);
        }
        return extensions;
    }

}