mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge remote-tracking branch 'origin/v5-dev' into v5-dev
This commit is contained in:
commit
7e0c73485b
@ -3,12 +3,17 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.6.3 (2021-03-31)
|
||||
# 5.6.3 (2021-04-04)
|
||||
|
||||
### 新特性
|
||||
* 【core 】 修改数字转换的实现,增加按照指定端序转换(pr#1492@Github)
|
||||
* 【core 】 修改拆分byte数组时最后一组长度的规则(pr#1494@Github)
|
||||
* 【core 】 新增根据日期获取节气(pr#1496@Github)
|
||||
* 【core 】 mapToBean()添加对布尔值is前缀的识别(pr#294@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复Validator.isUrl()传空返回true(issue#I3ETTY@Gitee)
|
||||
* 【db 】 修复数据库driver根据url的判断识别错误问题(issue#I3EWBI@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,7 +10,14 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map值提供者,支持驼峰和下划线的key兼容。<br>
|
||||
* 假设目标属性为firstName,则Map中为firstName或first_name都可以对应到值。
|
||||
* 假设目标属性为firstName,则Map中以下形式的值都可以对应:
|
||||
* <ul>
|
||||
* <li>firstName</li>
|
||||
* <li>first_name</li>
|
||||
* <li>isFirstName(如果为Boolean或boolean类型的值)</li>
|
||||
* <li>is_first_name(如果为Boolean或boolean类型的值)</li>
|
||||
* </ul>
|
||||
* 为firstName或first_name都可以对应到值。
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
@ -50,23 +57,53 @@ public class MapValueProvider implements ValueProvider<String> {
|
||||
|
||||
@Override
|
||||
public Object value(String key, Type valueType) {
|
||||
Object value = map.get(key);
|
||||
if (null == value) {
|
||||
//检查下划线模式
|
||||
value = map.get(StrUtil.toUnderlineCase(key));
|
||||
final String key1 = getKey(key, valueType);
|
||||
if (null == key1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object value = map.get(key1);
|
||||
return Convert.convertWithCheck(valueType, value, null, this.ignoreError);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
return null != getKey(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得map中可能包含的key,不包含返回null
|
||||
*
|
||||
* @param key map中可能包含的key
|
||||
* @param valueType 值类型,用于判断是否为Boolean,可以为null
|
||||
* @return map中可能包含的key
|
||||
*/
|
||||
private String getKey(String key, Type valueType) {
|
||||
if (map.containsKey(key)) {
|
||||
return true;
|
||||
} else {
|
||||
//检查下划线模式
|
||||
return map.containsKey(StrUtil.toUnderlineCase(key));
|
||||
return key;
|
||||
}
|
||||
|
||||
//检查下划线模式
|
||||
String customKey = StrUtil.toUnderlineCase(key);
|
||||
if (map.containsKey(customKey)) {
|
||||
return customKey;
|
||||
}
|
||||
|
||||
//检查boolean类型
|
||||
if (null == valueType || Boolean.class == valueType || boolean.class == valueType) {
|
||||
//boolean类型字段字段名支持两种方式
|
||||
customKey = StrUtil.upperFirstAndAddPre(key, "is");
|
||||
if (map.containsKey(customKey)) {
|
||||
return customKey;
|
||||
}
|
||||
|
||||
//检查下划线模式
|
||||
customKey = StrUtil.toUnderlineCase(customKey);
|
||||
if (map.containsKey(customKey)) {
|
||||
return customKey;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.date.chinese.ChineseMonth;
|
||||
import cn.hutool.core.date.chinese.GanZhi;
|
||||
import cn.hutool.core.date.chinese.LunarFestival;
|
||||
import cn.hutool.core.date.chinese.LunarInfo;
|
||||
import cn.hutool.core.date.chinese.SolarTerms;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.Calendar;
|
||||
@ -327,6 +328,16 @@ public class ChineseDate {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得节气
|
||||
* @return 获得节气
|
||||
* @since 5.6.3
|
||||
*/
|
||||
public String getTerm() {
|
||||
return SolarTerms.getTerm(gyear, gmonth, gday);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为标准的日期格式来表示农历日期,例如2020-01-13
|
||||
*
|
||||
|
@ -1,45 +1,21 @@
|
||||
package cn.hutool.core.date.chinese;
|
||||
|
||||
import cn.hutool.core.date.ChineseDate;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 24节气相关信息
|
||||
*
|
||||
* @author looly
|
||||
* @author looly, zak
|
||||
* @since 5.4.1
|
||||
*/
|
||||
public class SolarTerms {
|
||||
|
||||
/**
|
||||
* 根据节气修正干支月
|
||||
*
|
||||
* @param y 月
|
||||
* @param n 节气
|
||||
* @return 干支月
|
||||
*/
|
||||
public static int getTerm(int y, int n) {
|
||||
if (y < 1900 || y > 2100) {
|
||||
return -1;
|
||||
}
|
||||
if (n < 1 || n > 24) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
String _table = S_TERM_INFO[y - 1900];
|
||||
Integer[] _info = new Integer[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_info[i] = NumberUtil.parseInt("0x" + _table.substring(i * 5, 5 * (i + 1)));
|
||||
}
|
||||
String[] _calday = new String[24];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_calday[4 * i] = _info[i].toString().substring(0, 1);
|
||||
_calday[4 * i + 1] = _info[i].toString().substring(1, 3);
|
||||
_calday[4 * i + 2] = _info[i].toString().substring(3, 4);
|
||||
_calday[4 * i + 3] = _info[i].toString().substring(4, 6);
|
||||
}
|
||||
return NumberUtil.parseInt(_calday[n - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1900-2100各年的24节气日期速查表
|
||||
* 此表来自:https://github.com/jjonline/calendar.js/blob/master/calendar.js
|
||||
@ -112,4 +88,121 @@ public class SolarTerms {
|
||||
"7f0e36665b66a449801e9808297c35", "665f67f0e37f14898082b072297c35", "7ec967f0e37f14998082b0787b06bd",
|
||||
"7f07e7f0e47f531b0723b0b6fb0721", "7f0e26665b66a449801e9808297c35", "665f67f0e37f1489801eb072297c35",
|
||||
"7ec967f0e37f14998082b0787b06bd", "7f07e7f0e47f531b0723b0b6fb0721", "7f0e27f1487f531b0b0bb0b6fb0722"};
|
||||
|
||||
/**
|
||||
* 24节气
|
||||
*/
|
||||
private static final String[] TERMS = {
|
||||
"小寒", "大寒", "立春", "雨水", "惊蛰", "春分",
|
||||
"清明", "谷雨", "立夏", "小满", "芒种", "夏至",
|
||||
"小暑", "大暑", "立秋", "处暑", "白露", "秋分",
|
||||
"寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
|
||||
};
|
||||
|
||||
/**
|
||||
* 传入公历y年获得该年第n个节气的公历日期
|
||||
*
|
||||
* @param y 公历年(1900-2100)
|
||||
* @param n 二十四节气中的第几个节气(1~24);从n=1(小寒)算起
|
||||
* @return getTerm(1987,3) -》4;意即1987年2月4日立春
|
||||
*/
|
||||
public static int getTerm(int y, int n) {
|
||||
if (y < 1900 || y > 2100) {
|
||||
return -1;
|
||||
}
|
||||
if (n < 1 || n > 24) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final String _table = S_TERM_INFO[y - 1900];
|
||||
Integer[] _info = new Integer[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_info[i] = Integer.parseInt(_table.substring(i * 5, 5 * (i + 1)), 16);
|
||||
}
|
||||
String[] _calday = new String[24];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_calday[4 * i] = _info[i].toString().substring(0, 1);
|
||||
_calday[4 * i + 1] = _info[i].toString().substring(1, 3);
|
||||
_calday[4 * i + 2] = _info[i].toString().substring(3, 4);
|
||||
_calday[4 * i + 3] = _info[i].toString().substring(4, 6);
|
||||
}
|
||||
return NumberUtil.parseInt(_calday[n - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据日期获取节气
|
||||
* @param date 日期
|
||||
* @return 返回指定日期所处的节气
|
||||
*/
|
||||
public static String getTerm(Date date) {
|
||||
final DateTime dt = DateUtil.date(date);
|
||||
return getTermInternal(dt.year(), dt.month() + 1, dt.dayOfMonth());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据农历日期获取节气
|
||||
* @param chineseDate 农历日期
|
||||
* @return 返回指定日期所处的节气
|
||||
*/
|
||||
public static String getTerm(ChineseDate chineseDate) {
|
||||
return chineseDate.getTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据日期获取节气
|
||||
* @param date 日期
|
||||
* @return 返回指定日期所处的节气
|
||||
*/
|
||||
public static String getTerm(LocalDate date) {
|
||||
return getTermInternal(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年月日获取节气
|
||||
* @param year 公历年
|
||||
* @param mouth 公历月,从1开始
|
||||
* @param day 公历日,从1开始
|
||||
* @return 返回指定年月日所处的节气
|
||||
*/
|
||||
public static String getTerm(int year, int mouth, int day) {
|
||||
return getTerm(LocalDate.of(year, mouth, day));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年月日获取节气, 内部方法,不对月和日做有效校验
|
||||
* @param year 年
|
||||
* @param mouth 月,从1计数
|
||||
* @param day 日,从1计数
|
||||
* @return 返回指定年月日所处的节气
|
||||
*/
|
||||
private static String getTermInternal(int year, int mouth, int day) {
|
||||
if (year < 1900 || year > 2100) {
|
||||
throw new IllegalArgumentException("只支持1900-2100之间的日期获取节气");
|
||||
}
|
||||
|
||||
final String termTable = S_TERM_INFO[year - 1900];
|
||||
|
||||
// 节气速查表中每5个字符含有4个节气,通过月份直接计算偏移
|
||||
final int segment = (mouth + 1) / 2 - 1;
|
||||
final int termInfo = Integer.parseInt(termTable.substring(segment * 5, (segment + 1) * 5), 16);
|
||||
final String termInfoStr = String.valueOf(termInfo);
|
||||
|
||||
final String[] segmentTable = new String[24];
|
||||
segmentTable[0] = termInfoStr.substring(0, 1);
|
||||
segmentTable[1] = termInfoStr.substring(1, 3);
|
||||
segmentTable[2] = termInfoStr.substring(3, 4);
|
||||
segmentTable[3] = termInfoStr.substring(4, 6);
|
||||
|
||||
// 奇数月份的节气在前2个,偶数月份的节气在后两个
|
||||
int segmentOffset = (mouth & 1) == 1 ? 0 : 2;
|
||||
if (day < NumberUtil.parseInt(segmentTable[segmentOffset])) {
|
||||
int idx = segment * 4 + segmentOffset - 1;
|
||||
return TERMS[idx < 0 ? 23 : idx];
|
||||
}
|
||||
if(day >= NumberUtil.parseInt(segmentTable[segmentOffset + 1])) {
|
||||
return TERMS[segment * 4 + segmentOffset + 1];
|
||||
}
|
||||
return TERMS[segment * 4 + segmentOffset];
|
||||
}
|
||||
}
|
||||
|
@ -951,6 +951,9 @@ public class Validator {
|
||||
* @return 是否为URL
|
||||
*/
|
||||
public static boolean isUrl(CharSequence value) {
|
||||
if(StrUtil.isBlank(value)){
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
new java.net.URL(StrUtil.str(value));
|
||||
} catch (MalformedURLException e) {
|
||||
|
@ -10,6 +10,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -18,13 +19,7 @@ import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Bean工具单元测试
|
||||
@ -201,6 +196,8 @@ public class BeanUtilTest {
|
||||
person.setName("测试A11");
|
||||
person.setSubName("sub名字");
|
||||
person.setSlow(true);
|
||||
person.setBooleana(true);
|
||||
person.setBooleanb(true);
|
||||
|
||||
Map<String, Object> map = BeanUtil.beanToMap(person);
|
||||
Assert.assertEquals("sub名字", map.get("aliasSubName"));
|
||||
@ -211,9 +208,13 @@ public class BeanUtilTest {
|
||||
Map<String, Object> map = MapUtil.newHashMap();
|
||||
map.put("aliasSubName", "sub名字");
|
||||
map.put("slow", true);
|
||||
map.put("is_booleana", "1");
|
||||
map.put("is_booleanb", true);
|
||||
|
||||
final SubPersonWithAlias subPersonWithAlias = BeanUtil.toBean(map, SubPersonWithAlias.class);
|
||||
Assert.assertEquals("sub名字", subPersonWithAlias.getSubName());
|
||||
Assert.assertTrue(subPersonWithAlias.isBooleana());
|
||||
Assert.assertEquals(true, subPersonWithAlias.getBooleanb());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -360,11 +361,14 @@ public class BeanUtilTest {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public static class SubPersonWithAlias extends Person {
|
||||
// boolean参数值非isXXX形式
|
||||
@Alias("aliasSubName")
|
||||
private String subName;
|
||||
private Boolean slow;
|
||||
private boolean booleana;
|
||||
private Boolean booleanb;
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
@ -0,0 +1,105 @@
|
||||
package cn.hutool.core.date.chinese;
|
||||
|
||||
import cn.hutool.core.date.ChineseDate;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SolarTermsTest {
|
||||
|
||||
@Test
|
||||
public void getTermTest1(){
|
||||
final int term = SolarTerms.getTerm(1987, 3);
|
||||
Assert.assertEquals(4, term);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTermTest() {
|
||||
Assert.assertEquals("冬至", SolarTerms.getTerm(2021, 1, 4));
|
||||
|
||||
Assert.assertEquals("小寒", SolarTerms.getTerm(2021, 1, 5));
|
||||
Assert.assertEquals("小寒", SolarTerms.getTerm(2021, 1, 19));
|
||||
|
||||
Assert.assertEquals("大寒", SolarTerms.getTerm(2021, 1, 20));
|
||||
Assert.assertEquals("大寒", SolarTerms.getTerm(2021, 2, 2));
|
||||
|
||||
Assert.assertEquals("立春", SolarTerms.getTerm(2021, 2, 3));
|
||||
Assert.assertEquals("立春", SolarTerms.getTerm(2021, 2, 17));
|
||||
|
||||
Assert.assertEquals("雨水", SolarTerms.getTerm(2021, 2, 18));
|
||||
Assert.assertEquals("雨水", SolarTerms.getTerm(2021, 3, 4));
|
||||
|
||||
Assert.assertEquals("惊蛰", SolarTerms.getTerm(2021, 3, 5));
|
||||
Assert.assertEquals("惊蛰", SolarTerms.getTerm(2021, 3, 19));
|
||||
|
||||
Assert.assertEquals("春分", SolarTerms.getTerm(2021, 3, 20));
|
||||
Assert.assertEquals("春分", SolarTerms.getTerm(2021, 4, 3));
|
||||
|
||||
Assert.assertEquals("清明", SolarTerms.getTerm(2021, 4, 4));
|
||||
Assert.assertEquals("清明", SolarTerms.getTerm(2021, 4, 10));
|
||||
Assert.assertEquals("清明", SolarTerms.getTerm(2021, 4, 19));
|
||||
|
||||
Assert.assertEquals("谷雨", SolarTerms.getTerm(2021, 4, 20));
|
||||
Assert.assertEquals("谷雨", SolarTerms.getTerm(2021, 4, 29));
|
||||
Assert.assertEquals("谷雨", SolarTerms.getTerm(2021, 5, 4));
|
||||
|
||||
Assert.assertEquals("立夏", SolarTerms.getTerm(2021, 5, 5));
|
||||
Assert.assertEquals("立夏", SolarTerms.getTerm(2021, 5, 9));
|
||||
Assert.assertEquals("立夏", SolarTerms.getTerm(2021, 5, 20));
|
||||
|
||||
Assert.assertEquals("小满", SolarTerms.getTerm(2021, 5, 21));
|
||||
Assert.assertEquals("小满", SolarTerms.getTerm(2021, 6, 4));
|
||||
|
||||
Assert.assertEquals("芒种", SolarTerms.getTerm(2021, 6, 5));
|
||||
Assert.assertEquals("芒种", SolarTerms.getTerm(2021, 6, 20));
|
||||
|
||||
Assert.assertEquals("夏至", SolarTerms.getTerm(2021, 6, 21));
|
||||
Assert.assertEquals("夏至", SolarTerms.getTerm(2021, 7, 6));
|
||||
|
||||
Assert.assertEquals("小暑", SolarTerms.getTerm(2021, 7, 7));
|
||||
Assert.assertEquals("小暑", SolarTerms.getTerm(2021, 7, 21));
|
||||
|
||||
Assert.assertEquals("大暑", SolarTerms.getTerm(2021, 7, 22));
|
||||
Assert.assertEquals("大暑", SolarTerms.getTerm(2021, 8, 6));
|
||||
|
||||
Assert.assertEquals("立秋", SolarTerms.getTerm(2021, 8, 7));
|
||||
|
||||
Assert.assertEquals("处暑", SolarTerms.getTerm(2021, 8, 23));
|
||||
Assert.assertEquals("处暑", SolarTerms.getTerm(2021, 9, 6));
|
||||
|
||||
Assert.assertEquals("白露", SolarTerms.getTerm(2021, 9, 7));
|
||||
Assert.assertEquals("白露", SolarTerms.getTerm(2021, 9, 22));
|
||||
|
||||
Assert.assertEquals("秋分", SolarTerms.getTerm(2021, 9, 23));
|
||||
Assert.assertEquals("秋分", SolarTerms.getTerm(2021, 10, 7));
|
||||
|
||||
Assert.assertEquals("寒露", SolarTerms.getTerm(2021, 10, 8));
|
||||
Assert.assertEquals("寒露", SolarTerms.getTerm(2021, 10, 22));
|
||||
|
||||
Assert.assertEquals("霜降", SolarTerms.getTerm(2021, 10, 23));
|
||||
Assert.assertEquals("霜降", SolarTerms.getTerm(2021, 11, 6));
|
||||
|
||||
Assert.assertEquals("立冬", SolarTerms.getTerm(2021, 11, 7));
|
||||
Assert.assertEquals("立冬", SolarTerms.getTerm(2021, 11, 21));
|
||||
|
||||
Assert.assertEquals("小雪", SolarTerms.getTerm(2021, 11, 22));
|
||||
Assert.assertEquals("小雪", SolarTerms.getTerm(2021, 12, 6));
|
||||
|
||||
Assert.assertEquals("大雪", SolarTerms.getTerm(2021, 12, 7));
|
||||
Assert.assertEquals("大雪", SolarTerms.getTerm(2021, 12, 20));
|
||||
|
||||
Assert.assertEquals("冬至", SolarTerms.getTerm(2021, 12, 21));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getTermByDateTest() {
|
||||
Assert.assertEquals("春分", SolarTerms.getTerm(DateUtil.parseDate("2021-04-02")));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getTermByChineseDateTest() {
|
||||
Assert.assertEquals("清明", SolarTerms.getTerm(new ChineseDate(2021, 2, 25)));
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.db.dialect;
|
||||
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.db.dialect.impl.AnsiSqlDialect;
|
||||
import cn.hutool.db.dialect.impl.H2Dialect;
|
||||
@ -115,6 +116,12 @@ public class DialectFactory {
|
||||
// 全部转为小写,忽略大小写
|
||||
nameContainsProductInfo = StrUtil.cleanBlank(nameContainsProductInfo.toLowerCase());
|
||||
|
||||
// 首先判断是否为标准的JDBC URL,截取jdbc:xxxx:中间部分
|
||||
final String name = ReUtil.getGroup1("jdbc:(.*?):", nameContainsProductInfo);
|
||||
if(StrUtil.isNotBlank(name)){
|
||||
nameContainsProductInfo = name;
|
||||
}
|
||||
|
||||
String driver = null;
|
||||
if (nameContainsProductInfo.contains("mysql")) {
|
||||
driver = ClassLoaderUtil.isPresent(DRIVER_MYSQL_V6) ? DRIVER_MYSQL_V6 : DRIVER_MYSQL;
|
||||
|
@ -0,0 +1,14 @@
|
||||
package cn.hutool.db.dialect;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DriverUtilTest {
|
||||
|
||||
@Test
|
||||
public void identifyDriverTest(){
|
||||
String url = "jdbc:h2:file:./db/test;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL";
|
||||
String driver = DriverUtil.identifyDriver(url); // driver 返回 mysql 的 driver
|
||||
Assert.assertEquals("org.h2.Driver", driver);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user