package org.jboss.as.console.client.shared.help;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.jboss.as.console.client.shared.Preferences;
import org.jboss.as.console.client.shared.runtime.charts.Column;
import org.jboss.as.console.client.widgets.forms.ApplicationMetaData;
import org.jboss.as.console.client.widgets.forms.BeanMetaData;
import org.jboss.as.console.client.widgets.forms.PropertyBinding;
import org.jboss.ballroom.client.widgets.forms.FormAdapter;
import org.jboss.dmr.client.ModelNode;
import org.jboss.dmr.client.ModelType;
import org.jboss.dmr.client.Property;
import org.jboss.dmr.client.dispatch.DispatchAsync;
import org.jboss.dmr.client.dispatch.impl.DMRAction;
import org.jboss.dmr.client.dispatch.impl.DMRResponse;
import javax.inject.Inject;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static org.jboss.dmr.client.ModelDescriptionConstants.*;
/**
* @author Heiko Braun
* @date 6/8/11
*/
public class HelpSystem {
private DispatchAsync dispatcher;
private ApplicationMetaData propertyMetaData;
class Lookup
{
String detypedName;
String javaName;
Lookup(String detypedName, String javaName) {
this.detypedName = detypedName;
this.javaName = javaName;
}
public String getDetypedName() {
return detypedName;
}
public String getJavaName() {
return javaName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Lookup)) return false;
Lookup lookup = (Lookup) o;
if (!detypedName.equals(lookup.detypedName)) return false;
if (!javaName.equals(lookup.javaName)) return false;
return true;
}
@Override
public int hashCode() {
int result = detypedName.hashCode();
result = 31 * result + javaName.hashCode();
return result;
}
}
@Inject
public HelpSystem(DispatchAsync dispatcher, ApplicationMetaData propertyMetaData) {
this.dispatcher = dispatcher;
this.propertyMetaData = propertyMetaData;
}
public void getAttributeDescriptions(
ModelNode resourceAddress,
final FormAdapter form,
final AsyncCallback<List<FieldDesc>> callback)
{
final ModelNode operation = new ModelNode();
operation.get(OP).set(READ_RESOURCE_DESCRIPTION_OPERATION);
operation.get(ADDRESS).set(resourceAddress);
operation.get(RECURSIVE).set(true);
operation.get(LOCALE).set(getLocale());
// build field name list
List<String> formItemNames = form.getFormItemNames();
BeanMetaData beanMetaData = propertyMetaData.getBeanMetaData(form.getConversionType());
List<PropertyBinding> bindings = beanMetaData.getProperties();
final LinkedList<Lookup> fieldNames = new LinkedList<Lookup>();
for(String name : formItemNames)
{
for(PropertyBinding binding : bindings)
{
if(!binding.isKey() && binding.getJavaName().equals(name)) {
String[] splitDetypedNames = binding.getDetypedName().split("/");
// last one in the path is the attribute name
Lookup lookup = new Lookup(splitDetypedNames[splitDetypedNames.length - 1], binding.getJavaName());
if(!fieldNames.contains(lookup))
fieldNames.add(lookup);
}
}
}
dispatcher.execute(new DMRAction(operation), new AsyncCallback<DMRResponse>() {
@Override
public void onSuccess(DMRResponse result) {
ModelNode response = result.get();
if(response.isFailure())
{
Log.debug(response.toString());
onFailure(new Exception(response.getFailureDescription()));
}
else
{
LinkedList<FieldDesc> fields = new LinkedList<FieldDesc>();
ModelNode payload = response.get(RESULT);
ModelNode descriptionModel = null;
if(ModelType.LIST.equals(payload.getType()))
descriptionModel = payload.asList().get(0);
else
descriptionModel = payload;
matchSubElements(descriptionModel, fieldNames, fields);
callback.onSuccess(fields);
}
}
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
});
}
public interface AddressCallback
{
ModelNode getAddress();
}
private String getLocale() {
String locale = Preferences.get(Preferences.Key.LOCALE) != null ?
Preferences.get(Preferences.Key.LOCALE) : "en";
return locale;
}
public void getMetricDescriptions(
AddressCallback address,
Column[] columns,
final AsyncCallback<List<FieldDesc>> callback)
{
final List<Lookup> attributeNames = new LinkedList<Lookup>();
for(Column c : columns)
attributeNames.add(new Lookup(c.getDeytpedName(), c.getLabel()));
final ModelNode operation = address.getAddress();
operation.get(OP).set(READ_RESOURCE_DESCRIPTION_OPERATION);
operation.get(LOCALE).set(getLocale());
dispatcher.execute(new DMRAction(operation), new AsyncCallback<DMRResponse>() {
@Override
public void onSuccess(DMRResponse result) {
ModelNode response = result.get();
if(response.isFailure())
{
Log.debug(response.toString());
onFailure(new Exception(response.getFailureDescription()));
}
else
{
LinkedList<FieldDesc> fields = new LinkedList<FieldDesc>();
ModelNode payload = response.get(RESULT);
ModelNode descriptionModel = null;
if(ModelType.LIST.equals(payload.getType()))
descriptionModel = payload.asList().get(0);
else
descriptionModel = payload;
matchSubElements(descriptionModel, attributeNames, fields);
callback.onSuccess(fields);
}
}
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
});
}
private static void matchSubElements(ModelNode descriptionModel, List<Lookup> fieldNames, LinkedList<FieldDesc> fields) {
if (descriptionModel.hasDefined(RESULT))
descriptionModel = descriptionModel.get(RESULT).asObject();
try {
// match attributes
if(descriptionModel.hasDefined(ATTRIBUTES))
{
List<Property> elements = descriptionModel.get(ATTRIBUTES).asPropertyList();
for(Lookup lookup : fieldNames)
{
for(Property element : elements)
{
String childName = element.getName();
ModelNode value = element.getValue();
if(lookup.getDetypedName().equals(childName))
{
FieldDesc desc = new FieldDesc(lookup.getJavaName(), value.get("description").asString());
if(value.hasDefined("expressions-allowed"))
{
desc.setSupportExpressions(value.get("expressions-allowed").asBoolean());
}
if(!fields.contains(desc))
fields.add(desc);
}
}
}
}
if(fieldNames.isEmpty())
return;
// visit child elements
if (descriptionModel.hasDefined("children")) {
//List<Property> children = descriptionModel.get("children").asPropertyList();
ModelNode childrenModel = descriptionModel.get(CHILDREN);
Set<String> children = childrenModel.keys();
for(String child : children )
{
ModelNode childDesc = childrenModel.get(child);
ModelNode desc = childDesc.get(MODEL_DESCRIPTION);
if(desc.isDefined()) // TOOD: How can this happen?
{
for (Property modDescProp : desc.asPropertyList()) {
matchSubElements(childDesc.get(MODEL_DESCRIPTION, modDescProp.getName()), fieldNames, fields);
// exit early
if(fieldNames.isEmpty())
return;
}
}
}
}
} catch (IllegalArgumentException e) {
Log.error("Failed to read help descriptionModel", e);
}
}
}