Java tutorial
/* * Copyright 2017 Hewlett-Packard Development Company, L.P. * 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.hp.application.automation.tools.octane.configuration; import com.hp.mqm.client.MqmRestClient; import com.hp.mqm.client.exception.RequestException; import com.hp.mqm.client.model.*; import com.hp.octane.integrations.OctaneSDK; import com.hp.octane.integrations.dto.DTOFactory; import com.hp.octane.integrations.dto.general.CIServerInfo; import com.hp.octane.integrations.dto.pipelines.PipelineNode; import com.hp.application.automation.tools.octane.Messages; import com.hp.application.automation.tools.octane.client.JenkinsMqmRestClientFactory; import com.hp.application.automation.tools.octane.client.RetryModel; import com.hp.application.automation.tools.octane.model.ModelFactory; import hudson.ExtensionList; import hudson.model.Job; import jenkins.model.Jenkins; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.kohsuke.stapler.bind.JavaScriptMethod; import java.io.IOException; import java.util.*; import java.util.Map.Entry; import java.util.regex.Pattern; public class JobConfigurationProxy { private final static Logger logger = LogManager.getLogger(JobConfigurationProxy.class); private static final DTOFactory dtoFactory = DTOFactory.getInstance(); final private Job job; private RetryModel retryModel; private static final String PRODUCT_NAME = Messages.ServerName(); private static final String NOT_SPECIFIED = "-- Not specified --"; JobConfigurationProxy(Job job) { this.job = job; } @JavaScriptMethod public JSONObject createPipelineOnServer(JSONObject pipelineObject) throws IOException { JSONObject result = new JSONObject(); PipelineNode pipelineNode = ModelFactory.createStructureItem(job); CIServerInfo ciServerInfo = OctaneSDK.getInstance().getPluginServices().getServerInfo(); Long releaseId = pipelineObject.getLong("releaseId") != -1 ? pipelineObject.getLong("releaseId") : null; MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { Pipeline createdPipeline = client.createPipeline(ConfigurationService.getModel().getIdentity(), job.getName(), pipelineObject.getString("name"), pipelineObject.getLong("workspaceId"), releaseId, dtoFactory.dtoToJson(pipelineNode), dtoFactory.dtoToJson(ciServerInfo)); //WORKAROUND BEGIN //getting workspaceName - because the workspaceName is not returned from configuration API List<Workspace> workspaces = client .getWorkspaces(Collections.singletonList(createdPipeline.getWorkspaceId())); if (workspaces.size() != 1) { throw new ClientException("WorkspaceName could not be retrieved for workspaceId: " + createdPipeline.getWorkspaceId()); } //WORKAROUND END JSONObject pipelineJSON = fromPipeline(createdPipeline, workspaces.get(0)); //WORKAROUND BEGIN //all metadata have to be loaded in separate REST calls for this pipeline: releaseName, taxonomyNames and listFieldNames are not returned from configuration API enrichPipeline(pipelineJSON, client); //WORKAROUND END result.put("pipeline", pipelineJSON); JSONArray fieldsMetadata = getFieldMetadata(createdPipeline.getWorkspaceId(), client); result.put("fieldsMetadata", fieldsMetadata); } catch (RequestException e) { logger.warn("Failed to create pipeline", e); return error("Unable to create pipeline"); } catch (ClientException e) { logger.warn("Failed to create pipeline", e); return error(e.getMessage(), e.getLink()); } return result; } @JavaScriptMethod public JSONObject updatePipelineOnSever(JSONObject pipelineObject) throws IOException { JSONObject result = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { long pipelineId = pipelineObject.getLong("id"); LinkedList<Taxonomy> taxonomies = new LinkedList<>(); JSONArray taxonomyTags = pipelineObject.getJSONArray("taxonomyTags"); for (JSONObject jsonObject : toCollection(taxonomyTags)) { taxonomies.add(new Taxonomy(jsonObject.optLong("tagId"), jsonObject.getString("tagName"), new Taxonomy(jsonObject.optLong("tagTypeId"), jsonObject.getString("tagTypeName"), null))); } LinkedList<ListField> fields = new LinkedList<>(); JSONArray fieldTags = pipelineObject.getJSONArray("fieldTags"); for (JSONObject jsonObject : toCollection(fieldTags)) { List<ListItem> assignedValues = new LinkedList<>(); for (JSONObject value : toCollection(jsonObject.getJSONArray("values"))) { Long id; if (value.containsKey("id")) { id = value.getLong("id"); } else { id = null; } assignedValues.add(new ListItem(id, null, value.getString("name"), null)); } fields.add(new ListField(jsonObject.getString("name"), assignedValues)); } Pipeline pipeline = client.updatePipeline(ConfigurationService.getModel().getIdentity(), job.getName(), new Pipeline(pipelineId, pipelineObject.getString("name"), null, pipelineObject.getLong("workspaceId"), pipelineObject.getLong("releaseId"), taxonomies, fields, pipelineObject.getBoolean("ignoreTests"))); //WORKAROUND BEGIN //getting workspaceName - because the workspaceName is not returned from configuration API List<Workspace> workspaces = client.getWorkspaces(Collections.singletonList(pipeline.getWorkspaceId())); if (workspaces.size() != 1) { throw new ClientException( "WorkspaceName could not be retrieved for workspaceId: " + pipeline.getWorkspaceId()); } //WORKAROUND END JSONObject pipelineJSON = fromPipeline(pipeline, workspaces.get(0)); //WORKAROUND BEGIN //all metadata have to be loaded in separate REST calls for this pipeline: releaseName, taxonomyNames and listFieldNames are not returned from configuration API enrichPipeline(pipelineJSON, client); //WORKAROUND END result.put("pipeline", pipelineJSON); //Server might do partial sucess //So need to validate each item if it succedded or not //For now we add handling of duplicate pipeline name String originalName = pipelineObject.get("name").toString(); String updatedName = pipelineJSON.get("name").toString(); if (!originalName.equalsIgnoreCase(updatedName)) { JSONObject errorObj = new JSONObject(); errorObj.put("message", "Failed to update pipeline name. Make sure not to enter the name of an existing pipeline."); result.put("error", errorObj); } } catch (RequestException e) { logger.warn("Failed to update pipeline", e); return error("Unable to update pipeline"); } catch (ClientException e) { logger.warn("Failed to update pipeline", e); return error(e.getMessage(), e.getLink()); } return result; } @JavaScriptMethod public JSONObject deleteTests(JSONObject pipelineObject) throws IOException, InterruptedException { JSONObject result = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { long pipelineId = pipelineObject.getLong("id"); long workspaceId = pipelineObject.getLong("workspaceId"); client.deleteTestsFromPipelineNodes(job.getName(), pipelineId, workspaceId); result.put("Test deletion was succeful", ""); } catch (RequestException e) { logger.warn("Failed to delete tests", e); return error("Unable to delete tests"); } return result; } @JavaScriptMethod public JSONObject loadJobConfigurationFromServer() throws IOException { MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } JSONObject ret = new JSONObject(); JSONObject workspaces = new JSONObject(); JSONArray fieldsMetadata = new JSONArray(); try { JobConfiguration jobConfiguration = client .getJobConfiguration(ConfigurationService.getModel().getIdentity(), job.getName()); if (!jobConfiguration.getWorkspacePipelinesMap().isEmpty()) { Map<Long, List<Pipeline>> workspacesMap = jobConfiguration.getWorkspacePipelinesMap(); //WORKAROUND BEGIN //getting workspaceName - because the workspaceName is not returned from configuration API Map<Long, String> relatedWorkspaces = new HashMap<>(); List<Workspace> workspaceList = client.getWorkspaces(new LinkedList<>(workspacesMap.keySet())); for (Workspace workspace : workspaceList) { relatedWorkspaces.put(workspace.getId(), workspace.getName()); } //WORKAROUND END Map<Workspace, List<Pipeline>> sortedWorkspacesMap = new TreeMap<>(new Comparator<Workspace>() { @Override public int compare(final Workspace w1, final Workspace w2) { return w1.getName().compareTo(w2.getName()); } }); Comparator<Pipeline> pipelineComparator = new Comparator<Pipeline>() { @Override public int compare(final Pipeline p1, final Pipeline p2) { return p1.getName().compareTo(p2.getName()); } }; //create workspaces JSON Object for (Entry<Long, List<Pipeline>> workspacePipelines : workspacesMap.entrySet()) { Workspace relatedWorkspace = new Workspace(workspacePipelines.getKey(), relatedWorkspaces.get(workspacePipelines.getKey())); JSONObject relatedPipelinesJSON = new JSONObject(); for (Pipeline relatedPipeline : workspacePipelines.getValue()) { JSONObject pipelineJSON = fromPipeline(relatedPipeline, relatedWorkspace); relatedPipelinesJSON.put(String.valueOf(relatedPipeline.getId()), pipelineJSON); } JSONObject workspaceJSON = new JSONObject(); workspaceJSON.put("id", relatedWorkspace.getId()); workspaceJSON.put("name", relatedWorkspace.getName()); workspaceJSON.put("pipelines", relatedPipelinesJSON); workspaces.put(String.valueOf(relatedWorkspace.getId()), workspaceJSON); //inserting this workspace into sortedMap (sorted by workspaceName and by pipelineName, so that we can pick first workspace and its first pipeline as preselected values LinkedList<Pipeline> workspacePipelinesList = new LinkedList<Pipeline>( workspacePipelines.getValue()); Collections.sort(workspacePipelinesList, pipelineComparator); sortedWorkspacesMap.put(relatedWorkspace, workspacePipelinesList); } //create currentPipeline JSON Object //currently the first pipeline in the first workspace is picked Workspace preSelectedWorkspace = sortedWorkspacesMap.keySet().iterator().next(); Pipeline preSelectedPipeline = sortedWorkspacesMap.get(preSelectedWorkspace).get(0); JSONObject preSelectedPipelineJSON = fromPipeline(preSelectedPipeline, preSelectedWorkspace); //WORKAROUND BEGIN //all metadata have to be loaded in separate REST calls for this pipeline: releaseName, taxonomyNames and listFieldNames are not returned from configuration API enrichPipeline(preSelectedPipelineJSON, client); //WORKAROUND END ret.put("currentPipeline", preSelectedPipelineJSON); //retrieving metadata fields for preselected workspace fieldsMetadata = getFieldMetadata(preSelectedWorkspace.getId(), client); } ret.put("workspaces", workspaces); ret.put("fieldsMetadata", fieldsMetadata); } catch (RequestException e) { logger.warn("Failed to retrieve job configuration", e); return error("Unable to retrieve job configuration"); } return ret; } @JavaScriptMethod public JSONObject loadWorkspaceConfiguration(JSONObject pipelineJSON) { MqmRestClient client; JSONObject ret = new JSONObject(); try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { JSONArray fieldsMetadata = getFieldMetadata(pipelineJSON.getLong("workspaceId"), client); ret.put("fieldsMetadata", fieldsMetadata); enrichPipeline(pipelineJSON, client); ret.put("pipeline", pipelineJSON); } catch (RequestException e) { logger.warn("Failed to retrieve metadata for workspace", e); return error("Unable to retrieve metadata for workspace"); } return ret; } private JSONObject fromPipeline(final Pipeline pipeline, Workspace relatedWorkspace) { JSONObject pipelineJSON = new JSONObject(); pipelineJSON.put("id", pipeline.getId()); pipelineJSON.put("name", pipeline.getName()); pipelineJSON.put("releaseId", pipeline.getReleaseId() != null ? pipeline.getReleaseId() : -1); pipelineJSON.put("isRoot", pipeline.isRoot()); pipelineJSON.put("workspaceId", relatedWorkspace.getId()); pipelineJSON.put("workspaceName", relatedWorkspace.getName()); pipelineJSON.put("ignoreTests", pipeline.getIgnoreTests()); addTaxonomyTags(pipelineJSON, pipeline); addFields(pipelineJSON, pipeline); return pipelineJSON; } @JavaScriptMethod public JSONObject enrichPipeline(JSONObject pipelineJSON) { MqmRestClient client; JSONObject ret = new JSONObject(); try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { enrichPipeline(pipelineJSON, client); ret.put("pipeline", pipelineJSON); } catch (RequestException e) { logger.warn("Failed to retrieve metadata for pipeline", e); return error("Unable to retrieve metadata for pipeline"); } return ret; } private void enrichPipeline(JSONObject pipelineJSON, MqmRestClient client) { enrichRelease(pipelineJSON, client); enrichTaxonomies(pipelineJSON, client); enrichFields(pipelineJSON, client); } private void enrichRelease(JSONObject pipeline, MqmRestClient client) { long workspaceId = pipeline.getLong("workspaceId"); if (pipeline.containsKey("releaseId") && pipeline.getLong("releaseId") != -1) { long releaseId = pipeline.getLong("releaseId"); String releaseName = client.getRelease(releaseId, workspaceId).getName(); pipeline.put("releaseName", releaseName); } } private void enrichTaxonomies(JSONObject pipeline, MqmRestClient client) { JSONArray ret = new JSONArray(); if (pipeline.has("taxonomyTags")) { JSONArray taxonomyTags = pipeline.getJSONArray("taxonomyTags"); List<Long> taxonomyIdsList = new LinkedList<>(); for (int i = 0; i < taxonomyTags.size(); i++) { JSONObject taxonomy = taxonomyTags.getJSONObject(i); if (taxonomy.has("tagId")) { taxonomyIdsList.add(taxonomy.getLong("tagId")); } } List<Taxonomy> taxonomies = client.getTaxonomies(taxonomyIdsList, pipeline.getLong("workspaceId")); for (Taxonomy tax : taxonomies) { ret.add(tag(tax)); } } pipeline.put("taxonomyTags", ret); } private void enrichFields(JSONObject pipeline, MqmRestClient client) { JSONObject ret = new JSONObject(); if (pipeline.has("fields")) { long workspaceId = pipeline.getLong("workspaceId"); JSONObject pipelineFields = pipeline.getJSONObject("fields"); Iterator<?> keys = pipelineFields.keys(); //iteration over listFields while (keys.hasNext()) { String key = (String) keys.next(); if (pipelineFields.get(key) instanceof JSONArray) { List<Long> fieldTagsIdsList = new LinkedList<>(); //getting all ids assigned to listField for (JSONObject singleField : toCollection(pipelineFields.getJSONArray(key))) { fieldTagsIdsList.add(singleField.getLong("id")); } //retrieving names of assigned items if (fieldTagsIdsList.size() > 0) { List<ListItem> enrichedFields = client.getListItems(fieldTagsIdsList, workspaceId); JSONArray values = new JSONArray(); for (ListItem item : enrichedFields) { JSONObject value = new JSONObject(); value.put("id", item.getId()); value.put("name", item.getName()); values.add(value); } ret.put(key, values); } } } } pipeline.put("fields", ret); } private JSONArray getFieldMetadata(final long workspaceId, MqmRestClient client) { JSONArray fieldMetadataArray = new JSONArray(); List<FieldMetadata> metadataList = client.getFieldsMetadata(workspaceId); for (FieldMetadata fieldMetadata : metadataList) { fieldMetadataArray.add(fromFieldMetadata(fieldMetadata)); } return fieldMetadataArray; } private JSONObject fromFieldMetadata(FieldMetadata fieldMetadata) { JSONObject fieldMetadataJSON = new JSONObject(); fieldMetadataJSON.put("name", fieldMetadata.getName()); fieldMetadataJSON.put("listName", fieldMetadata.getListName()); fieldMetadataJSON.put("logicalListName", fieldMetadata.getLogicalListName()); fieldMetadataJSON.put("extensible", fieldMetadata.isExtensible()); fieldMetadataJSON.put("multiValue", fieldMetadata.isMultiValue()); fieldMetadataJSON.put("order", fieldMetadata.getOrder()); return fieldMetadataJSON; } @JavaScriptMethod public JSONObject searchListItems(String logicalListName, String term, long workspaceId, boolean multiValue, boolean extensible) { int defaultSize = 10; JSONObject ret = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { PagedList<ListItem> listItemPagedList = client.queryListItems(logicalListName, term, workspaceId, 0, defaultSize); List<ListItem> listItems = listItemPagedList.getItems(); boolean moreResults = listItemPagedList.getTotalCount() > listItems.size(); JSONArray retArray = new JSONArray(); if (moreResults) { retArray.add(createMoreResultsJson()); } if (!multiValue) { String quotedTerm = Pattern.quote(term.toLowerCase()); if (Pattern.matches(".*" + quotedTerm + ".*", NOT_SPECIFIED.toLowerCase())) { JSONObject notSpecifiedItemJson = new JSONObject(); notSpecifiedItemJson.put("id", -1); notSpecifiedItemJson.put("text", NOT_SPECIFIED); retArray.add(notSpecifiedItemJson); } } for (ListItem item : listItems) { if (!toBeFiltered(item)) { JSONObject itemJson = new JSONObject(); itemJson.put("id", item.getId()); itemJson.put("text", item.getName()); retArray.add(itemJson); } } // we shall use "if (extensible){}" on following line, but we do not have UI ready for the case: multiValue = true & extensible = true if (extensible && !multiValue) { //if exactly one item matches, we do not want to bother user with "new value" item if ((listItems.size() != 1) || (!listItems.get(0).getName().toLowerCase().equals(term.toLowerCase()))) { retArray.add(createNewValueJson("0")); } } ret.put("results", retArray); } catch (RequestException e) { logger.warn("Failed to retrieve list items", e); return error("Unable to retrieve job configuration"); } return ret; } private boolean toBeFiltered(ListItem item) { return (item.getLogicalName().equalsIgnoreCase("list_node.testing_tool_type.manual")); } @JavaScriptMethod public JSONObject searchReleases(String term, long workspaceId) { int defaultSize = 5; JSONObject ret = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { PagedList<Release> releasePagedList = client.queryReleases(term, workspaceId, 0, defaultSize); List<Release> releases = releasePagedList.getItems(); boolean moreResults = releasePagedList.getTotalCount() > releases.size(); JSONArray retArray = new JSONArray(); if (moreResults) { retArray.add(createMoreResultsJson()); } String quotedTerm = Pattern.quote(term.toLowerCase()); if (Pattern.matches(".*" + quotedTerm + ".*", NOT_SPECIFIED.toLowerCase())) { JSONObject notSpecifiedItemJson = new JSONObject(); notSpecifiedItemJson.put("id", -1); notSpecifiedItemJson.put("text", NOT_SPECIFIED); retArray.add(notSpecifiedItemJson); } for (Release release : releases) { JSONObject relJson = new JSONObject(); relJson.put("id", release.getId()); relJson.put("text", release.getName()); retArray.add(relJson); } ret.put("results", retArray); } catch (RequestException e) { logger.warn("Failed to retrieve releases", e); return error("Unable to retrieve releases"); } return ret; } @JavaScriptMethod public JSONObject searchWorkspaces(String term) { int defaultSize = 5; JSONObject ret = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { PagedList<Workspace> workspacePagedList = client.queryWorkspaces(term, 0, defaultSize); List<Workspace> workspaces = workspacePagedList.getItems(); boolean moreResults = workspacePagedList.getTotalCount() > workspaces.size(); JSONArray retArray = new JSONArray(); if (moreResults) { retArray.add(createMoreResultsJson()); } for (Workspace workspace : workspaces) { JSONObject relJson = new JSONObject(); relJson.put("id", workspace.getId()); relJson.put("text", workspace.getName()); retArray.add(relJson); } ret.put("results", retArray); } catch (RequestException e) { logger.warn("Failed to retrieve workspaces", e); return error("Unable to retrieve workspaces"); } return ret; } @JavaScriptMethod public JSONObject searchTaxonomies(String term, long workspaceId, JSONArray pipelineTaxonomies) { int defaultSize = 20; JSONObject ret = new JSONObject(); MqmRestClient client; try { client = createClient(); } catch (ClientException e) { logger.warn(PRODUCT_NAME + " connection failed", e); return error(e.getMessage(), e.getLink()); } try { //currently existing taxonomies on pipeline -> we need to show these options as disabled List<Long> pipelineTaxonomiesList = new LinkedList<>(); for (int i = 0; i < pipelineTaxonomies.size(); i++) { JSONObject pipelineTaxonomy = pipelineTaxonomies.getJSONObject(i); if (pipelineTaxonomy.containsKey("tagId") && pipelineTaxonomy.containsKey("tagTypeId")) { // we need to compare only taxonomies which already exist on server pipelineTaxonomiesList.add(pipelineTaxonomy.getLong("tagId")); } } //retrieving taxonomies from server PagedList<Taxonomy> foundTaxonomies = client.queryTaxonomies(term, workspaceId, 0, defaultSize); final List<Taxonomy> foundTaxonomiesList = foundTaxonomies.getItems(); boolean moreResults = foundTaxonomies.getTotalCount() > foundTaxonomiesList.size(); //creating map <TaxonomyCategoryID : Set<Taxonomy>> // for easier creating result JSON Map<Long, Set<Taxonomy>> taxonomyMap = new HashMap<>(); Map<Long, String> taxonomyCategories = new HashMap<>(); for (Taxonomy taxonomy : foundTaxonomiesList) { if (taxonomy.getRoot() != null) { if (taxonomyMap.containsKey(taxonomy.getRoot().getId())) { taxonomyMap.get(taxonomy.getRoot().getId()).add(taxonomy); } else { taxonomyMap.put(taxonomy.getRoot().getId(), new LinkedHashSet<>(Arrays.asList(taxonomy))); taxonomyCategories.put(taxonomy.getRoot().getId(), taxonomy.getRoot().getName()); } } } //writing result json JSONArray select2InputArray = new JSONArray(); JSONObject allTags = new JSONObject(); JSONObject tagTypesByName = new JSONObject(); JSONObject tagTypes = new JSONObject(); //show warning, that there are more results and user should filter more specific if (moreResults) { select2InputArray.add(createMoreResultsJson()); } for (Entry<Long, Set<Taxonomy>> taxonomyType : taxonomyMap.entrySet()) { Long tagTypeId = taxonomyType.getKey(); String tagTypeName = taxonomyCategories.get(tagTypeId); JSONArray childrenArray = new JSONArray(); JSONObject optgroup = new JSONObject(); optgroup.put("text", tagTypeName); //for tagTypesByName JSONObject tagTypeJson = new JSONObject(); tagTypeJson.put("tagTypeId", tagTypeId); tagTypeJson.put("tagTypeName", tagTypeName); JSONArray tagTypeByNameValues = new JSONArray(); for (Taxonomy tax : taxonomyType.getValue()) { //creating input format for select2, so that this structure does not have to be refactored in javascript JSONObject taxonomyJson = new JSONObject(); taxonomyJson.put("id", tax.getId()); taxonomyJson.put("text", tax.getName()); taxonomyJson.put("value", tax.getId()); if (pipelineTaxonomiesList.contains(tax.getId())) { taxonomyJson.put("disabled", "disabled"); } childrenArray.add(taxonomyJson); //for allTags - adding tag into table of selected ones JSONObject tagObject = new JSONObject(); tagObject.put("tagId", tax.getId()); tagObject.put("tagName", tax.getName()); tagObject.put("tagTypeId", tax.getRoot().getId()); tagObject.put("tagTypeName", tax.getRoot().getName()); allTags.put(String.valueOf(tax.getId()), tagObject); //for tagTypesByName JSONObject tagTypeByNameValue = new JSONObject(); tagTypeByNameValue.put("tagId", tax.getId()); tagTypeByNameValue.put("tagName", tax.getName()); tagTypeByNameValues.add(tagTypeByNameValue); } //New value.. for current type JSONObject newValueJson = createNewValueJson(Long.toString(tagTypeValue(tagTypeId))); childrenArray.add(newValueJson); optgroup.put("children", childrenArray); select2InputArray.add(optgroup); tagTypeJson.put("values", tagTypeByNameValues); tagTypesByName.put(tagTypeName, tagTypeJson); tagTypes.put(Long.toString(tagTypeId), tagTypeJson); } // New type... New value... JSONObject optgroup = new JSONObject(); optgroup.put("text", "New type..."); JSONObject newValueJson = createNewValueJson("newTagType"); JSONArray childrenArray = new JSONArray(); childrenArray.add(newValueJson); optgroup.put("children", childrenArray); select2InputArray.add(optgroup); ret.put("select2Input", select2InputArray); ret.put("allTags", allTags); ret.put("tagTypesByName", tagTypesByName); ret.put("tagTypes", tagTypes); ret.put("more", moreResults); } catch (RequestException e) { logger.warn("Failed to retrieve environments", e); return error("Unable to retrieve environments"); } return ret; } private JSONObject createMoreResultsJson() { JSONObject moreResultsJson = new JSONObject(); moreResultsJson.put("id", "moreResultsFound"); moreResultsJson.put("text", Messages.TooManyResults()); moreResultsJson.put("warning", "true"); moreResultsJson.put("disabled", "disabled"); return moreResultsJson; } private JSONObject createNewValueJson(String id) { JSONObject newValueJson = new JSONObject(); newValueJson.put("id", id); newValueJson.put("text", "New value..."); newValueJson.put("newValue", "true"); return newValueJson; } private long tagTypeValue(long n) { // mapping to ensure negative value (solve the "0" tag type ID) return -(n + 1); } private void addTaxonomyTags(JSONObject result, Pipeline pipeline) { JSONArray pipelineTaxonomies = new JSONArray(); for (Taxonomy taxonomy : pipeline.getTaxonomies()) { pipelineTaxonomies.add(tag(taxonomy)); } result.put("taxonomyTags", pipelineTaxonomies); } private void addFields(JSONObject result, Pipeline pipeline) { JSONObject listFields = new JSONObject(); for (ListField field : pipeline.getFields()) { JSONArray assignedValuesArray = listFieldValues(field); listFields.put(field.getName(), assignedValuesArray); } result.put("fields", listFields); } private JSONArray listFieldValues(ListField field) { JSONArray ret = new JSONArray(); for (ListItem item : field.getValues()) { JSONObject value = new JSONObject(); value.put("id", item.getId()); if (item.getName() != null) { value.put("name", item.getName()); } ret.add(value); } return ret; } private static Collection<JSONObject> toCollection(JSONArray array) { return (Collection<JSONObject>) array.subList(0, array.size()); } private JSONObject tag(Long tagId, String value) { JSONObject tag = new JSONObject(); tag.put("tagId", String.valueOf(tagId)); tag.put("tagName", value); return tag; } private JSONObject tag(Taxonomy taxonomy) { JSONObject tag = tag(taxonomy.getId(), taxonomy.getName()); if (taxonomy.getRoot() != null) { tag.put("tagTypeId", String.valueOf(taxonomy.getRoot().getId())); tag.put("tagTypeName", taxonomy.getRoot().getName()); } return tag; } private JSONObject error(String message) { return error(message, null); } private JSONObject error(String message, ExceptionLink exceptionLink) { JSONObject result = new JSONObject(); JSONArray errors = new JSONArray(); JSONObject error = new JSONObject(); error.put("message", message); if (exceptionLink != null) { error.put("url", exceptionLink.getUrl()); error.put("label", exceptionLink.getLabel()); } errors.add(error); result.put("errors", errors); return result; } private MqmRestClient createClient() throws ClientException { ServerConfiguration configuration = ConfigurationService.getServerConfiguration(); if (StringUtils.isEmpty(configuration.location)) { String label = "Please configure server here"; throw new ClientException(PRODUCT_NAME + " not configured", new ExceptionLink("/configure", label)); } RetryModel retryModel = getRetryModel(); if (retryModel.isQuietPeriod()) { String label = "Please validate your configuration settings here"; throw new ClientException(PRODUCT_NAME + " not connected", new ExceptionLink("/configure", label)); } JenkinsMqmRestClientFactory clientFactory = getExtension(JenkinsMqmRestClientFactory.class); MqmRestClient client = clientFactory.obtain(configuration.location, configuration.sharedSpace, configuration.username, configuration.password); try { client.validateConfigurationWithoutLogin(); } catch (RequestException e) { logger.warn(PRODUCT_NAME + " connection failed", e); retryModel.failure(); throw new ClientException("Connection to " + PRODUCT_NAME + " failed"); } retryModel.success(); return client; } private RetryModel getRetryModel() { if (retryModel == null) { retryModel = getExtension(RetryModel.class); } return retryModel; } private static <T> T getExtension(Class<T> clazz) { ExtensionList<T> items = Jenkins.getInstance().getExtensionList(clazz); assert 1 == items.size() : "Expected to have one and only one extension of type " + clazz; return items.get(0); } private static class ClientException extends Exception { private ExceptionLink link; ClientException(String message) { this(message, null); } ClientException(String message, ExceptionLink link) { super(message); this.link = link; } public ExceptionLink getLink() { return link; } } private static class ExceptionLink { private String url; private String label; ExceptionLink(String url, String label) { this.url = url; this.label = label; } public String getUrl() { return url; } public String getLabel() { return label; } } }