org.jabylon.rest.ui.wicket.panels.ProjectResourcePanel.java Source code

Java tutorial

Introduction

Here is the source code for org.jabylon.rest.ui.wicket.panels.ProjectResourcePanel.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.panels;

import java.text.MessageFormat;
import java.util.Locale;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.Session;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.eclipse.emf.common.util.EList;
import org.jabylon.properties.Project;
import org.jabylon.properties.ProjectLocale;
import org.jabylon.properties.ProjectVersion;
import org.jabylon.properties.PropertiesPackage;
import org.jabylon.properties.PropertyFileDescriptor;
import org.jabylon.properties.Resolvable;
import org.jabylon.properties.ResourceFolder;
import org.jabylon.properties.Review;
import org.jabylon.properties.ReviewState;
import org.jabylon.properties.Workspace;
import org.jabylon.properties.util.PropertiesSwitch;
import org.jabylon.rest.ui.model.ComplexEObjectListDataProvider;
import org.jabylon.rest.ui.security.CDOAuthenticatedSession;
import org.jabylon.rest.ui.security.RestrictedComponent;
import org.jabylon.rest.ui.util.GlobalResources;
import org.jabylon.rest.ui.util.WicketUtil;
import org.jabylon.rest.ui.wicket.BasicResolvablePanel;
import org.jabylon.rest.ui.wicket.pages.XliffDownloadPage;
import org.jabylon.security.CommonPermissions;
import org.jabylon.users.User;

/**
 * @author Johannes Utzig (jutzig.dev@googlemail.com)
 */
public class ProjectResourcePanel extends BasicResolvablePanel<Resolvable<?, ?>> implements RestrictedComponent {

    private static final long serialVersionUID = 1L;

    public ProjectResourcePanel(Resolvable<?, ?> object, PageParameters parameters) {
        super("content", object, parameters);
        if (object instanceof Project) {
            Project project = (Project) object;
            String announcement = project.getAnnouncement();
            if (announcement != null && !announcement.isEmpty())
                info(announcement);
        }
        add(new Label("header", new LabelSwitch(getLocale()).doSwitch(object)));
        String href = WicketUtil.getContextPath() + "/api/" + getModelObject().toURI().appendQuery("type=file");
        ExternalLink downloadLink = new ExternalLink("download.link", href);
        downloadLink.setVisible(object != null && !(object instanceof Workspace) && !(object instanceof Project));
        add(downloadLink);

        BookmarkablePageLink<String> downloadXliff = new BookmarkablePageLink<String>("link-download-xliff", //$NON-NLS-1$
                XliffDownloadPage.class, parameters);
        downloadXliff.setVisible(object instanceof ProjectVersion);
        add(downloadXliff);

        XliffUploadPanel panel = new XliffUploadPanel("panel-upload-xliff", getModel(), parameters);
        panel.setVisible(uploadPanelVisible(object));
        add(panel);
    }

    @Override
    public void renderHead(IHeaderResponse response) {
        response.render(JavaScriptHeaderItem.forReference(GlobalResources.JS_JQUERY_DATATABLES));
        response.render(JavaScriptHeaderItem.forReference(GlobalResources.JS_BOOTSTRAP_DATATABLES));
        response.render(JavaScriptHeaderItem.forReference(GlobalResources.JS_DATATABLES_CUSTOMSORT));
        super.renderHead(response);
    }

    @Override
    protected void onBeforeRenderPanel() {
        ComplexEObjectListDataProvider<Resolvable<?, ?>> provider = new ComplexEObjectListDataProvider<Resolvable<?, ?>>(
                getModel(), PropertiesPackage.Literals.RESOLVABLE__CHILDREN);
        final boolean endsOnSlash = urlEndsOnSlash();
        final DataView<Resolvable<?, ?>> dataView = new DataView<Resolvable<?, ?>>("children", provider) {

            private static final long serialVersionUID = -3530355534807668227L;

            @Override
            protected void populateItem(Item<Resolvable<?, ?>> item) {
                Resolvable<?, ?> resolvable = item.getModelObject();

                item.setVisible(canView(resolvable));
                if (resolvable instanceof ProjectLocale) {
                    // hide the template language by default
                    ProjectLocale locale = (ProjectLocale) resolvable;
                    if (locale.isMaster())
                        item.setVisible(false);

                }

                LinkTarget target = buildLinkTarget(resolvable, endsOnSlash);

                ExternalLink link = new ExternalLink("link", Model.of(target.getHref()), target.getLabel());
                item.add(link);

                Triplet widths = computeProgressBars(target.getEndPoint());
                Label progress = new Label("progress", String.valueOf(widths.getSuccess()) + "%");
                progress.add(new AttributeModifier("style", "width: " + widths.getSuccess() + "%"));
                Label warning = new Label("warning", "");
                warning.add(new AttributeModifier("style", "width: " + widths.getWarning() + "%"));
                Label danger = new Label("danger", "");
                danger.add(new AttributeModifier("style", "width: " + widths.getDanger() + "%"));
                item.add(progress);
                item.add(warning);
                item.add(danger);

                new ImageSwitch(item).doSwitch(target.getEndPoint());
                item.add(new Label("summary", new Summary(item).doSwitch(target.getEndPoint())));
            }

        };
        // dataView.setItemsPerPage(10);
        add(dataView);
    }

    protected boolean canView(Resolvable<?, ?> resolvable) {
        Session session = getSession();
        if (session instanceof CDOAuthenticatedSession) {
            CDOAuthenticatedSession authSession = (CDOAuthenticatedSession) session;
            User user = authSession.getUser();
            if (user == null)
                user = authSession.getAnonymousUser();
            if (user != null)
                return CommonPermissions.hasViewPermission(user, resolvable);
        }
        return false;
    }

    /**
      * computes the width of the two stacked progress bars
      * @param resolvable
      * @return
      */
    protected Triplet computeProgressBars(Resolvable<?, ?> resolvable) {

        int greenWidth = resolvable.getPercentComplete();
        int yellowWidth = 0;
        if (resolvable instanceof PropertyFileDescriptor) {
            PropertyFileDescriptor descriptor = (PropertyFileDescriptor) resolvable;
            int keys = descriptor.getMaster() == null ? descriptor.getKeys() : descriptor.getMaster().getKeys();
            if (keys > 0) {
                EList<Review> reviews = descriptor.getReviews();
                int activeReviews = 0;
                for (Review review : reviews) {
                    if (review.getState() == ReviewState.OPEN || review.getState() == ReviewState.REOPENED)
                        activeReviews++;
                }
                yellowWidth = (int) (activeReviews * 100 / (double) keys);
                greenWidth -= yellowWidth;
            }
        }
        return new Triplet(greenWidth, yellowWidth);

    }

    private LinkTarget buildLinkTarget(Resolvable<?, ?> resolvable, boolean endsOnSlash) {
        StringBuilder hrefBuilder = new StringBuilder();
        LabelSwitch labelSwitch = new LabelSwitch(getLocale());
        StringBuilder name = new StringBuilder();
        name.append(labelSwitch.doSwitch(resolvable));
        if (resolvable.getParent() == null)
            hrefBuilder.append("/");
        else if (resolvable.getParent() instanceof Workspace)
            hrefBuilder.append(endsOnSlash ? resolvable.getName() : "workspace/" + resolvable.getName());
        else
            hrefBuilder.append(endsOnSlash ? resolvable.getName()
                    : resolvable.getParent().getName() + "/" + resolvable.getName());

        Resolvable<?, ?> folder = resolvable;
        if (folder instanceof ResourceFolder) {
            // if it is a folder, squash more children, if there is only one
            while (folder.getChildren().size() == 1) {
                folder = folder.getChildren().get(0);
                hrefBuilder.append("/");
                hrefBuilder.append(folder.getName());
                name.append("/");
                name.append(labelSwitch.doSwitch(folder));
            }
        }
        LinkTarget target = new LinkTarget(Model.of(name.toString()), hrefBuilder.toString(), folder);
        return target;

    }

    @Override
    public String getRequiredPermission() {
        Resolvable<?, ?> object = getModelObject();
        while (object != null) {
            if (object instanceof Project) {
                return CommonPermissions.constructPermissionName(object, CommonPermissions.ACTION_VIEW);
            } else if (object instanceof Workspace) {
                return CommonPermissions.constructPermissionName(object, CommonPermissions.ACTION_VIEW);
            }
            object = object.getParent();
        }
        return null;
    }

    /**
     * @return true if the user is allowed to upload/import XLIFF files for this
     *         {@link ProjectVersion}.<br>
     */
    private boolean uploadPanelVisible(Resolvable<?, ?> object) {
        if (!(object instanceof ProjectVersion)) {
            return false;
        }

        ProjectVersion version = (ProjectVersion) object;
        if (version.isReadOnly()) {
            return false;
        }

        Session session = getSession();

        if (!(session instanceof CDOAuthenticatedSession)) {
            return false;
        }

        Project project = version.getParent();
        CDOAuthenticatedSession authSession = (CDOAuthenticatedSession) session;
        return authSession.hasPermission(CommonPermissions.constructPermission(CommonPermissions.PROJECT,
                project.getName(), CommonPermissions.ACTION_EDIT));
    }
}

class LinkTarget {
    private IModel<String> label;
    private String href;
    private Resolvable<?, ?> endPoint;

    public LinkTarget(IModel<String> label, String href, Resolvable<?, ?> endPoint) {
        super();
        this.label = label;
        this.href = href;
        this.endPoint = endPoint;
    }

    public Resolvable<?, ?> getEndPoint() {
        return endPoint;
    }

    public String getHref() {
        return href;
    }

    public IModel<String> getLabel() {
        return label;
    }

}

class LabelSwitch extends PropertiesSwitch<String> {

    private Locale locale;

    public LabelSwitch(Locale locale) {
        super();
        this.locale = locale;
        if (locale == null)
            this.locale = Locale.getDefault();
    }

    @Override
    public <P extends Resolvable<?, ?>, C extends Resolvable<?, ?>> String caseResolvable(Resolvable<P, C> object) {
        return object.getName();
    }

    @Override
    public String caseProjectLocale(ProjectLocale object) {
        if (object.getLocale() != null)
            return object.getLocale().getDisplayName(locale);
        return "Template";
    }

    @Override
    public String caseWorkspace(Workspace object) {
        return "Workspace";
    }
}

class Summary extends PropertiesSwitch<IModel<String>> {
    private static final String NUMBER_OF_KEYS_KEY = "number.of.keys";
    private static final String TRANSLATION_PERCENTAGE_KEY = "translation.percentage";
    private static final String TRANSLATION_PERCENTAGE_SHORT_KEY = "translation.percentage.short";
    private transient Component parent;

    public Summary(Component parent) {
        this.parent = parent;
    }

    @Override
    public <P extends Resolvable<?, ?>, C extends Resolvable<?, ?>> IModel<String> caseResolvable(
            Resolvable<P, C> object) {
        return new StringResourceModel(TRANSLATION_PERCENTAGE_SHORT_KEY, parent, null, object.getPercentComplete());
    }

    @Override
    public IModel<String> caseProjectLocale(ProjectLocale object) {
        if (object.getParent() == null && object.getParent().getTemplate() == null)
            return null;
        ProjectLocale template = object.getParent().getTemplate();
        int propertyCount = template.getPropertyCount();
        int translatedCount = object.getPropertyCount();
        return new StringResourceModel(TRANSLATION_PERCENTAGE_KEY, parent, null, translatedCount, propertyCount,
                object.getPercentComplete());
    }

    @Override
    public IModel<String> casePropertyFileDescriptor(PropertyFileDescriptor object) {
        int propertyCount = object.getKeys();
        if (object.isMaster()) {
            String message = NUMBER_OF_KEYS_KEY;
            message = MessageFormat.format(message, propertyCount);
            return new StringResourceModel(NUMBER_OF_KEYS_KEY, parent, null, propertyCount);
        } else {
            int templateCount = object.getMaster().getKeys();
            return new StringResourceModel(TRANSLATION_PERCENTAGE_KEY, parent, null, propertyCount, templateCount,
                    object.getPercentComplete());

        }
    }

}

class ImageSwitch extends PropertiesSwitch<Item<?>> {

    private transient Item<?> item;

    public ImageSwitch(Item<?> item) {
        super();
        this.item = item;
    }

    @Override
    public Item<?> caseProject(Project object) {
        return addCSSIcon("icon-folder-close");
    }

    @Override
    public Item<?> caseProjectLocale(ProjectLocale object) {
        if (object.getLocale() == null)
            return addCSSIcon("icon-book");
        WebMarkupContainer markupContainer = new WebMarkupContainer("css-icon");
        item.add(markupContainer);
        markupContainer.setVisible(false);

        Image image = new Image("regular-image", WicketUtil.getIconForLocale(object.getLocale()));
        item.add(image);
        return item;
    }

    @Override
    public Item<?> caseProjectVersion(ProjectVersion object) {
        return addCSSIcon("icon-time");
    }

    @Override
    public Item<?> caseResourceFolder(ResourceFolder object) {
        return addCSSIcon("icon-folder-open");
    }

    @Override
    public <P extends Resolvable<?, ?>, C extends Resolvable<?, ?>> Item<?> caseResolvable(
            Resolvable<P, C> object) {
        return addCSSIcon("icon-file");
    }

    protected Item<?> addCSSIcon(String icon) {
        WebMarkupContainer markupContainer = new WebMarkupContainer("css-icon");
        item.add(markupContainer);
        markupContainer.add(new AttributeModifier("class", icon));
        Image image = new Image("regular-image", "not-there.gif");
        image.setVisible(false);
        item.add(image);
        return item;
    }
}

class Triplet {
    int success, warning;

    public Triplet(int success, int warning) {
        super();
        this.success = success;
        this.warning = warning;
    }

    public int getSuccess() {
        return success;
    }

    public int getWarning() {
        return warning;
    }

    public int getDanger() {
        int danger = 100 - success - warning;
        //only show danger level if the remainder is <=5
        //        https://github.com/jutzig/jabylon/issues/122
        if (danger <= 5)
            return danger;
        return 0;
    }

}