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