Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/AssociationHelper.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/AssociationHelper.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/AssociationHelper.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/AssociationHelper.java Mon Oct 28 17:03:53 2013 @@ -39,6 +39,10 @@ public class AssociationHelper { private Set<?> m_activeSelection; private SelectionListener m_activeSelectionListener; + public void addAssociatedItem(RepositoryObject item) { + m_associatedItems.add(item); + } + public void removeAssociatedItem(RepositoryObject item) { m_associatedItems.remove(item); }
Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java Mon Oct 28 17:03:53 2013 @@ -31,7 +31,7 @@ import org.apache.ace.client.repository. import org.apache.ace.webui.NamedObject; import org.apache.ace.webui.UIExtensionFactory; import org.apache.ace.webui.domain.NamedObjectFactory; -import org.apache.ace.webui.vaadin.AssociationRemover; +import org.apache.ace.webui.vaadin.AssociationManager; import org.apache.ace.webui.vaadin.EditWindow; import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; @@ -41,6 +41,12 @@ import org.osgi.service.event.EventHandl import com.vaadin.data.Item; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.event.Transferable; +import com.vaadin.event.dd.DragAndDropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.TargetDetails; +import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.event.dd.acceptcriteria.Or; import com.vaadin.terminal.Resource; import com.vaadin.terminal.ThemeResource; import com.vaadin.ui.Button; @@ -53,21 +59,76 @@ import com.vaadin.ui.themes.Reindeer; /** * Provides a custom table for displaying artifacts, features and so on. */ -abstract class BaseObjectPanel<REPO_OBJ extends RepositoryObject, REPO extends ObjectRepository<REPO_OBJ>> extends TreeTable implements EventHandler { +abstract class BaseObjectPanel<REPO_OBJ extends RepositoryObject, REPO extends ObjectRepository<REPO_OBJ>, LEFT_ASSOC_REPO_OBJ extends RepositoryObject, RIGHT_ASSOC_REPO_OBJ extends RepositoryObject> extends TreeTable implements EventHandler { + /** + * Drop handler for associations. + */ + private class AssociationDropHandler implements DropHandler { + + public void drop(DragAndDropEvent event) { + Transferable transferable = event.getTransferable(); + + TargetDetails targetDetails = event.getTargetDetails(); + if (!(transferable instanceof Table.TableTransferable) || !(targetDetails instanceof Table.AbstractSelectTargetDetails)) { + return; + } + + Table.TableTransferable tt = (Table.TableTransferable) transferable; + Table.AbstractSelectTargetDetails ttd = (Table.AbstractSelectTargetDetails) targetDetails; + + // get the active selection, but only if we drag from the same table + Set<?> selection = m_associations.isActiveTable(tt.getSourceComponent()) ? m_associations.getActiveSelection() : null; + + Object fromItemId = tt.getItemId(); + Object toItemId = ttd.getItemIdOver(); + + if (tt.getSourceComponent().equals(m_leftTable)) { + REPO_OBJ rightObject = getFromId((String) toItemId); + + if (selection != null) { + for (Object item : selection) { + createLeftSideAssociation(m_leftTable.getFromId((String) item), rightObject); + } + } + else { + createLeftSideAssociation(m_leftTable.getFromId((String) fromItemId), rightObject); + } + } + else if (tt.getSourceComponent().equals(m_rightTable)) { + REPO_OBJ leftObject = getFromId((String) toItemId); + + if (selection != null) { + for (Object item : selection) { + createRightSideAssociation(leftObject, m_rightTable.getFromId((String) item)); + } + } + else { + createRightSideAssociation(leftObject, m_rightTable.getFromId((String) fromItemId)); + } + } + } + + public AcceptCriterion getAcceptCriterion() { + return new Or(VerticalLocationIs.MIDDLE); + } + } /** * Provides a generic remove item button. */ - private class RemoveItemButton extends Button { - public RemoveItemButton(final REPO repository, final REPO_OBJ object) { + protected class RemoveItemButton extends Button { + public RemoveItemButton(final REPO_OBJ object) { super("x"); setStyleName(Reindeer.BUTTON_SMALL); setDescription("Delete " + getDisplayName(object)); addListener(new Button.ClickListener() { public void buttonClick(ClickEvent event) { + // Give some clue that this click is being processed... + event.getButton().setEnabled(false); + try { - repository.remove(object); + getRepository().remove(object); } catch (Exception e) { // ACE-246: notify user when the removal failed! @@ -82,8 +143,8 @@ abstract class BaseObjectPanel<REPO_OBJ /** * Provides a generic remove-link (or association) button. */ - private class RemoveLinkButton extends Button { - public RemoveLinkButton(final REPO_OBJ object, final Table toLeft, final Table toRight) { + protected class RemoveLinkButton extends Button { + public RemoveLinkButton(final REPO_OBJ object) { super("-"); setStyleName(Reindeer.BUTTON_SMALL); setData(object.getDefinition()); @@ -93,18 +154,19 @@ abstract class BaseObjectPanel<REPO_OBJ addListener(new Button.ClickListener() { public void buttonClick(ClickEvent event) { + // Give some clue that this click is being processed... + event.getButton().setEnabled(false); + Set<?> selection = m_associations.getActiveSelection(); if (selection != null) { - if (m_associations.isActiveTable(toLeft)) { - for (Object item : selection) { - RepositoryObject selected = m_associations.lookupInActiveSelection(item); - removeLeftSideAssociation(object, selected); + if (m_associations.isActiveTable(m_leftTable)) { + for (Object itemId : selection) { + removeLeftSideAssociation(m_leftTable.getFromId((String) itemId), object); } } - else if (m_associations.isActiveTable(toRight)) { - for (Object item : selection) { - RepositoryObject selected = m_associations.lookupInActiveSelection(item); - removeRightSideAssocation(object, selected); + else if (m_associations.isActiveTable(m_rightTable)) { + for (Object itemId : selection) { + removeRightSideAssocation(object, m_rightTable.getFromId((String) itemId)); } } } @@ -180,14 +242,14 @@ abstract class BaseObjectPanel<REPO_OBJ /** Empirically determined (most common width appears to be 36px). */ protected static final int FIXED_COLUMN_WIDTH = 36; - private final AssociationHelper m_associations; - protected final AssociationRemover m_associationRemover; + protected final AssociationHelper m_associations; + protected final AssociationManager m_associationManager; private final List<UIExtensionFactoryHolder> m_extensionFactories; private final String m_extensionPoint; - private Table m_leftTable; - private Table m_rightTable; + protected BaseObjectPanel<LEFT_ASSOC_REPO_OBJ, ?, ?, ?> m_leftTable; + protected BaseObjectPanel<RIGHT_ASSOC_REPO_OBJ, ?, ?, ?> m_rightTable; /** * Creates a new {@link BaseObjectPanel} instance. @@ -204,12 +266,12 @@ abstract class BaseObjectPanel<REPO_OBJ * <code>true</code> if double clicking an row in this table should show an editor, <code>false</code> to * disallow editing. */ - public BaseObjectPanel(final AssociationHelper associations, final AssociationRemover associationRemover, + public BaseObjectPanel(final AssociationHelper associations, final AssociationManager associationRemover, final String name, final String extensionPoint, final boolean hasEdit) { super(name + "s"); m_associations = associations; - m_associationRemover = associationRemover; + m_associationManager = associationRemover; m_extensionFactories = new ArrayList<UIExtensionFactoryHolder>(); m_extensionPoint = extensionPoint; @@ -266,12 +328,7 @@ abstract class BaseObjectPanel<REPO_OBJ synchronized (getApplication()) { if (isSupportedEntity(entity)) { - try { - handleEvent(topic, entity, event); - } - finally { - refreshRenderedCells(); - } + handleEvent(topic, entity, event); } else if (RepositoryAdmin.TOPIC_REFRESH.equals(topic) || RepositoryAdmin.TOPIC_LOGIN.equals(topic)) { populate(); @@ -322,36 +379,67 @@ abstract class BaseObjectPanel<REPO_OBJ } /** - * Sets the left-side table, that defines the left-hand side of the assocations of the entities. + * Sets the tables that are associated this this panel. * * @param leftTable - * the table to set, can be <code>null</code>. + * the left-side table to associate with, can be <code>null</code>; + * @param rightTable + * the right-side table to associate with, can be <code>null</code>. */ - public final void setLeftTable(Table leftTable) { + public final void setAssociatedTables(BaseObjectPanel<LEFT_ASSOC_REPO_OBJ, ?, ?, ?> leftTable, BaseObjectPanel<RIGHT_ASSOC_REPO_OBJ, ?, ?, ?> rightTable) { m_leftTable = leftTable; + m_rightTable = rightTable; + + setDropHandler(new AssociationDropHandler()); } /** - * Sets the right-side table, that defines the right-hand side of the assocations of the entities. + * Creates the left-hand side associations for a given repository object. * - * @param rightTable - * the table to set, can be <code>null</code>. + * @param leftObject + * the (left-hand side) repository object to create the associations for. + * @param rightObject + * the repository object to create the left-hand side associations; */ - public final void setRightTable(Table rightTable) { - m_rightTable = rightTable; + final void createLeftSideAssociation(LEFT_ASSOC_REPO_OBJ leftObject, REPO_OBJ rightObject) { + if (doCreateLeftSideAssociation(leftObject, rightObject)) { + m_associations.addAssociatedItem(rightObject); + refreshRowCache(); + if (m_leftTable != null) { + m_leftTable.refreshRowCache(); + } + } + } + + /** + * Creates the right-hand side associations for a given repository object. + * + * @param leftObject + * the repository object to create the right-hand side associations; + * @param rightObject + * the (right-hand side) repository object to create the associations for. + */ + final void createRightSideAssociation(REPO_OBJ leftObject, RIGHT_ASSOC_REPO_OBJ rightObject) { + if (doCreateRightSideAssociation(leftObject, rightObject)) { + m_associations.addAssociatedItem(leftObject); + refreshRowCache(); + if (m_rightTable != null) { + m_rightTable.refreshRowCache(); + } + } } /** * Removes the left-hand side associations for a given repository object. * - * @param object - * the repository object to remove the left-hand side associations; - * @param other + * @param leftObject * the (left-hand side) repository object to remove the associations for. + * @param rightObject + * the repository object to remove the left-hand side associations; */ - final void removeLeftSideAssociation(REPO_OBJ object, RepositoryObject other) { - if (doRemoveLeftSideAssociation(object, other)) { - m_associations.removeAssociatedItem(object); + final void removeLeftSideAssociation(LEFT_ASSOC_REPO_OBJ leftObject, REPO_OBJ rightObject) { + if (doRemoveLeftSideAssociation(leftObject, rightObject)) { + m_associations.removeAssociatedItem(rightObject); refreshRowCache(); if (m_leftTable != null) { m_leftTable.refreshRowCache(); @@ -362,14 +450,14 @@ abstract class BaseObjectPanel<REPO_OBJ /** * Removes the right-hand side associations for a given repository object. * - * @param object + * @param leftObject * the repository object to remove the right-hand side associations; - * @param other + * @param rightObject * the (right-hand side) repository object to remove the associations for. */ - final void removeRightSideAssocation(REPO_OBJ object, RepositoryObject other) { - if (doRemoveRightSideAssociation(object, other)) { - m_associations.removeAssociatedItem(object); + final void removeRightSideAssocation(REPO_OBJ leftObject, RIGHT_ASSOC_REPO_OBJ rightObject) { + if (doRemoveRightSideAssociation(leftObject, rightObject)) { + m_associations.removeAssociatedItem(leftObject); refreshRowCache(); if (m_rightTable != null) { m_rightTable.refreshRowCache(); @@ -383,26 +471,29 @@ abstract class BaseObjectPanel<REPO_OBJ * @param object * the repository object to add, cannot be <code>null</code>. */ - protected void add(REPO_OBJ object) { - Item item = addItem(object.getDefinition()); - if (item != null) { - setChildrenAllowed(object.getDefinition(), false); + protected final void add(REPO_OBJ object) { + String itemId = object.getDefinition(); + String parentId = getParentId(object); + + if ((parentId != null) && !containsId(parentId)) { + Item parentItem = addItem(parentId); + if (parentItem != null) { + populateParentItem(object, parentId, parentItem); + } + } + Item item = addItem(itemId); + if (item != null) { populateItem(object, item); - setItemIcon(object); } - } - protected void updateItemIcon(Object itemId) { - REPO_OBJ obj = getFromId((String) itemId); - setItemIcon(obj); - } - - protected void setItemIcon(REPO_OBJ object) { - if (object != null) { - Resource icon = getWorkingStateIcon(object); - setItemIcon(object.getDefinition(), icon); + if (parentId != null) { + setParent(itemId, parentId); + setCollapsed(parentId, false); + setItemIcon(object); } + + setChildrenAllowed(itemId, false); } protected abstract EditWindow createEditor(NamedObject object, List<UIExtensionFactory> extensions); @@ -437,28 +528,6 @@ abstract class BaseObjectPanel<REPO_OBJ } /** - * Factory method to create a remove-item button. - * - * @param object - * the repository object to create the remove-item button for, cannot be <code>null</code>. - * @return a button, can be <code>null</code> if removal of this repository object is not supported. - */ - protected Button createRemoveItemButton(REPO_OBJ object) { - return new RemoveItemButton(getRepository(), object); - } - - /** - * Factory method to create a remove-link button. - * - * @param object - * the repository object to create the remove-link button for, cannot be <code>null</code>. - * @return a button, can be <code>null</code> if remove-link is not supported. - */ - protected Button createUnlinkButton(REPO_OBJ object) { - return new RemoveLinkButton(object, m_leftTable, m_rightTable); - } - - /** * Defines the table columns for this panel. */ protected void defineTableColumns() { @@ -478,28 +547,46 @@ abstract class BaseObjectPanel<REPO_OBJ } /** + * @param leftObject + * @param rightObject + * @return + */ + protected boolean doCreateLeftSideAssociation(LEFT_ASSOC_REPO_OBJ leftObject, REPO_OBJ rightObject) { + return m_leftTable != null; + } + + /** + * @param leftObject + * @param rightObject + * @return + */ + protected boolean doCreateRightSideAssociation(REPO_OBJ leftObject, RIGHT_ASSOC_REPO_OBJ rightObject) { + return m_rightTable != null; + } + + /** * Does the actual removal of the left-hand side associations for a given repository object. * - * @param object - * the repository object to remove the left-hand side associations; - * @param other + * @param leftObject * the (left-hand side) repository object to remove the associations for. + * @param rightObject + * the repository object to remove the left-hand side associations; * @return <code>true</code> if the associations were removed, <code>false</code> if not. */ - protected boolean doRemoveLeftSideAssociation(REPO_OBJ object, RepositoryObject other) { + protected boolean doRemoveLeftSideAssociation(LEFT_ASSOC_REPO_OBJ leftObject, REPO_OBJ rightObject) { return m_leftTable != null; } /** * Does the actual removal of the right-hand side associations for a given repository object. * - * @param object + * @param leftObject * the repository object to remove the right-hand side associations; - * @param other + * @param rightObject * the (right-hand side) repository object to remove the associations for. * @return <code>true</code> if the associations were removed, <code>false</code> if not. */ - protected boolean doRemoveRightSideAssociation(REPO_OBJ object, RepositoryObject other) { + protected boolean doRemoveRightSideAssociation(REPO_OBJ leftObject, RIGHT_ASSOC_REPO_OBJ rightObject) { return m_rightTable != null; } @@ -525,6 +612,26 @@ abstract class BaseObjectPanel<REPO_OBJ } /** + * @param object + * @return a display name for the parent of the given repository object, cannot be <code>null</code>. + */ + protected String getParentDisplayName(REPO_OBJ object) { + return object.getDefinition(); + } + + /** + * Determines the parent Id of a given repository object. + * + * @param object + * the repository object to determine the parent for, cannot be <code>null</code>. + * @return the ID of the parent for the given repository object, or <code>null</code> in case no parent could be + * determined. + */ + protected String getParentId(REPO_OBJ object) { + return null; + } + + /** * Returns the actual repository for objects. * * @return the actual repository for obtaining the repository objects, cannot be <code>null</code>. @@ -593,13 +700,45 @@ abstract class BaseObjectPanel<REPO_OBJ protected abstract void populateItem(REPO_OBJ object, Item item); /** + * Populates the given table item with information about the parent for a given repository object. + * + * @param object + * the repository object to take the information from, cannot be <code>null</code>; + * @param parentId + * the ID of the parent, cannot be <code>null</code>; + * @param item + * the table item to populate, cannot be <code>null</code>. + */ + protected void populateParentItem(REPO_OBJ object, String parentId, Item item) { + item.getItemProperty(OBJECT_NAME).setValue(getParentDisplayName(object)); + item.getItemProperty(OBJECT_DESCRIPTION).setValue(""); + // we *must* set a non-null icon for the parent as well to ensure that the tree-table open/collapse icon is + // rendered properly... + setItemIcon(parentId, createIconResource("resource_workingstate_unchanged")); + } + + /** * Removes a given repository object from this table. * * @param object * the repository object to remove, cannot be <code>null</code>. */ - protected void remove(REPO_OBJ object) { - removeItem(object.getDefinition()); + protected final void remove(REPO_OBJ object) { + String itemID = object.getDefinition(); + Object parentID = getParent(itemID); + + if (removeItem(itemID)) { + if (!hasChildren(parentID)) { + removeItem(parentID); + } + } + } + + protected final void setItemIcon(REPO_OBJ object) { + if (object != null) { + Resource icon = getWorkingStateIcon(object); + setItemIcon(object.getDefinition(), icon); + } } /** @@ -608,7 +747,7 @@ abstract class BaseObjectPanel<REPO_OBJ * @param object * the repository object to update, cannot be <code>null</code>. */ - protected void update(REPO_OBJ object) { + protected final void update(REPO_OBJ object) { if (object != null) { String definition = object.getDefinition(); if (definition != null) { @@ -620,6 +759,11 @@ abstract class BaseObjectPanel<REPO_OBJ } } + protected final void updateItemIcon(Object itemId) { + REPO_OBJ obj = getFromId((String) itemId); + setItemIcon(obj); + } + /** * Returns all repository objects. * Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java Mon Oct 28 17:03:53 2013 @@ -26,17 +26,17 @@ import org.apache.ace.client.repository. import org.apache.ace.client.repository.object.DistributionObject; import org.apache.ace.client.repository.object.Feature2DistributionAssociation; import org.apache.ace.client.repository.object.FeatureObject; -import org.apache.ace.client.repository.object.TargetObject; import org.apache.ace.client.repository.repository.DistributionRepository; +import org.apache.ace.client.repository.stateful.StatefulTargetObject; import org.apache.ace.webui.UIExtensionFactory; -import org.apache.ace.webui.vaadin.AssociationRemover; +import org.apache.ace.webui.vaadin.AssociationManager; import com.vaadin.data.Item; /** * Provides an object panel for displaying distributions. */ -public abstract class DistributionsPanel extends BaseObjectPanel<DistributionObject, DistributionRepository> { +public abstract class DistributionsPanel extends BaseObjectPanel<DistributionObject, DistributionRepository, FeatureObject, StatefulTargetObject> { /** * Creates a new {@link DistributionsPanel} instance. @@ -46,25 +46,37 @@ public abstract class DistributionsPanel * @param associationRemover * the helper for removing associations. */ - public DistributionsPanel(AssociationHelper associations, AssociationRemover associationRemover) { + public DistributionsPanel(AssociationHelper associations, AssociationManager associationRemover) { super(associations, associationRemover, "Distribution", UIExtensionFactory.EXTENSION_POINT_VALUE_DISTRIBUTION, true /* hasEdit */); } @Override - protected boolean doRemoveLeftSideAssociation(DistributionObject object, RepositoryObject other) { - List<Feature2DistributionAssociation> associations = object.getAssociationsWith((FeatureObject) other); + protected boolean doCreateLeftSideAssociation(FeatureObject feature, DistributionObject distribution) { + m_associationManager.createFeature2DistributionAssociation(feature, distribution); + return true; + } + + @Override + protected boolean doCreateRightSideAssociation(DistributionObject distribution, StatefulTargetObject target) { + m_associationManager.createDistribution2TargetAssociation(distribution, target); + return true; + } + + @Override + protected boolean doRemoveLeftSideAssociation(FeatureObject feature, DistributionObject object) { + List<Feature2DistributionAssociation> associations = object.getAssociationsWith(feature); for (Feature2DistributionAssociation association : associations) { - m_associationRemover.removeAssociation(association); + m_associationManager.removeAssociation(association); } return true; } @Override - protected boolean doRemoveRightSideAssociation(DistributionObject object, RepositoryObject other) { - List<Distribution2TargetAssociation> associations = object.getAssociationsWith((TargetObject) other); + protected boolean doRemoveRightSideAssociation(DistributionObject object, StatefulTargetObject target) { + List<Distribution2TargetAssociation> associations = object.getAssociationsWith(target.getTargetObject()); for (Distribution2TargetAssociation association : associations) { - m_associationRemover.removeAssociation(association); + m_associationManager.removeAssociation(association); } return true; } @@ -97,7 +109,7 @@ public abstract class DistributionsPanel protected void populateItem(DistributionObject distribution, Item item) { item.getItemProperty(OBJECT_NAME).setValue(distribution.getName()); item.getItemProperty(OBJECT_DESCRIPTION).setValue(distribution.getDescription()); - item.getItemProperty(ACTION_UNLINK).setValue(createUnlinkButton(distribution)); - item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(distribution)); + item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(distribution)); + item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(distribution)); } } Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java Mon Oct 28 17:03:53 2013 @@ -29,14 +29,14 @@ import org.apache.ace.client.repository. import org.apache.ace.client.repository.object.FeatureObject; import org.apache.ace.client.repository.repository.FeatureRepository; import org.apache.ace.webui.UIExtensionFactory; -import org.apache.ace.webui.vaadin.AssociationRemover; +import org.apache.ace.webui.vaadin.AssociationManager; import com.vaadin.data.Item; /** * Provides an object panel for displaying features. */ -public abstract class FeaturesPanel extends BaseObjectPanel<FeatureObject, FeatureRepository> { +public abstract class FeaturesPanel extends BaseObjectPanel<FeatureObject, FeatureRepository, ArtifactObject, DistributionObject> { /** * Creates a new {@link FeaturesPanel} instance. @@ -46,28 +46,40 @@ public abstract class FeaturesPanel exte * @param associationRemover * the helper for removing associations. */ - public FeaturesPanel(AssociationHelper associations, AssociationRemover associationRemover) { + public FeaturesPanel(AssociationHelper associations, AssociationManager associationRemover) { super(associations, associationRemover, "Feature", UIExtensionFactory.EXTENSION_POINT_VALUE_FEATURE, true); } @Override - protected boolean doRemoveLeftSideAssociation(FeatureObject object, RepositoryObject other) { - List<Artifact2FeatureAssociation> associations = object.getAssociationsWith((ArtifactObject) other); + protected boolean doCreateLeftSideAssociation(ArtifactObject artifact, FeatureObject feature) { + m_associationManager.createArtifact2FeatureAssociation(artifact, feature); + return true; + } + + @Override + protected boolean doCreateRightSideAssociation(FeatureObject feature, DistributionObject distribution) { + m_associationManager.createFeature2DistributionAssociation(feature, distribution); + return true; + } + + @Override + protected boolean doRemoveLeftSideAssociation(ArtifactObject artifact, FeatureObject feature) { + List<Artifact2FeatureAssociation> associations = feature.getAssociationsWith(artifact); for (Artifact2FeatureAssociation association : associations) { - m_associationRemover.removeAssociation(association); + m_associationManager.removeAssociation(association); } return true; } @Override - protected boolean doRemoveRightSideAssociation(FeatureObject object, RepositoryObject other) { - List<Feature2DistributionAssociation> associations = object.getAssociationsWith((DistributionObject) other); + protected boolean doRemoveRightSideAssociation(FeatureObject feature, DistributionObject distribution) { + List<Feature2DistributionAssociation> associations = feature.getAssociationsWith(distribution); for (Feature2DistributionAssociation association : associations) { - m_associationRemover.removeAssociation(association); + m_associationManager.removeAssociation(association); } return true; } - + @Override protected String getDisplayName(FeatureObject object) { return object.getName(); @@ -96,7 +108,7 @@ public abstract class FeaturesPanel exte protected void populateItem(FeatureObject feature, Item item) { item.getItemProperty(OBJECT_NAME).setValue(feature.getName()); item.getItemProperty(OBJECT_DESCRIPTION).setValue(feature.getDescription()); - item.getItemProperty(ACTION_UNLINK).setValue(createUnlinkButton(feature)); - item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(feature)); + item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(feature)); + item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(feature)); } } Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java Mon Oct 28 17:03:53 2013 @@ -87,7 +87,8 @@ public abstract class MainActionToolbar } /** - * @param e the exception to handle. + * @param e + * the exception to handle. */ private void handleIOException(IOException e) { getWindow().showNotification("Warning", @@ -98,7 +99,8 @@ public abstract class MainActionToolbar /** * Does the actual logout of the user. * - * @throws IOException in case of I/O problems during the logout. + * @throws IOException + * in case of I/O problems during the logout. */ private void logout() throws IOException { getRepositoryAdmin().logout(true /* force */); @@ -147,7 +149,8 @@ public abstract class MainActionToolbar } /** - * @param e the exception to handle. + * @param e + * the exception to handle. */ private void handleIOException(IOException e) { getWindow().showNotification("Retrieve failed", @@ -158,7 +161,8 @@ public abstract class MainActionToolbar /** * Does the actual retrieval of the latest version. * - * @throws IOException in case of I/O problems during the retrieve. + * @throws IOException + * in case of I/O problems during the retrieve. */ private void retrieveData() throws IOException { getRepositoryAdmin().checkout(); @@ -208,7 +212,8 @@ public abstract class MainActionToolbar } /** - * @param e the exception to handle. + * @param e + * the exception to handle. */ private void handleIOException(IOException e) { getWindow().showNotification("Revert failed", @@ -218,7 +223,8 @@ public abstract class MainActionToolbar /** * Does the actual revert of changes. * - * @throws IOException in case of problems during I/O exception. + * @throws IOException + * in case of problems during I/O exception. */ private void revertChanges() throws IOException { getRepositoryAdmin().revert(); @@ -263,7 +269,8 @@ public abstract class MainActionToolbar /** * Does the actual commit of changes. * - * @throws IOException in case of I/O problems during the commit. + * @throws IOException + * in case of I/O problems during the commit. */ private void commitChanges() throws IOException { getRepositoryAdmin().commit(); @@ -278,84 +285,67 @@ public abstract class MainActionToolbar private Button m_revertButton; private Button m_logoutButton; - private final DependencyManager m_manager; private final ConcurrentHashMap<ServiceReference, UIExtensionFactory> m_extensions = new ConcurrentHashMap<ServiceReference, UIExtensionFactory>(); private final User m_user; - private HorizontalLayout m_extraComponentBar; + private HorizontalLayout m_extraComponentBar; /** * Creates a new {@link MainActionToolbar} instance. - * @param user - * @param manager * - * @param showLogoutButton <code>true</code> if a logout button should be shown, <code>false</code> if it should not. + * @param user + * @param manager + * + * @param showLogoutButton + * <code>true</code> if a logout button should be shown, <code>false</code> if it should not. */ public MainActionToolbar(User user, DependencyManager manager, boolean showLogoutButton) { super(5, 1); - m_user = user; - m_manager = manager; + m_user = user; m_showLogoutButton = showLogoutButton; setWidth("100%"); setSpacing(true); - + initComponent(); } + /** + * {@inheritDoc} + */ + public void handleEvent(org.osgi.service.event.Event event) { + boolean modified = false; + try { + modified = getRepositoryAdmin().isModified(); + } + catch (IOException e) { + getWindow().showNotification("Communication failed!", + "Failed to communicate with the server.<br />Reason: " + e.getMessage(), + Notification.TYPE_ERROR_MESSAGE); + } + + m_storeButton.setEnabled(modified); + m_revertButton.setEnabled(modified); + } + public void init(org.apache.felix.dm.Component component) { - DependencyManager dm = component.getDependencyManager(); - component.add(dm.createServiceDependency() + DependencyManager dm = component.getDependencyManager(); + component.add(dm.createServiceDependency() .setService(UIExtensionFactory.class, "(" + UIExtensionFactory.EXTENSION_POINT_KEY + "=" + UIExtensionFactory.EXTENSION_POINT_VALUE_MENU + ")") .setCallbacks("add", "remove") .setRequired(false) .setInstanceBound(true) - ); - } - - public void add(ServiceReference ref, UIExtensionFactory factory) { - m_extensions.put(ref, factory); - setExtraComponents(); + ); } - private void setExtraComponents() { - m_extraComponentBar.removeAllComponents(); - for (Component c : getExtraComponents()) { - m_extraComponentBar.addComponent(c); - } - } - - public void remove(ServiceReference ref, UIExtensionFactory factory) { - m_extensions.remove(ref); + protected final void add(ServiceReference ref, UIExtensionFactory factory) { + m_extensions.put(ref, factory); setExtraComponents(); } /** - * {@inheritDoc} - */ - public void handleEvent(org.osgi.service.event.Event event) { - String topic = event.getTopic(); - if (RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic) || RepositoryAdmin.TOPIC_REFRESH.equals(topic) - || RepositoryAdmin.TOPIC_LOGIN.equals(topic)) { - - boolean modified = false; - try { - modified = getRepositoryAdmin().isModified(); - } - catch (IOException e) { - getWindow().showNotification("Communication failed!", - "Failed to communicate with the server.<br />Reason: " + e.getMessage(), - Notification.TYPE_ERROR_MESSAGE); - } - - m_storeButton.setEnabled(modified); - m_revertButton.setEnabled(modified); - } - } - - /** * Called after a commit/store has taken place, allows additional UI-updates to be performed. * * @throws IOException @@ -383,11 +373,26 @@ public abstract class MainActionToolbar */ protected abstract void doAfterRevert() throws IOException; + protected final List<Component> getExtraComponents() { + List<Component> result = new ArrayList<Component>(); + for (UIExtensionFactory f : m_extensions.values()) { + Map<String, Object> context = new HashMap<String, Object>(); + context.put("user", m_user); + result.add(f.create(context)); + } + return result; + } + /** * @return a repository admin instance, never <code>null</code>. */ protected abstract RepositoryAdmin getRepositoryAdmin(); + protected final void remove(ServiceReference ref, UIExtensionFactory factory) { + m_extensions.remove(ref); + setExtraComponents(); + } + /** * Initializes this component. */ @@ -420,14 +425,11 @@ public abstract class MainActionToolbar // button to appear at the right side of the screen.... setColumnExpandRatio(3, 5); } - - protected List<Component> getExtraComponents() { - List<Component> result = new ArrayList<Component>(); - for (UIExtensionFactory f : m_extensions.values()) { - Map<String, Object> context = new HashMap<String, Object>(); - context.put("user", m_user); - result.add(f.create(context)); + + private void setExtraComponents() { + m_extraComponentBar.removeAllComponents(); + for (Component c : getExtraComponents()) { + m_extraComponentBar.addComponent(c); } - return result; } } Added: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/StatusLine.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/StatusLine.java?rev=1536411&view=auto ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/StatusLine.java (added) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/StatusLine.java Mon Oct 28 17:03:53 2013 @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ace.webui.vaadin.component; + +import org.apache.ace.client.repository.RepositoryObject; +import org.apache.ace.client.repository.object.Artifact2FeatureAssociation; +import org.apache.ace.client.repository.object.ArtifactObject; +import org.apache.ace.client.repository.object.Distribution2TargetAssociation; +import org.apache.ace.client.repository.object.DistributionObject; +import org.apache.ace.client.repository.object.Feature2DistributionAssociation; +import org.apache.ace.client.repository.object.FeatureObject; +import org.apache.ace.client.repository.object.TargetObject; +import org.apache.ace.webui.NamedObject; +import org.apache.ace.webui.domain.NamedObjectFactory; +import org.osgi.service.event.EventHandler; + +import com.vaadin.ui.Label; + +/** + * Denotes a status line in which a short summary of the latest actions in the UI are displayed. + */ +@SuppressWarnings("unchecked") +public class StatusLine extends Label implements EventHandler { + + /** + * Creates a new {@link StatusLine} instance. + */ + public StatusLine() { + setImmediate(true); + } + + @Override + public void handleEvent(org.osgi.service.event.Event event) { + String topic = event.getTopic(); + RepositoryObject entity = (RepositoryObject) event.getProperty(RepositoryObject.EVENT_ENTITY); + + String type = getType(topic); + String action = getAction(topic); + String name = getName(entity); + + if (type != null) { + if (name != null) { + setStatus("%s '%s' %s...", type, name, action); + } + else if (action != null) { + setStatus("%s %s...", type, action); + } + } + } + + /** + * Sets the status to the given message. + * + * @param msg + * the message; + * @param args + * the (optional) arguments. + */ + public void setStatus(String msg, Object... args) { + setValue(String.format(msg, args)); + } + + /** + * @param topic + * @return + */ + private String getAction(String topic) { + if (topic.endsWith("/" + RepositoryObject.TOPIC_REMOVED_SUFFIX)) { + return "removed"; + } + else if (topic.endsWith("/" + RepositoryObject.TOPIC_ADDED_SUFFIX)) { + return "added"; + } + else if (topic.endsWith("/" + RepositoryObject.TOPIC_CHANGED_SUFFIX)) { + return "changed"; + } + return null; + } + + private String getName(RepositoryObject entity) { + NamedObject obj = NamedObjectFactory.getNamedObject(entity); + if (obj == null) { + return null; + } + String name = obj.getName(); + return name == null || "".equals(name.trim()) ? null : name; + } + + private String getType(String topic) { + if (topic.contains(ArtifactObject.TOPIC_ENTITY_ROOT)) { + return "Artifact"; + } + else if (topic.contains(FeatureObject.TOPIC_ENTITY_ROOT)) { + return "Feature"; + } + else if (topic.contains(DistributionObject.TOPIC_ENTITY_ROOT)) { + return "Distribution"; + } + else if (topic.contains(TargetObject.TOPIC_ENTITY_ROOT)) { + return "Target"; + } + else if (topic.contains(Artifact2FeatureAssociation.TOPIC_ENTITY_ROOT) + || topic.contains(Feature2DistributionAssociation.TOPIC_ENTITY_ROOT) + || topic.contains(Distribution2TargetAssociation.TOPIC_ENTITY_ROOT)) { + return "Association"; + } + return null; + } +} Propchange: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/StatusLine.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java?rev=1536411&r1=1536410&r2=1536411&view=diff ============================================================================== --- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java (original) +++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java Mon Oct 28 17:03:53 2013 @@ -28,7 +28,7 @@ import org.apache.ace.client.repository. import org.apache.ace.client.repository.stateful.StatefulTargetObject; import org.apache.ace.client.repository.stateful.StatefulTargetRepository; import org.apache.ace.webui.UIExtensionFactory; -import org.apache.ace.webui.vaadin.AssociationRemover; +import org.apache.ace.webui.vaadin.AssociationManager; import com.vaadin.data.Item; import com.vaadin.terminal.Resource; @@ -38,7 +38,7 @@ import com.vaadin.ui.Embedded; /** * Provides an object panel for displaying (stateful) targets. */ -public abstract class TargetsPanel extends BaseObjectPanel<StatefulTargetObject, StatefulTargetRepository> { +public abstract class TargetsPanel extends BaseObjectPanel<StatefulTargetObject, StatefulTargetRepository, DistributionObject, RepositoryObject> { private static final String REGISTRATION_STATE_ICON = "regStateIcon"; private static final String PROVISIONING_STATE_ICON = "provStateIcon"; @@ -52,17 +52,10 @@ public abstract class TargetsPanel exten * @param associationRemover * the helper for removing associations. */ - public TargetsPanel(AssociationHelper associations, AssociationRemover associationRemover) { + public TargetsPanel(AssociationHelper associations, AssociationManager associationRemover) { super(associations, associationRemover, "Target", UIExtensionFactory.EXTENSION_POINT_VALUE_TARGET, true /* hasEdit */); } - @Override - protected Button createRemoveItemButton(StatefulTargetObject object) { - Button b = super.createRemoveItemButton(object); - b.setEnabled(object.isRegistered()); - return b; - } - protected void defineTableColumns() { addContainerProperty(ICON, Resource.class, null, "", null, ALIGN_CENTER); addContainerProperty(OBJECT_NAME, String.class, null); @@ -78,17 +71,23 @@ public abstract class TargetsPanel exten setColumnWidth(REGISTRATION_STATE_ICON, ICON_WIDTH); setColumnWidth(STORE_STATE_ICON, ICON_WIDTH); setColumnWidth(PROVISIONING_STATE_ICON, ICON_WIDTH); - + setColumnCollapsible(ICON, false); setColumnCollapsible(ACTION_UNLINK, false); setColumnCollapsible(ACTION_DELETE, false); } @Override - protected boolean doRemoveLeftSideAssociation(StatefulTargetObject object, RepositoryObject other) { - List<Distribution2TargetAssociation> associations = object.getAssociationsWith((DistributionObject) other); + protected boolean doCreateLeftSideAssociation(DistributionObject distribution, StatefulTargetObject target) { + m_associationManager.createDistribution2TargetAssociation(distribution, target); + return true; + } + + @Override + protected boolean doRemoveLeftSideAssociation(DistributionObject distribution, StatefulTargetObject target) { + List<Distribution2TargetAssociation> associations = target.getAssociationsWith(distribution); for (Distribution2TargetAssociation association : associations) { - m_associationRemover.removeAssociation(association); + m_associationManager.removeAssociation(association); } return true; } @@ -131,10 +130,28 @@ public abstract class TargetsPanel exten item.getItemProperty(REGISTRATION_STATE_ICON).setValue(getRegistrationStateIcon(target)); item.getItemProperty(STORE_STATE_ICON).setValue(getStoreStateIcon(target)); item.getItemProperty(PROVISIONING_STATE_ICON).setValue(getProvisioningStateIcon(target)); - item.getItemProperty(ACTION_UNLINK).setValue(createUnlinkButton(target)); + item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(target)); item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(target)); } + /** + * + * @param entity + * @return + */ + private StatefulTargetObject asStatefulTargetObject(RepositoryObject entity) { + if (entity instanceof StatefulTargetObject) { + return (StatefulTargetObject) entity; + } + return getFromId(((TargetObject) entity).getDefinition()); + } + + private RemoveItemButton createRemoveItemButton(StatefulTargetObject object) { + RemoveItemButton b = new RemoveItemButton(object); + b.setEnabled(object.isRegistered()); + return b; + } + private Embedded getProvisioningStateIcon(StatefulTargetObject object) { String name = object.getProvisioningState().name(); Resource res = createIconResource("target_provisioning_" + name); @@ -160,16 +177,4 @@ public abstract class TargetsPanel exten Resource res = createIconResource("target_store_" + name); return createIcon(name, res); } - - /** - * - * @param entity - * @return - */ - private StatefulTargetObject asStatefulTargetObject(RepositoryObject entity) { - if (entity instanceof StatefulTargetObject) { - return (StatefulTargetObject) entity; - } - return getFromId(((TargetObject) entity).getDefinition()); - } }
