/*
* Copyright (c) 2009-2011 Lockheed Martin Corporation
*
* Licensed 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.eurekastreams.web.client.ui.common.form.elements.userassociation;
import java.io.Serializable;
import java.util.ArrayList;
import org.eurekastreams.server.domain.MembershipCriteria;
import org.eurekastreams.server.domain.SystemSettings;
import org.eurekastreams.web.client.events.EventBus;
import org.eurekastreams.web.client.events.MembershipCriteriaAddedEvent;
import org.eurekastreams.web.client.events.MembershipCriteriaRemovedEvent;
import org.eurekastreams.web.client.events.MembershipCriteriaVerificationFailureEvent;
import org.eurekastreams.web.client.events.MembershipCriteriaVerificationNoUsersEvent;
import org.eurekastreams.web.client.events.Observer;
import org.eurekastreams.web.client.jsni.WidgetJSNIFacade;
import org.eurekastreams.web.client.jsni.WidgetJSNIFacadeImpl;
import org.eurekastreams.web.client.model.MembershipCriteriaVerificationModel;
import org.eurekastreams.web.client.model.requests.MembershipCriteriaVerificationRequest;
import org.eurekastreams.web.client.ui.Session;
import org.eurekastreams.web.client.ui.common.form.elements.FormElement;
import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
/**
* User association form element.
*/
public class UserAssociationFormElement extends FlowPanel implements FormElement
{
/** Group description. */
private static final String GROUP_DESC = "Enter the name of the LDAP group.";
/** Attribute description. */
private static final String ATTR_DESC = "Specify an LDAP attribute (in the format: attribute=value)";
/** Message for verification with no users. */
private static final String VERIFY_NO_USERS_MESSAGE = //\n
"No matching groups or users were found. Please check your query and search again.";
/** Message for verification failures. */
private static final String VERIFY_FAILURE_MESSAGE = //\n
"There was an error processing your request. Please check your query and search again.";
/** The access groups panel. */
private FlowPanel accessGroupsPanel;
/** Textbox containing the LDAP group. */
private TextBox membershipCriteria;
/** Radio button to search LDAP by group name. */
private RadioButton group;
/** Verifying label. */
private Label verifying;
/** Verify button. */
private Anchor verifyButton;
/** Required label. */
private Label requiredLabel;
/** Results label. */
private Label results;
/** Description. */
private Label description;
/** Radio button to search LDAP by attribute. */
private RadioButton attr;
/** The JSNI Facade. */
private final WidgetJSNIFacade jSNIFacade = new WidgetJSNIFacadeImpl();
/** Membership criteria items. */
private final ArrayList<MembershipCriteria> items = new ArrayList<MembershipCriteria>();
/**
* Constructor.
*
* @param inSettings
* the system settings.
*/
public UserAssociationFormElement(final SystemSettings inSettings)
{
setupWidgets();
setupEvents();
for (MembershipCriteria criterion : inSettings.getMembershipCriteria())
{
addMembershipCriteria(criterion);
}
}
/**
* Builds the UI.
*/
private void setupWidgets()
{
this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formUserAssociation());
Label label = new Label("Access List");
label.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formLabel());
Label topDesc = new Label("Specify the users that you want to have access to Eureka.");
topDesc.addStyleName(StaticResourceBundle.INSTANCE.coreCss().topLabel());
topDesc.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formInstructions());
requiredLabel = new Label();
requiredLabel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().requiredFormLabel());
requiredLabel.setText("(required)");
FlowPanel radioButtons = new FlowPanel();
radioButtons.addStyleName(StaticResourceBundle.INSTANCE.coreCss().radioButtonContainer());
Label searchLDAPBy = new Label("Search by LDAP");
searchLDAPBy.addStyleName(StaticResourceBundle.INSTANCE.coreCss().searchLdapLabel());
searchLDAPBy.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formLabel());
group = new RadioButton("ldap", "Group Name");
attr = new RadioButton("ldap", "Attribute");
group.setValue(true);
group.addStyleName(StaticResourceBundle.INSTANCE.coreCss().groupCheckBox());
radioButtons.add(searchLDAPBy);
radioButtons.add(group);
radioButtons.add(attr);
membershipCriteria = new TextBox();
// Need to do this to fix an especially nasty IE CSS bug (input margin inheritance)
final SimplePanel textWrapper = new SimplePanel();
textWrapper.addStyleName(StaticResourceBundle.INSTANCE.coreCss().inputWrapper());
textWrapper.add(membershipCriteria);
verifyButton = new Anchor("");
verifyButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().addButtonSubmit());
verifyButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formButton());
verifying = new Label("");
verifying.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formVerifyingSpinny());
verifying.setVisible(false);
results = new Label();
description = new Label(GROUP_DESC);
description.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formInstructions());
this.add(results);
this.add(label);
this.add(topDesc);
this.add(requiredLabel);
this.add(radioButtons);
this.add(textWrapper);
this.add(verifyButton);
this.add(verifying);
this.add(description);
accessGroupsPanel = new FlowPanel();
accessGroupsPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().accessGroups());
this.add(accessGroupsPanel);
}
/**
* Wires up events.
*/
private void setupEvents()
{
EventBus eventBus = Session.getInstance().getEventBus();
// update the UI when group / attribute search is selected.
group.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
description.setText(GROUP_DESC);
}
});
attr.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
description.setText(ATTR_DESC);
}
});
// make verification request to the server when user clicks verify button / presses enter
verifyButton.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent inArg0)
{
initiateVerification();
}
});
membershipCriteria.addKeyUpHandler(new KeyUpHandler()
{
public void onKeyUp(final KeyUpEvent ev)
{
if (ev.getNativeKeyCode() == KeyCodes.KEY_ENTER)
{
initiateVerification();
}
}
});
// got verification result: criterion matched some users
eventBus.addObserver(MembershipCriteriaAddedEvent.class, new Observer<MembershipCriteriaAddedEvent>()
{
public void update(final MembershipCriteriaAddedEvent ev)
{
membershipCriteria.setText("");
results.setVisible(false);
verifyingDone();
addMembershipCriteria(ev.getMembershipCriteria());
}
});
// got verification result: criterion matched no users
eventBus.addObserver(MembershipCriteriaVerificationNoUsersEvent.class,
new Observer<MembershipCriteriaVerificationNoUsersEvent>()
{
public void update(final MembershipCriteriaVerificationNoUsersEvent event)
{
results.setVisible(true);
results.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formErrorBox());
results.setText(VERIFY_NO_USERS_MESSAGE);
verifyingDone();
}
});
// got verification result: query failed
eventBus.addObserver(MembershipCriteriaVerificationFailureEvent.class,
new Observer<MembershipCriteriaVerificationFailureEvent>()
{
public void update(final MembershipCriteriaVerificationFailureEvent event)
{
results.setVisible(true);
results.setText(VERIFY_FAILURE_MESSAGE);
verifyingDone();
}
});
}
/**
* Do the verification.
*/
private void initiateVerification()
{
verifying.setVisible(true);
verifyButton.setVisible(false);
requiredLabel.setVisible(false);
results.setVisible(false);
MembershipCriteriaVerificationModel.getInstance().fetch(
new MembershipCriteriaVerificationRequest(membershipCriteria.getText(), group.getValue()), false);
}
/**
* Actions taken when a verification finishes.
*/
private void verifyingDone()
{
verifying.setVisible(false);
verifyButton.setVisible(true);
requiredLabel.setVisible(true);
}
/**
* @return the form element key.
*/
public String getKey()
{
return "ldapGroups";
}
/**
* @return the value of the form element.
*/
public Serializable getValue()
{
return items;
}
/**
* Handles an error.
*
* @param errMessage
* the error message.
*/
public void onError(final String errMessage)
{
}
/**
* Handles success.
*/
public void onSuccess()
{
}
/**
* Add membership criteria.
*
* @param criterion
* the membership criteria.
*/
public void addMembershipCriteria(final MembershipCriteria criterion)
{
items.add(criterion);
final MembershipCriteriaItemComposite membershipCriteriaComposite = new MembershipCriteriaItemComposite(
criterion.getCriteria());
accessGroupsPanel.add(membershipCriteriaComposite);
membershipCriteriaComposite.addDeleteClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
if (jSNIFacade.confirm("Are you sure you want to delete '" + criterion.getCriteria() + "'"))
{
accessGroupsPanel.remove(membershipCriteriaComposite);
Session.getInstance().getEventBus().notifyObservers(new MembershipCriteriaRemovedEvent(criterion));
items.remove(criterion);
}
}
});
}
}