/** * (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.sections; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.form.ListChoice; import org.apache.wicket.markup.html.form.RequiredTextField; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.util.ListModel; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.util.EcoreUtil; import org.jabylon.properties.Project; import org.jabylon.properties.ProjectLocale; import org.jabylon.properties.ProjectVersion; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.PropertiesPackage; import org.jabylon.properties.util.PropertyResourceUtil; import org.jabylon.rest.ui.model.AttachableModel; import org.jabylon.rest.ui.model.EObjectPropertyModel; import org.jabylon.rest.ui.wicket.BasicPanel; import org.jabylon.rest.ui.wicket.components.ControlGroup; import org.jabylon.rest.ui.wicket.config.AbstractConfigSection; import org.jabylon.rest.ui.wicket.validators.UniqueNameValidator; import org.jabylon.security.CommonPermissions; import org.osgi.service.prefs.Preferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VersionConfigSection extends BasicPanel<ProjectVersion> { private static final String TEMPLATE_ID = "template"; private static final long serialVersionUID = 1L; private ListModel<String> choiceModel; public VersionConfigSection(String id, IModel<ProjectVersion> model, ListModel<String> locales, Preferences prefs) { super(id, model); IModel<String> nameProperty = new EObjectPropertyModel<String, ProjectVersion>(model, PropertiesPackage.Literals.RESOLVABLE__NAME); TextField<String> field = new RequiredTextField<String>("inputName", nameProperty); field.add(UniqueNameValidator.fromCollection(getBranches(model),PropertiesPackage.Literals.RESOLVABLE__NAME,model.getObject())); add(field); ControlGroup readOnlyGroup = new ControlGroup("readonly-group",null, nls("readonly.help")); CheckBox readonly = new CheckBox("readonly", new EObjectPropertyModel<Boolean, ProjectVersion>(model, PropertiesPackage.Literals.PROJECT_VERSION__READ_ONLY)); readOnlyGroup.add(readonly); add(readOnlyGroup); // add(buildAddNewLink(getModel())); final WebMarkupContainer rowPanel = new WebMarkupContainer("rowPanel"); rowPanel.setOutputMarkupId(true); add(rowPanel); Form<?> form = new Form<Object>("locale-form"); form.setOutputMarkupId(true); rowPanel.add(form); final TextField<String> languageField = new TextField<String>("inputLanguage", Model.of("")); languageField.setOutputMarkupId(true); form.add(languageField); final TextField<String> countryField = new TextField<String>("inputCountry", Model.of("")); countryField.setOutputMarkupId(true); form.add(countryField); final TextField<String> variantField = new TextField<String>("inputVariant", Model.of("")); variantField.setOutputMarkupId(true); form.add(variantField); choiceModel = locales; final ListChoice<String> choice = new ListChoice<String>("children", choiceModel); choice.setModel(choiceModel.getObject().isEmpty() ? Model.of("") : Model.of(choiceModel.getObject().get(0))); choice.setMaxRows(15); choice.add(new AjaxFormComponentUpdatingBehavior ("onchange") { private static final long serialVersionUID = 1L; @Override protected void onUpdate(AjaxRequestTarget target) { target.add(languageField); target.add(countryField); target.add(variantField); String localeString = choice.getModelObject(); if(localeString==null || TEMPLATE_ID.equals(localeString)) { languageField.setModelObject(""); countryField.setModelObject(""); variantField.setModelObject(""); } else { Locale locale = (Locale) PropertiesFactory.eINSTANCE.createFromString(PropertiesPackage.Literals.LOCALE, localeString); languageField.setModelObject(locale.getLanguage()); countryField.setModelObject(locale.getCountry()); variantField.setModelObject(locale.getVariant()); } } }); choice.setChoiceRenderer(new IChoiceRenderer<String>() { private static final long serialVersionUID = 1L; @Override public Object getDisplayValue(String object) { if(TEMPLATE_ID.equals(object)) return "Template"; Locale locale = (Locale) PropertiesFactory.eINSTANCE.createFromString(PropertiesPackage.Literals.LOCALE, object); String displayName = locale == null ? "Template" : locale.getDisplayName(getSession().getLocale()); return displayName; } @Override public String getIdValue(String locale, int index) { if(locale==null) return TEMPLATE_ID; return locale.toString(); } }); rowPanel.add(choice); AjaxSubmitLink addLink = new AjaxSubmitLink("addLocale", form) { private static final long serialVersionUID = 1L; @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { // ProjectLocale newLocale = PropertiesFactory.eINSTANCE.createProjectLocale(); Locale locale = new Locale(safeGet(languageField.getModelObject()),safeGet(countryField.getModelObject()),safeGet(variantField.getModelObject())); //make sure to avoid duplicates if(!choiceModel.getObject().contains(locale.toString())) choiceModel.getObject().add(locale.toString()); choice.setModelObject(locale.toString()); // newLocale.setLocale(locale); // PropertyResourceUtil.addNewLocale(newLocale, getModelObject()); if (target != null) target.add(rowPanel); } }; // addLink.setDefaultFormProcessing(false); form.add(addLink); AjaxSubmitLink removeLink = new AjaxSubmitLink("removeLocale", form) { private static final long serialVersionUID = 1L; @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { choiceModel.getObject().remove(choice.getModelObject()); // provider.getObject().remove(choice.getModelObject()); if (target != null) target.add(rowPanel); } }; // removeLink.setDefaultFormProcessing(false); form.add(removeLink); } public Collection<ProjectVersion> getBranches(IModel<ProjectVersion> current) { if(current==null) return Collections.emptyList(); Project parent = current.getObject().getParent(); if(parent==null && current instanceof AttachableModel) { AttachableModel<ProjectVersion> model = (AttachableModel<ProjectVersion>)current; parent = (Project) model.getParent().getObject(); } if(parent==null) return Collections.emptyList(); return parent.getChildren(); } public static class VersionConfig extends AbstractConfigSection<ProjectVersion> { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(VersionConfig.class); private ListModel<String> locales; @Override public WebMarkupContainer doCreateContents(String id, IModel<ProjectVersion> input, Preferences prefs) { locales = createListModel(input); return new VersionConfigSection(id, input, locales,prefs); } @Override public void commit(IModel<ProjectVersion> input, Preferences config) { applyLocaleList(locales.getObject(), input); } /** * calculates a diff between existing locales and selected ones. * Deletes and adds ProjectLocales as needed * @param object * @param input */ protected void applyLocaleList(List<String> object, IModel<ProjectVersion> input) { Set<String> locales = new HashSet<String>(object); ProjectVersion version = input.getObject(); List<ProjectLocale> projectLocales = version.getChildren(); List<ProjectLocale> toDelete = new ArrayList<>(); for (Iterator<ProjectLocale> iterator = projectLocales.iterator(); iterator.hasNext();) { ProjectLocale projectLocale = iterator.next(); if(projectLocale.isMaster()) continue; if(!locales.remove(projectLocale.getName())) { toDelete.add(projectLocale); } } for (ProjectLocale projectLocale : toDelete) { LOGGER.info("Deleting ProjectLocale {} from {}",projectLocale.getName(), version.fullPath()); EcoreUtil.delete(projectLocale, true); } for (String locale : locales) { ProjectLocale projectLocale = PropertiesFactory.eINSTANCE.createProjectLocale(); projectLocale.setLocale((Locale) PropertiesFactory.eINSTANCE.createFromString(PropertiesPackage.Literals.LOCALE, locale)); LOGGER.info("Adding ProjectLocale {} to {}",projectLocale.getName(), version.fullPath()); PropertyResourceUtil.addNewLocale(projectLocale, input.getObject()); } } private ListModel<String> createListModel(IModel<ProjectVersion> parent) { ProjectVersion projectVersion = parent.getObject(); EList<ProjectLocale> children = projectVersion.getChildren(); List<String> list = new ArrayList<String>(children.size()); for (ProjectLocale projectLocale : children) { if(projectLocale.isMaster()) //don't allow to delete the template continue; list.add(projectLocale.getName()); } return new ListModel<String>(list); } @Override public String getRequiredPermission() { String projectName = null; if(getDomainObject()!=null && getDomainObject().getParent()!=null) projectName = getDomainObject().getParent().getName(); return CommonPermissions.constructPermission(CommonPermissions.PROJECT,projectName,CommonPermissions.ACTION_CONFIG); } } private String safeGet(String s) { if(s!=null) return s; return ""; } }