PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/JS.Library/SolidWorks/SWAssembly/SWAssemblyHelper.cs

https://bitbucket.org/J0ach1m/swbomexporter
C# | 510 lines | 364 code | 80 blank | 66 comment | 64 complexity | 24783080b75207a00ac10b67040badf6 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Xml.Linq;
  7. using SolidWorks.Interop.sldworks;
  8. using SolidWorks.Interop.swconst;
  9. using System.Reflection;
  10. using System.Text.RegularExpressions;
  11. using System.Linq;
  12. namespace JS.Library.SolidWorks.SWAssembly
  13. {
  14. public struct PatternContent
  15. {
  16. public string regex;
  17. public string infodatatype;
  18. public string customproperty;
  19. }
  20. public class SWAssemblyHelper
  21. {
  22. public enum InfoType { COMPONENTTYPE, MAJORVERSION, MINORVERSION,Id,NAME,TYPE,SUBTYPE }
  23. public enum InfoDataType { TEXT, NUMERIC }
  24. public enum ComponentSelection { VISIBLE, UNSUPPRESED, ALL}
  25. public static List<object> RemoveSuppressed(object[] components)
  26. {
  27. List<object> cleaned = new List<object>();
  28. foreach(Component2 c in components)
  29. {
  30. if (!c.IsSuppressed())
  31. {
  32. cleaned.Add(c);
  33. }
  34. }
  35. return cleaned;
  36. }
  37. /// <summary>
  38. /// Receives a list with assembly components and returns a list with components that meet the
  39. /// requirements specified in the select parameter
  40. /// </summary>
  41. /// <param name="components"></param>
  42. /// <param name="select"></param>
  43. /// <returns></returns>
  44. public static List<object> SelectComponents(object[] components, ComponentSelection select)
  45. {
  46. List<object> cleaned = new List<object>();
  47. switch (select)
  48. {
  49. case ComponentSelection.ALL:
  50. return components.ToList();
  51. case ComponentSelection.UNSUPPRESED:
  52. foreach (Component2 c in components)
  53. {
  54. if (!c.IsSuppressed())
  55. {
  56. cleaned.Add(c);
  57. }
  58. }
  59. return cleaned;
  60. case ComponentSelection.VISIBLE:
  61. foreach (Component2 c in components)
  62. {
  63. if (!c.IsHidden(true))
  64. {
  65. cleaned.Add(c);
  66. }
  67. }
  68. return cleaned;
  69. default:
  70. return components.ToList();
  71. }
  72. }
  73. public static List<AsmComponent> GetDataFromAssemblyEntries(object[] components, XDocument config)
  74. {
  75. //List<Dictionary<InfoType, string>> allpatterns = ReadPatterns2(config);
  76. List<Dictionary<InfoType, PatternContent>> allpatterns = ReadPatterns2(config);
  77. Dictionary<string, Dictionary<InfoType, PatternContent>> allpatterns2 = ReadPatterns3(config);
  78. List<AsmComponent> comps = new List<AsmComponent>();
  79. // new 2018-08-13
  80. // TODO: read from config
  81. List<KeyValuePair<string,string>> cusPropNames = new List<KeyValuePair<string,string>>();
  82. cusPropNames.Add(new KeyValuePair<string,string>("subtype","ListPrtType"));
  83. foreach (Component2 c in components)
  84. {
  85. AsmComponent comp = GetDataFromAssemblyEntry4(allpatterns2, c,cusPropNames);
  86. if (comp == null)
  87. {
  88. Console.WriteLine("comp==null ", c.Name);
  89. continue;
  90. }
  91. if (comp != null && (comp.id.Length > 0 || comp.name.Length > 0))
  92. {
  93. if (comps.Find(x => (x.id == comp.id) && (x.majorversion == comp.majorversion) && (x.minorversion == comp.minorversion) && (x.name == comp.name)) != null)
  94. {
  95. comps.Find(x => (x.id == comp.id) && (x.majorversion == comp.majorversion) && (x.minorversion == comp.minorversion) && (x.name == comp.name)).quantity++;
  96. }
  97. else
  98. {
  99. comps.Add(comp);
  100. }
  101. }
  102. else
  103. {
  104. comps.Add(comp);
  105. }
  106. }
  107. return comps;
  108. }
  109. public static AsmComponent BuildAsmComponent(Dictionary<InfoType,PatternContent> infopatterns, List<string> results, string rawentrydata)
  110. {
  111. if(infopatterns.Count != results.Count)
  112. {
  113. return null;
  114. }
  115. AsmComponent ac = new AsmComponent();
  116. ac.rawdata = rawentrydata;
  117. int i = 0;
  118. foreach(InfoType it in infopatterns.Keys)
  119. {
  120. try
  121. {
  122. if (results[i] == null) { results[i] = ""; }
  123. JS.Library.Helper.Objects.SetPropertyValue(ac, it.ToString(), results[i]);
  124. }
  125. catch (Exception e)
  126. {
  127. }
  128. ++i;
  129. }
  130. return ac;
  131. }
  132. public static List<string> GetDataFromAssemblyEntry(Dictionary<InfoType,PatternContent> infopatterns, Component2 entry)
  133. {
  134. //throw new NotImplementedException();
  135. List<string> results = new List<string>();
  136. List<InfoType> ipkeys = infopatterns.Keys.ToList();
  137. foreach(InfoType it in ipkeys)
  138. {
  139. PatternContent pc;
  140. string pattern;
  141. if(infopatterns.TryGetValue(it,out pc) == true)
  142. {
  143. pattern = pc.regex;
  144. string result = Helper.Strings.GetFirstRegexMatch(entry.Name, pattern);
  145. result = FormatToType(result, pc.infodatatype);
  146. results.Add(result);
  147. }
  148. }
  149. return results;
  150. }
  151. public static string FormatToType(string input, string idt)
  152. {
  153. InfoDataType i;
  154. string allowed = "[^0123456789]";
  155. if(Enum.TryParse(idt,true,out i))
  156. {
  157. switch (i)
  158. {
  159. case InfoDataType.NUMERIC:
  160. return Regex.Replace(input, allowed, string.Empty, RegexOptions.IgnoreCase);
  161. case InfoDataType.TEXT:
  162. return input;
  163. }
  164. }
  165. return input;
  166. }
  167. public static AsmComponent GetDataFromAssemblyEntry2(List<Dictionary<InfoType,PatternContent>> infopatterns, Component2 entry)
  168. {
  169. List<AsmComponent> comps = new List<AsmComponent>();
  170. foreach (Dictionary<InfoType,PatternContent> dic in infopatterns)
  171. {
  172. // check the component type first (assembly, part, standartpart,....)
  173. if (dic.ContainsKey(InfoType.COMPONENTTYPE))
  174. {
  175. string comptpe;
  176. PatternContent pc;
  177. dic.TryGetValue(InfoType.COMPONENTTYPE, out pc);
  178. comptpe = pc.regex;
  179. if (Helper.Strings.GetFirstRegexMatch(entry.Name, comptpe) != null)
  180. {
  181. List<string> data = GetDataFromAssemblyEntry(dic, entry);
  182. string rawdata = entry.Name;
  183. AsmComponent comp = BuildAsmComponent(dic, data,rawdata);
  184. return comp;
  185. }
  186. }
  187. else
  188. {
  189. // entry is not the current componenttype, try the next one....
  190. continue;
  191. }
  192. }
  193. return null;
  194. }
  195. public static AsmComponent GetDataFromAssemblyEntry3(Dictionary<string,Dictionary<InfoType, PatternContent>> infopatterns, Component2 entry)
  196. {
  197. List<AsmComponent> comps = new List<AsmComponent>();
  198. foreach (KeyValuePair<string,Dictionary<InfoType,PatternContent>> dicentry in infopatterns)
  199. {
  200. Dictionary<InfoType, PatternContent> dic = dicentry.Value;
  201. // check the component type first (assembly, part, standartpart,....)
  202. if (dic.ContainsKey(InfoType.COMPONENTTYPE))
  203. {
  204. string comptpe;
  205. PatternContent pc;
  206. dic.TryGetValue(InfoType.COMPONENTTYPE, out pc);
  207. comptpe = pc.regex;
  208. if (Helper.Strings.GetFirstRegexMatch(entry.Name, comptpe) != null)
  209. {
  210. List<string> data = GetDataFromAssemblyEntry(dic, entry);
  211. string rawdata = entry.Name;
  212. AsmComponent comp = BuildAsmComponent(dic, data, rawdata);
  213. if (comp != null)
  214. {
  215. comp.componenttypename = dicentry.Key;
  216. }
  217. return comp;
  218. }
  219. }
  220. else
  221. {
  222. // entry is not the current componenttype, try the next one....
  223. continue;
  224. }
  225. }
  226. return null;
  227. }
  228. /// <summary>
  229. /// Reads the components properties from custom properties and from the filename as specified in config.xml
  230. /// </summary>
  231. /// <param name="infopatterns"></param>
  232. /// <param name="entry"></param>
  233. /// <param name="cusPropNames">List with key-value-pairs where the key is the target member name of the Component object, value the solidworks custom property name</param>
  234. /// <returns></returns>
  235. public static AsmComponent GetDataFromAssemblyEntry4(Dictionary<string, Dictionary<InfoType, PatternContent>> infopatterns, Component2 entry, List<KeyValuePair<string,string>> cusPropNames)
  236. {
  237. List<AsmComponent> comps = new List<AsmComponent>();
  238. foreach (KeyValuePair<string, Dictionary<InfoType, PatternContent>> dicentry in infopatterns)
  239. {
  240. Dictionary<InfoType, PatternContent> dic = dicentry.Value;
  241. // check the component type first (assembly, part, standartpart,....)
  242. if (dic.ContainsKey(InfoType.COMPONENTTYPE))
  243. {
  244. string comptpe;
  245. PatternContent pc;
  246. dic.TryGetValue(InfoType.COMPONENTTYPE, out pc);
  247. comptpe = pc.regex;
  248. if (Helper.Strings.GetFirstRegexMatch(entry.Name, comptpe) != null)
  249. {
  250. List<string> data = GetDataFromAssemblyEntry(dic, entry);
  251. string rawdata = entry.Name;
  252. AsmComponent comp = BuildAsmComponent(dic, data, rawdata);
  253. if (comp != null)
  254. {
  255. comp.componenttypename = dicentry.Key;
  256. }
  257. // if there is a link to a custom property, try to use it first
  258. // TODO 2018-08-28
  259. // get all solidworks custom property names
  260. List<string> allMemberNames = (from propConf in cusPropNames select propConf.Key).Distinct().ToList();
  261. List<string> allCusPropNames = (from propConf in cusPropNames select propConf.Value).Distinct().ToList();
  262. // get all values to the property names
  263. Dictionary<string, string> properties = GetCustomProperties(entry, allCusPropNames);
  264. if (properties != null)
  265. {
  266. List<string> allPropValues = (from propVal in properties select propVal.Value).Distinct().ToList();
  267. // find a member according to each found property, if there is a member-> set value
  268. if (comp != null && (allMemberNames.Count == allPropValues.Count))
  269. {
  270. for (int i = 0; i < allMemberNames.Count(); ++i)
  271. {
  272. JS.Library.Helper.Objects.SetPropertyValue(comp, allMemberNames[i], allPropValues[i]);
  273. }
  274. }
  275. }
  276. return comp;
  277. }
  278. }
  279. else
  280. {
  281. // entry is not the current componenttype, try the next one....
  282. continue;
  283. }
  284. }
  285. return null;
  286. }
  287. /// <summary>
  288. /// returns a dictionary with the custom properties where the property name is key, the custom property value is the according value
  289. /// if no property with specified name is found, the value will be an empty string
  290. /// </summary>
  291. /// <param name="component"></param>
  292. /// <param name="cusPropNames"></param>
  293. /// <returns></returns>
  294. public static Dictionary<string,string> GetCustomProperties(Component2 component, List<string> cusPropNames)
  295. {
  296. Dictionary<string, string> properties = new Dictionary<string, string>();
  297. try
  298. {
  299. ModelDoc2 swModel = component.GetModelDoc2();
  300. ModelDocExtension swModelDocExt = swModel.Extension;
  301. CustomPropertyManager swCustProp = swModelDocExt.CustomPropertyManager[""];
  302. foreach (string cusPropName in cusPropNames)
  303. {
  304. string cusPropVal;
  305. string cusPropValOut;
  306. bool status = swCustProp.Get4(cusPropName, false, out cusPropVal, out cusPropValOut);
  307. properties.Add(cusPropName, cusPropValOut);
  308. }
  309. }catch(Exception e)
  310. {
  311. return null;
  312. }
  313. return properties;
  314. }
  315. public List<InfoDataType> GetInfoDatatype(XDocument config)
  316. {
  317. throw new NotImplementedException();
  318. }
  319. /// <summary>
  320. /// Reads all desired regex patterns in the given order of the InfoType array and returns it as a dictionary whith infopattern as
  321. /// key and the regex pattern as value
  322. /// </summary>
  323. /// <param name="its"></param>
  324. /// <param name="configfilepath"></param>
  325. /// <returns></returns>
  326. public static Dictionary<InfoType,string> ReadPatterns(InfoType[] its, XDocument config)
  327. {
  328. Dictionary<InfoType, string> patternlist = new Dictionary<InfoType, string>();
  329. foreach (InfoType it in its)
  330. {
  331. patternlist.Add(it, ReadRegexPattern(it,config));
  332. }
  333. return patternlist;
  334. }
  335. /// <summary>
  336. /// Reads the regular expression patterns for the specified types from the config file.
  337. /// configuration file must contain the structure /Config/RegexConfig/<SolidworksTypename>/<pattern>
  338. /// </summary>
  339. /// <param name="config"></param>
  340. /// <returns></returns>
  341. public static List<Dictionary<InfoType,PatternContent>> ReadPatterns2(XDocument config)
  342. {
  343. List<Dictionary<InfoType, PatternContent>> allpatterns = new List<Dictionary<InfoType, PatternContent>>();
  344. // find regexconfig root element
  345. XElement regexroot = config.Element("Config").Element("RegexConfig");
  346. if (regexroot == null)
  347. {
  348. return null;
  349. }
  350. //get all descendents and add a dictionary with patterns and infotypes to the list
  351. foreach(XElement regexchild in regexroot.Elements())
  352. {
  353. Dictionary<InfoType, PatternContent> rchild = new Dictionary<InfoType, PatternContent>();
  354. foreach(XElement pattern in regexchild.Elements("pattern"))
  355. {
  356. InfoType it;
  357. if(Enum.TryParse(pattern.Attribute("name").Value,true, out it))
  358. {
  359. PatternContent pc;
  360. pc.infodatatype = pattern.Attribute("type").Value;
  361. pc.regex = pattern.Attribute("regex").Value;
  362. pc.customproperty = (pattern.Attribute("customproperty") != null) ?pattern.Attribute("customproperty").Value:"";
  363. rchild.Add(it, pc);
  364. }
  365. }
  366. allpatterns.Add(rchild);
  367. }
  368. return allpatterns;
  369. }
  370. /// <summary>
  371. /// Reads the regular expression patterns for the specified types from the config file.
  372. /// configuration file must contain the structure /Config/RegexConfig/<SolidworksTypename>/<pattern>
  373. /// </summary>
  374. /// <param name="config"></param>
  375. /// <returns></returns>
  376. public static Dictionary<string,Dictionary<InfoType, PatternContent>> ReadPatterns3(XDocument config)
  377. {
  378. Dictionary<string,Dictionary<InfoType, PatternContent>> allpatterns = new Dictionary<string,Dictionary<InfoType, PatternContent>>();
  379. // find regexconfig root element
  380. XElement regexroot = config.Element("Config").Element("RegexConfig");
  381. if (regexroot == null)
  382. {
  383. return null;
  384. }
  385. //get all descendents and add a dictionary with patterns and infotypes to the list
  386. foreach (XElement regexchild in regexroot.Elements())
  387. {
  388. Dictionary<InfoType, PatternContent> rchild = new Dictionary<InfoType, PatternContent>();
  389. foreach (XElement pattern in regexchild.Elements("pattern"))
  390. {
  391. InfoType it;
  392. if (Enum.TryParse(pattern.Attribute("name").Value, true, out it))
  393. {
  394. PatternContent pc;
  395. pc.infodatatype = pattern.Attribute("type").Value;
  396. pc.regex = pattern.Attribute("regex").Value;
  397. pc.customproperty = (pattern.Attribute("customproperty") != null) ? pattern.Attribute("customproperty").Value : "";
  398. rchild.Add(it, pc);
  399. }
  400. }
  401. string key = regexchild.Name.ToString();
  402. allpatterns.Add(key,rchild);
  403. }
  404. return allpatterns;
  405. }
  406. /// <summary>
  407. /// Reads the regex pattern according to the infotype from the config xml file
  408. /// </summary>
  409. /// <param name="infotype"></param>
  410. /// <returns></returns>
  411. public static string ReadRegexPattern(InfoType infotype, XDocument xd, string regexconfigelementname="/RegexConfig/SWAssembly")
  412. {
  413. try
  414. {
  415. // Find the xelement with attribute name == infotype and read it's "pattern" attribute's value
  416. XElement xe = File.Xml.GetElementByAttributeNameAndValue("name", infotype.ToString(), xd,regexconfigelementname);
  417. if (xe == null)
  418. {
  419. return null;
  420. }
  421. return File.Xml.GetAttributeValue(xe,"regex");
  422. }
  423. catch (Exception ex)
  424. {
  425. return null;
  426. }
  427. //throw new NotImplementedException();
  428. }
  429. }
  430. }