Commit 9bfb81c7 authored by wujiang's avatar wujiang

修改采集问题

parent 8f3f8ec6
......@@ -11,293 +11,307 @@ import com.yeejoin.amos.api.householdapi.constant.ImasterConstant;
import com.yeejoin.amos.api.householdapi.face.orm.houseapi.entity.houseapi.HousepvapiRecords;
import com.yeejoin.amos.api.householdapi.face.orm.mapper.houseapi.HousepvapiRecordsMapper;
import com.yeejoin.amos.api.householdapi.face.service.impl.GoodWeDataAcquisitionServiceImpl;
import com.yeejoin.amos.openapi.enums.PVProducerInfoEnum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import java.util.*;
@Component
@Slf4j
public class ImasterUtils {
private String redisKey = "XSRF-TOKEN";
private String redisKey = "XSRF-TOKEN";
@Autowired
HousepvapiRecordsMapper housepvapiRecordsMapper;
@Autowired
RedisUtils redisUtils;
final static Logger logger = LoggerFactory.getLogger(ImasterUtils.class);
@Autowired
HousepvapiRecordsMapper housepvapiRecordsMapper;
@Autowired
RedisUtils redisUtils;
/**
* @return HashMap<String, Object> 发送请求前的准备 准备header信息
* @deprecated 根据厂商编码获取厂商的hearer
*/
public static HashMap<String, String> getHeader() {
HashMap<String, String> hashMap = new HashMap<>();
String requestParam="";
HashMap<String, String> hashMaphead = new HashMap<>();
try {
requestParam = "{ \"userName\": \""+ImasterConstant.account+"\", \"systemCode\": \""+ImasterConstant.password+"\"}";
} catch (Exception e) {
throw new RuntimeException(e);
}
String url = ImasterConstant.baseurl + ImasterConstant.tokenUrl;
HttpResponse execute = HttpUtil.createRequest(Method.POST, url).body(requestParam).execute();
String token = execute.header("xsrf-token");
/**
* @return HashMap<String, Object> 发送请求前的准备 准备header信息
* @deprecated 根据厂商编码获取厂商的hearer
*/
public static HashMap<String, String> getHeader() {
HashMap<String, String> hashMap = new HashMap<>();
String requestParam = "";
HashMap<String, String> hashMaphead = new HashMap<>();
try {
requestParam = "{ \"userName\": \"" + ImasterConstant.account + "\", \"systemCode\": \""
+ ImasterConstant.password + "\"}";
} catch (Exception e) {
throw new RuntimeException(e);
}
String url = ImasterConstant.baseurl + ImasterConstant.tokenUrl;
HttpResponse execute = HttpUtil.createRequest(Method.POST, url).body(requestParam).execute();
String token = execute.header("xsrf-token");
hashMap.put("XSRF-TOKEN", token);
return hashMap;
}
hashMap.put("XSRF-TOKEN", token);
return hashMap;
}
/**
* @param apiurl 请求url
* @param requestMethod 请求方式
* @param requestParmInfo 请求参数mapper
* @param ResultResolveRule 请求的解析
* @param tClass 需要转换成的bean
* @param <T> 泛型数据
* @return List<T> list<Result>
* @desc 根据请求参数发送http请求并且对于返回的数据进行处理
*/
public <T> List<T> getResPonse(String apiurl, String requestMethod, String requestParmInfo, String ResultResolveRule, Class<T> tClass) {
String respone = "";
String params = "";
JSONArray jsonArray = null;
List<T> result = new ArrayList<>();
try {
Object o = redisUtils.get(redisKey);
if(o != null) {
HashMap<String, String> headMap = new HashMap<>();
headMap.put("XSRF-TOKEN", o.toString());
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
JSONObject jsonObject = JSONObject.parseObject(respone);
if(jsonObject.get("failCode").toString().equals("305")) {
headMap = getHeader();
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey,headMap.get("XSRF-TOKEN"));
}
} else {
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
}
}
} else {
HashMap<String, String> headMap = getHeader();
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey,headMap.get("XSRF-TOKEN"));
}
}
} catch (Exception exception) {
return result;
}
return result;
}
/**
* @param apiurl 请求url
* @param requestMethod 请求方式
* @param requestParmInfo 请求参数mapper
* @param ResultResolveRule 请求的解析
* @param tClass 需要转换成的bean
* @param <T> 泛型数据
* @return List<T> list<Result>
* @desc 根据请求参数发送http请求并且对于返回的数据进行处理
*/
public <T> List<T> getResPonse(String apiurl, String requestMethod, String requestParmInfo,
String ResultResolveRule, Class<T> tClass) {
String respone = "";
String params = "";
JSONArray jsonArray = null;
List<T> result = new ArrayList<>();
try {
Object o = redisUtils.get(redisKey);
if (o != null) {
HashMap<String, String> headMap = new HashMap<>();
headMap.put("XSRF-TOKEN", o.toString());
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
JSONObject jsonObject = JSONObject.parseObject(respone);
if (jsonObject.get("failCode").toString().equals("305")) {
headMap = getHeader();
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey, headMap.get("XSRF-TOKEN"));
}
} else {
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
}
}
} else {
HashMap<String, String> headMap = getHeader();
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey, headMap.get("XSRF-TOKEN"));
}
}
} catch (Exception exception) {
return result;
}
return result;
}
/**
* @param apiurl 请求url
* @param requestMethod 请求方式
* @param requestParmInfo 请求参数mapper
* @param ResultResolveRule 请求的解析
* @param tClass 需要转换成的bean
* @param <T> 泛型数据
* @return List<T> list<Result>
* @desc 根据请求参数发送http请求并且对于返回的数据进行处理
*/
public <T> List<T> getResPonseOther(String apiurl, String requestMethod, String requestParmInfo, String ResultResolveRule, Class<T> tClass) {
String respone = "";
String params = "";
JSONArray jsonArray = null;
List<T> result = new ArrayList<>();
try {
Object o = redisUtils.get(redisKey);
if(o != null) {
HashMap<String, String> headMap = new HashMap<>();
headMap.put("XSRF-TOKEN", o.toString());
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
JSONObject jsonObject = JSONObject.parseObject(respone);
if(jsonObject.get("failCode").toString().equals("305")) {
headMap = getHeader();
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey,headMap.get("XSRF-TOKEN"));
}
} else {
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
}
}
} else {
HashMap<String, String> headMap = getHeader();
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey,headMap.get("XSRF-TOKEN"));
}
}
} catch (Exception exception) {
exception.printStackTrace();
return result;
}
return result;
}
/**
* @param apiurl 请求url
* @param requestMethod 请求方式
* @param requestParmInfo 请求参数mapper
* @param ResultResolveRule 请求的解析
* @param tClass 需要转换成的bean
* @param <T> 泛型数据
* @return List<T> list<Result>
* @desc 根据请求参数发送http请求并且对于返回的数据进行处理
*/
public <T> List<T> getResPonseOther(String apiurl, String requestMethod, String requestParmInfo,
String ResultResolveRule, Class<T> tClass) {
String respone = "";
String params = "";
JSONArray jsonArray = null;
List<T> result = new ArrayList<>();
try {
Object o = redisUtils.get(redisKey);
if (o != null) {
HashMap<String, String> headMap = new HashMap<>();
headMap.put("XSRF-TOKEN", o.toString());
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
JSONObject jsonObject = JSONObject.parseObject(respone);
if (jsonObject.get("failCode").toString().equals("305")) {
headMap = getHeader();
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey, headMap.get("XSRF-TOKEN"));
}
} else {
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
}
}
} else {
HashMap<String, String> headMap = getHeader();
String url = ImasterConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolveruleOther(ResultResolveRule, respone);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
redisUtils.set(redisKey, headMap.get("XSRF-TOKEN"));
}
}
} catch (Exception exception) {
exception.printStackTrace();
return result;
}
return result;
}
/**
* @param resultResovle 请求返回的解析规则 来源与数据库
* @param response 请求返回的字符串
* @return 解析后的数据
* @desc 根据解析规则解析请求返回数据
*/
public static JSONArray handlerResponseByResultResolverule(String resultResovle, String response) {
JSONObject jsonObject = JSONObject.parseObject(response);
JSONArray jsonArray = new JSONArray();
if (ObjectUtil.isNotEmpty(resultResovle)) {
String[] rules = resultResovle.split(",");
if (rules.length > 0) {
for (int i = 0; i < rules.length; i++) {
try {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
if (jsonObject == null) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
} catch (Exception exception) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
}
}
if (jsonArray.size() == 0) {
jsonArray.addAll((JSONArray)jsonObject.get("list"));
}
}
return jsonArray;
}
/**
* @param resultResovle 请求返回的解析规则 来源与数据库
* @param response 请求返回的字符串
* @return 解析后的数据
* @desc 根据解析规则解析请求返回数据
*/
public static JSONArray handlerResponseByResultResolverule(String resultResovle, String response) {
JSONObject jsonObject = JSONObject.parseObject(response);
JSONArray jsonArray = new JSONArray();
if (ObjectUtil.isNotEmpty(resultResovle)) {
String[] rules = resultResovle.split(",");
if (rules.length > 0) {
for (int i = 0; i < rules.length; i++) {
try {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
if (jsonObject == null) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
} catch (Exception exception) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
}
}
if (jsonArray.size() == 0) {
jsonArray.addAll((JSONArray) jsonObject.get("list"));
}
}
return jsonArray;
}
/**
* @param resultResovle 请求返回的解析规则 来源与数据库
* @param response 请求返回的字符串
* @return 解析后的数据
* @desc 根据解析规则解析请求返回数据
*/
public static JSONArray handlerResponseByResultResolveruleOther(String resultResovle, String response) {
JSONObject jsonObject = JSONObject.parseObject(response);
JSONArray jsonArray = new JSONArray();
JSONArray jsonArrayRet = new JSONArray();
if (ObjectUtil.isNotEmpty(resultResovle)) {
String[] rules = resultResovle.split(",");
if (rules.length > 0) {
for (int i = 0; i < rules.length; i++) {
try {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
if (jsonObject == null) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
} catch (Exception exception) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
}
}
if (jsonArray.size() != 0) {
for( int i=0; i<jsonArray.size();i++ ) {
JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
if(jsonObject1.get("dataItemMap") != null) {
JSONObject jsonObject2 = (JSONObject)jsonObject1.get("dataItemMap");
if(jsonObject1.get("sn") != null) {
jsonObject2.put("inverterId", jsonObject1.get("sn").toString());
}
if(jsonObject1.get("stationCode") != null) {
jsonObject2.put("stationCode", jsonObject1.get("stationCode").toString());
}
if(jsonObject1.get("collectTime") != null) {
jsonObject2.put("collectTime", jsonObject1.get("collectTime").toString());
}
/**
* @param resultResovle 请求返回的解析规则 来源与数据库
* @param response 请求返回的字符串
* @return 解析后的数据
* @desc 根据解析规则解析请求返回数据
*/
public static JSONArray handlerResponseByResultResolveruleOther(String resultResovle, String response) {
JSONObject jsonObject = JSONObject.parseObject(response);
JSONArray jsonArray = new JSONArray();
JSONArray jsonArrayRet = new JSONArray();
if (ObjectUtil.isNotEmpty(resultResovle)) {
String[] rules = resultResovle.split(",");
if (rules.length > 0) {
for (int i = 0; i < rules.length; i++) {
try {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
if (jsonObject == null) {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
}
} catch (Exception exception) {
try {
jsonArray = (JSONArray) jsonObject.get(rules[i]);
} catch (Exception e) {
e.printStackTrace();
logger.error("华为数据解析错误:" + jsonObject.get(rules[i]));
}
}
}
}
if (jsonArray.size() != 0) {
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
if (jsonObject1.get("dataItemMap") != null) {
JSONObject jsonObject2 = (JSONObject) jsonObject1.get("dataItemMap");
if (jsonObject1.get("sn") != null) {
jsonObject2.put("inverterId", jsonObject1.get("sn").toString());
}
if (jsonObject1.get("stationCode") != null) {
jsonObject2.put("stationCode", jsonObject1.get("stationCode").toString());
}
if (jsonObject1.get("collectTime") != null) {
jsonObject2.put("collectTime", jsonObject1.get("collectTime").toString());
}
jsonArrayRet.add(jsonObject2);
}
}
}
}
return jsonArrayRet;
}
jsonArrayRet.add(jsonObject2);
}
}
}
}
return jsonArrayRet;
}
public String sendRequest(String requestMethod, String url, String params, HashMap<String, String> headMap) {
HousepvapiRecords housepvapiRecords = new HousepvapiRecords();
housepvapiRecords.setRecDate(new Date());
housepvapiRecords.setRequestUrl(url);
housepvapiRecords.setRequestMothed(requestMethod);
housepvapiRecords.setRequestHeaders(JSONObject.toJSONString(headMap));
housepvapiRecords.setRequestParams(params);
housepvapiRecords.setThridCode(PVProducerInfoEnum.HUAWEI.getCode());
String respone = "";
if (requestMethod.equals("POST")) {
respone = HttpUtil.createPost(url).headerMap(headMap, false).
body(params).execute().body();
}
if (requestMethod.equals("GET")) {
respone = HttpUtil.createGet(url).headerMap(headMap, true).
body(params).execute().body();
}
housepvapiRecords.setResponse(respone);
// housepvapiRecordsMapper.insert(housepvapiRecords);
//log.info("华为数据请求详情:"+JSONObject.toJSONString(housepvapiRecords));
return respone;
}
public String sendRequest(String requestMethod, String url, String params, HashMap<String, String> headMap) {
HousepvapiRecords housepvapiRecords = new HousepvapiRecords();
housepvapiRecords.setRecDate(new Date());
housepvapiRecords.setRequestUrl(url);
housepvapiRecords.setRequestMothed(requestMethod);
housepvapiRecords.setRequestHeaders(JSONObject.toJSONString(headMap));
housepvapiRecords.setRequestParams(params);
housepvapiRecords.setThridCode(PVProducerInfoEnum.HUAWEI.getCode());
String respone = "";
if (requestMethod.equals("POST")) {
respone = HttpUtil.createPost(url).headerMap(headMap, false).body(params).execute().body();
}
if (requestMethod.equals("GET")) {
respone = HttpUtil.createGet(url).headerMap(headMap, true).body(params).execute().body();
}
housepvapiRecords.setResponse(respone);
// housepvapiRecordsMapper.insert(housepvapiRecords);
// log.info("华为数据请求详情:"+JSONObject.toJSONString(housepvapiRecords));
return respone;
}
/***
*
* @param params 参数字符窜
* @param headMap header头
* @param orginalAuthorization 原始的orginalAuthorization
* @param appsecret appsecret
* @desc 锦浪云请求参数及head头处理
*/
public void JLYHeaderMapHandler(String params, HashMap<String, String> headMap, String orginalAuthorization, String appsecret, String apiurl) {
String contentMD5 = GoLangHeaderUtils.getDigest(params);
headMap.put("Date", GoLangHeaderUtils.getGMTTime());
String param = "POST" + "\n" + contentMD5 + "\n" + "application/json" + "\n" + headMap.get("Date") + "\n" + apiurl;
String sign = "";
try {
sign = GoLangHeaderUtils.HmacSHA1Encrypt(param, appsecret);
} catch (Exception e) {
throw new RuntimeException(e);
}
headMap.put("Content-MD5", contentMD5);
headMap.put("Authorization", orginalAuthorization + sign);
}
/***
*
* @param params 参数字符窜
* @param headMap header头
* @param orginalAuthorization 原始的orginalAuthorization
* @param appsecret appsecret
* @desc 锦浪云请求参数及head头处理
*/
public void JLYHeaderMapHandler(String params, HashMap<String, String> headMap, String orginalAuthorization,
String appsecret, String apiurl) {
String contentMD5 = GoLangHeaderUtils.getDigest(params);
headMap.put("Date", GoLangHeaderUtils.getGMTTime());
String param = "POST" + "\n" + contentMD5 + "\n" + "application/json" + "\n" + headMap.get("Date") + "\n"
+ apiurl;
String sign = "";
try {
sign = GoLangHeaderUtils.HmacSHA1Encrypt(param, appsecret);
} catch (Exception e) {
throw new RuntimeException(e);
}
headMap.put("Content-MD5", contentMD5);
headMap.put("Authorization", orginalAuthorization + sign);
}
/**
* @param pageSizeResovle
* @param response
* @return
* @desc 根据分页规则 获取分页数
*/
public Integer getPagesize(String pageSizeResovle, String response) {
Integer pageSize = 0;
String[] rules = pageSizeResovle.split(",");
JSONObject jsonObject = JSONObject.parseObject(response);
if (rules.length > 0) {
for (int i = 0; i < rules.length - 1; i++) {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
}
}
pageSize = (Integer) jsonObject.get(rules[rules.length - 1]);
return pageSize;
}
/**
* @param pageSizeResovle
* @param response
* @return
* @desc 根据分页规则 获取分页数
*/
public Integer getPagesize(String pageSizeResovle, String response) {
Integer pageSize = 0;
String[] rules = pageSizeResovle.split(",");
JSONObject jsonObject = JSONObject.parseObject(response);
if (rules.length > 0) {
for (int i = 0; i < rules.length - 1; i++) {
jsonObject = (JSONObject) jsonObject.get(rules[i]);
}
}
pageSize = (Integer) jsonObject.get(rules[rules.length - 1]);
return pageSize;
}
// public static void main(String[] args) {
// HashMap<String, Object> requestInfo = new HashMap<>();
......
......@@ -70,7 +70,7 @@ public class KsolarRequestUtil {
String url = KSolarConstant.baseurl + apiurl;
respone = sendRequest(requestMethod, url, requestParmInfo, headMap);
jsonArray = handlerResponseByResultResolverule(ResultResolveRule, respone);
log.info("原始数据:{}", jsonArray);
//log.info("原始数据:{}", jsonArray);
if (!ObjectUtils.isEmpty(jsonArray)) {
result = JSONArray.parseArray(jsonArray.toJSONString(), tClass);
}
......
......@@ -320,7 +320,7 @@ public class GoodWeDataAcquisitionServiceImpl implements GoodWeDataAcquisitionSe
@Async
public void stationDetail() {
long ts = System.currentTimeMillis();
logger.info("-------固德威同步场站和告警开始" + ts + "------- " + sdf.format(new Date()));
logger.info("-------固德威同步场站详情开始" + ts + "------- " + sdf.format(new Date()));
List<String> stationIds = goodWeStationMonitorListMapper.getStationIds();
stationIds.forEach(stationId -> {
HashMap<String, Object> requestInfo = new HashMap<>();
......@@ -349,7 +349,7 @@ public class GoodWeDataAcquisitionServiceImpl implements GoodWeDataAcquisitionSe
});
}
});
logger.info("-------固德威同步场站和告警结束" + ts + "------- " + sdf.format(new Date()));
logger.info("-------固德威同步场站详情结束" + ts + "------- " + sdf.format(new Date()));
}
@Override
......
......@@ -495,10 +495,8 @@ public class SunlightServiceImpl implements SunlightService {
if (device != null) {
// 获取逆变器信息存库
JpInverter jpInverter = jpInverterMapper.selectOne(
new QueryWrapper<JpInverter>().eq("third_station_id", device.getPs_id().toString())
.eq("third_code", PVProducerInfoEnum.YG.getCode())
.eq("ID", device.getUuid().toString()));
new QueryWrapper<JpInverter>().eq("sn_code", device.getDevice_sn().toString())
.eq("third_code", PVProducerInfoEnum.YG.getCode()));
if (ObjectUtils.isEmpty(jpInverter)) {
jpInverter = new JpInverter();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment