001/** 002 * Copyright (C) 2006-2018 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.emptyMap; 020import static java.util.Collections.singletonList; 021import static java.util.Comparator.comparing; 022import static java.util.Optional.ofNullable; 023import static lombok.AccessLevel.PRIVATE; 024 025import java.io.ByteArrayOutputStream; 026import java.lang.annotation.Annotation; 027import java.lang.reflect.Type; 028import java.nio.charset.StandardCharsets; 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.Map; 032import java.util.stream.Collectors; 033 034import org.talend.sdk.component.runtime.manager.ParameterMeta; 035import org.talend.sdk.component.runtime.manager.configuration.ConfigurationMapper; 036import org.talend.sdk.component.runtime.manager.reflect.ParameterModelService; 037 038import lombok.AllArgsConstructor; 039import lombok.NoArgsConstructor; 040 041@NoArgsConstructor(access = PRIVATE) 042public class SimpleFactory { 043 044 public static ByExample configurationByExample() { 045 return new ByExample(); 046 } 047 048 public static <T> Map<String, String> configurationByExample(final T instance) { 049 return configurationByExample().forInstance(instance).configured().toMap(); 050 } 051 052 public static <T> Map<String, String> configurationByExample(final T instance, final String prefix) { 053 return configurationByExample().forInstance(instance).withPrefix(prefix).configured().toMap(); 054 } 055 056 private static class SimpleParameterModelService extends ParameterModelService { 057 058 private ParameterMeta build(final String name, final String prefix, final Type genericType, 059 final Annotation[] annotations, final Collection<String> i18nPackages) { 060 return super.buildParameter(name, prefix, null, genericType, annotations, i18nPackages, false); 061 } 062 } 063 064 @NoArgsConstructor(access = PRIVATE) 065 public static class ByExample { 066 067 private String prefix; 068 069 private Object instance; 070 071 public ByExample withPrefix(final String prefix) { 072 this.prefix = prefix; 073 return this; 074 } 075 076 public <T> ByExample forInstance(final T instance) { 077 this.instance = instance; 078 return this; 079 } 080 081 public ConfigurationByExample configured() { 082 return new ConfigurationByExample(this); 083 } 084 } 085 086 @AllArgsConstructor(access = PRIVATE) 087 public static class ConfigurationByExample { 088 089 private static final ConfigurationMapper CONFIGURATION_MAPPER = new ConfigurationMapper(); 090 091 private final ByExample byExample; 092 093 public Map<String, String> toMap() { 094 if (byExample.instance == null) { 095 return emptyMap(); 096 } 097 final String usedPrefix = ofNullable(byExample.prefix).orElse("configuration."); 098 final ParameterMeta params = new SimpleParameterModelService().build(usedPrefix, usedPrefix, 099 byExample.instance.getClass(), new Annotation[0], 100 new ArrayList<>(singletonList(byExample.instance.getClass().getPackage().getName()))); 101 return CONFIGURATION_MAPPER.map(params.getNestedParameters(), byExample.instance); 102 } 103 104 public String toQueryString() { 105 return toMap() 106 .entrySet() 107 .stream() 108 .sorted(comparing(Map.Entry::getKey)) 109 .map(entry -> entry.getKey() + "=" + encode(entry.getValue())) 110 .collect(Collectors.joining("&")); 111 } 112 113 private static String encode(final String source) { 114 final byte[] bytes = source.getBytes(StandardCharsets.UTF_8); 115 final ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length); 116 boolean changed = false; 117 for (final byte rawByte : bytes) { 118 byte b = rawByte; 119 if (b < 0) { 120 b += 256; 121 } 122 if ((b >= 'a' && b <= 'z' || b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || '-' == b || '.' == b 123 || '_' == b || '~' == b) { 124 bos.write(b); 125 } else { 126 bos.write('%'); 127 char hex1 = toUpperCase(Character.forDigit((b >> 4) & 0xF, 16)); 128 char hex2 = toUpperCase(Character.forDigit(b & 0xF, 16)); 129 bos.write(hex1); 130 bos.write(hex2); 131 changed = true; 132 } 133 } 134 return changed ? new String(bos.toByteArray(), StandardCharsets.UTF_8) : source; 135 } 136 } 137}