/**
* Copyright 2014 Microsoft Open Technologies Inc.
*
* 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 com.microsoftopentechnologies.intellij.serviceexplorer.azure.mobileservice;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.intellij.openapi.application.ApplicationManager;
import com.microsoftopentechnologies.intellij.forms.CustomAPIForm;
import com.microsoftopentechnologies.intellij.forms.JobForm;
import com.microsoftopentechnologies.intellij.forms.TableForm;
import com.microsoftopentechnologies.intellij.forms.ViewLogForm;
import com.microsoftopentechnologies.intellij.helpers.UIHelper;
import com.microsoftopentechnologies.intellij.helpers.azure.AzureCmdException;
import com.microsoftopentechnologies.intellij.helpers.azure.AzureManager;
import com.microsoftopentechnologies.intellij.helpers.azure.AzureRestAPIHelper;
import com.microsoftopentechnologies.intellij.helpers.azure.AzureRestAPIManager;
import com.microsoftopentechnologies.intellij.model.CustomAPI;
import com.microsoftopentechnologies.intellij.model.Job;
import com.microsoftopentechnologies.intellij.model.Service;
import com.microsoftopentechnologies.intellij.model.Table;
import com.microsoftopentechnologies.intellij.serviceexplorer.Node;
import com.microsoftopentechnologies.intellij.serviceexplorer.NodeActionEvent;
import com.microsoftopentechnologies.intellij.serviceexplorer.NodeActionListener;
import javax.swing.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MobileServiceNode extends Node {
private static final String ICON_PATH = "service.png";
public static final String TABLES = "Tables";
public static final String CUSTOM_APIS = "Custom APIs";
public static final String SCHEDULED_JOBS = "Scheduled Jobs";
protected Service mobileService;
protected boolean childNodesLoaded = false;
protected Node tablesNode; // the parent node for all table nodes
protected Node customAPIsNode; // the parent node for all custom api nodes
protected Node jobsNode; // the parent node for all scheduled job nodes
public MobileServiceNode(Node parent, Service service) {
super(service.getName(), service.getName(), parent, ICON_PATH, true, true);
mobileService = service;
loadActions();
}
@Override
protected void refreshItems() throws AzureCmdException {
if (AzureRestAPIHelper.existsMobileService(mobileService.getName())) {
try {
AzureManager apiManager = AzureRestAPIManager.getManager();
UUID subscriptionId = mobileService.getSubcriptionId();
String serviceName = mobileService.getName();
if (isNodeRuntime()) {
// load tables
tablesNode = loadServiceNode(
apiManager.getTableList(subscriptionId, serviceName),
"_tables",
TABLES,
tablesNode,
TableNode.class,
Table.class);
// load custom APIs
customAPIsNode = loadServiceNode(
apiManager.getAPIList(subscriptionId, serviceName),
"_apis",
CUSTOM_APIS,
customAPIsNode,
CustomAPINode.class,
CustomAPI.class);
// load scheduled jobs
jobsNode = loadServiceNode(
apiManager.listJobs(subscriptionId, serviceName),
"_jobs",
SCHEDULED_JOBS,
jobsNode,
ScheduledJobNode.class,
Job.class);
}
} catch (NoSuchMethodException e) {
handleError(e);
} catch (IllegalAccessException e) {
handleError(e);
} catch (InvocationTargetException e) {
handleError(e);
} catch (InstantiationException e) {
handleError(e);
}
} else {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(null,
"The mobile service " + mobileService.getName() +
" could not be reached. Please try again after some time.",
"Microsoft Services Plugin",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
private void handleError(Exception e) {
UIHelper.showException(
"An error occurred while initializing the mobile service: " +
mobileService.getName(), e);
}
private <E, N> Node loadServiceNode(
List<E> nodesList,
String idSuffix,
String displayName,
Node parentNode,
Class<N> nodeClass,
Class<E> modelClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// create and add a new parent node for this item; we add the "node"
// variable as a child *before* adding the element nodes so that the
// service explorer tool window is automatically notified when they are
// added; if we called "addChildNode" after the children of "node"
// have been added then the service explorer tool window will not be
// notified of those new nodes
if (parentNode == null) {
parentNode = new Node(mobileService.getName() + idSuffix, displayName, this, null, false);
addChildNode(parentNode);
} else {
// clear the parent node since we are re-initializing it
parentNode.removeAllChildNodes();
}
// create child table nodes for this node
Constructor<N> constructor = nodeClass.getConstructor(Node.class, modelClass);
for (E nodeElement : nodesList) {
parentNode.addChildNode((Node) constructor.newInstance(parentNode, nodeElement));
}
return parentNode;
}
@Override
protected Map<String, Class<? extends NodeActionListener>> initActions() {
if (isNodeRuntime()) {
return ImmutableMap.of(
"Create table", CreateTableAction.class,
"Create API", CreateAPIAction.class,
"Create new job", CreateNewJobAction.class,
"Show log", ShowLogAction.class);
} else {// register the sole edit table action
addAction("Show log", new ShowLogAction());
return null;
}
}
@Override
protected void onNodeClick(NodeActionEvent event) {
// we attempt loading the services only if we haven't already
// loaded them
if (!childNodesLoaded) {
Futures.addCallback(load(), new FutureCallback<List<Node>>() {
@Override
public void onSuccess(List<Node> nodes) {
childNodesLoaded = true;
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
}
public Service getMobileService() {
return mobileService;
}
public class CreateTableAction extends NodeActionListener {
@Override
public void actionPerformed(NodeActionEvent e) {
TableForm form = new TableForm();
form.setServiceName(mobileService.getName());
form.setSubscriptionId(mobileService.getSubcriptionId());
form.setProject(getProject());
ArrayList<String> existingTables = new ArrayList<String>();
for (Table table : mobileService.getTables())
existingTables.add(table.getName());
form.setExistingTableNames(existingTables);
form.setAfterSave(new Runnable() {
@Override
public void run() {
// refresh the tables node
tablesNode.removeAllChildNodes();
try {
loadServiceNode(
AzureRestAPIManager.getManager().getTableList(
mobileService.getSubcriptionId(),
mobileService.getName()),
"_tables",
TABLES,
tablesNode,
TableNode.class,
Table.class);
} catch (NoSuchMethodException e1) {
handleError(e1);
} catch (IllegalAccessException e1) {
handleError(e1);
} catch (InvocationTargetException e1) {
handleError(e1);
} catch (InstantiationException e1) {
handleError(e1);
} catch (AzureCmdException e1) {
handleError(e1);
}
}
});
UIHelper.packAndCenterJDialog(form);
form.setVisible(true);
}
}
public class CreateAPIAction extends NodeActionListener {
@Override
public void actionPerformed(NodeActionEvent e) {
CustomAPIForm form = new CustomAPIForm();
form.setServiceName(mobileService.getName());
form.setSubscriptionId(mobileService.getSubcriptionId());
form.setProject(getProject());
form.setAfterSave(new Runnable() {
@Override
public void run() {
// refresh the apis node
customAPIsNode.removeAllChildNodes();
try {
loadServiceNode(
AzureRestAPIManager.getManager().getAPIList(
mobileService.getSubcriptionId(),
mobileService.getName()),
"_apis",
CUSTOM_APIS,
customAPIsNode,
CustomAPINode.class,
CustomAPI.class);
} catch (NoSuchMethodException e1) {
handleError(e1);
} catch (IllegalAccessException e1) {
handleError(e1);
} catch (InvocationTargetException e1) {
handleError(e1);
} catch (InstantiationException e1) {
handleError(e1);
} catch (AzureCmdException e1) {
handleError(e1);
}
}
});
UIHelper.packAndCenterJDialog(form);
form.setVisible(true);
}
}
public class CreateNewJobAction extends NodeActionListener {
@Override
public void actionPerformed(NodeActionEvent e) {
JobForm form = new JobForm();
form.setServiceName(mobileService.getName());
form.setSubscriptionId(mobileService.getSubcriptionId());
form.setTitle("Create new Job");
form.setAfterSave(new Runnable() {
@Override
public void run() {
// refresh the jobs node
jobsNode.removeAllChildNodes();
try {
loadServiceNode(
AzureRestAPIManager.getManager().listJobs(
mobileService.getSubcriptionId(),
mobileService.getName()),
"_jobs",
SCHEDULED_JOBS,
jobsNode,
ScheduledJobNode.class,
Job.class);
} catch (NoSuchMethodException e1) {
handleError(e1);
} catch (IllegalAccessException e1) {
handleError(e1);
} catch (InvocationTargetException e1) {
handleError(e1);
} catch (InstantiationException e1) {
handleError(e1);
} catch (AzureCmdException e1) {
handleError(e1);
}
}
});
UIHelper.packAndCenterJDialog(form);
form.setVisible(true);
}
}
public class ShowLogAction extends NodeActionListener {
@Override
public void actionPerformed(NodeActionEvent e) {
final ViewLogForm form = new ViewLogForm();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
form.queryLog(mobileService.getSubcriptionId(), mobileService.getName(), mobileService.getRuntime());
}
});
UIHelper.packAndCenterJDialog(form);
form.setVisible(true);
}
}
private boolean isNodeRuntime() {
return Service.NODE_RUNTIME.equals(mobileService.getRuntime());
}
}