001/** 002 * Copyright (C) 2006-2019 Talend Inc. - www.talend.com 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.talend.sdk.component.junit; 017 018import static java.lang.Character.toUpperCase; 019import static java.util.Collections.emptyList; 020import static java.util.Collections.emptyMap; 021import static java.util.Collections.singletonList; 022import static java.util.Comparator.comparing; 023import static java.util.Optional.ofNullable; 024import static lombok.AccessLevel.PRIVATE; 025 026import java.io.ByteArrayOutputStream; 027import java.lang.annotation.Annotation; 028import java.lang.reflect.Type; 029import java.nio.charset.StandardCharsets; 030import java.util.ArrayList; 031import java.util.Collection; 032import java.util.Map; 033import java.util.stream.Collectors; 034 035import org.apache.xbean.propertyeditor.PropertyEditorRegistry; 036import org.talend.sdk.component.runtime.manager.ParameterMeta; 037import org.talend.sdk.component.runtime.manager.configuration.ConfigurationMapper; 038import org.talend.sdk.component.runtime.manager.reflect.ParameterModelService; 039import org.talend.sdk.component.runtime.manager.reflect.parameterenricher.BaseParameterEnricher; 040import org.talend.sdk.component.runtime.manager.service.LocalConfigurationService; 041 042import lombok.AllArgsConstructor; 043import lombok.NoArgsConstructor; 044 045@NoArgsConstructor(access = PRIVATE) 046public class SimpleFactory { 047 048 public static ByExample configurationByExample() { 049 return new ByExample(); 050 } 051 052 public static <T> Map<String, String> configurationByExample(final T instance) { 053 return configurationByExample().forInstance(instance).configured().toMap(); 054 } 055 056 public static <T> Map<String, String> configurationByExample(final T instance, final String prefix) { 057 return configurationByExample().forInstance(instance).withPrefix(prefix).configured().toMap(); 058 } 059 060 private static class SimpleParameterModelService extends ParameterModelService { 061 062 public SimpleParameterModelService() { 063 super(new PropertyEditorRegistry()); 064 } 065 066 private ParameterMeta build(final String name, final String prefix, final Type genericType, 067 final Annotation[] annotations, final Collection<String> i18nPackages) { 068 return super.buildParameter(name, prefix, null, genericType, annotations, i18nPackages, false, 069 new BaseParameterEnricher.Context(new LocalConfigurationService(emptyList(), "test"))); 070 } 071 } 072 073 @NoArgsConstructor(access = PRIVATE) 074 public static class ByExample { 075 076 private String prefix; 077 078 private Object instance; 079 080 public ByExample withPrefix(final String prefix) { 081 this.prefix = prefix; 082 return this; 083 } 084 085 public <T> ByExample forInstance(final T instance) { 086 this.instance = instance; 087 return this; 088 } 089 090 public ConfigurationByExample configured() { 091 return new ConfigurationByExample(this); 092 } 093 } 094 095 @AllArgsConstructor(access = PRIVATE) 096 public static class ConfigurationByExample { 097 098 private static final ConfigurationMapper CONFIGURATION_MAPPER = new ConfigurationMapper(); 099 100 private final ByExample byExample; 101 102 public Map<String, String> toMap() { 103 if (byExample.instance == null) { 104 return emptyMap(); 105 } 106 final String usedPrefix = ofNullable(byExample.prefix).orElse("configuration."); 107 final ParameterMeta params = new SimpleParameterModelService() 108 .build(usedPrefix, usedPrefix, byExample.instance.getClass(), new Annotation[0], 109 new ArrayList<>(singletonList(byExample.instance.getClass().getPackage().getName()))); 110 return CONFIGURATION_MAPPER.map(params.getNestedParameters(), byExample.instance); 111 } 112 113 public String toQueryString() { 114 return toMap() 115 .entrySet() 116 .stream() 117 .sorted(comparing(Map.Entry::getKey)) 118 .map(entry -> entry.getKey() + "=" + encode(entry.getValue())) 119 .collect(Collectors.joining("&")); 120 } 121 122 private static String encode(final String source) { 123 final byte[] bytes = source.getBytes(StandardCharsets.UTF_8); 124 final ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length); 125 boolean changed = false; 126 for (final byte rawByte : bytes) { 127 byte b = rawByte; 128 if (b < 0) { 129 b += 256; 130 } 131 if ((b >= 'a' && b <= 'z' || b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || '-' == b || '.' == b 132 || '_' == b || '~' == b) { 133 bos.write(b); 134 } else { 135 bos.write('%'); 136 char hex1 = toUpperCase(Character.forDigit((b >> 4) & 0xF, 16)); 137 char hex2 = toUpperCase(Character.forDigit(b & 0xF, 16)); 138 bos.write(hex1); 139 bos.write(hex2); 140 changed = true; 141 } 142 } 143 return changed ? new String(bos.toByteArray(), StandardCharsets.UTF_8) : source; 144 } 145 } 146}