All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.testing.client.ComponentClient Maven / Gradle / Ivy

There is a newer version: 1.2.8
Show newest version
/*
 * Copyright 2017 Adobe Systems Incorporated
 *
 * 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.adobe.cq.testing.client;

import com.adobe.cq.testing.client.components.AbstractComponent;
import com.adobe.cq.testing.client.components.collab.Ratings;
import com.adobe.cq.testing.client.components.commerce.ShoppingCart;
import com.adobe.cq.testing.client.components.foundation.Carousel;
import com.adobe.cq.testing.client.components.foundation.Chart;
import com.adobe.cq.testing.client.components.foundation.Download;
import com.adobe.cq.testing.client.components.foundation.External;
import com.adobe.cq.testing.client.components.foundation.Flash;
import com.adobe.cq.testing.client.components.foundation.Image;
import com.adobe.cq.testing.client.components.foundation.List;
import com.adobe.cq.testing.client.components.foundation.ParSys;
import com.adobe.cq.testing.client.components.foundation.Reference;
import com.adobe.cq.testing.client.components.foundation.Search;
import com.adobe.cq.testing.client.components.foundation.Sitemap;
import com.adobe.cq.testing.client.components.foundation.Slideshow;
import com.adobe.cq.testing.client.components.foundation.Table;
import com.adobe.cq.testing.client.components.foundation.Text;
import com.adobe.cq.testing.client.components.foundation.TextImage;
import com.adobe.cq.testing.client.components.foundation.Title;
import com.adobe.cq.testing.client.components.foundation.form.Address;
import com.adobe.cq.testing.client.components.foundation.form.Captcha;
import com.adobe.cq.testing.client.components.foundation.form.Checkbox;
import com.adobe.cq.testing.client.components.foundation.form.Dropdown;
import com.adobe.cq.testing.client.components.foundation.form.End;
import com.adobe.cq.testing.client.components.foundation.form.FileUpload;
import com.adobe.cq.testing.client.components.foundation.form.Hidden;
import com.adobe.cq.testing.client.components.foundation.form.ImageButton;
import com.adobe.cq.testing.client.components.foundation.form.ImageUpload;
import com.adobe.cq.testing.client.components.foundation.form.Password;
import com.adobe.cq.testing.client.components.foundation.form.RadioGroup;
import com.adobe.cq.testing.client.components.foundation.form.Start;
import com.adobe.cq.testing.client.components.foundation.parsys.ColCtrl;
import com.adobe.cq.testing.client.components.tagging.TagCloud;
import org.apache.http.HttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.sling.testing.clients.ClientException;
import org.apache.sling.testing.clients.SlingClientConfig;
import org.apache.sling.testing.clients.util.FormEntityBuilder;
import org.codehaus.jackson.JsonNode;

import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.HashMap;

public class ComponentClient extends CQClient {

    /**
     * The key name for the default 'relativeLocation' component property
     *
     * 

Used as a default for the {@link AbstractComponent#getLocation()} method.

*/ private static final String CONFIG_KEY_RELATIVE_LOCATION = "componentDefaultRelativeLocation"; public static final String ORDER_FIRST = "first"; public static final String ORDER_LAST = "last"; public static final String ORDER_BEFORE_PREFIX = "before "; public static final String ORDER_AFTER_PREFIX = "after "; private static HashMap> components = new HashMap<>(); // registers all known component wrappers static { // foundation components components.put(Carousel.RESOURCE_TYPE,Carousel.class); components.put(Chart.RESOURCE_TYPE, Chart.class); components.put(ColCtrl.RESOURCE_TYPE,ColCtrl.class); components.put(Download.RESOURCE_TYPE,Download.class); components.put(External.RESOURCE_TYPE,External.class); components.put(Flash.RESOURCE_TYPE,Flash.class); components.put(Image.RESOURCE_TYPE,Image.class); components.put(List.RESOURCE_TYPE,List.class); components.put(Reference.RESOURCE_TYPE,Reference.class); components.put(Search.RESOURCE_TYPE,Search.class); components.put(Sitemap.RESOURCE_TYPE,Sitemap.class); components.put(Slideshow.RESOURCE_TYPE,Slideshow.class); components.put(Table.RESOURCE_TYPE,Table.class); components.put(Text.RESOURCE_TYPE,Text.class); components.put(TextImage.RESOURCE_TYPE,TextImage.class); components.put(Title.RESOURCE_TYPE,Title.class); components.put(TagCloud.RESOURCE_TYPE,TagCloud.class); components.put(ParSys.RESOURCE_TYPE,ParSys.class); // form components components.put(Start.RESOURCE_TYPE,Start.class); components.put(End.RESOURCE_TYPE,End.class); components.put(com.adobe.cq.testing.client.components.foundation.form.Text.RESOURCE_TYPE, com.adobe.cq.testing.client.components.foundation.form.Text.class); components.put(Address.RESOURCE_TYPE,Address.class); components.put(Captcha.RESOURCE_TYPE,Captcha.class); components.put(Checkbox.RESOURCE_TYPE,Checkbox.class); components.put(Dropdown.RESOURCE_TYPE,Dropdown.class); components.put(FileUpload.RESOURCE_TYPE,FileUpload.class); components.put(ImageUpload.RESOURCE_TYPE,ImageUpload.class); components.put(Hidden.RESOURCE_TYPE,Hidden.class); components.put(ImageButton.RESOURCE_TYPE,ImageButton.class); components.put(Password.RESOURCE_TYPE,Password.class); components.put(RadioGroup.RESOURCE_TYPE,RadioGroup.class); components.put(Start.RESOURCE_TYPE,Start.class); // collab components components.put(Ratings.RESOURCE_TYPE,Ratings.class); // commerce components components.put(Address.RESOURCE_TYPE,Address.class); components.put(ShoppingCart.RESOURCE_TYPE,ShoppingCart.class); } public ComponentClient(CloseableHttpClient http, SlingClientConfig config) throws ClientException { super(http, config); } public ComponentClient(URI serverUrl, String user, String password) throws ClientException { super(serverUrl, user, password); } /** * Adds a new, empty component to a CQ page. The component is added at the default * location in the page inside the page. * * @param componentClass the {@link com.adobe.cq.testing.client.components.AbstractComponent} * subclass to be created * @param pagePath path to the page where the component gets added * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed. * @param A subclass of {@link com.adobe.cq.testing.client.components.AbstractComponent} * @return A instance of the class passed in {@code componentClass} * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public T addComponent(Class componentClass, String pagePath, int... expectedStatus) throws ClientException, InterruptedException { // call the generic version return addComponent(componentClass, pagePath, null, null,null, expectedStatus); } /** * Adds a new, empty component to a CQ page. The component is added at the default * location in the page inside the page. * * @param componentClass the {@link com.adobe.cq.testing.client.components.AbstractComponent} * subclass to be created * @param pagePath path to the page where the component gets added * @param order Defines where the component should be added in relation to its siblings. Possible values * are {@code first}, {@code last}, {@code before [nodeName]}, {@code after [nodeName]}. * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed. * @param A subclass of {@link com.adobe.cq.testing.client.components.AbstractComponent} * @return A instance of the class passed in {@code componentClass} * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public T addComponent(Class componentClass, String pagePath,String order, int... expectedStatus) throws ClientException, InterruptedException { // call the generic version return addComponent(componentClass, pagePath, null, null,order, expectedStatus); } /** * Adds a new, empty component to a CQ page. * * @param componentClass the {@link com.adobe.cq.testing.client.components.AbstractComponent} subclass to be * created * @param pagePath path to the page where the component gets added * @param location relative path inside the page where the component gets added * @param nameHint proposed node for the new component node. Might get altered if the name if there is * already * a node with the same name on the same level. {@link AbstractComponent#getName()} * returns the name as is it is really set. * @param order Defines where the component should be added in relation to its siblings. Possible values * are {@code first}, {@code last}, {@code before [nodeName]}, {@code after [nodeName]}. * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed. * @param A subclass of {@link com.adobe.cq.testing.client.components.AbstractComponent} * @return An instance of the class passed in {@code componentClass} * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public T addComponent(Class componentClass, String pagePath, String location, String nameHint, String order, int... expectedStatus) throws ClientException, InterruptedException { if ( location == null ) { location = getValue(CONFIG_KEY_RELATIVE_LOCATION); } T component; try { // get the constructor for the component subclass Constructor cons = componentClass.getConstructor(ComponentClient.class, String.class, String.class, String.class); // execute the constructor component = cons.newInstance(this, pagePath, location, nameHint); } catch (Exception e) { throw new ClientException("Instantiation failed", e); } // call the create method on the component class component.create(order, expectedStatus); // return the newly created component return component; } /** * Initializes an {@link com.adobe.cq.testing.client.components.AbstractComponent} subclass * against an existing foundation component node. * * @param componentPath complete path to the the repository node that forms the root node of a * component. Must contain a property named {@code sling:resourceType} referencing * a valid component. * @param compClass The component wrapper class to be initialized * @param A subclass of {@link com.adobe.cq.testing.client.components.AbstractComponent} * @return A instance of the class passed in {@code componentClass} * @throws ClientException if the request fails */ public T getComponent(String componentPath, Class compClass) throws ClientException { // check if path even exists if(!this.exists(componentPath)) return null; // Get the json for this node JsonNode node = adaptTo(JsonClient.class).doGetJson(componentPath, 1); // check if the node has a sling:resourceType property if (node.get("sling:resourceType").isMissingNode()) { throw new ClientException(componentPath + " is not pointing to a foundation component node, no " + "sling:resourceType property was found!"); } return initializeComponent(componentPath,compClass); } /** * Initializes an {@link com.adobe.cq.testing.client.components.AbstractComponent} subclass * against an existing foundation component node. t looks for the sling:resourceType property an tries to find a * matching component wrapper that has been registered with the ComponentClient (see {@link * com.adobe.cq.testing.client.ComponentClient#registerComponent(String, Class)}) * * @param componentPath complete path to the the repository node that forms the root node of a * component. Must contain a property named {@code sling:resourceType} referencing * a valid component. * @param A subclass of {@link com.adobe.cq.testing.client.components.AbstractComponent} * @return A instance of the class passed in {@code componentClass} * @throws ClientException if the request fails */ @SuppressWarnings("unchecked") public T getComponent(String componentPath) throws ClientException { // check if path even exists if(!this.exists(componentPath)) return null; // Get the json for this node JsonNode node = adaptTo(JsonClient.class).doGetJson(componentPath, 1); // check if the node has a sling:resourceType property if (node.get("sling:resourceType").isMissingNode()) { throw new ClientException(componentPath + " is not pointing to a foundation component node, no " + "sling:resourceType property was found!"); } // get the class Class compClass = getCompClassByResourceType(node.get("sling:resourceType").getTextValue()); // no class found ? if (compClass == null) return null; // instantiate return (T) initializeComponent(componentPath,compClass); } /** * Helper method to execute the constructor of passed class using reflection. * * @param componentPath The path is used to generate the constructor parameters * @param compClass The class to instantiate * @param a subclass of an AbstractComponent * @return an instance of the passed class * @throws ClientException if instantiation through reflection fails for any reason. */ private T initializeComponent(String componentPath, Class compClass) throws ClientException { try { // get the constructor for the component subclass Constructor cons = compClass.getConstructor(ComponentClient.class, String.class, String.class, String.class); // prepare the constructor parameters String[] parts = componentPath.split("/jcr:content"); String location = "/jcr:content" + parts[1].substring(0, (parts[1].lastIndexOf("/") + 1)); String name = componentPath.substring(componentPath.lastIndexOf("/") + 1); // execute the constructor T comp = cons.newInstance(this, parts[0], location, name); comp.getComponentNode(); return comp; } catch (Exception e) { throw new ClientException("Instantiation failed", e); } } /** * Use this method to register additional component wrappers with the client. All wrappers * from the framework are registered by default. The registered components are used by {@link #getComponent(String)} * to return the correct wrapper for a given component path, and by the * {@link com.adobe.cq.testing.client.components.AbstractComponent#getNext() AbstractComponent.getNext()} and * {@link com.adobe.cq.testing.client.components.AbstractComponent#getPrevious() AbstractComponent.getPrevious()} * to return the next/previous component * @param resourceType the resource type to register * @param c the corresponding component wrapper class */ public void registerComponent(String resourceType, Class c){ components.put(resourceType,c); } /** * Returns the component wrapper class, that has been registered with this resourceType or * null if no such resourceType is known. you can register additional component wrappers * using {@link #registerComponent(String, Class)}}. * * @param resourceType resource type to look up * @return the corresponding component wrapper class or null if not fund */ public Class getCompClassByResourceType(String resourceType){ return components.get(resourceType); } /** * Deletes a component. * @param delComp The component to delete * * @throws ClientException If the delete request fails */ public void deleteComponent(AbstractComponent delComp) throws ClientException { deleteComponent(delComp.getComponentPath()); } /** * Deletes a component. * @param componentPath the path to the components node * @throws ClientException If the delete request fails */ public void deleteComponent(String componentPath) throws ClientException { HttpEntity entity = FormEntityBuilder.create().addParameter(":operation","delete").build(); doPost(componentPath, entity); } /** * @return the value of the component's default relative location, possibly null */ public String getDefaultComponentRelativeLocation() { return getValue(CONFIG_KEY_RELATIVE_LOCATION); } /** * Sets a new value for the component's default relative location * * @param defaultComponentRelativeLocation the new value for the default component relative location */ public void setDefaultComponentRelativeLocation(String defaultComponentRelativeLocation) { getValues().put(CONFIG_KEY_RELATIVE_LOCATION, defaultComponentRelativeLocation); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy