/*
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 Adobe
* %%
* 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.
* #L%
*/
package com.adobe.acs.commons.quickly.results.impl;
import com.adobe.acs.commons.quickly.Command;
import com.adobe.acs.commons.quickly.QuicklyEngine;
import com.adobe.acs.commons.quickly.results.Action;
import com.adobe.acs.commons.quickly.results.Result;
import com.adobe.acs.commons.quickly.results.ResultBuilder;
import com.adobe.acs.commons.quickly.results.ResultSerializer;
import com.adobe.acs.commons.quickly.results.impl.serializers.GenericResultSerializerImpl;
import com.day.cq.wcm.api.AuthoringUIMode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* ACS AEM Commons - Quickly - Result Builder
*/
@Component
@Reference(
name = "resultSerializers",
referenceInterface = ResultSerializer.class,
policy = ReferencePolicy.DYNAMIC,
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE
)
@Service
public class ResultBuilderImpl implements ResultBuilder {
private static final Logger log = LoggerFactory.getLogger(ResultBuilderImpl.class);
private Map<String, ResultSerializer> resultSerializers = new ConcurrentHashMap<String, ResultSerializer>();
@Reference(target = "(" + ResultSerializer.PROP_TYPE + "=" + GenericResultSerializerImpl.TYPE + ")")
private ResultSerializer defaultResultSerialize;
@Override
public JSONObject toJSON(final Command cmd, Result result, final ValueMap config) throws JSONException {
if (!this.acceptsAuthoringUIMode(result,
config.get(AuthoringUIMode.class.getName(), AuthoringUIMode.TOUCH))) {
// Rejected by Authoring UI Mode
log.debug("Rejected by Authoring UI Mode: {}", result.getTitle());
return null;
} else if (!this.acceptsQuicklyMode(result, Arrays.asList(config.get(QuicklyEngine.CONFIG_RESULTS,
String[].class)))) {
// Rejected by Quickly Mode
log.debug("Rejected by Quickly Mode: {}", result.getTitle());
return null;
}
// Apply punctuation rules
result = this.processPunctuation(cmd.getPunctuation(), result);
ResultSerializer serializer = null;
if (StringUtils.isNotBlank(result.getResultType()) && resultSerializers.containsKey(result.getResultType())) {
serializer = resultSerializers.get(result.getResultType());
}
if (serializer == null) {
serializer = resultSerializers.get(GenericResultSerializerImpl.TYPE);
}
if (serializer != null) {
//log.trace("Serializing results using Result Serializer [ {} ] w/ [ {} ]", result.getResultType(), serializer.getClass().getSimpleName());
return serializer.toJSON(result, config);
} else {
log.trace("Could not find Quickly Result Serializer for type [ {} ]", result.getResultType());
if (defaultResultSerialize != null) {
log.trace("Using Default Quickly Result Serializer for type [ {} ]", GenericResultSerializerImpl.TYPE);
return defaultResultSerialize.toJSON(result, config);
} else {
log.error("Could not find Default Quickly Result Serializer of type [ {} ]",
GenericResultSerializerImpl.TYPE);
}
}
return null;
}
protected final boolean acceptsAuthoringUIMode(Result result, AuthoringUIMode authoringUIMode) {
if (result.getAuthoringMode() == null) {
// All Authoring Modes
return true;
} else if (result.getAuthoringMode().equals(authoringUIMode)) {
return true;
} else {
return false;
}
}
protected final boolean acceptsQuicklyMode(Result result, List<String> modes) {
if (result.getModes().contains(Result.Mode.ANY)
|| CollectionUtils.isEmpty(result.getModes())) {
return true;
}
for (Result.Mode mode : result.getModes()) {
for (String resultMode : modes) {
if (StringUtils.equalsIgnoreCase(mode.toString(), resultMode)) {
return true;
}
}
}
return false;
}
protected final Result processPunctuation(final String[] punctuation, final Result result) {
for (final String p : punctuation) {
if ("!".equals(p) && (Action.Method.GET.equals(result.getAction().getMethod())
|| Action.Method.POST.equals(result.getAction().getMethod()))) {
result.getAction().setTarget(Action.Target.BLANK);
}
}
return result;
}
@Deactivate
protected final void deactivate(Map<String, String> map) {
resultSerializers = new ConcurrentHashMap<String, ResultSerializer>();
}
// Bind
protected final void bindResultSerializers(final ResultSerializer service, final Map<Object, Object> props) {
final String type = PropertiesUtil.toString(props.get(ResultSerializer.PROP_TYPE), null);
if (type != null) {
resultSerializers.put(type.toUpperCase(), service);
log.info("Collected Result Serializer [ {} ]", type.toUpperCase());
}
}
// Unbind
protected final void unbindResultSerializers(final ResultSerializer service, final Map<Object, Object> props) {
final String type = PropertiesUtil.toString(props.get(ResultSerializer.PROP_TYPE), null);
if (type != null) {
resultSerializers.remove(type.toUpperCase());
log.info("Discarded Result Serializer [ {} ]", type.toUpperCase());
}
}
}