/** * Copyright (C) 2011 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.web.toolkit.client.data.item; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.bonitasoft.web.toolkit.client.data.APIID; import org.bonitasoft.web.toolkit.client.data.item.attribute.ItemAttribute; import org.bonitasoft.web.toolkit.client.data.item.attribute.ValidationException; import org.bonitasoft.web.toolkit.client.data.item.attribute.modifier.Modifier; import org.bonitasoft.web.toolkit.client.data.item.attribute.validator.Validator; /** * This class is the super class of all Items definitions. * <p> * To define a new IItem type, just create a class that extends ItemDefinition.<br> * Then, you will have to override the function beginning with <i>define....</i> and in each overridden functions, you will call the corresponding setters. * <p> * There are some functions for which the override is not mandatory but you can override any define function. * <p> * <b>It's highly recommended to define attributes names using <code>public static final</code> strings</b> * * @author Séverin Moussel */ public abstract class ItemDefinition<E extends IItem> { public ItemDefinition() { setToken(defineToken()); defineAttributes(); setAPIUrl(defineAPIUrl()); definePrimaryKeys(); defineDeploys(); } // /////////////////////////////////////////////////////////////////////////////////////////////////// // Token // /////////////////////////////////////////////////////////////////////////////////////////////////// private String token = null; /** * This function must be override to define the token to use to access to the current view. */ protected abstract String defineToken(); /** * @param token * the token to set */ public final void setToken(final String token) { this.token = token; } /** * @return the token */ public final String getToken() { return this.token; } // /////////////////////////////////////////////////////////////////////////////////////////////////// // SINGULAR RESOURCE URL // /////////////////////////////////////////////////////////////////////////////////////////////////// private String APIUrl = null; public final String getAPIUrl() { return this.APIUrl; } protected final void setAPIUrl(final String url) { this.APIUrl = url; } /** * This function must be overridden to define the singular version of the resource URL. * <p> * This function must call this.setSingularResourceUrl(...) * <p> * <b>Example</b> :<br> * <code>this.setUrl("/API/organization/user");</code> */ protected abstract String defineAPIUrl(); // /////////////////////////////////////////////////////////////////////////////////////////////////// // ATTRIBUTES // /////////////////////////////////////////////////////////////////////////////////////////////////// private final LinkedHashMap<String, ItemAttribute> attributes = new LinkedHashMap<String, ItemAttribute>(); private final ArrayList<String> primaryKeys = new ArrayList<String>(); /** * Create and save a new attribute for the current item type. * <p> * <b>Example :</b><br> * <code>final ItemAttribute firstName = this.createAttribute(this.FIRSTNAME, ItemAttribute.TYPE.STRING);</code> * * @param name * The name of the attribute * @param type * The type of the attribute. Must be one of ItemAttribute.TYPE.xxx * @return This function returns the Attribute created to allow to add other details on it. */ public ItemAttribute createAttribute(final String name, final ItemAttribute.TYPE type) { final ItemAttribute attribute = new ItemAttribute(name, type); this.attributes.put(name, attribute); return attribute; } /** * This function must be overridden to define the attributes of an Item. * <p> * Defining attributes is made by calling several <i>createAttribute()</i> * <p> * <b>Example :</b><br> * <code> * final ItemAttribute firstName = this.createAttribute(this.FIRSTNAME, ItemAttribute.TYPE.STRING);<br> * firstName.setLabel("Firstname");<br> * firstName.setTooltip("Enter your firstname");<br> * firstName.setTableSortable(true);<br> * firstName.setFormEditable(true);<br> * <br> * final ItemAttribute firstName = this.createAttribute(this.LASTNAME, ItemAttribute.TYPE.STRING);<br> * firstName.setLabel("Lastname");<br> * firstName.setTooltip("Enter your lastname");<br> * firstName.setTableSortable(true);<br> * firstName.setFormEditable(true);<br> * ... * </code> */ protected abstract void defineAttributes(); public final ArrayList<ItemAttribute> getAttributes() { return new ArrayList<ItemAttribute>(this.attributes.values()); } protected abstract void definePrimaryKeys(); protected final void setPrimaryKeys(final String... primaryKeys) { this.primaryKeys.clear(); for (final String key : primaryKeys) { this.primaryKeys.add(key); // Create the attribute if it's missing if (!this.attributes.containsKey(key)) { createAttribute(key, ItemAttribute.TYPE.ITEM_ID); } } } public final ArrayList<String> getPrimaryKeys() { return this.primaryKeys; } /** * Retrieve an attribute by its name. * * @param name * The name of the attribute * @return This function returns the attribute or null if there is no attribute with the defined name. */ public final ItemAttribute getAttribute(final String name) { return this.attributes.get(name); } public final boolean containsAttribute(final String attributeName) { return this.attributes.containsKey(attributeName); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DEPLOYS // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private final Map<String, ItemDefinition<?>> deploys = new HashMap<String, ItemDefinition<?>>(); protected void defineDeploys() { // No deploys by default } /** * Declare an attribute as deployable. * * @param attributeName * The name of the deployable attribute. * @param definition * The ItemDefinition of the item contained in the deployed attribute. */ protected final void declareDeployable(final String attributeName, final ItemDefinition<?> definition) { this.deploys.put(attributeName, definition); } public final ItemDefinition<?> getDeployDefinition(final String attributeName) { return this.deploys.containsKey(attributeName) ? this.deploys.get(attributeName) : Definitions.get(DummyItemDefinition.TOKEN); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // VALIDATORS AND MODIFIERS // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Get the validators in a map <attribute name, list of validators> */ public final Map<String, List<Validator>> getValidators() { final Map<String, List<Validator>> validators = new HashMap<String, List<Validator>>(); for (final ItemAttribute attribute : getAttributes()) { validators.put(attribute.getName(), attribute.getValidators()); } return validators; } /** * Get the Modifiers in a map <attribute name, list of modifiers> */ public final Map<String, List<Modifier>> getInputModifiers() { final Map<String, List<Modifier>> modifiers = new HashMap<String, List<Modifier>>(); for (final ItemAttribute attribute : getAttributes()) { modifiers.put(attribute.getName(), attribute.getInputModifiers()); } return modifiers; } /** * Get the Modifiers in a map <attribute name, list of modifiers> */ public final Map<String, List<Modifier>> getOutputModifiers() { final Map<String, List<Modifier>> modifiers = new HashMap<String, List<Modifier>>(); for (final ItemAttribute attribute : getAttributes()) { modifiers.put(attribute.getName(), attribute.getOutputModifiers()); } return modifiers; } // /////////////////////////////////////////////////////////////////////////////////////////////////// // AUTOMATICALY INSTANCIATE ITEM AND ITEM DEPENDENT TOOLS // /////////////////////////////////////////////////////////////////////////////////////////////////// /** * This function create a new empty Item * * @return This function returns the new Item */ abstract protected E _createItem(); public final E createItem() { try { return this.createItem((Map<String, String>) null); } catch (final ValidationException e) { // DO NOTHING : this can't fail due to validation because validation is disabled. return null; } } public final E createItem(final Map<String, String> attributes) throws ValidationException { final E item = _createItem(); if (attributes != null) { item.setAttributes(attributes); } return item; } public final E createItem(IItem sourceItem) { return sourceItem == null ? null : createItem(sourceItem.getAttributes()); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MAKE APIID // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public final APIID makeAPIID(final String... id) { return makeAPIID(Arrays.asList(id)); } public final APIID makeAPIID(final Long... ids) { final APIID apiid = APIID.makeAPIID(ids); apiid.setItemDefinition(this); return apiid; } public final APIID makeAPIID(final List<String> ids) { final APIID apiid = APIID.makeAPIID(ids); apiid.setItemDefinition(this); return apiid; } }