/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.camel.component.jolt;
import java.io.InputStream;
import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.Defaultr;
import com.bazaarvoice.jolt.JsonUtils;
import com.bazaarvoice.jolt.Removr;
import com.bazaarvoice.jolt.Shiftr;
import com.bazaarvoice.jolt.Sortr;
import com.bazaarvoice.jolt.Transform;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.component.ResourceEndpoint;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.util.ObjectHelper;
/**
* The jolt component allows you to process a JSON messages using an JOLT specification (such as JSON-JSON transformation).
*/
@UriEndpoint(firstVersion = "2.16.0", scheme = "jolt", title = "JOLT", syntax = "jolt:resourceUri", producerOnly = true, label = "transformation")
public class JoltEndpoint extends ResourceEndpoint {
private Transform transform;
@UriParam(defaultValue = "Hydrated")
private JoltInputOutputType outputType;
@UriParam(defaultValue = "Hydrated")
private JoltInputOutputType inputType;
@UriParam(defaultValue = "Chainr")
private JoltTransformType transformDsl = JoltTransformType.Chainr;
public JoltEndpoint() {
}
public JoltEndpoint(String uri, JoltComponent component, String resourceUri) {
super(uri, component, resourceUri);
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public ExchangePattern getExchangePattern() {
return ExchangePattern.InOut;
}
@Override
protected String createEndpointUri() {
return "jolt:" + getResourceUri();
}
private synchronized Transform getTransform() throws Exception {
if (transform == null) {
if (log.isDebugEnabled()) {
String path = getResourceUri();
log.debug("Jolt content read from resource {} with resourceUri: {} for endpoint {}", new Object[]{getResourceUri(), path, getEndpointUri()});
}
// Sortr does not require a spec
if (this.transformDsl == JoltTransformType.Sortr) {
this.transform = new Sortr();
} else {
// getResourceAsInputStream also considers the content cache
Object spec = JsonUtils.jsonToObject(getResourceAsInputStream());
switch(this.transformDsl) {
case Shiftr:
this.transform = new Shiftr(spec);
break;
case Defaultr:
this.transform = new Defaultr(spec);
break;
case Removr:
this.transform = new Removr(spec);
break;
case Chainr:
default:
this.transform = Chainr.fromSpec(spec);
break;
}
}
}
return transform;
}
/**
* Sets the Transform to use. If not set a Transform specified by the transformDsl will be created
*/
public void setTransform(Transform transform) {
this.transform = transform;
}
public JoltInputOutputType getOutputType() {
return outputType;
}
/**
* Specifies if the output should be hydrated JSON or a JSON String.
*/
public void setOutputType(JoltInputOutputType outputType) {
this.outputType = outputType;
}
public JoltInputOutputType getInputType() {
return inputType;
}
/**
* Specifies if the input is hydrated JSON or a JSON String.
*/
public void setInputType(JoltInputOutputType inputType) {
this.inputType = inputType;
}
public JoltTransformType getTransformDsl() {
return transformDsl;
}
/**
* Specifies the Transform DSL of the endpoint resource. If none is specified <code>Chainr</code> will be used.
*/
public void setTransformDsl(JoltTransformType transformType) {
this.transformDsl = transformType;
}
public JoltEndpoint findOrCreateEndpoint(String uri, String newResourceUri) {
String newUri = uri.replace(getResourceUri(), newResourceUri);
log.debug("Getting endpoint with URI: {}", newUri);
return getCamelContext().getEndpoint(newUri, JoltEndpoint.class);
}
@Override
protected void onExchange(Exchange exchange) throws Exception {
String path = getResourceUri();
ObjectHelper.notNull(path, "resourceUri");
String newResourceUri = exchange.getIn().getHeader(JoltConstants.JOLT_RESOURCE_URI, String.class);
if (newResourceUri != null) {
exchange.getIn().removeHeader(JoltConstants.JOLT_RESOURCE_URI);
log.debug("{} set to {} creating new endpoint to handle exchange", JoltConstants.JOLT_RESOURCE_URI, newResourceUri);
JoltEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri);
newEndpoint.onExchange(exchange);
return;
}
Object input;
if (getInputType() == JoltInputOutputType.JsonString) {
input = JsonUtils.jsonToObject(exchange.getIn().getBody(InputStream.class));
} else {
input = exchange.getIn().getBody();
}
Object output = getTransform().transform(input);
// now lets output the results to the exchange
Message out = exchange.getOut();
if (getOutputType() == JoltInputOutputType.JsonString) {
out.setBody(JsonUtils.toJsonString(output));
} else {
out.setBody(output);
}
out.setHeaders(exchange.getIn().getHeaders());
out.setAttachments(exchange.getIn().getAttachments());
}
}