/* * Copyright (c) 2010-2013 Evolveum * * 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.evolveum.midpoint.web.util; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.xnode.MapXNode; import com.evolveum.midpoint.prism.xnode.RootXNode; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.apache.commons.lang.StringUtils; import javax.xml.bind.JAXBElement; import java.util.List; /** * @author shood * */ public class ExpressionUtil { private static final Trace LOGGER = TraceManager.getTrace(ExpressionUtil.class); public static enum ExpressionEvaluatorType{ LITERAL, AS_IS, PATH, SCRIPT, GENERATE } public static enum Language{ GROOVY("http://midpoint.evolveum.com/xml/ns/public/expression/language#Groovy"), XPATH("http://www.w3.org/TR/xpath/"), JAVASCRIPT("http://midpoint.evolveum.com/xml/ns/public/expression/language#ECMAScript"); protected String language; Language(String language){ this.language = language; } public String getLanguage() { return language; } } public static final String SCRIPT_START_NS = "<c:script xmlns:c=\"http://midpoint.evolveum.com/xml/ns/public/common/common-3\">"; public static final String SCRIPT_END_NS = "</c:script>"; public static final String CODE_START_NS = "<c:code>"; public static final String CODE_END_NS = "</c:code>"; public static final String VALUE_START_NS = "<c:value xmlns:c=\"http://midpoint.evolveum.com/xml/ns/public/common/common-3\">"; public static final String VALUE_END_NS = "</c:value>"; public static final String PATH_START_NS = "<c:path xmlns:c=\"http://midpoint.evolveum.com/xml/ns/public/common/common-3\">"; public static final String PATH_END_NS = "</c:path>"; public static final String EXPRESSION_SCRIPT = "<script>\n" + " <code>\n" + " Insert your script here\n" + " </code>\n" + "</script>"; public static final String EXPRESSION_LITERAL = "<value>Insert value(s) here</value>"; public static final String EXPRESSION_AS_IS = "<asIs/>"; public static final String EXPRESSION_PATH = "<path>Insert path here</path>"; public static final String EXPRESSION_GENERATE = "<generate>\n" + //" <valuePolicyRef oid=\"Insert value policy oid\"/>\n" + "</generate>"; public static final String ELEMENT_SCRIPT = "</script>"; public static final String ELEMENT_GENERATE = "</generate>"; public static final String ELEMENT_GENERATE_WITH_NS = "<generate"; public static final String ELEMENT_PATH = "</path>"; public static final String ELEMENT_VALUE = "</value>"; public static final String ELEMENT_AS_IS = "<asIs/>"; public static final String ELEMENT_AS_IS_WITH_NS = "<asIs"; public static String getExpressionString(ExpressionEvaluatorType type, ObjectReferenceType policy){ if(ExpressionEvaluatorType.GENERATE.equals(type) && policy != null){ StringBuilder sb = new StringBuilder(); sb.append("<generate>\n" + " <valuePolicyRef oid=\"").append(policy.getOid()).append("\"/>\n" + "</generate>"); return sb.toString(); } return EXPRESSION_GENERATE; } public static String getExpressionString(ExpressionEvaluatorType type, Language lang){ if(ExpressionEvaluatorType.SCRIPT.equals(type) && !Language.GROOVY.equals(lang)){ StringBuilder sb = new StringBuilder(); sb.append("<script>\n"); sb.append(" <language>").append(lang.getLanguage()).append("</language>\n"); sb.append(" <code>\n" + " Insert your script here\n" + " </code>\n" + "<script>"); return sb.toString(); } return EXPRESSION_SCRIPT; } public static String getExpressionString(ExpressionEvaluatorType type){ if(type == null){ return ""; } switch(type){ case AS_IS: return EXPRESSION_AS_IS; case GENERATE: return EXPRESSION_GENERATE; case LITERAL: return EXPRESSION_LITERAL; case PATH: return EXPRESSION_PATH; case SCRIPT: return EXPRESSION_SCRIPT; default: return ""; } } public static ExpressionEvaluatorType getExpressionType(String expression){ if(expression.contains(ELEMENT_AS_IS) || expression.contains(ELEMENT_AS_IS_WITH_NS)){ return ExpressionEvaluatorType.AS_IS; } else if(expression.contains(ELEMENT_GENERATE) || expression.contains(ELEMENT_GENERATE_WITH_NS)){ return ExpressionEvaluatorType.GENERATE; } else if(expression.contains(ELEMENT_PATH)){ return ExpressionEvaluatorType.PATH; } else if(expression.contains(ELEMENT_SCRIPT)){ return ExpressionEvaluatorType.SCRIPT; } else if(expression.contains(ELEMENT_VALUE)){ return ExpressionEvaluatorType.LITERAL; } return null; } public static Language getExpressionLanguage(String expression){ if(expression.contains("<language>")){ if(expression.contains(Language.XPATH.getLanguage())){ return Language.XPATH; } else if(expression.contains(Language.JAVASCRIPT.getLanguage())) { return Language.JAVASCRIPT; } else { return Language.GROOVY; } } else { return Language.GROOVY; } } public static String addNamespaces(String expression, ExpressionEvaluatorType type){ String newExpression = expression; if(ExpressionEvaluatorType.PATH.equals(type)){ newExpression = newExpression.replaceAll("<path>", PATH_START_NS); newExpression = newExpression.replaceAll("</path>", PATH_END_NS); } else if(ExpressionEvaluatorType.LITERAL.equals(type)){ newExpression = newExpression.replaceAll("<value>", VALUE_START_NS); newExpression = newExpression.replaceAll("</value>", VALUE_END_NS); } else if(ExpressionEvaluatorType.SCRIPT.equals(type)){ newExpression = newExpression.replaceAll("<code>", CODE_START_NS); newExpression = newExpression.replaceAll("</code>", CODE_END_NS); newExpression = newExpression.replaceAll("<script>", SCRIPT_START_NS); newExpression = newExpression.replaceAll("</script>", SCRIPT_END_NS); } return newExpression; } public static String loadExpression(ExpressionType expression, PrismContext prismContext, Trace LOGGER) { if (expression == null || expression.getExpressionEvaluator().isEmpty()) { return ""; } List<JAXBElement<?>> evaluators = expression.getExpressionEvaluator(); try { return serializeEvaluators(evaluators, prismContext); } catch (SchemaException e) { //TODO - how can we show this error to user? LoggingUtils.logUnexpectedException(LOGGER, "Could not load expressions from mapping.", e, e.getStackTrace()); return e.getMessage(); } } private static String serializeEvaluators(List<JAXBElement<?>> evaluators, PrismContext prismContext) throws SchemaException { if (evaluators.size() == 1) { return serialize(evaluators.get(0), prismContext); } else { StringBuilder sb = new StringBuilder(); for (JAXBElement<?> element : evaluators) { String subElement = serialize(element, prismContext); sb.append(subElement).append("\n"); } return sb.toString(); } } private static String serialize(JAXBElement<?> element, PrismContext prismContext) throws SchemaException { String xml; if (element.getValue() instanceof RawType) { RawType raw = (RawType) element.getValue(); RootXNode rootNode = new RootXNode(element.getName(), raw.serializeToXNode()); xml = prismContext.xmlSerializer().serialize(rootNode); } else { xml = prismContext.xmlSerializer().serialize(element); } return WebXmlUtil.stripNamespaceDeclarations(xml); } public static boolean isEmpty(ExpressionType expression) { return expression == null || expression.getExpressionEvaluator().isEmpty(); } public static void parseExpressionEvaluators(String xml, ExpressionType expressionObject, PrismContext context) throws SchemaException { expressionObject.getExpressionEvaluator().clear(); if (StringUtils.isNotBlank(xml)) { xml = WebXmlUtil.wrapInElement("expression", xml, true); LOGGER.info("Expression to serialize: {}", xml); JAXBElement<?> newElement = context.parserFor(xml).xml().parseRealValueToJaxbElement(); expressionObject.getExpressionEvaluator().addAll(((ExpressionType) (newElement.getValue())).getExpressionEvaluator()); } } // TODO move somewhere else? generalize a bit? public static RootXNode parseSearchFilter(String data, PrismContext context) throws SchemaException { String xml = WebXmlUtil.wrapInElement("root", data, false); RootXNode rootXNode = context.parserFor(xml).xml().parseToXNode(); if (rootXNode.getSubnode() instanceof MapXNode) { MapXNode mapXNode = (MapXNode) rootXNode.getSubnode(); if (mapXNode.size() != 1) { throw new SchemaException("Content cannot be parsed as a search filter: " + mapXNode.debugDump()); } return mapXNode.getEntryAsRoot(mapXNode.keySet().iterator().next()); } else { throw new SchemaException("Content cannot be parsed as a search filter: " + DebugUtil.debugDump(rootXNode.getSubnode())); } } }