/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.wso2.carbon.governance.rest.api.internal;
import com.google.gson.stream.JsonWriter;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaxen.JaxenException;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.governance.api.common.dataobjects.GovernanceArtifact;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.util.GovernanceArtifactConfiguration;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.governance.rest.api.model.TypedList;
import org.wso2.carbon.governance.rest.api.util.Util;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.RegistryService;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class GenericArtifactJSONWriter {
public static final String ASSETS = "assets";
public static final String INDENT = " ";
public static final String NAME = "name";
public static final String ID = "id";
public static final String TYPE = "type";
public static final String OVERVIEW = "overview_";
public static final String SELF_LINK = "self-link";
public static final String CONTENT_LINK = "content-link";
public static final String LINKS = "links";
public static final String SELF = "self";
public static final String PREV = "prev";
public static final String NEXT = "next";
public static final String BELONG_TO = "belong-to";
private final Log log = LogFactory.getLog(GenericArtifactJSONWriter.class);
public void writeTo(TypedList<GovernanceArtifact> typedList, OutputStream entityStream, String baseURI)
throws IOException, GovernanceException {
PrintWriter printWriter = new PrintWriter(entityStream);
JsonWriter writer = new JsonWriter(printWriter);
writer.setIndent(INDENT);
writer.beginObject();
writer.name(ASSETS);
String shortName = null;
if (typedList.hasData()) {
writer.beginArray();
try {
for (Map.Entry<String, List<GovernanceArtifact>> entry : typedList.getArtifacts().entrySet()) {
shortName = entry.getKey();
GovernanceArtifactConfiguration artifactConfiguration = null;
for (GovernanceArtifact artifact : entry.getValue()) {
if (artifactConfiguration == null) {
artifactConfiguration = GovernanceUtils
.findGovernanceArtifactConfigurationByMediaType(artifact.getMediaType(),
getUserRegistry());
}
writeGenericArtifact(writer, shortName, artifact, baseURI, artifactConfiguration);
}
}
} catch (RegistryException e) {
throw new GovernanceException("Error while finding artifact configuration.", e);
}
writer.endArray();
} else {
writer.nullValue();
}
TypedList.Pagination pagination = typedList.getPagination();
if (pagination != null) {
String nextURI = null;
String prevURI = null;
String selfURI = generateLink(shortName, baseURI, pagination.getQuery(), pagination.getSelfStart(),
pagination.getCount(), pagination.getTenant());
if (pagination.getNextStart() != null) {
nextURI = generateLink(shortName, baseURI, pagination.getQuery(), pagination.getNextStart(),
pagination.getCount(), pagination.getTenant());
}
if (pagination.getPreviousStart() != null) {
prevURI = generateLink(shortName, baseURI, pagination.getQuery(), pagination.getPreviousStart(),
pagination.getCount(), pagination.getTenant());
}
writer.name(LINKS);
writer.beginObject();
writer.name(SELF).value(selfURI);
if (prevURI != null) {
writer.name(PREV).value(prevURI);
}
if (nextURI != null) {
writer.name(NEXT).value(nextURI);
}
writer.endObject();
}
writer.endObject();
writer.flush();
writer.close();
printWriter.flush();
printWriter.close();
}
private String generateLink(String shortName, String baseURI, String query, int start, int count, String tenant) {
if (query != null && !query.isEmpty()) {
query = query + "&";
}
StringBuilder builder = new StringBuilder();
builder.append(Util.generateLink(shortName, baseURI, true));
builder.append("?");
builder.append(query);
builder.append(PaginationInfo.PAGINATION_PARAM_START);
builder.append("=");
builder.append(start);
builder.append("&");
builder.append(PaginationInfo.PAGINATION_PARAM_COUNT);
builder.append("=");
builder.append(count);
if (tenant != null) {
builder.append("&");
builder.append(PaginationInfo.PAGINATION_PARAM_TENANT);
builder.append("=");
builder.append(tenant);
}
return builder.toString();
}
private void writeGenericArtifact(JsonWriter writer, String shortName, GovernanceArtifact artifact, String baseURI,
GovernanceArtifactConfiguration artifactConfiguration) throws IOException, GovernanceException {
writer.beginObject();
writer.name(NAME).value(artifact.getQName().getLocalPart());
writer.name(ID).value(artifact.getId());
writer.name(TYPE).value(shortName);
String belongToLink = Util.generateBelongToLink(artifact, baseURI);
for (String key : artifact.getAttributeKeys()) {
//TODO value can be something else not a String value
// Get all attributes.
String[] value = artifact.getAttributes(key);
if (key.indexOf(OVERVIEW) > -1) {
key = key.replace(OVERVIEW, "");
}
// If the attributes are more than one.
if (!NAME.equals(key) && value != null)
if (value.length > 1) {
String optionTextTableName = key.split("_", 2)[0];
//Get the table name as a upper camel string.
optionTextTableName = optionTextTableName.substring(0, 1).toUpperCase() +
optionTextTableName.substring(1).toLowerCase();
List subheadings = evaluateXpath(artifactConfiguration.getContentDefinition(),
"/artifactType/content/table[@name='" + optionTextTableName + "']/subheading/heading",
null);
List<String> headings = new ArrayList<>();
for (Object subheadingObject : subheadings) {
OMElement subheadingElement = (OMElement) subheadingObject;
headings.add(subheadingElement.getText());
}
if (headings.size() > 0) {
writer.name(key);
writer.beginArray();
writer.setIndent(" ");
for (int i = 0; i < value.length; i++) {
writer.beginObject();
// Setting the key and empty string map in JSON for empty values.
if (value[i] == null) {
value[i] = "";
}
String[] optionValues = value[i].split(":", headings.size());
if (optionValues.length > 0) {
for (int j = 0; j < optionValues.length; j++) {
writer.name(headings.get(j)).value(optionValues[j]);
}
}
writer.endObject();
}
writer.endArray();
}
// If only one attribute is received.
} else if (value.length == 1) {
writer.name(key).value(value[0]);
} else {
writer.name(key).nullValue();
}
}
String self_link = Util.generateLink(shortName, artifact.getId(), baseURI);
writer.name(SELF_LINK).value(self_link);
writer.name(CONTENT_LINK).value(self_link + "/content");
if (belongToLink != null) {
writer.name(BELONG_TO).value(belongToLink);
}
writer.endObject();
}
/**
* This method is used to get the user registry.
*
* @return user registry object.
* @throws RegistryException
*/
private Registry getUserRegistry() throws RegistryException {
CarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RegistryService registryService = (RegistryService) carbonContext.
getOSGiService(RegistryService.class, null);
return registryService.getGovernanceUserRegistry(carbonContext.getUsername(), carbonContext.getTenantId());
}
/**
* This method is used to evaluate an xpath.
*
* @param contentElement OM element that the xpath is bean evaluated.
* @param xpathString xPath
* @param nsPrefix namespace prefix
* @return
*/
public List evaluateXpath(OMElement contentElement, String xpathString, String nsPrefix) {
List resultsList = new ArrayList();
try {
AXIOMXPath xpath = new AXIOMXPath(xpathString);
Iterator nsIterator = contentElement.getAllDeclaredNamespaces();
if (nsIterator.hasNext()) {
while (nsIterator.hasNext()) {
OMNamespace next = (OMNamespace) nsIterator.next();
xpath.addNamespace(nsPrefix, next.getNamespaceURI());
resultsList.addAll(xpath.selectNodes(contentElement));
}
} else if (contentElement.getDefaultNamespace() != null) {
xpath.addNamespace(nsPrefix, contentElement.getDefaultNamespace().getNamespaceURI());
resultsList.addAll(xpath.selectNodes(contentElement));
} else if (nsPrefix != null) {
xpathString = xpathString.replace(nsPrefix + ":", "");
xpath = new AXIOMXPath(xpathString);
resultsList.addAll(xpath.selectNodes(contentElement));
} else {
xpath = new AXIOMXPath(xpathString);
resultsList.addAll(xpath.selectNodes(contentElement));
}
return resultsList;
} catch (JaxenException e) {
log.error("Error while evaluating xPath: '" + xpathString + "'.", e);
}
return null;
}
}