/* * Copyright 2015 cruxframework.org. * * 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 org.cruxframework.crux.core.declarativeui.conditional; import java.util.ArrayList; import java.util.List; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Device; import org.cruxframework.crux.core.client.utils.StringUtils; import org.cruxframework.crux.core.declarativeui.CruxXmlPreProcessor; import org.cruxframework.crux.core.declarativeui.XPathUtils; import org.cruxframework.crux.core.declarativeui.template.TemplateException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * @author Samuel Almeida Cardoso * */ public class IfDevicePreProcessor implements CruxXmlPreProcessor { private static final String INPUT = "input"; private static final String SIZE = "size"; private XPathExpression findIfDefiveExpression; public IfDevicePreProcessor() { XPath findPath = XPathUtils.getCruxPagesXPath(); try { findIfDefiveExpression = findPath.compile("//c:ifDevice"); } catch (XPathExpressionException e) { throw new TemplateException("Error initializing ifDevice pre-processor.", e); } } @Override public Document preprocess(Document doc, String device) { if (doc == null || device == null) { return doc; } Element documentElement = doc.getDocumentElement(); preprocessIfDevice(documentElement, device); return doc; } private void preprocessIfDevice(Element documentElement, String device) { try { NodeList childNodes = (NodeList)findIfDefiveExpression.evaluate(documentElement, XPathConstants.NODESET); List<Element> elements = new ArrayList<Element>(); for (int i = 0; i < childNodes.getLength(); i++) { Element element = (Element)childNodes.item(i); if (isAttached(element)) { elements.add(element); } } for (Element element: elements) { preprocessIfDefiveTag(element, device); } } catch (XPathExpressionException e) { throw new TemplateException("Error pre-processing ifDevice directive.", e); } } private boolean isAttached(Node element) { boolean attached = false; while (element.getParentNode() != null) { if (element.equals(element.getOwnerDocument().getDocumentElement())) { attached = true; break; } element = element.getParentNode(); } return attached; } private void preprocessIfDefiveTag(Element element, String device) { NodeList nodes = element.getChildNodes(); Node parentNode = element.getParentNode(); if(!renderForThisDevice(element, device)) { parentNode.removeChild(element); return; } for (int i=0; i< nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element child = (Element)node; element.removeChild(child); parentNode.insertBefore(child, element); } } parentNode.removeChild(element); } private boolean renderForThisDevice(Element ifDeviceElement, String strDevice) { Device device = Device.valueOf(strDevice); Node excludesNode = getExcludesNode(ifDeviceElement); boolean render = false; String strSize = ifDeviceElement.getAttribute(SIZE); String strInput = ifDeviceElement.getAttribute(INPUT); if((StringUtils.isEmpty(strSize) || device.getSize().toString().equals(strSize))) { render = true; } else { render = false; } if(render && (StringUtils.isEmpty(strInput) || device.getInput().toString().equals(strInput))) { render = true; } else { render = false; } if(render) { render = renderBasedInExclusions(excludesNode, device.getSize().toString(), device.getInput().toString()); } if(excludesNode != null) { excludesNode.getParentNode().removeChild(excludesNode); } return render; } private boolean renderBasedInExclusions(Node excludesNode, String compilationSize, String compilationInput) { if(excludesNode == null) { return true; } NodeList childNodes = excludesNode.getChildNodes(); for (int i=0; i< childNodes.getLength(); i++) { Node excludeNode = childNodes.item(i); if(excludeNode.getNodeType() == Node.ELEMENT_NODE) { String excludeSize = ((Element)excludeNode).getAttribute(SIZE); String excludeInput = ((Element)excludeNode).getAttribute(INPUT); if( (StringUtils.isEmpty(excludeSize) || excludeSize.equals(compilationSize)) && (StringUtils.isEmpty(excludeInput) || excludeInput.equals(compilationInput)) ) { return false; } } } return true; } private Node getExcludesNode(Element ifDeviceElement) { NodeList nodes = ifDeviceElement.getChildNodes(); for (int i=0; i< nodes.getLength(); i++) { Node node = nodes.item(i); if(node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().contains("excludes")) { return node; } } return null; } }