· 8 years ago · May 03, 2018, 02:32 PM
1//#define PROFILING
2//#define TRACE_LOG
3//#define LOAD_LOCAL
4#define CYLINDER_TYPE_FROM_NAME
5
6using System;
7using System.Collections.Generic;
8using System.Linq;
9using System.Data;
10using System.Data.Linq;
11using System.Data.Sql;
12using System.Data.SqlClient;
13using System.Text;
14using System.Diagnostics;
15using PDMLog;
16using System.Linq.Expressions;
17using Pdm.Caderp.CaderpConfigurators;
18using Pdm.Models.MateRulesEngines.MateDBinterface.DBentities;
19using Pdm.Models.SurfaceTypeAnalysis;
20using Pdm.Models.BasicGeometry3D;
21using System.IO;
22using System.Data.Linq.Mapping;
23using System.Reflection;
24using Pdm.Caderp.CaderpConfigurators.Mates;
25using Pdm.Models.MateRulesEngines.MateDBinterface.TouchCache;
26using Pdm.Caderps.BasicData.CAD;
27using Pdm.Caderps;
28using Pdm.Models.MateRulesEngines;
29using System.Data.Linq.SqlClient;
30using Pdm.Caderps.BasicData;
31using Pdm.Models.MateRulesEngines.Surfaces;
32using Pdm.Models.ProfilingTools;
33
34namespace Pdm.Models.MateRulesEngines.MateDBinterface
35{
36 /// <summary>
37 /// Enumeration containing types of surfaces. It is meant to be used in DbSurfaceUsability class.
38 /// </summary>
39 public enum DbSurfaceTypes : byte
40 {
41 None = 0, Plane = 1, Cylinder = 2, None_WorkFeature = 3, Plane_WorkFeature = 4, Cylinder_WorkFeature = 5
42 }
43
44 public class DbManager
45 {
46 #region inner classes
47
48 class DbGroupAndContext
49 {
50 public DbGroup Group { get; set; }
51 public DbBso FirstCommonParent { get; set; }
52
53 public DbGroupAndContext(DbGroup gr, DbBso firstCommonParent)
54 {
55 this.Group = gr;
56 this.FirstCommonParent = firstCommonParent;
57 }
58 }
59
60 delegate bool ObjectAreCorrespondigDelegate(DbBso dbBso, BsInfo partInfo, int partClassificationId);
61
62 private bool ObjectAreCorrespondig_Exact(DbBso dbBso, BsInfo partInfo, int partClassificationId)
63 {
64 return partInfo.Id == dbBso.ObjectId &&
65 partInfo.Version == dbBso.ObjectVersion &&
66 partInfo.Variant == dbBso.ObjectVariant;
67 }
68
69 private bool ObjectAreCorrespondig_Version(DbBso dbBso, BsInfo partInfo, int partClassificationId)
70 {
71 return partInfo.Id == dbBso.ObjectId &&
72 partInfo.Version != dbBso.ObjectVersion &&
73 partInfo.Variant == dbBso.ObjectVariant;
74 }
75
76 private bool ObjectAreCorrespondig_Variant(DbBso dbBso, BsInfo partInfo, int partClassificationId)
77 {
78 return partInfo.Id == dbBso.ObjectId &&
79 partInfo.Variant != dbBso.ObjectVariant;
80 }
81
82 private bool ObjectAreCorrespondig_Classification(DbBso dbBso, BsInfo partInfo, int partClassificationId)
83 {
84 return partClassificationId == dbBso.ClassificationId;
85 }
86
87 #endregion
88#if TRACE_LOG
89 static short _traceLogCounter = 0;
90#endif
91 static LogWriter _logger;
92 DbTouchAnalysis _dbTA;
93 public const int ZERO_INDEX = 0;
94 public const int EMPTY_DB_INDEX = -1;
95
96 private const string CONFIG_FILE_NAME = "ConnectionConfig.xml";
97 private const string _connectionStringMateRules = @"c:\myDatabases\mateRules1.mdf";
98
99 private static string _connectionSettingsFile = null;
100 private static ConnectionSettings _connectionSettings = null;
101 private static DbManager _dbManager = null;
102
103 /// <summary>
104 /// a name of a view containing the data of the last query
105 /// </summary>
106 private int _currentViewIndex = 0;
107 private string _baseNameViewDescrDB = "ViewDescr";
108 InheritanceSourceBso _inheritanceSource = null;
109
110 bool _exceptionOccurred = false;
111 DbInheritanceTable _inheritanceTable;
112 private IErp _erp = null;
113 System.Threading.AutoResetEvent _runningQuery = null; //is this a proper solution? In LWI, two threads can try to query MateDB at once and that causes System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
114 Dictionary<BsInfo, DbBso> _cacheBsInfoDbBso = null; //a cache used to speed up search of DbBso for BsIfno
115
116 #region Properties
117
118 public static DbManager Instance
119 {
120 get { return DbManager._dbManager; }
121 }
122
123 public static bool Connected
124 {
125 get
126 {
127 bool connected = Instance != null && Instance.DbTouchAnalysis != null && Instance.DbTouchAnalysis.DatabaseExists();
128 return connected;
129 }
130 }
131
132 public static string ConnectionSettingsFile
133 {
134 get { return DbManager._connectionSettingsFile; }
135 set { DbManager._connectionSettingsFile = value; }
136 }
137
138 public static ConnectionSettings ConnectionSettings
139 {
140 get { return DbManager._connectionSettings; }
141 set { DbManager._connectionSettings = value; }
142 }
143
144 /// <summary>
145 /// Gets the PDM logger.
146 /// </summary>
147 /// <value>
148 /// The PDM logger.
149 /// </value>
150 public static LogWriter Logger
151 {
152 get { return DbManager._logger; }
153 }
154
155 /// <summary>
156 /// Gets the db touch analysis.
157 /// </summary>
158 /// <value>
159 /// The db ouch analysis.
160 /// </value>
161 public DbTouchAnalysis DbTouchAnalysis
162 {
163 get { return _dbTA; }
164 }
165
166
167 #endregion
168
169 public DbManager()
170 : this(InheritanceSourceTypes.LocalSource)
171 {
172 }
173
174 public DbManager(InheritanceSourceTypes inheritanceSourceType)
175 {
176 _inheritanceSource = InheritanceSourceBso.GetSource(inheritanceSourceType);
177 _runningQuery = new System.Threading.AutoResetEvent(true);
178 }
179
180 static DbManager()
181 {
182 _logger = new PDMLog.LogWriter(LogLevel.Error, LogMethod.EventLog, "", "BlueStar", "TouchAnalysis - DbManager");
183 string asmDir = BasicTool.BasicTools.GetDirectoryOfExecutingAssembly();
184 //string fullName = System.IO.Path.Combine(asmDir, "DBmanager.log");
185 //_logger = new LogWriter(LogLevel.Information, LogMethod.FileLog, fullName, "", "");
186
187#if LOAD_LOCAL
188 //used until 2015-12-07. But the settings should be fetched from a server
189 _connectionSettingsFile = System.IO.Path.Combine(asmDir, CONFIG_FILE_NAME);
190 _connectionSettings = ConnectionSettings.LoadFromXML(_connectionSettingsFile);
191 if (_connectionSettings == null)
192 {
193 System.Diagnostics.Debug.Fail("Cannot load connection settings.");
194 _connectionSettings = ConnectionSettings.GetDefaultSettings();
195 }
196 return;
197#endif
198
199 //TODO - should we fetch the settings here, in a static constructor?
200 _connectionSettings = ConnectionSettings.FetchFromServer();
201
202 if (_connectionSettings == null)
203 {
204 System.Diagnostics.Debug.Fail("Cannot load connection settings.");
205 _connectionSettings = ConnectionSettings.GetDefaultSettings();
206 }
207 }
208
209 public static void TraceLog(string mess, LogLevel logLevel = LogLevel.Error)
210 {
211 TraceLog(mess, null, logLevel);
212 }
213
214 public static void TraceLog(string mess, Exception ex, LogLevel logLevel = LogLevel.Error)
215 {
216#if TRACE_LOG
217 _traceLogCounter++;
218 if (mess != null)
219 {
220 Logger.Log(mess, logLevel, _traceLogCounter);
221 }
222 if (ex != null)
223 {
224 Logger.Log(ex, logLevel, _traceLogCounter);
225 }
226#endif
227 }
228
229 /// <summary>
230 /// Creates a new database for descriptors, inits the field _dbDescr (a database of descriptors)
231 /// </summary>
232 /// <param name="descriptors">a list of descriptors. If not null, the descriptors are added into the database</param>
233 /// <returns>
234 /// the connection string
235 /// </returns>
236 public string CreateEmptyDatabase()
237 {
238 //string connectionString = LoadConnectionStringFromConfigFile();
239 string connectionString = _connectionSettings.GetConnectionString();
240 _dbTA = DatabaseCreation.CreateDbTouchAnalysis(connectionString, true);
241 return connectionString;
242 }
243
244 /// <summary>
245 /// Creates a new database for descriptors, inits the field _dbDescr (a database of descriptors)
246 /// </summary>
247 /// <param name="descriptors">a list of descriptors. If not null, the descriptors are added into the database</param>
248 /// <returns>
249 /// the connection string
250 /// </returns>
251 public string CreateEmptyDatabase(string connectionString, bool deleteExisting)
252 {
253 //string connectionString = "";
254 try
255 {
256 _dbTA = DatabaseCreation.CreateDbTouchAnalysis(connectionString, true);
257 }
258 catch (Exception ex)
259 {
260 TraceLog("DbManager.CreateEmptyDatabse - exception catched", ex);
261 ShowError("Cannot create the descriptors-database.", ex);
262 _dbTA = null;
263 }
264 return connectionString;
265 }
266
267 /// <summary>
268 /// Creates indexes for several columns in several tables in the Mate db.
269 /// </summary>
270 /// <param name="connectionString">The connection string.</param>
271 public void CreateIndexesInDatabase(string connectionString)
272 {
273 //if (_dbTA != null) //used until 10.3.2015. But we do not use Linq to create indices, so we do not need the _dbTA to be initialized.
274 //{
275 try
276 {
277 using (SqlConnection sqlConnnection = new SqlConnection(connectionString))
278 {
279 sqlConnnection.Open();
280 CreateIndexForOneColumn(DbMateRulesNames.TableAnonymPairs, DbMateRulesNames.GroupId, sqlConnnection);
281 CreateIndexForOneColumn(DbMateRulesNames.TableInstancePairs, DbMateRulesNames.AnonymPairId, sqlConnnection);
282 CreateIndexForOneColumn(DbMateRulesNames.TableMateRules, DbMateRulesNames.GroupId, sqlConnnection);
283
284 CreateIndexForOneColumn(DbMateRulesNames.TableSurfaceUsability, DbMateRulesNames.PartId, sqlConnnection);
285 CreateIndexForOneColumn(DbMateRulesNames.TableSurfaceUsability, DbMateRulesNames.Surface, sqlConnnection);
286
287 CreateIndexForOneColumn(DbMateRulesNames.TableGroups, DbMateRulesNames.PartAId, sqlConnnection);
288 CreateIndexForOneColumn(DbMateRulesNames.TableGroups, DbMateRulesNames.PartBId, sqlConnnection);
289 }
290 }
291 catch (Exception ex)
292 {
293 PDMLog.Logger.Log(ex);
294 }
295 //}
296 }
297
298 private static void CreateIndexForOneColumn(string tableName, string columnName, SqlConnection sqlConnnection)
299 {
300 try
301 {
302 string indexName = "index_" + tableName.ToLower() + "_" + columnName.ToLower();
303 string sql = String.Format("CREATE NONCLUSTERED INDEX {0} ON {1}({2});", indexName, tableName, columnName);
304 SqlCommand cmd = new SqlCommand(sql, sqlConnnection);
305 cmd.ExecuteNonQuery();
306 }
307 catch (Exception ex)
308 {
309 Logger.Log(ex, LogLevel.Error, 0);
310 }
311 }
312
313 public static void AddColumnIfNotExist(string connectionString)
314 {
315 try
316 {
317 using (SqlConnection sqlConnnection = new SqlConnection(connectionString))
318 {
319 sqlConnnection.Open();
320 AddColumnIfNotExist(DbMateRulesNames.TableMateRules, DbMateRulesNames.Flag, sqlConnnection);
321 }
322 }
323 catch (Exception ex)
324 {
325 PDMLog.Logger.Log(ex);
326 }
327 }
328
329 public static void AddColumnIfNotExist(string tableName, string columnName, SqlConnection sqlConnnection)
330 {
331 try
332 {
333 string sql = String.Format("if not exists (select * from syscolumns " +
334 "where id=object_id('{0}') and name='{1}') " +
335 "alter table {0} add {1} int NOT NULL DEFAULT(0)", tableName, columnName);
336
337 SqlCommand cmd = new SqlCommand(sql, sqlConnnection);
338 cmd.ExecuteNonQuery();
339 }
340 catch (Exception ex)
341 {
342 Logger.Log(ex, LogLevel.Error, 0);
343 }
344 }
345
346 /// <summary>
347 /// Creates the connection to the geometric-search database.
348 /// </summary>
349 /// <returns>true if the database was successfully connected</returns>
350 public bool ConnectToTouchAnalysisDB()
351 {
352 try
353 {
354 //string connString = DbManager.LoadConnectionStringFromConfigFile();
355 string connString = _connectionSettings.GetConnectionString();
356 return ConnectToTouchAnalysisDB(connString);
357 }
358 catch (Exception ex)
359 {
360 ShowError("Cannot connect to the database.", ex);
361 _dbTA = null;
362 return false;
363 }
364 }
365
366 /// <summary>
367 /// Creates the connection to the geometric-search database.
368 /// </summary>
369 /// <param name="connectionString">The connection string.</param>
370 /// <returns>true if the database was successfully connected</returns>
371 public bool ConnectToTouchAnalysisDB(string connectionString)
372 {
373 try
374 {
375 _dbTA = new DbTouchAnalysis(connectionString);
376 if (!_dbTA.DatabaseExists())
377 {
378 ShowError("Cannot connect to the database " + connectionString, null);
379 _dbTA = null;
380 return false;
381 }
382 return true;
383 }
384 catch (Exception ex)
385 {
386 ShowError("Cannot connect to the database " + connectionString, ex);
387 _dbTA = null;
388 return false;
389 }
390 }
391
392 public bool IsConnected()
393 {
394 return _dbTA != null && _dbTA.DatabaseExists();
395 }
396
397 public void CloseConnection()
398 {
399 try
400 {
401 if (_dbTA != null && _dbTA.Connection != null)
402 {
403 _dbTA.Connection.Close();
404 }
405 }
406 catch (Exception ex)
407 {
408 PDMLog.Logger.Log(ex);
409 }
410 }
411
412 /// <summary>
413 /// Creates the connection to the geometric-search database.
414 /// </summary>
415 /// <param name="connectionString">The connection string.</param>
416 /// <returns>true if the database was successfully connected</returns>
417 public bool ConnectToTouchAnalysisDB_CreateNewIfNotExist(string connectionString)
418 {
419 try
420 {
421 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - Before new DbTouchAnalysis " + connectionString);
422 _dbTA = new DbTouchAnalysis(connectionString);
423 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - After new DbTouchAnalysis " + connectionString);
424 if (!_dbTA.DatabaseExists())
425 {
426 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - Database does not exist, try to create a new one.");
427 CreateEmptyDatabase(connectionString, false);
428 bool databaseCreated = _dbTA != null;
429 if (databaseCreated)
430 {
431 CreateIndexesInDatabase(connectionString);
432 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - A new database was created successfully.");
433 }
434 else
435 {
436 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - No new database was created.");
437 }
438 return databaseCreated;
439 }
440 else
441 {
442 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - Connected to the database.");
443 return true;
444 }
445 }
446 catch (Exception ex)
447 {
448 TraceLog("DbManager.ConnectToTouchAnalysisDB_CreateNewIfNotExist - Cannot connect to the database");
449 ShowError("Cannot connect to the database " + connectionString, ex);
450 _dbTA = null;
451 return false;
452 }
453 }
454 /// Deletes groups from database including all underlying records.
455 /// </summary>
456 /// <param name="groups"></param>
457 public void DeleteGroupsFromDatabase(IEnumerable<DbGroup> groups)
458 {
459 List<int> groupIds = IdExtractor.GetIdsList(groups);
460 var mateRulesForGroups = from mateRule in DbTouchAnalysis.TableMateRules
461 where groupIds.Contains(mateRule.GroupId)
462 select mateRule;
463 List<DbMateRule> rules = mateRulesForGroups.ToList();
464 DbTouchAnalysis.TableMateRules.DeleteAllOnSubmit(rules);
465
466 var anonymPathsForGroups = from anonymPair in DbTouchAnalysis.TableAnonymPairs
467 where groupIds.Contains(anonymPair.GroupId)
468 select anonymPair;
469 List<DbAnonymPair> anonyms = anonymPathsForGroups.ToList();
470 DbTouchAnalysis.TableAnonymPairs.DeleteAllOnSubmit(anonyms);
471
472 List<int> anonymPairIds = IdExtractor.GetIdsList(anonyms);
473 var instancePathsForAnonyms = from instancePair in DbTouchAnalysis.TableInstancePairs
474 where groupIds.Contains(instancePair.AnonymPairId)
475 select instancePair;
476 DbTouchAnalysis.TableInstancePairs.DeleteAllOnSubmit(instancePathsForAnonyms.ToList());
477
478 var groupsFromDb = from gr in DbTouchAnalysis.TableGroups
479 where groupIds.Contains(gr.GroupId)
480 select gr;
481 DbTouchAnalysis.TableGroups.DeleteAllOnSubmit(groupsFromDb.ToList());
482
483 DbTouchAnalysis.SubmitChanges(ConflictMode.ContinueOnConflict);
484 }
485
486 public void DeleteMateRulesFromDatabase(List<DbMateRule> rulesToDelete)
487 {
488 foreach (DbMateRule ruleFromUser in rulesToDelete)
489 {
490 List<DbGroup> groupsFromDb = FindDbGroupsForTwoParts(ruleFromUser.Group.PartA, ruleFromUser.Group.PartB);
491 DbGroup groupForRule = ExistsDbGroupInDatabase(ruleFromUser.Group, true);
492
493 if (groupForRule != null)
494 {
495 foreach (DbMateRule ruleFromDb in groupForRule.MateRules)
496 {
497 if (DbMateRuleComparer.CompareStatic(ruleFromDb, ruleFromUser) == 0)
498 {
499 DbTouchAnalysis.TableMateRules.DeleteOnSubmit(ruleFromDb);
500 break;
501 }
502 }
503 }
504 }
505
506 DbTouchAnalysis.SubmitChanges(ConflictMode.ContinueOnConflict);
507 }
508
509 public void DeleteInstancePairsFromDatabase(List<DbInstancePair> pairsToDelete)
510 {
511 foreach (DbInstancePair pairFromUser in pairsToDelete)
512 {
513 DbAnonymPair anonymForInstance = ExistsDbAnonymPairInDatabase(pairFromUser.AnonymPair, true);
514
515 if (anonymForInstance != null)
516 {
517 IList<DbInstancePair> pairsFromDb = FindFullPathsForAnonymousPath(anonymForInstance);
518
519 foreach (DbInstancePair pairFromDb in pairsFromDb)
520 {
521 if (pairFromDb.InstanceA == pairFromUser.InstanceA && pairFromDb.InstanceB == pairFromUser.InstanceB &&
522 pairFromDb.InstancePathA == pairFromUser.InstancePathA && pairFromDb.InstancePathB == pairFromUser.InstancePathB)
523 {
524 DbTouchAnalysis.TableInstancePairs.DeleteOnSubmit(pairFromDb);
525 break;
526 }
527 }
528 }
529 }
530
531 DbTouchAnalysis.SubmitChanges(ConflictMode.ContinueOnConflict);
532 }
533
534 public void DeleteAnonymousPairsFromDatabase(List<DbAnonymPair> anonymsToDelete)
535 {
536 foreach (DbAnonymPair pairFromUser in anonymsToDelete)
537 {
538 DbGroup groupForPair = ExistsDbGroupInDatabase(pairFromUser.Group, true);
539
540 if (groupForPair != null)
541 {
542 IList<DbAnonymPair> anonymPairsFromDb = FindAnonymousPathsForDbGroup(groupForPair);
543
544 foreach (DbAnonymPair pairFromDb in anonymPairsFromDb)
545 {
546 if (pairFromDb.Equals_ByFields(pairFromUser))
547 {
548 DbTouchAnalysis.TableAnonymPairs.DeleteOnSubmit(pairFromDb);
549 break;
550 }
551 }
552 }
553 }
554
555 DbTouchAnalysis.SubmitChanges(ConflictMode.ContinueOnConflict);
556 }
557
558 public DbGroup ExistsDbGroupInDatabase(DbGroup dbGroup)
559 {
560 return ExistsDbGroupInDatabase(dbGroup, false);
561 }
562
563 private DbGroup ExistsDbGroupInDatabase(DbGroup dbGroup, bool fetchPartsFromDb)
564 {
565 int partAId = dbGroup.PartAId;
566 int partBId = dbGroup.PartBId;
567
568 if (fetchPartsFromDb)
569 {
570 partAId = FetchSameDbBsoFromDb(dbGroup.PartA).BsoId;
571 partBId = FetchSameDbBsoFromDb(dbGroup.PartB).BsoId;
572 }
573
574 return ExistsDbGroupInDatabase(dbGroup, partAId, partBId);
575 }
576
577 private DbBso FetchSameDbBsoFromDb(DbBso dbBso)
578 {
579 var recFromDb = from rec in DbTouchAnalysis.TableBlueStarObjects
580 where rec.BsoType == dbBso.BsoType && rec.ObjectId == dbBso.ObjectId && rec.ObjectVariant == dbBso.ObjectVariant &&
581 rec.ObjectVersion == dbBso.ObjectVersion
582 select rec;
583 List<DbBso> ret = recFromDb.ToList();
584
585 if (ret == null || ret.Count == 0 || ret.Count > 1)
586 {
587 throw new Exception(string.Format("Ambiguous result for DbBso - {0}", dbBso.ToString(), ret));
588 }
589
590 return ret[0];
591 }
592
593 public DbAnonymPair ExistsDbAnonymPairInDatabase(DbAnonymPair dbAnonymPair, bool fetchIdsFromDb)
594 {
595 if (fetchIdsFromDb)
596 {
597 dbAnonymPair.ParentAId = FetchSameDbBsoFromDb(dbAnonymPair.ParentA).BsoId;
598 dbAnonymPair.ParentBId = FetchSameDbBsoFromDb(dbAnonymPair.ParentB).BsoId;
599 dbAnonymPair.FirstCommonParentId = FetchSameDbBsoFromDb(dbAnonymPair.FirstCommonParent).BsoId;
600 }
601
602 return ExistsDbAnonymPairInDatabase(dbAnonymPair);
603 }
604
605 //public void ListRecordsDescrDB(int startIndex, int count)
606 //{
607 // if (_dbDescrs == null)
608 // {
609 // System.Diagnostics.Debug.Fail("Descriptors database is not initialized.");
610 // }
611
612 // var query = from desc in _dbDescrs.TableDescriptors
613 // where desc.PrimaryKey >= startIndex && desc.PrimaryKey < startIndex + count
614 // select desc.FileName;
615
616 // foreach (var item in query)
617 // {
618 // Console.Out.WriteLine(item.ToString());
619 // }
620 //}
621
622 public static void TranslateDbSurfaceTypes(DbSurfaceTypes[] dbSurfTypes, out SurfaceTypes[] surfTypes, out bool[] isWorkFeatures, string[] surfaceNames)
623 {
624 if (dbSurfTypes == null)
625 {
626 surfTypes = null;
627 isWorkFeatures = null;
628 return;
629 }
630 else
631 {
632 surfTypes = new SurfaceTypes[dbSurfTypes.Length];
633 isWorkFeatures = new bool[dbSurfTypes.Length];
634 for (int i = 0; i < dbSurfTypes.Length; i++)
635 {
636 bool isWF;
637 SurfaceTypes surfType;
638 TranslateDbSurfaceType(dbSurfTypes[i], surfaceNames[i], out surfType, out isWF);
639 surfTypes[i] = surfType;
640 isWorkFeatures[i] = isWF;
641 }
642 }
643 }
644
645 public static void TranslateDbSurfaceType(DbSurfaceTypes dbSurfType, string surfaceName, out SurfaceTypes surfType, out bool isWorkFeature)
646 {
647 switch (dbSurfType)
648 {
649 case DbSurfaceTypes.None:
650 surfType = SurfaceTypes.None;
651 isWorkFeature = false;
652 break;
653 case DbSurfaceTypes.Plane:
654 surfType = SurfaceTypes.Plane;
655 isWorkFeature = false;
656 break;
657 case DbSurfaceTypes.Cylinder:
658 surfType = SurfaceTypes.Cylinder;
659 isWorkFeature = false;
660 break;
661 case DbSurfaceTypes.None_WorkFeature:
662 surfType = SurfaceTypes.None;
663 isWorkFeature = true;
664 break;
665 case DbSurfaceTypes.Plane_WorkFeature:
666 surfType = SurfaceTypes.Plane;
667 isWorkFeature = true;
668 break;
669 case DbSurfaceTypes.Cylinder_WorkFeature:
670 surfType = SurfaceTypes.Cylinder;
671 isWorkFeature = true;
672 GetSurfaceTypeFromSurfaceName(ref isWorkFeature, dbSurfType, surfaceName);
673 break;
674 default:
675 surfType = SurfaceTypes.None;
676 isWorkFeature = false;
677 break;
678 }
679 }
680
681 public static DbSurfaceTypes TranslateSurfaceType(SurfaceTypes surfType, bool isWorkFeature)
682 {
683 switch (surfType)
684 {
685 case SurfaceTypes.None:
686 return isWorkFeature ? DbSurfaceTypes.None_WorkFeature : DbSurfaceTypes.None;
687 case SurfaceTypes.Plane:
688 return isWorkFeature ? DbSurfaceTypes.Plane_WorkFeature : DbSurfaceTypes.Plane;
689 case SurfaceTypes.Cylinder:
690 return isWorkFeature ? DbSurfaceTypes.Cylinder_WorkFeature : DbSurfaceTypes.Cylinder;
691 default:
692 return DbSurfaceTypes.None;
693 }
694 }
695
696 public List<DbMateRule> LoadTouchRecords(int startIndex, int count)
697 {
698 if (_dbTA == null)
699 {
700 System.Diagnostics.Debug.Fail("The database for geometric search is not initialized.");
701 return null;
702 }
703
704 var query2 = _dbTA.TableMateRules.Skip(startIndex).Take(count);
705
706 return query2.ToList<DbMateRule>();
707 }
708
709 public void ShowError(string message, Exception ex)
710 {
711 if (message != null)
712 {
713 Logger.Log(message, LogLevel.Error, 0);
714 }
715 if (ex != null)
716 {
717 Logger.Log(ex, LogLevel.Error, 0);
718 }
719 string s = String.Format("{0}; ex: {1}", message, ex);
720#if DEBUG
721 Debug.Fail(s);
722#else
723 //MessageBox.Show(s, "Error");
724#endif
725 }
726
727 public void ClearAllTablesInDatabase()
728 {
729 //Truncate(_dbTA.TableOriginOfGroups);
730 Truncate(_dbTA.TableSurfaceUsabilities);
731 Truncate(_dbTA.TableMateRules);
732 Truncate(_dbTA.TableGroups);
733 Truncate(_dbTA.TableBlueStarObjects);
734 Truncate(_dbTA.TableAnonymPairs);
735 Truncate(_dbTA.TableInstancePairs);
736 }
737
738 public void Truncate<TEntity>(Table<TEntity> table) where TEntity : class
739 {
740 var rowType = table.GetType().GetGenericArguments()[0];
741 var tableName = table.Context.Mapping.GetTable(rowType).TableName;
742 var sqlCommand = String.Format("TRUNCATE TABLE {0}", tableName);
743 table.Context.ExecuteCommand(sqlCommand);
744 }
745
746 /// <summary>
747 /// Inserts one record into the TableTouchAnalysis.
748 /// Records with duplicate keys are ignored.
749 /// </summary>
750 /// <param name="touchRec">The touch rec.</param>
751 public void InsertTouchRecords(DbMateRule touchRec)
752 {
753 if (_dbTA == null)
754 {
755 System.Diagnostics.Debug.Fail("The database is not initialized.");
756 return;
757 }
758
759 _dbTA.TableMateRules.InsertOnSubmit(touchRec);
760 try
761 {
762 _dbTA.SubmitChanges();
763 }
764 catch (Exception ex)
765 {
766 DbManager.Logger.Log(touchRec.ToString() + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
767 }
768 }
769
770 /// <summary>
771 /// If the table OriginOfGroups already contains a records dbGroup + originAssembly, only the frequency is updated in the record.
772 /// Otherwise a new record is added.
773 /// </summary>
774 /// <param name="originAssembly">CombinedId of an assembly, from which the group of mate rules has been generated.</param>
775 /// <param name="frequency">The frequency.</param>
776 /// <param name="dbGroup">The db group.</param>
777 private void UpdateOriginOfMateGroup(string originAssembly, int frequency, DbGroup dbGroup)
778 {
779 //var q = _dbTA.TableOriginOfGroups.SingleOrDefault(x => x.GroupId == dbGroup.GroupId && x.Assembly == originAssembly);
780 //if (q != null)
781 //{
782 // q.Frequency = Math.Max(frequency, q.Frequency);
783 //}
784 //else
785 //{
786 // _dbTA.TableOriginOfGroups.InsertOnSubmit(new DbOriginOfGroup(dbGroup.GroupId, originAssembly, frequency));
787 //}
788
789 //try
790 //{
791 // SubmitChangesToDB();
792 //}
793 //catch (Exception ex)
794 //{
795 // Logger.Log(ex, LogLevel.Error, 0);
796 //}
797 }
798
799
800 /// <summary>
801 /// Tries to find a given assembly in the TableParentAssemblies.
802 /// </summary>
803 /// <param name="commonParent">The common parent.</param>
804 /// <returns>id of the assembly or -1 if the table does not contain the assembly</returns>
805 private int TryFindExistingParentAssembly(BsInfo commonParent)
806 {
807 throw new NotImplementedException("db");
808 //var q =
809 // from asy in _dbTA.TableParentAssemblies
810 // where (asy.Assembly == commonParent.CombinedId)
811 // select asy;
812
813 //List<DbParentAssembly> list = q.ToList<DbParentAssembly>();
814 //if (list == null || list.Count == 0)
815 //{
816 // return -1;
817 //}
818 //else
819 //{
820 // if (list.Count > 1)
821 // {
822 // System.Diagnostics.Debug.Fail("The table ParentAssemblies contains more occurrences of the assembly " + commonParent.CombinedId);
823 // }
824 // return list[0].ParentAssemblyId;
825 //}
826 }
827
828 /// <summary>
829 /// Finds the db-groups of mate rules using two given parts (and optionally with a given restriction).
830 /// </summary>
831 /// <param name="idPartA">The id of a part A.</param>
832 /// <param name="idPartB">The id of a part B.</param>
833 /// <param name="restriction">The restriction. Use value byte.MaxValue if the restriction is not to be used as a filter.</param>
834 /// <returns>
835 /// groups of mate rules using given parts
836 /// </returns>
837 public List<DbGroup> FindDbGroupsContainingParts(int idPartA, int idPartB, byte restriction)
838 {
839 var q =
840 from gr in _dbTA.TableGroups
841 where gr.PartAId == idPartA && gr.PartBId == idPartB
842 //|| (gr.DesignatorA == designator2 && gr.DesignatorB == designator1)
843 select gr;
844
845 if (restriction != byte.MaxValue)
846 {
847 q = from gr in q
848 where gr.GroupRestriction == restriction
849 select gr;
850 }
851
852 return q.ToList<DbGroup>();
853 }
854
855 public List<DbMateRule> FindDbMateRulesForDesignatorsAndSurfaces(string designator1, string surface1, string designator2, string surface2)
856 {
857 throw new NotImplementedException();
858 //var relevantGroups = from gr in _dbTA.TableGroups
859 // where (gr.DesignatorA == designator1 && gr.DesignatorB == designator2)
860 // select gr.GroupId;
861 //var mateRules = from mateRule in _dbTA.TableMateRules
862 // where relevantGroups.Contains(mateRule.GroupId) &&
863 // mateRule.SurfaceA == surface1 && mateRule.SurfaceB == surface2
864 // select mateRule;
865 //var relevantGroupsReverted = from gr in _dbTA.TableGroups
866 // where (gr.DesignatorA == designator2 && gr.DesignatorB == designator1)
867 // select gr.GroupId;
868 //var mateRulesReverted = from mateRule in _dbTA.TableMateRules
869 // where relevantGroupsReverted.Contains(mateRule.GroupId) &&
870 // mateRule.SurfaceA == surface2 && mateRule.SurfaceB == surface1
871 // select mateRule;
872 //var finalQuery = mateRulesReverted.Union(mateRulesReverted);
873 //List<DbMateRule> ret = finalQuery.ToList();
874
875 //return ret;
876 }
877
878 /// <summary>
879 /// //switch the designators, so the "lesser" is in designatorA. This designator is comapred with the designator of the grounded instance.
880 /// </summary>
881 /// <param name="designator1">The designator1.</param>
882 /// <param name="designator2">The designator2.</param>
883 private static void SwitchDesignatorsIfNecessary(ref string designator1, ref string designator2)
884 {
885 if (string.Compare(designator1, designator2) > 0)
886 {
887 string d = designator1;
888 designator1 = designator2;
889 designator2 = d;
890 }
891 }
892
893 /// <summary>
894 /// Finds the db-groups of mate rules, whose designators end with the given endOfDesignator1, endOfDesignator2 (and optionally with a given restriction).
895 /// </summary>
896 /// <param name="endOfDesignator1">The end of designator1 (typically a designator of a part).</param>
897 /// <param name="endOfDesignator2">The end of designator2 (typically a designator of a part).</param>
898 /// <param name="restriction">The restriction. Use value byte.MaxValue if the restriction is not to be used as a filter.</param>
899 /// <returns>groups of mate rules using given designators</returns>
900 public List<DbGroup> FindDbGroupsContainingFragmentsOfDesignators(string endOfDesignator1, string endOfDesignator2, byte restriction)
901 {
902 throw new NotImplementedException();
903 ////because we compare only end of designators, it makes no sense to sort them alphabetically!
904 ////SwitchDesignatorsIfNecessary(ref designator1, ref designator2);
905
906 //var q =
907 // from gr in _dbTA.TableGroups
908 // where (gr.DesignatorA.EndsWith(endOfDesignator1) && gr.DesignatorB.EndsWith(endOfDesignator2)) ||
909 // (gr.DesignatorA.EndsWith(endOfDesignator2) && gr.DesignatorB.EndsWith(endOfDesignator1))
910 // select gr;
911
912 //if (restriction != byte.MaxValue)
913 //{
914 // q = from gr in q
915 // where gr.GroupRestriction == restriction
916 // select gr;
917 //}
918
919 //return q.ToList<DbGroup>();
920 }
921
922 /// <summary>
923 /// Gets from the database all groups of mate rules which are using the two given anonymous designators (and optionally hvae a given restriction).
924 /// </summary>
925 /// <param name="designator1">The designator1.</param>
926 /// <param name="designator2">The designator2.</param>
927 /// <param name="restriction">The restriction.</param>
928 /// <returns>lsit of groups of mate rules</returns>
929 public List<GroupOfMateInfos> FindGroupsOfMateRulesContainingDesignators(string designator1, string designator2, byte restriction)
930 {
931 throw new NotImplementedException("db");
932 //List<DbGroup> dbGroups = FindDbGroupsContainingParts(designator1, designator2, restriction);
933 //if (dbGroups == null)
934 //{
935 // return null;
936 //}
937 //else
938 //{
939 // FindFrequencyOfDbGroups(dbGroups);
940 // List<GroupOfMateInfos> listOfGroupsRules = CreateGroupsOfMateRules(dbGroups);
941 // return listOfGroupsRules;
942 //}
943 }
944
945 /// <summary>
946 /// Finds the frequency of each dbGroup and sets it into the properties dbGroup.Frequency.
947 /// All dbGroup.GroupId must be initialized!
948 /// </summary>
949 /// <param name="dbGroups">The list of dbGroups.</param>
950 public void FindFrequencyOfDbGroups(List<DbGroup> dbGroups)
951 {
952 if (dbGroups == null)
953 {
954 return;
955 }
956
957 for (int i = 0; i < dbGroups.Count; i++)
958 {
959 DbGroup dbGroup = dbGroups[i];
960 FindFrequencyOfDbGroup(dbGroup);
961 }
962 }
963
964 /// <summary>
965 /// Gets from the database all groups of mate rules, whose designators end with the given endOfDesignator1, endOfDesignator2 (and optionally hvae a given restriction).
966 /// </summary>
967 /// <param name="endOfDesignator1">The end of designator1.</param>
968 /// <param name="endOfDesignator2">The end of designator2.</param>
969 /// <param name="restriction">The restriction.</param>
970 /// <returns>
971 /// list of groups of mate rules
972 /// </returns>
973 public List<GroupOfMateInfos> FindMateInfosForAssembly(BsInfo asmInfo)
974 {
975 throw new NotImplementedException("db");
976 //var q =
977 // from asm in _dbTA.TableParentAssemblies
978 // where (asm.Assembly == asmInfo.CombinedId)
979 // select asm;
980
981 //List<DbParentAssembly> assemblies = q.ToList<DbParentAssembly>();
982 //if (assemblies == null || assemblies.Count == 0)
983 //{
984 // return null;
985 //}
986 //else
987 //{
988 // if (assemblies.Count > 1)
989 // {
990 // System.Diagnostics.Debug.Fail("The database contains more records corresponding to a given bsInfo " + asmInfo.CombinedId);
991 // }
992 // List<GroupOfMateInfos> listOfGroupsOfMateInfos = CreateGroupsOfMateInfos(assemblies[0], asmInfo);
993 // return listOfGroupsOfMateInfos;
994 //}
995 }
996
997 /// <summary>
998 /// Finds all surface usabilities for a given part-designator.
999 /// The designator should cover only a single part, not its parent.
1000 /// </summary>
1001 /// <param name="partDesignator">The designator.</param>
1002 /// <param name="surfaces">returns names of all known surfaces of the given part. usabilities[i] corresponds to surfaces[i]</param>
1003 /// <param name="usabilities">returns usabilities of all known surfaces. usabilities[i] corresponds to surfaces[i].</param>
1004 public void FindSurfaceUsabilitiesForDesignator(string partDesignator, out string[] surfaces, out int[] usabilities)
1005 {
1006 throw new NotImplementedException("db");
1007 //var q = from su in _dbTA.TableSurfaceUsabilities
1008 // where su.Designator == partDesignator
1009 // select su;
1010 //if (q == null)
1011 //{
1012 // surfaces = null;
1013 // usabilities = null;
1014 //}
1015 //else
1016 //{
1017 // surfaces = new string[q.Count()];
1018 // usabilities = new uint[q.Count()];
1019 // int i = 0;
1020 // foreach (var su in q)
1021 // {
1022 // surfaces[i] = su.Surface;
1023 // usabilities[i] = su.Usability;
1024 // i++;
1025 // }
1026 //}
1027 }
1028
1029 public DbSurfaceUsability FindSurfaceId(int partId, string surfaceName)
1030 {
1031 var q = _dbTA.TableSurfaceUsabilities.FirstOrDefault(x => x.PartId == partId &&
1032 x.Surface == surfaceName);
1033 return q;
1034 }
1035
1036 /// <summary>
1037 /// Finds all surface usabilities for a given part.
1038 /// </summary>
1039 /// <param name="part">The part.</param>
1040 /// <param name="surfaces">returns names of all known surfaces of the given part. usabilities[i] corresponds to surfaces[i]</param>
1041 /// <param name="usabilities">returns usabilities of all known surfaces. usabilities[i] corresponds to surfaces[i].</param>
1042 /// <param name="samplePoints">returns The sample points.</param>
1043 /// <param name="dbSurfTypes">returns The db surf types.</param>
1044 public void FindSurfaceUsabilitiesOfPart(BsInfo part, out string[] surfaces, out int[] usabilities, out Point3D[] samplePoints, out DbSurfaceTypes[] dbSurfTypes, out BaseSurface[] geomSurfaces)
1045 {
1046 int[] surfIds;
1047 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(part);
1048 int id = dbBso != null ? dbBso.BsoId : EMPTY_DB_INDEX;
1049 //int id = FindBsInfoInTableBsObjects(part);
1050 FindSurfaceUsabilitiesOfPart_inner(id, out surfaces, out usabilities, out samplePoints, out dbSurfTypes, out geomSurfaces, out surfIds);
1051 }
1052
1053 /// <summary>
1054 /// Finds all surface usabilities for a given part.
1055 /// </summary>
1056 /// <param name="part">The part.</param>
1057 /// <param name="surfaces">returns names of all known surfaces of the given part. usabilities[i] corresponds to surfaces[i]</param>
1058 /// <param name="usabilities">returns usabilities of all known surfaces. usabilities[i] corresponds to surfaces[i].</param>
1059 /// <param name="samplePoints">returns The sample points.</param>
1060 /// <param name="dbSurfTypes">returns The db surf types.</param>
1061 public void FindSurfaceUsabilitiesOfPart(BsInfo part, out string[] surfaces, out int[] usabilities, out Point3D[] samplePoints, out DbSurfaceTypes[] dbSurfTypes, out BaseSurface[] geomSurfaces, out bool exactVersion, out int[] surfIds)
1062 {
1063 DbBso dbBso = FindBsInfoInTableBsObjects_NewestPrevious(part, out exactVersion);
1064 int id = dbBso != null ? dbBso.BsoId : EMPTY_DB_INDEX;
1065 FindSurfaceUsabilitiesOfPart_inner(id, out surfaces, out usabilities, out samplePoints, out dbSurfTypes, out geomSurfaces, out surfIds);
1066 }
1067
1068
1069 private void FindSurfaceUsabilitiesOfPart_inner(int id, out string[] surfaces, out int[] usabilities, out Point3D[] samplePoints, out DbSurfaceTypes[] dbSurfTypes, out BaseSurface[] geomSurfaces, out int[] surfIds)
1070 {
1071 if (id != EMPTY_DB_INDEX)
1072 {
1073 var q = from su in _dbTA.TableSurfaceUsabilities
1074 where su.PartId == id
1075 select su;
1076 if (q == null)
1077 {
1078 surfaces = null;
1079 usabilities = null;
1080 samplePoints = null;
1081 dbSurfTypes = null;
1082 geomSurfaces = null;
1083 surfIds = null;
1084 }
1085 else
1086 {
1087 int count = q.Count();
1088 surfaces = new string[count];
1089 usabilities = new int[count];
1090 samplePoints = new Point3D[count];
1091 dbSurfTypes = new DbSurfaceTypes[count];
1092 geomSurfaces = new BaseSurface[count];
1093 surfIds = new int[count];
1094
1095 int i = 0;
1096 foreach (var su in q)
1097 {
1098 surfaces[i] = su.Surface;
1099 usabilities[i] = su.Usability;
1100 //samplePoints[i] = su.PointOnSurface_AsPoint3D;
1101 dbSurfTypes[i] = su.Type;
1102 BaseSurface surf;
1103 Point3D samplePoint;
1104 SurfaceTypes surfType;
1105 bool workFeature;
1106 TranslateDbSurfaceType(su.Type, su.Surface, out surfType, out workFeature);
1107 //bool workFeature = (su.Type == DbSurfaceTypes.Cylinder_WorkFeature) ||
1108 // (su.Type == DbSurfaceTypes.Plane_WorkFeature) ||
1109 // (su.Type == DbSurfaceTypes.None_WorkFeature);
1110
1111 DbSurfaceUsability.ParseSamplePointAndSurfaceFromByteArray(su.PointOnSurface, out samplePoint, out surf);
1112 samplePoints[i] = samplePoint;
1113 if (surf != null)
1114 {
1115 surf.WorkFeature = workFeature;
1116 surf.Name = su.Surface;
1117 }
1118 geomSurfaces[i] = surf;
1119 surfIds[i] = su.SurfaceId;
1120 i++;
1121 }
1122 }
1123 }
1124 else
1125 {
1126 surfaces = null;
1127 usabilities = null;
1128 samplePoints = null;
1129 dbSurfTypes = null;
1130 geomSurfaces = null;
1131 surfIds = null;
1132 }
1133 }
1134
1135 /// <summary>
1136 /// TODO - 2015-02-23. This is a TEMPORARY fix. Some common cylinders in DB are marked as workfeatures.
1137 /// The following code uses the fact that automatically generated names of cylinders have the format cylinder-[3-digit-number]_[id], e.g. //cylinder_123-100020
1138 /// </summary>
1139 /// <param name="workFeature">this flag is set to false if the surface appears to be a normal cylinder (not a workfeature)</param>
1140 /// <param name="dbSurfType">Type of the database surf.</param>
1141 /// <param name="dbSurfName">Name of the database surf.</param>
1142 private static void GetSurfaceTypeFromSurfaceName(ref bool workFeature, DbSurfaceTypes dbSurfType, string dbSurfName)
1143 {
1144#if CYLINDER_TYPE_FROM_NAME
1145 //TODO - 2015-02-23. This is a TEMPORARY fix. Some common cylinders in DB are marked as workfeatures.
1146 //The following code uses the fact that automatically generated names of cylinders have the format cylinder-[3-digit-number]_[id], e.g. //cylinder-123_100020
1147 if (dbSurfType == DbSurfaceTypes.Cylinder_WorkFeature)
1148 {
1149 //cylinder-123_1
1150 if (dbSurfName != null && dbSurfName.StartsWith("cylinder-", StringComparison.OrdinalIgnoreCase) && dbSurfName.Length > 12 && dbSurfName[12] == '_')
1151 {
1152 workFeature = false;
1153 }
1154 }
1155#endif
1156 }
1157
1158 /// <summary>
1159 /// Finds the frequency of a given dbGroup and sets it into the properties dbGroup.Frequency.
1160 /// The dbGroup.GroupId must be initialized!
1161 /// </summary>
1162 /// <param name="dbGroup">The db group.</param>
1163 public void FindFrequencyOfDbGroup(DbGroup dbGroup)
1164 {
1165 throw new NotImplementedException();
1166 //int frequency = (from og in _dbTA.TableOriginOfGroups
1167 // where og.GroupId == dbGroup.GroupId
1168 // select og.Frequency).Sum();
1169 //dbGroup.Frequency = frequency;
1170 }
1171
1172
1173 public List<GroupOfMateInfos> DbMateRulesToGroupsOfMateInfos(List<DbMateRule> dbMateRules)
1174 {
1175 return null;
1176 //if (dbMateRules == null)
1177 //{
1178 // return null;
1179 //}
1180 //Dictionary<uint, GroupOfMateInfos> table = new Dictionary<uint, GroupOfMateInfos>();
1181 //for (int i = 0; i < dbMateRules.Count; i++)
1182 //{
1183 // DbMateRule dbMR = dbMateRules[i];
1184 // MateInfo mateRule = dbMR.CreateAnonymousMateInfo();
1185 // GroupOfMateInfos group;
1186 // if (!table.TryGetValue(dbMR.GroupId, out group))
1187 // {
1188 // group = new GroupOfMateInfos();
1189 // group.Add(mateRule);
1190 // table[dbMR.GroupId] = group;
1191 // }
1192 // else
1193 // {
1194 // group.Add(mateRule);
1195 // }
1196 //}
1197 //return table.Values.ToList<GroupOfMateInfos>();
1198 }
1199
1200 /// <summary>
1201 /// Drops the given view.
1202 /// //TODO - execute drop view only if the view exists
1203 /// </summary>
1204 /// <param name="viewName">Name of the view.</param>
1205 private void DropView(string viewName)
1206 {
1207 //TODO - execute drop view only if the view exists
1208 string sqlDropOldView = SqlQueryCreator.DropViewDescrDB(viewName);
1209 try
1210 {
1211 int cModifiedRows = _dbTA.ExecuteCommand(sqlDropOldView);
1212 }
1213 catch (Exception ex)
1214 {
1215 Logger.Log(ex, LogLevel.Error, 0);
1216 }
1217 }
1218
1219 /// <summary>
1220 /// Only a testing method.
1221 /// </summary>
1222 public void CreateViewOfMateRules(string viewName)
1223 {
1224 DropView(viewName);
1225
1226 string sql = SqlQueryCreator.CreateSimpleViewMateRulesDB(viewName);
1227 try
1228 {
1229 int cModifiedRows = _dbTA.ExecuteCommand(sql);
1230 }
1231 catch (Exception ex)
1232 {
1233 Logger.Log(ex, LogLevel.Error, 0);
1234 }
1235 }
1236
1237 /// <summary>
1238 /// Only a testing method.
1239 /// </summary>
1240 public void CreateTwoViewsOfDescriptors()
1241 {
1242 CreateViewOfMateRules(GetCurrentViewName());
1243 CreateViewOfMateRules(GetNextViewName());
1244 }
1245
1246 /// <summary>
1247 /// returns true if a mate rule with equal designators, surface names, a mating type and a group id exists.
1248 /// </summary>
1249 /// <param name="mr">mate rule.</param>
1250 /// <returns>
1251 /// <c>true</c> if a mate rule with equal designators, surface names, a mating type and a group id is already in the database; otherwise, <c>false</c>.
1252 /// </returns>
1253 private bool IsKnownMateRule(DbMateRule mr)
1254 {
1255 ////TODO - how to compare two mate rules correctly?
1256 //var query = from p in _dbTA.TableMateRules
1257 // where ((p.DesignatorA == mr.DesignatorA && p.DesignatorB == mr.DesignatorB && p.SurfaceA == mr.SurfaceA && p.SurfaceB == mr.SurfaceB) ||
1258 // (p.DesignatorA == mr.DesignatorB && p.DesignatorB == mr.DesignatorA && p.SurfaceA == mr.SurfaceB && p.SurfaceB == mr.SurfaceA)) &&
1259 // p.MatingType == mr.MatingType &&
1260 // p.GroupId == mr.GroupId
1261 // select p;
1262 //return query.Count() > 0;
1263 return false;
1264 }
1265
1266 /// <summary>
1267 /// returns true if a given surface usability exists in the table.
1268 /// </summary>
1269 /// <param name="mr">mate rule.</param>
1270 /// <returns>
1271 /// true if a given surface usability exists in the table.
1272 /// </returns>
1273 private bool IsKnownSurfaceUsability(DbSurfaceUsability su)
1274 {
1275 throw new NotImplementedException("db");
1276 //var query = from p in _dbTA.TableSurfaceUsabilities
1277 // where p.Designator == su.Designator && p.Surface == su.Surface
1278 // select p;
1279 //return query.Count() > 0;
1280 }
1281
1282 [System.Obsolete("2015-12-07 - this is not used anywhere")]
1283 public static string LoadConnectionStringFromConfigFile()
1284 {
1285 ConnectionSettings cs = ConnectionSettings.LoadFromXML(_connectionSettingsFile);
1286 if (cs == null)
1287 {
1288 string error = String.Format("Cannot find or read the xml configuration file {0} describing the connection settings to the geometric search database.", _connectionSettingsFile);
1289 DbManager.Logger.Log(error, LogLevel.Error, 0);
1290 throw new Exception(error);
1291 }
1292
1293 //Data Source Identifies the server. Could be local machine, machine domain name, or IP Address.
1294 //Initial Catalog Database name.
1295 //Integrated Security Set to SSPI to make connection with user's Windows login
1296 //User ID Name of user configured in SQL Server.
1297 //Password Password matching SQL Server User ID.
1298
1299 //if (cs.UseThisConnectionString != null && cs.UseThisConnectionString.Length > 0)
1300 //{
1301 // return cs.UseThisConnectionString;
1302 //}
1303 //else
1304 //{
1305 // SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
1306 // builder.DataSource = cs.DataSource;
1307 // builder.InitialCatalog = cs.InitialCatalog;
1308 // if (cs.User != null && cs.User.Length > 0) builder.UserID = cs.User;
1309 // if (cs.Password != null && cs.Password.Length > 0) builder.Password = cs.Password;
1310 // builder.IntegratedSecurity = cs.UseWindowsUserName;
1311
1312 // return builder.ConnectionString;
1313 //}
1314 return cs.GetConnectionString();
1315 }
1316
1317 #region view names
1318
1319 private string ResetViewNames_GetFirst()
1320 {
1321 _currentViewIndex = 0;
1322 return GetCurrentViewName();
1323 }
1324
1325 private string GetCurrentViewName()
1326 {
1327 return GetViewNameByIndex(_currentViewIndex);
1328 }
1329
1330 private string GetViewNameByIndex(int viewIndex)
1331 {
1332 return _baseNameViewDescrDB + viewIndex.ToString();
1333 }
1334
1335 private string GetNextViewName()
1336 {
1337 return GetViewNameByIndex(_currentViewIndex + 1);
1338 }
1339
1340 private void MoveToNextViewName()
1341 {
1342 _currentViewIndex++;
1343 }
1344
1345 /// <summary>
1346 /// Drops all views.
1347 /// </summary>
1348 private void DropAllViews()
1349 {
1350 DropView(GetViewNameByIndex(0)); //it is enough to drop the first view. The other derived views are freed automatically.
1351 //for (int i = _currentViewIndex; i >= 0; i--)
1352 //{
1353 // DropView(GetViewNameByIndex(i));
1354 //}
1355 }
1356
1357 #endregion
1358
1359
1360 private List<DbGroup> FindDbGroupsForTwoParts(DbBso part1, DbBso part2)
1361 {
1362 BsInfo info1 = part1.CreateBsInfo();
1363 BsInfo info2 = part2.CreateBsInfo();
1364
1365 //sort the infos lexicographically
1366 if (BsInfo.Compare(info1, info2) > 0)
1367 {
1368 DbBso tmp = part1;
1369 part1 = part2;
1370 part2 = tmp;
1371 }
1372
1373 var q = from gr in _dbTA.TableGroups
1374 where gr.PartAId == part1.BsoId && gr.PartBId == part2.BsoId
1375 select gr;
1376
1377 if (q != null)
1378 {
1379 return q.ToList();
1380 }
1381 else
1382 {
1383 return null;
1384 }
1385 }
1386
1387 #region Insertion into database
1388
1389 /// <summary>
1390 /// Inserts group of mate rules into the TableGroups and TableMateRules.
1391 /// </summary>
1392 /// <param name="groupOfMateRules">The group of mate rules.</param>
1393 /// <returns>
1394 /// false if insertion fails
1395 /// </returns>
1396 public bool InsertGroupOfMateRules_New(GroupOfMateInfos groupOfMateRules)
1397 {
1398 if (_dbTA == null)
1399 {
1400 System.Diagnostics.Debug.Fail("The database is not initialized.");
1401 return false;
1402 }
1403 if (groupOfMateRules == null || groupOfMateRules.Count == 0)
1404 {
1405 System.Diagnostics.Debug.Fail("The group of mate rules is empty.");
1406 return false;
1407 }
1408
1409 bool ok = true;
1410
1411 groupOfMateRules = groupOfMateRules.Clone(); //we do not ant to modify the original mate rules - they can be used elsewhere
1412 groupOfMateRules.AlignMateRules_ByPartsInfo();
1413
1414
1415 //DbGroup dbGroup = new DbGroup(mr.TransformedNode.AnonymousDesignator, mr.GroundedNode.AnonymousDesignator, groupOfMateRules.ApproximateRestriction);
1416 int groundedId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(groupOfMateRules.GroundedInfo);
1417 int transformedId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(groupOfMateRules.TransformedInfo);
1418 DbGroup dbGroup = new DbGroup(groupOfMateRules, groundedId, transformedId, this);
1419
1420 DbGroup equalGroup = ExistsDbGroupInDatabase(dbGroup);
1421 if (equalGroup != null)
1422 {
1423 //Compare anonymousPair. If an equal exists, compare its instancePairs (create new if an equal does not exist).
1424 //If equal anonymousPair does not exist, create a new one (and also a new instancePair)
1425 DbAnonymPair anonymPair = new DbAnonymPair(groupOfMateRules, equalGroup.GroupId, this);
1426 DbAnonymPair equalAnonymPair = ExistsDbAnonymPairInDatabase(anonymPair);
1427 if (equalAnonymPair == null)
1428 {
1429 ok &= InsertAnonymPair(anonymPair);
1430 DbInstancePair instancePair = new DbInstancePair(groupOfMateRules, anonymPair.AnonymPairId);
1431 ok &= InsertInstancePair(instancePair);
1432 }
1433 else //an equal dbAnonymPair already exists
1434 {
1435 DbInstancePair instancePair = new DbInstancePair(groupOfMateRules, equalAnonymPair.AnonymPairId);
1436 DbInstancePair equalInstancePair = ExistsDbInstancePairInDatabase(instancePair);
1437 if (equalInstancePair == null)
1438 {
1439 ok &= InsertInstancePair(instancePair);
1440 }
1441 }
1442 return true;
1443 }
1444 else //an equal DbGroup does not exist, so we just insert new records into tables Groups, MateRules, AnonymPairs and InstancePairs
1445 {
1446 ok &= InsertGroupAndMateRules(dbGroup);
1447 DbAnonymPair anonymPair = new DbAnonymPair(groupOfMateRules, dbGroup.GroupId, this);
1448 ok &= InsertAnonymPair(anonymPair);
1449 DbInstancePair instancePair = new DbInstancePair(groupOfMateRules, anonymPair.AnonymPairId);
1450 ok &= InsertInstancePair(instancePair);
1451
1452 return ok;
1453 }
1454 }
1455
1456 private bool InsertGroupAndMateRules(DbGroup dbGroup)
1457 {
1458 //For some reason, LINQ does not set the GroupId in mateRules automatically.
1459 //So we hide them from LINQ, save only the groupOfMateRules (but without rules)
1460 //and then save the mate rules (using the new GroupId).
1461 dbGroup.HideMateGroups();
1462 _dbTA.TableGroups.InsertOnSubmit(dbGroup);
1463
1464 bool ok = true;
1465 try
1466 {
1467 SubmitChangesToDB();
1468 }
1469 catch (Exception ex)
1470 {
1471 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1472 ok = false;
1473 }
1474
1475 //set the GroupId into mate rules and save the mate rules into database
1476 dbGroup.UnhideMateGroups();
1477 foreach (var dbMR in dbGroup.MateRules)
1478 {
1479 dbMR.GroupId = dbGroup.GroupId;
1480 }
1481
1482 try
1483 {
1484 SubmitChangesToDB();
1485 }
1486 catch (Exception ex)
1487 {
1488 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1489 ok = false;
1490 }
1491 return ok;
1492 }
1493
1494 private bool InsertAnonymPair(DbAnonymPair anonymPair)
1495 {
1496 if (_dbTA == null)
1497 {
1498 System.Diagnostics.Debug.Fail("The database is not initialized.");
1499 return false;
1500 }
1501
1502 if (anonymPair == null)
1503 {
1504 System.Diagnostics.Debug.Fail("The anonym pair is null.");
1505 return false;
1506 }
1507
1508 _dbTA.TableAnonymPairs.InsertOnSubmit(anonymPair);
1509 try
1510 {
1511 SubmitChangesToDB();
1512 }
1513 catch (Exception ex)
1514 {
1515 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1516 return false;
1517 }
1518 return true;
1519 }
1520
1521 private bool InsertInstancePair(DbInstancePair instancePair)
1522 {
1523 if (_dbTA == null)
1524 {
1525 System.Diagnostics.Debug.Fail("The database is not initialized.");
1526 return false;
1527 }
1528
1529 if (instancePair == null)
1530 {
1531 System.Diagnostics.Debug.Fail("The instance pair is null.");
1532 return false;
1533 }
1534
1535 _dbTA.TableInstancePairs.InsertOnSubmit(instancePair);
1536 try
1537 {
1538 SubmitChangesToDB();
1539 }
1540 catch (Exception ex)
1541 {
1542 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1543 return false;
1544 }
1545 return true;
1546 }
1547
1548 /// <summary>
1549 /// Inserts usabilities of surfaces into TableSurfaceUsabilities
1550 /// </summary>
1551 /// <param name="tableSurfaceUsabilities">The table surface usabilities.</param>
1552 /// <param name="updateExisting">if true, surface usabilities already existing in the table are rewritten with the new value, otherwise the original value is kept.</param>
1553 /// <returns>
1554 /// false if insertion fails
1555 /// </returns>
1556 public bool InsertSurfaceUsabilities(SurfaceUsabilities tableSurfaceUsabilities, bool updateExisting)
1557 {
1558 if (_dbTA == null)
1559 {
1560 System.Diagnostics.Debug.Fail("The database is not initialized.");
1561 return false;
1562 }
1563
1564 foreach (KeyValuePair<SurfaceKey, SurfaceUsability> keyVal in tableSurfaceUsabilities)
1565 {
1566 string surfaceName;
1567 SurfaceUsability surfUs = keyVal.Value;
1568 //surfaceName = BsOccurrenceId.GetAndRemoveSurfaceName(keyVal.Key, out designator);
1569 //string combinedId = surfUs.PartInfo.CombinedId;
1570 //BsInfo partInfo = BsInfo.CreateFromCombinedId(combinedId, CadObjectTypes.Part);
1571 BsInfo partInfo = surfUs.PartInfo.Clone();
1572 partInfo.CadObjectType = CadObjectTypes.Part;
1573 //BsOccurrenceId bsOcc = BsOccurrenceId.InitFromDesignator(designator, CadObjectTypes.Part);
1574 //BsInfo partInfo = bsOcc.BsInfo;
1575 int bsId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(partInfo);
1576
1577
1578 DbSurfaceUsability dbSu = InsertOneSurfaceUsability(surfUs, bsId, updateExisting);
1579 }
1580
1581 int cErrors = 0;
1582 try
1583 {
1584 SubmitChangesToDB();
1585 }
1586 catch (Exception ex)
1587 {
1588 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1589 cErrors++;
1590 }
1591
1592 return cErrors == 0;
1593 }
1594
1595 /// <summary>
1596 /// Inserts one surface usability.
1597 /// </summary>
1598 /// <param name="surfUs">The surf us.</param>
1599 /// <param name="partId">The part identifier.</param>
1600 /// <param name="updateExisting">if set to <c>true</c> [update existing].</param>
1601 /// <returns></returns>
1602 public DbSurfaceUsability InsertOneSurfaceUsability(SurfaceUsability surfUs, int partId, bool updateExisting)
1603 {
1604 DbSurfaceUsability resultSurfUsab = null;
1605 string surfaceName;
1606 int surfUsability = surfUs.Usability;
1607 BaseSurface geomSurf = surfUs.GeomSurface;
1608 surfaceName = surfUs.SurfaceName;
1609 DbSurfaceUsability suOld;
1610 if (partId >= 0 &&
1611 (suOld = _dbTA.TableSurfaceUsabilities.FirstOrDefault(x => x.PartId == partId && x.Surface == surfaceName)) != null)
1612 {
1613 if (updateExisting)
1614 {
1615 //suOld.Usability = surfUsability;
1616 suOld.Usability = Math.Max(surfUsability, suOld.Usability);
1617
1618 if (surfUs.GeomSurface != null)
1619 {
1620 suOld.PointOnSurface = BasicTool.BasicTools.DoublesToBytes(surfUs.GeomSurface.GetGeometryAsDoubleArray());
1621 }
1622 else
1623 {
1624 suOld.PointOnSurface_AsPoint3D = surfUs.SamplePoint;
1625 }
1626 suOld.Type = TranslateSurfaceType(surfUs.SurfType, surfUs.WorkFeature);
1627 resultSurfUsab = suOld;
1628 }
1629 }
1630 else
1631 {
1632 DbSurfaceTypes dbSurfType = TranslateSurfaceType(surfUs.SurfType, surfUs.WorkFeature);
1633 DbSurfaceUsability su = new DbSurfaceUsability(surfaceName, surfUs.SamplePoint, surfUsability, dbSurfType, geomSurf, partId);
1634 _dbTA.TableSurfaceUsabilities.InsertOnSubmit(su);
1635 resultSurfUsab = su;
1636 }
1637 return resultSurfUsab;
1638 }
1639
1640 public bool UpdateSurfaceUsabilitiesOfOnePart(BsInfo part, List<BaseSurface> surfaces, bool ignoreWorkfeatures)
1641 {
1642 bool ok;
1643 int bsoId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(part, true);
1644 if (bsoId != EMPTY_DB_INDEX)
1645 {
1646 for (int i = 0; i < surfaces.Count; i++)
1647 {
1648 BaseSurface surf = surfaces[i];
1649 if (!surf.WorkFeature || !ignoreWorkfeatures) //optionally, skip workfeatures
1650 {
1651 SurfaceUsability su = new SurfaceUsability(part, surf.Name, surf.GetSurfaceType(), surf.SamplePointInModelCoord, surf.WorkFeature, 0, surf);
1652 DbSurfaceUsability dbSurfUs = InsertOneSurfaceUsability(su, bsoId, true);
1653 }
1654 }
1655 ok = true;
1656
1657 try
1658 {
1659 this.SubmitChangesToDB();
1660 }
1661 catch (Exception ex)
1662 {
1663 ok = false;
1664 DbManager.Logger.Log("SubmitChanges has failed." + '\n' + ex.Message, PDMLog.LogLevel.Error, 0);
1665 }
1666 }
1667 else
1668 {
1669 ok = false;
1670 }
1671 return ok;
1672 }
1673
1674 #endregion
1675
1676 /// <summary>
1677 /// Finds the bs info in table bs objects.
1678 /// </summary>
1679 /// <param name="bsInfo">The common parent.</param>
1680 /// <returns>database id of the object or DbManager.EMPTY_DB_INDEX if nothing was found</returns>
1681 public int FindBsInfoInTableBsObjects_CreateNewIfNotExist(BsInfo bsInfo, bool createAncestors = true)
1682 {
1683 if (bsInfo == null)
1684 {
1685 Logger.Log("FindBsInfoInTableBsObjects_CreateNewIfNotExist called with null param", LogLevel.Error, 0);
1686 return EMPTY_DB_INDEX;
1687 }
1688
1689 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(bsInfo);
1690 int id = dbBso != null ? dbBso.BsoId : DbManager.EMPTY_DB_INDEX;
1691 //int id = FindBsInfoInTableBsObjects(bsInfo);
1692 if (dbBso != null && !string.IsNullOrEmpty(dbBso.CadSystem))
1693 {
1694 //the record is already created in DB and its property CadSystem was set
1695 return dbBso.BsoId;
1696 }
1697 else
1698 {
1699 //either the record does not exist yet, or its property CadSystem was not set (this happens, when the image hashes are created and stored in MateDB during stx conversion)
1700 string baseClass;
1701 BSObjectLight ancestorBso = null;
1702 List<BSObjectLight> ancestorsBsos;
1703 List<BSObjectLight> descendants;
1704 AxServer.Instance.GetAncestors(Convert.ConvertBsInfoToBso(bsInfo), out ancestorsBsos, out descendants, out baseClass);
1705 string cadSystem = AxServer.Instance.GetCadSystem(bsInfo.Id, bsInfo.Variant, bsInfo.Version, bsInfo.Type);
1706
1707 if (ancestorsBsos != null && ancestorsBsos.Count > 0)
1708 {
1709 ancestorBso = ancestorsBsos[0];
1710 }
1711
1712 //BlueViewControls.AxService.FetchOriginAndClassification(Convert.ConvertBsInfoToBso(bsInfo), out origin, out baseClass);
1713 int classifId = GetClassificationId(baseClass);
1714 int ancestorId;
1715 if (ancestorBso == null || String.IsNullOrEmpty(ancestorBso.ObjectID))
1716 {
1717 ancestorId = EMPTY_DB_INDEX;
1718 }
1719 else
1720 {
1721 BsInfo ancestorInfo = Convert.ConvertBsoToBsInfo(ancestorBso);
1722 if (ancestorInfo != null && bsInfo != null)
1723 {
1724 ancestorInfo.CadObjectType = bsInfo.CadObjectType;
1725 }
1726
1727 ancestorId = FindAncestor_CreateNewIfNotExists(ancestorInfo, createAncestors);
1728 }
1729
1730
1731 if (dbBso == null)
1732 {
1733 //the record does not exist. Create a new one.
1734 dbBso = new DbBso(bsInfo, ancestorId, classifId, cadSystem);
1735
1736 try
1737 {
1738 _dbTA.TableBlueStarObjects.InsertOnSubmit(dbBso);
1739 }
1740 catch (Exception ex2)
1741 {
1742 Logger.Log("an error while inserting: " + bsInfo.CombinedId, LogLevel.Error, 0);
1743 Logger.Log("exception" + ex2, LogLevel.Error, 0);
1744 }
1745 }
1746 else
1747 {
1748 //the record was already created. Update some of its properties
1749 dbBso.CadSystem = cadSystem;
1750 dbBso.ClassificationId = classifId;
1751 dbBso.AncestorId = ancestorId;
1752 }
1753
1754 try
1755 {
1756 SubmitChangesToDB();
1757 if (_exceptionOccurred)
1758 {
1759 _exceptionOccurred = false;
1760 Logger.Log("successful insertion after a previous exception: " + bsInfo.CombinedId, LogLevel.Trace, 0);
1761 }
1762 return dbBso.BsoId;
1763 }
1764 catch (Exception ex)
1765 {
1766 _exceptionOccurred = true;
1767 ChangeConflictException conflEx = ex as ChangeConflictException;
1768 if (conflEx != null)
1769 {
1770 Logger.Log("my ChangeConflictException: " + conflEx.SerializeForLog(_dbTA), LogLevel.Error, 0);
1771 }
1772 try
1773 {
1774 Logger.Log("an error while submitting an insertion: " + bsInfo.CombinedId, LogLevel.Error, 0);
1775 string ancestorStr = ancestorBso != null && ancestorBso.CombinedId != null ? ancestorBso.CombinedId.ToString() : "null";
1776 Logger.Log("ancestor info: " + ancestorStr, LogLevel.Error, 0);
1777 Logger.Log("ancestor id: " + ancestorId.ToString(), LogLevel.Error, 0);
1778 Logger.Log("exception: " + ex, LogLevel.Error, 0);
1779 Logger.Log("stack: " + ex.StackTrace, LogLevel.Error, 0);
1780 string innerExc = ex.InnerException != null ? ex.InnerException.ToString() : "null";
1781 Logger.Log("inner ex: " + innerExc, LogLevel.Error, 0);
1782 }
1783 catch (Exception ex2)
1784 {
1785 Logger.Log("an error while logging exception: " + ex2, LogLevel.Error, 0);
1786 }
1787 return DbManager.EMPTY_DB_INDEX;
1788 }
1789 }
1790 }
1791
1792 public DbBso InsertNewBsInfo(BsInfo bsInfo, int ancestorId, int classifId, string cadSystem)
1793 {
1794 DbBso dbBso = new DbBso(bsInfo, ancestorId, classifId, cadSystem);
1795 _dbTA.TableBlueStarObjects.InsertOnSubmit(dbBso);
1796 return dbBso;
1797 }
1798
1799#if PROFILING
1800 public int tmpNumberOfSubmitChanges = 0;
1801#endif
1802
1803 public void SubmitChangesToDB()
1804 {
1805 _dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
1806
1807#if PROFILING
1808 tmpNumberOfSubmitChanges++;
1809#endif
1810 }
1811
1812 private int FindAncestor_CreateNewIfNotExists(BsInfo ancestorInfo, bool createAncestors)
1813 {
1814 if (ancestorInfo == null || String.IsNullOrEmpty(ancestorInfo.Id)) //the ancestor is empty
1815 {
1816 return EMPTY_DB_INDEX;
1817 }
1818 List<DbBso> ancestors = FindDbBso_ByObjectId_Variant(ancestorInfo.Id, ancestorInfo.Variant);
1819 if (ancestors != null && ancestors.Count > 0)
1820 {
1821 DbBso dbBso = FindBestAncestorFromSetWithEqualObjectId(ancestors);
1822 return dbBso.BsoId;
1823 }
1824 else if (createAncestors)
1825 {
1826 //BsInfo newAncestorInfo = new BsInfo(CadObjectTypes.Part, ancestorInfo.Id, "1", ancestorInfo.Variant);
1827 //ancestorInfo.CadObjectType = CadObjectTypes.Part;
1828 int ancestorId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(ancestorInfo, createAncestors);
1829 return ancestorId;
1830 }
1831 else
1832 {
1833 return EMPTY_DB_INDEX;
1834 }
1835 }
1836
1837 private DbBso FindBestAncestorFromSetWithEqualObjectId(List<DbBso> ancestors)
1838 {
1839 if (ancestors != null && ancestors.Count > 0)
1840 {
1841 return ancestors[0];
1842 }
1843 else
1844 {
1845 return null;
1846 }
1847 }
1848
1849 public int GetClassificationId(string baseClass)
1850 {
1851 int classifId;
1852 if (baseClass != null)
1853 {
1854 classifId = FindClassificationId_CreateNewIfNotExist(baseClass);
1855 }
1856 else
1857 {
1858 classifId = EMPTY_DB_INDEX;
1859 }
1860 return classifId;
1861 }
1862
1863 /// <summary>
1864 /// Checks, whether a given classification already exists in the database. If so, it returns its id.
1865 /// Otherwise it inserts a new record into the database and returns its id.
1866 /// </summary>
1867 /// <param name="className">Name of the class.</param>
1868 /// <returns>id of the classification</returns>
1869 public int FindClassificationId_CreateNewIfNotExist(string className)
1870 {
1871 int id = FindClassificationId(className);
1872 if (id != EMPTY_DB_INDEX)
1873 {
1874 return id;
1875 }
1876 else
1877 {
1878 DbClassification dbClassif = new DbClassification(className);
1879
1880 _dbTA.TableClassification.InsertOnSubmit(dbClassif);
1881 try
1882 {
1883 SubmitChangesToDB();
1884 return dbClassif.ClassificationId;
1885 }
1886 catch (Exception ex)
1887 {
1888 Logger.Log(ex, LogLevel.Error, 0);
1889 return DbManager.EMPTY_DB_INDEX;
1890 }
1891 }
1892 }
1893
1894 private int FindClassificationId(string className)
1895 {
1896 if (className == null)
1897 {
1898 return EMPTY_DB_INDEX;
1899 }
1900
1901 className = className.ToLower();
1902 var q = _dbTA.TableClassification.FirstOrDefault(x => x.ClassName == className);
1903 if (q != null)
1904 {
1905 return q.ClassificationId;
1906 }
1907 else
1908 {
1909 return EMPTY_DB_INDEX;
1910 }
1911 }
1912
1913 internal int FindBsInfoInTableBsObjects(BsInfo bsInfo)
1914 {
1915 //DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(bsInfo); //used until 2015-12-04. If an exact version is not found, it search by id and variant only. This must not be used for an insertion!
1916 //search by id, variant, version
1917 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(bsInfo);
1918 if (dbBso != null)
1919 {
1920 return dbBso.BsoId;
1921 }
1922 else
1923 {
1924 return DbManager.EMPTY_DB_INDEX;
1925 }
1926 }
1927
1928 /// <summary>
1929 /// Finds a given bs info in database by its id, variant and version.
1930 /// </summary>
1931 /// <param name="bsInfo">The bs info.</param>
1932 /// <returns>dbBso or null</returns>
1933 public DbBso FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(BsInfo bsInfo)
1934 {
1935 if (_dbTA == null)
1936 return null;
1937 //search by id, variant, version
1938 var q = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.ObjectId == bsInfo.Id &&
1939 x.ObjectVariant == bsInfo.Variant &&
1940 x.ObjectVersion == bsInfo.Version);
1941 DbBso dbBso = q;
1942 return dbBso;
1943 }
1944
1945 public List<DbBso> FindBsosGeometricClass(int geomClass)
1946 {
1947 Table<DbFeatures> tb = _dbTA.GetTable<DbFeatures>();
1948 var q = tb.Where(x => x.MainGeomClass == geomClass);
1949
1950 List<DbBso> results = new List<DbBso>();
1951 Table<DbBso> tb2 = _dbTA.GetTable<DbBso>();
1952 foreach (var feature in q)
1953 {
1954 var b = tb2.FirstOrDefault(x => x.BsoId == feature.PartId);
1955 if (b != null)
1956 results.Add(b);
1957 }
1958
1959 return results;
1960 }
1961
1962 /// <summary>
1963 /// Finds dbBsos with a given id and variant but with a different version!
1964 /// </summary>
1965 /// <param name="bsInfo">The bs info.</param>
1966 /// <returns>dbBso or null</returns>
1967 public List<int> FindDbBsos_WithDifferentVersion(BsInfo bsInfo)
1968 {
1969 //search by id, variant, version
1970 //var q = _dbTA.TableBlueStarObjects.Select(x => x.ObjectId == bsInfo.Id &&
1971 // x.ObjectVariant == bsInfo.Variant &&
1972 // x.ObjectVersion != bsInfo.Version);
1973 IQueryable<int> ids = from dbBso in _dbTA.TableBlueStarObjects
1974 where (bsInfo.Id == dbBso.ObjectId &&
1975 bsInfo.Version != dbBso.ObjectVersion &&
1976 bsInfo.Variant == dbBso.ObjectVariant)
1977 select dbBso.BsoId;
1978 return ids.ToList();
1979 }
1980
1981 /// <summary>
1982 /// Finds a given bs info in database by its id, variant and version. If nothing is found,
1983 /// it searches only by id and variant (but not a version).
1984 /// </summary>
1985 /// <param name="bsInfo">The bs info.</param>
1986 /// <returns>dbBso or null</returns>
1987 public DbBso FindBsInfoInTableBsObjects_GetDbBso(BsInfo bsInfo)
1988 {
1989 DbBso dbBso = null;
1990 if (_cacheBsInfoDbBso != null && _cacheBsInfoDbBso.TryGetValue(bsInfo, out dbBso))
1991 {
1992 return dbBso;
1993 }
1994
1995 //search by id, variant, version
1996 dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(bsInfo);
1997 if (dbBso == null)
1998 {
1999 if (_dbTA == null)
2000 return null;
2001
2002 var qIgnoreVersion = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.ObjectId == bsInfo.Id &&
2003 x.ObjectVariant == bsInfo.Variant);
2004 dbBso = qIgnoreVersion;
2005 }
2006
2007 if (_cacheBsInfoDbBso != null)
2008 {
2009 _cacheBsInfoDbBso[bsInfo] = dbBso;
2010 }
2011
2012 return dbBso;
2013 }
2014
2015 /// <summary>
2016 /// Finds a given bs info in database by its id, variant and version. If nothing is found,
2017 /// it searches for a newest previous version.
2018 /// </summary>
2019 /// <param name="bsInfo">The bs info.</param>
2020 /// <returns>dbBso or null</returns>
2021 public DbBso FindBsInfoInTableBsObjects_NewestPrevious(BsInfo bsInfo, out bool exactVersion)
2022 {
2023 //search by id, variant, version
2024 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(bsInfo);
2025 if (dbBso != null)
2026 {
2027 exactVersion = true;
2028 }
2029 else
2030 {
2031 exactVersion = false;
2032 string sVer = bsInfo.Version;
2033 int version;
2034 if (int.TryParse(sVer, out version))
2035 {
2036 version--;
2037 BsInfo prevVersion = bsInfo.Clone();
2038 while (dbBso == null && version > 0)
2039 {
2040 prevVersion.Version = version.ToString();
2041 dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(prevVersion);
2042 version--;
2043 }
2044 }
2045 }
2046 return dbBso;
2047 }
2048
2049 public List<DbBso> FindDbBso_ByObjectId(string objectId)
2050 {
2051 //var q = _dbTA.TableBlueStarObjects.SelectMany(x => x.ObjectId == objectId);
2052 var q = from dbBso in _dbTA.TableBlueStarObjects
2053 where dbBso.ObjectId == objectId
2054 select dbBso;
2055 return q.ToList();
2056 }
2057
2058 public List<DbBso> FindDbBso_ByObjectId_Version(string combinedId, CadObjectTypes type)
2059 {
2060 BsInfo info = BsInfo.CreateFromCombinedId(combinedId, type);
2061
2062 var q = from dbBso in _dbTA.TableBlueStarObjects
2063 where dbBso.ObjectId == info.Id && dbBso.ObjectVersion == info.Version
2064 select dbBso;
2065
2066 return q.ToList();
2067 }
2068
2069 public List<DbBso> FindDbBso_ByObjectId_Variant(string objectId, string objectVariant)
2070 {
2071 //var q = _dbTA.TableBlueStarObjects.SelectMany(x => x.ObjectId == objectId);
2072 var q = from dbBso in _dbTA.TableBlueStarObjects
2073 where dbBso.ObjectId == objectId && dbBso.ObjectVariant == objectVariant
2074 select dbBso;
2075 return q.ToList();
2076 }
2077
2078 public List<DbBso> FindDbBso_WithSmallerVersion(DbBso queryDbBso)
2079 {
2080 if (queryDbBso != null)
2081 {
2082 //var q = _dbTA.TableBlueStarObjects.SelectMany(x => x.ObjectId == objectId);
2083 var q = from dbBso in _dbTA.TableBlueStarObjects
2084 where dbBso.ObjectId == queryDbBso.ObjectId &&
2085 dbBso.ObjectVariant == queryDbBso.ObjectVariant
2086 select dbBso;
2087
2088 List<DbBso> listDbBso = q.ToList();
2089
2090 List<DbBso> smallerVersions = new List<DbBso>();
2091 float queryVersion = queryDbBso.GetObjectVersionAsNumber();
2092 for (int i = 0; i < listDbBso.Count; i++)
2093 {
2094 DbBso dbBso = listDbBso[i];
2095 float version = dbBso.GetObjectVersionAsNumber();
2096 if (version < queryVersion)
2097 {
2098 smallerVersions.Add(dbBso);
2099 }
2100 }
2101 return smallerVersions;
2102 }
2103 else
2104 {
2105 return null;
2106 }
2107 }
2108
2109 public List<DbBso> FindDbBso_WithDifferentVersion(DbBso queryDbBso)
2110 {
2111 if (queryDbBso != null)
2112 {
2113 //var q = _dbTA.TableBlueStarObjects.SelectMany(x => x.ObjectId == objectId);
2114 var q = from dbBso in _dbTA.TableBlueStarObjects
2115 where dbBso.ObjectId == queryDbBso.ObjectId &&
2116 dbBso.ObjectVariant == queryDbBso.ObjectVariant &&
2117 dbBso.ObjectVersion != queryDbBso.ObjectVersion
2118 select dbBso;
2119
2120 List<DbBso> listDbBso = q.ToList();
2121
2122 return listDbBso;
2123 }
2124 else
2125 {
2126 return null;
2127 }
2128 }
2129
2130 public IList<DbAnonymPair> FindAnonymousPathsForDbGroup(DbGroup dbGroup)
2131 {
2132 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2133 where anonymPath.GroupId == dbGroup.GroupId
2134 select anonymPath;
2135
2136 return anonymPaths.ToList();
2137 }
2138
2139 public List<int> FindAnonymousPathsForDbGroup(int groupId)
2140 {
2141 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2142 where anonymPath.GroupId == groupId
2143 select anonymPath.AnonymPairId;
2144
2145 return anonymPaths.ToList();
2146 }
2147
2148
2149 public IList<DbAnonymPair> FindAnonymousPathsForDbGroup_OnlyForParent_ById(DbGroup dbGroup, BsInfo commonParent)
2150 {
2151 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2152 where anonymPath.GroupId == dbGroup.GroupId &&
2153 String.Compare(commonParent.Id, anonymPath.FirstCommonParent.ObjectId, true) == 0
2154 select anonymPath;
2155
2156 return anonymPaths.ToList();
2157 }
2158
2159 public IList<DbAnonymPair> FindAnonymousPathsForDbGroup_OnlyForParent_ByIdVariant(DbGroup dbGroup, BsInfo commonParent)
2160 {
2161 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2162 where anonymPath.GroupId == dbGroup.GroupId &&
2163 String.Compare(commonParent.Id, anonymPath.FirstCommonParent.ObjectId, true) == 0 &&
2164 String.Compare(commonParent.Variant, anonymPath.FirstCommonParent.ObjectVariant, true) == 0
2165 select anonymPath;
2166
2167 return anonymPaths.ToList();
2168 }
2169
2170 public List<TwoInts> FindAnonymousPathsForCommonParent(int commonParentId)
2171 {
2172 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2173 where anonymPath.FirstCommonParentId == commonParentId
2174 select new TwoInts { RecordId = anonymPath.AnonymPairId, ParentId = anonymPath.GroupId };
2175
2176 return anonymPaths.ToList();
2177 }
2178
2179 public List<DbAnonymPair> FindAnonymousPathsForCommonParent_Object(int commonParentId)
2180 {
2181 var anonymPaths = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
2182 where anonymPath.FirstCommonParentId == commonParentId
2183 select anonymPath;
2184
2185 return anonymPaths.ToList();
2186 }
2187
2188 public IList<DbMateRule> FindMateRulesForDbGroup(DbGroup dbGroup)
2189 {
2190 var mateRules = from mateRule in this.DbTouchAnalysis.TableMateRules
2191 where mateRule.GroupId == dbGroup.GroupId
2192 select mateRule;
2193
2194 return mateRules.ToList();
2195 }
2196
2197 public IList<DbInstancePair> FindFullPathsForAnonymousPath(DbAnonymPair anonymousPair)
2198 {
2199 return FindFullPathsForAnonymousPath(anonymousPair.AnonymPairId);
2200 }
2201
2202 public IList<DbInstancePair> FindFullPathsForAnonymousPaths(params int[] anonymousPairsIds)
2203 {
2204 var ret = from instancePair in this.DbTouchAnalysis.TableInstancePairs
2205 where anonymousPairsIds.Contains(instancePair.AnonymPairId)
2206 select instancePair;
2207
2208 return ret.ToList();
2209 }
2210
2211 public IList<DbInstancePair> FindFullPathsForAnonymousPath(int anonymousPairsId)
2212 {
2213 var ret = from instancePair in this.DbTouchAnalysis.TableInstancePairs
2214 where anonymousPairsId == instancePair.AnonymPairId
2215 select instancePair;
2216
2217 return ret.ToList();
2218 }
2219
2220 public DbInstancePair FindFullPathForAnonymousPath_FirstOnly(int anonymousPairsId)
2221 {
2222 var ret = from instancePair in this.DbTouchAnalysis.TableInstancePairs
2223 where anonymousPairsId == instancePair.AnonymPairId
2224 select instancePair;
2225
2226 return ret.FirstOrDefault();
2227 }
2228
2229
2230 public int FindCountOfFullPathsForAnonymousPaths(int anonymousPairId)
2231 {
2232 var count = this.DbTouchAnalysis.TableInstancePairs.Where(x => x.AnonymPairId == anonymousPairId).Count();
2233 return count;
2234 }
2235
2236
2237
2238 /// <summary>
2239 /// Checks, whether a group of mate rules equal to the given one exists in the database.
2240 /// Two groups of mate rules are considered to be equal, if they target the same two parts
2241 /// and have the same sets of mate rules.
2242 /// </summary>
2243 /// <param name="dbGroup">The db group.</param>
2244 /// <returns>an existing equal mate group or null</returns>
2245 private DbGroup ExistsDbGroupInDatabase(DbGroup dbGroup, int partAId, int partBId)
2246 {
2247 List<DbGroup> similarGroups = FindDbGroupsContainingParts(dbGroup.PartAId, dbGroup.PartBId, dbGroup.GroupRestriction);
2248 if (similarGroups != null)
2249 {
2250 for (int i = 0; i < similarGroups.Count; i++)
2251 {
2252 DbGroup oldDbGroup = similarGroups[i];
2253 if (dbGroup.CompareMateRules(oldDbGroup))
2254 {
2255 return oldDbGroup;
2256 }
2257 }
2258 }
2259 return null;
2260 }
2261
2262 /// <summary>
2263 /// Checks, whether a given anonym pair already exists in the database.
2264 /// </summary>
2265 /// <param name="dbAnonymPair">The db anonym pair.</param>
2266 /// <returns>
2267 /// an existing equal dbAnonymPair or null
2268 /// </returns>
2269 public DbAnonymPair ExistsDbAnonymPairInDatabase(DbAnonymPair dbAnonymPair)
2270 {
2271 var q = from ap in _dbTA.TableAnonymPairs
2272 where ap.GroupId == dbAnonymPair.GroupId &&
2273 ap.ParentAId == dbAnonymPair.ParentAId &&
2274 ap.ParentBId == dbAnonymPair.ParentBId &&
2275 ap.FirstCommonParentId == dbAnonymPair.FirstCommonParentId &&
2276 ap.AnonymPathA == dbAnonymPair.AnonymPathA &&
2277 ap.AnonymPathB == dbAnonymPair.AnonymPathB
2278 select ap;
2279
2280 return q.FirstOrDefault();
2281 //if (q == null)
2282 //{
2283 // return null;
2284 //}
2285 //else
2286 //{
2287 // List<DbAnonymPair> list = q.ToList<DbAnonymPair>();
2288 // if (list == null || list.Count == 0)
2289 // {
2290 // return null;
2291 // }
2292 // else
2293 // {
2294 // System.Diagnostics.Debug.Assert(list.Count == 1, "More than one equal dbAnonymPair have been found!");
2295 // return list[0];
2296 // }
2297 //}
2298 }
2299
2300 /// <summary>
2301 /// Checks, whether a given instance pair already exists in the database.
2302 /// </summary>
2303 /// <param name="dbInstancePair">The db instance pair.</param>
2304 /// <returns>
2305 /// an existing equal dbinstancePair or null
2306 /// </returns>
2307 public DbInstancePair ExistsDbInstancePairInDatabase(DbInstancePair dbInstancePair)
2308 {
2309 var q = from ap in _dbTA.TableInstancePairs
2310 where ap.AnonymPairId == dbInstancePair.AnonymPairId &&
2311 ap.InstanceA == dbInstancePair.InstanceA &&
2312 ap.InstanceB == dbInstancePair.InstanceB &&
2313 ap.InstancePathA == dbInstancePair.InstancePathA &&
2314 ap.InstancePathB == dbInstancePair.InstancePathB
2315 select ap;
2316 if (q == null)
2317 {
2318 return null;
2319 }
2320 else
2321 {
2322 List<DbInstancePair> list = q.ToList<DbInstancePair>();
2323 if (list == null || list.Count == 0)
2324 {
2325 return null;
2326 }
2327 else
2328 {
2329 //compare transformation matrices
2330 for (int i = 0; i < list.Count; i++)
2331 {
2332 DbInstancePair ip = list[i];
2333 if (EqualByteArrays(ip.MatrixOfTransformed, dbInstancePair.MatrixOfTransformed))
2334 {
2335 return ip;
2336 }
2337 }
2338 }
2339 return null;
2340 }
2341 }
2342
2343 private bool EqualByteArrays(byte[] arr1, byte[] arr2)
2344 {
2345 if (arr1 == null && arr2 == null) return true;
2346 if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) return false;
2347 if (arr1.Length != arr2.Length) return false;
2348
2349 for (int i = 0; i < arr1.Length; i++)
2350 {
2351 if (arr1[i] != arr2[i])
2352 {
2353 return false;
2354 }
2355 }
2356 return true;
2357 }
2358
2359 public List<DbGroup> FindDbGroupsContainingParts(DbBso partA, DbBso partB)
2360 {
2361 return FindDbGroupsContainingParts(partA.BsoId, partB.BsoId, Byte.MaxValue);
2362 }
2363
2364 /// <summary>
2365 /// Returns all distinct groups for all combinations of partA and partB.
2366 /// </summary>
2367 /// <param name="partsA">Parts A.</param>
2368 /// <param name="partsB">Parts B.</param>
2369 /// <returns>Distinct groups containing partA and partB.</returns>
2370 public List<DbGroup> FindDbGroupsContainingParts(List<DbBso> partsA, List<DbBso> partsB)
2371 {
2372 IEnumerable<DbBso> distinctAParts = partsA.Distinct();
2373 IEnumerable<DbBso> distinctBParts = partsB.Distinct();
2374
2375 var ret = from myGroup in this.DbTouchAnalysis.TableGroups
2376 where distinctAParts.Contains(myGroup.PartA) && distinctBParts.Contains(myGroup.PartB)
2377 select myGroup;
2378
2379 return ret.Distinct().OrderBy(func => func.GroupId).ToList();
2380 }
2381
2382 public IQueryable<int> FindGroupIdsForParts(DbBso partA, DbBso partB)
2383 {
2384 var myGroups = from myGroup in this.DbTouchAnalysis.TableGroups
2385 where partA.Equals(myGroup.PartA) && partB.Equals(myGroup.PartB)
2386 orderby myGroup.GroupId
2387 select myGroup.GroupId;
2388
2389 return myGroups;
2390 }
2391
2392 public IQueryable<DbGroup> FindDbGroupsForOnePart(int bsoId)
2393 {
2394 var myGroups = from myGroup in this.DbTouchAnalysis.TableGroups
2395 where bsoId == myGroup.PartAId || bsoId == myGroup.PartBId
2396 select myGroup;
2397 return myGroups;
2398 }
2399
2400 public IList<DbMateRule> FindMateRulesForParts(DbBso partA, DbBso partB)
2401 {
2402 var myGroups = FindGroupIdsForParts(partA, partB);
2403 return FindMateRulesForGroupIds(myGroups);
2404 }
2405
2406 public IList<DbMateRule> FindMateRulesForGroupIds(IEnumerable<int> groupIds)
2407 {
2408 var myRules = from myRule in this.DbTouchAnalysis.TableMateRules
2409 where groupIds.Contains(myRule.GroupId)
2410 select myRule;
2411
2412 return myRules.ToList();
2413 }
2414
2415 public IList<DbAnonymPair> FindAnonymousPathsForParts(DbBso partA, DbBso partB)
2416 {
2417 var myGroups = FindGroupIdsForParts(partA, partB);
2418
2419 return FindAnonymousPathsForGroups(myGroups);
2420 }
2421
2422 public IList<DbAnonymPair> FindAnonymousPathsForGroups(IEnumerable<int> groupIds)
2423 {
2424 var myAnonymousPairs = from anonymPair in this.DbTouchAnalysis.TableAnonymPairs
2425 where groupIds.Contains(anonymPair.GroupId)
2426 select anonymPair;
2427
2428 return myAnonymousPairs.ToList();
2429 }
2430
2431 public bool AnonymousPathsForGroupIsEmpty(int groupId)
2432 {
2433 var myAnonymousPairs = from anonymPair in this.DbTouchAnalysis.TableAnonymPairs
2434 where anonymPair.GroupId == groupId
2435 select anonymPair;
2436
2437 var item = myAnonymousPairs.FirstOrDefault();
2438 return item == null;
2439 }
2440
2441 public bool MateRulesForGroupIsEmpty(int groupId)
2442 {
2443 var mateRules = from mateRule in this.DbTouchAnalysis.TableMateRules
2444 where mateRule.GroupId == groupId
2445 select mateRule;
2446
2447 var item = mateRules.FirstOrDefault();
2448 return item == null;
2449 }
2450
2451 public IList<DbSurfaceUsability> FindSurfaceUsabilitiesForSurfaceNames(ISet<SurfaceSearchData> surfaceNames)
2452 {
2453 ISet<DbSurfaceUsability> ret = new HashSet<DbSurfaceUsability>(new SurfaceUsabilityEqualityComparer());
2454
2455 foreach (SurfaceSearchData searchData in surfaceNames)
2456 {
2457 var surfaceList = from surface in this.DbTouchAnalysis.TableSurfaceUsabilities
2458 where surface.Surface == searchData.SurfaceName && surface.Part == searchData.Part
2459 select surface;
2460
2461 foreach (DbSurfaceUsability usability in surfaceList.ToList())
2462 {
2463 ret.Add(usability);
2464 }
2465 }
2466
2467 return ret.ToList(); ;
2468 }
2469
2470 public List<DbGroup> LoadMateRulesFromDatabase(List<BsInfo> partsA, List<BsInfo> partsB,BsInfo commonParent, bool loadAllMateInfos = false)
2471 {
2472 return LoadMateRulesFromDatabase(partsA, partsB, commonParent, false, loadAllMateInfos); //MIZ 20.8.2013 - changed from true
2473 }
2474
2475 public List<DbGroup> LoadMateRulesFromDatabase(List<BsInfo> partsA, List<BsInfo> partsB, BsInfo commonParent, bool includePartialMatches, bool loadAllMateInfos = false)
2476 {
2477 Pdm.Models.ProfilingTools.Watches.Start("DbManager.LoadMateRulesFromDatabase");
2478 try
2479 {
2480 CheckInheritanceTable();
2481
2482 List<DbGroup> dbGroups = FindDbGroupsForTwoCollectionsOfParts(partsA, partsB, includePartialMatches);
2483 if (dbGroups != null)
2484 {
2485 Dictionary<BsInfo, short> tableContextFrequency = FindFrequencyOfContexts(dbGroups);
2486
2487 for (int i = 0; i < dbGroups.Count; i++)
2488 {
2489 if (MateEngineState.Stopped) return null;
2490
2491 DbGroup dbGroup = dbGroups[i];
2492 FillDbGroupWithAnonymAndInstancePairs(dbGroup, commonParent, tableContextFrequency, loadAllMateInfos);
2493 }
2494 dbGroups = RemoveInvalidDbGroupFromList(dbGroups);
2495 return dbGroups;
2496 }
2497 else
2498 {
2499 return null;
2500 }
2501 }
2502 finally
2503 {
2504 Pdm.Models.ProfilingTools.Watches.Stop("DbManager.LoadMateRulesFromDatabase");
2505 }
2506 }
2507
2508 /// <summary>
2509 /// Finds "frequencies" of contexts. That means, how many mate rules for given query parts were found in a context.
2510 /// </summary>
2511 /// <param name="dbGroups">The database groups.</param>
2512 /// <returns>a table, where a key is a context and a value is a frequency (how many mate rules were found in this context)</returns>
2513 private Dictionary<BsInfo, short> FindFrequencyOfContexts(List<DbGroup> dbGroups)
2514 {
2515 Pdm.Models.ProfilingTools.Watches.Start("FindFrequencyOfContexts");
2516 Dictionary<BsInfo, short> tableContextFrequency = new Dictionary<BsInfo, short>();
2517 for (int i = 0; i < dbGroups.Count; i++)
2518 {
2519 DbGroup dbGroup = dbGroups[i];
2520 IList<DbAnonymPair> anonymPairs = FindAnonymousPathsForDbGroup(dbGroup);
2521 dbGroup.HiddenAnonymPairs = new EntitySet<DbAnonymPair>();
2522 dbGroup.HiddenAnonymPairs.AddRange(anonymPairs);
2523
2524 if (anonymPairs != null)
2525 {
2526 for (int j = 0; j < anonymPairs.Count; j++)
2527 {
2528 DbAnonymPair anonymPair = anonymPairs[j];
2529 short freq;
2530 if (anonymPair != null && anonymPair.FirstCommonParent != null)
2531 {
2532 BsInfo context = anonymPair.FirstCommonParent.CreateBsInfo();
2533 if (tableContextFrequency.TryGetValue(context, out freq))
2534 {
2535 freq++;
2536 }
2537 else
2538 {
2539 freq = 1;
2540 }
2541 tableContextFrequency[context] = freq;
2542 }
2543 }
2544 }
2545 }
2546 Pdm.Models.ProfilingTools.Watches.Stop("FindFrequencyOfContexts");
2547 return tableContextFrequency;
2548 }
2549
2550 private List<DbGroup> RemoveInvalidDbGroupFromList(List<DbGroup> dbGroups)
2551 {
2552 if (dbGroups != null)
2553 {
2554 for (int i = dbGroups.Count - 1; i >= 0; i--)
2555 {
2556 DbGroup dbGroup = dbGroups[i];
2557 if (dbGroup != null && dbGroup.IsInvalid())
2558 {
2559 dbGroups.RemoveAt(i);
2560 }
2561 }
2562 }
2563 return dbGroups;
2564 }
2565
2566 private void CheckInheritanceTable()
2567 {
2568 if (_inheritanceTable == null)
2569 {
2570 _inheritanceTable = new DbInheritanceTable(this);
2571 }
2572 }
2573
2574 public List<DbGroup> LoadMateRulesFromDatabase_OnlyForParent(List<BsInfo> partsA, List<BsInfo> partsB, BsInfo commonParent, bool useVariant)
2575 {
2576 CheckInheritanceTable();
2577
2578 List<DbGroup> dbGroups = FindDbGroupsForTwoCollectionsOfParts(partsA, partsB, false);
2579 if (dbGroups != null)
2580 {
2581 for (int i = 0; i < dbGroups.Count; i++)
2582 {
2583 DbGroup dbGroup = dbGroups[i];
2584 FillDbGroupWithAnonymAndInstancePairs_OnlyForParent(dbGroup, commonParent, useVariant);
2585 }
2586 return dbGroups;
2587 }
2588 else
2589 {
2590 return null;
2591 }
2592 }
2593
2594 /// <summary>
2595 /// Fills the database group with anonym and instance pairs.
2596 /// </summary>
2597 /// <param name="dbGroup">The database group.</param>
2598 /// <param name="preferredContext">The preferred context.</param>
2599 /// <param name="tableContextFrequency">The table context frequency.</param>
2600 /// <param name="loadAllMateInfos">if set to <c>true</c>, it loads all available mate ifnos (all instance pairs). if set to false,
2601 /// it filter some instance pairs (it skips instance pairs with an equal transformation matrix).</param>
2602 private void FillDbGroupWithAnonymAndInstancePairs(DbGroup dbGroup, BsInfo preferredContext, Dictionary<BsInfo, short> tableContextFrequency = null, bool loadAllMateInfos = false)
2603 {
2604 Pdm.Models.ProfilingTools.Watches.Start("FillDbGroupWithAnonymAndInstancePairs");
2605
2606 //if (dbGroup.Debug_UseObjectIds("110169", "110149"))
2607 //{
2608 // int x = dbGroup.GroupId;
2609 //}
2610
2611 IList<DbAnonymPair> anonymPairs;
2612 if (dbGroup.HiddenAnonymPairs == null || dbGroup.HiddenAnonymPairs.Count == 0) //if the HiddenAnonymPairs was not already initialized
2613 {
2614 anonymPairs = FindAnonymousPathsForDbGroup(dbGroup);
2615 }
2616 else //the dbGroup.HiddenAnonymPairs was already initialized (see the method FindFrequencyOfContexts)
2617 {
2618 anonymPairs = dbGroup.HiddenAnonymPairs.ToList();
2619 }
2620
2621 if (loadAllMateInfos)
2622 {
2623 //load mate infos from all contexts - this is necessary, when we recosntruct touch graph from Mate DB in the automatic mating!
2624 for (int i = 0; i < anonymPairs.Count; i++)
2625 {
2626 DbAnonymPair anonymPair = anonymPairs[i];
2627 FillDbAnonymPairWithInstancePairs(anonymPair);
2628 anonymPair.CountOfContexts = anonymPairs.Count;
2629 }
2630 }
2631 else
2632 {
2633 if (anonymPairs != null && anonymPairs.Count > 0)
2634 {
2635 _inheritanceTable.AddOneRecordAndFindFamily(preferredContext);
2636
2637 //If the group of mate rules was found in more contexts, use only the one, which is closest to a preferred context.
2638 //Or, if a given prefered context is not related to any contexts found in Mate DB,
2639 //use the context, in which most mate rules were found (for a whole query set).
2640 DbAnonymPair nearestAnonymPair = null;
2641 int minDistance = -1;
2642
2643 DbAnonymPair anonymPairWithHighestFreq = null;
2644 BsInfo parentWithHighestFreq = null;
2645 short maxFreq = -1;
2646
2647 for (int i = 0; i < anonymPairs.Count; i++)
2648 {
2649 DbAnonymPair dbAnonymPair = anonymPairs[i];
2650 int distance = _inheritanceTable.GetDistanceOf(preferredContext, dbAnonymPair.FirstCommonParent);
2651 if (nearestAnonymPair == null || minDistance > distance)
2652 {
2653 nearestAnonymPair = dbAnonymPair;
2654 minDistance = distance;
2655 }
2656
2657 if (tableContextFrequency != null && dbAnonymPair.FirstCommonParent != null)
2658 {
2659 BsInfo parent = dbAnonymPair.FirstCommonParent.CreateBsInfo();
2660 short freq;
2661 if (tableContextFrequency.TryGetValue(parent, out freq))
2662 {
2663 if (freq > maxFreq || (freq == maxFreq && (parentWithHighestFreq == null || String.Compare(parent.CombinedId, parentWithHighestFreq.CombinedId) < 0)))
2664 {
2665 maxFreq = freq;
2666 anonymPairWithHighestFreq = dbAnonymPair;
2667 parentWithHighestFreq = parent;
2668 }
2669 }
2670 }
2671 }
2672
2673 //we have not found anything related to the preferredContext,
2674 //so we will use the anonymPairWithHighestFreq
2675 if (minDistance == int.MaxValue && anonymPairWithHighestFreq != null)
2676 {
2677 nearestAnonymPair = anonymPairWithHighestFreq;
2678 }
2679
2680 dbGroup.HiddenAnonymPairs = new EntitySet<DbAnonymPair>(); //keep only the one selected HiddenAnonymPairs
2681 if (nearestAnonymPair != null)
2682 {
2683 //used until 2016-07-18. But if more instances of an item X is mated to the same surface of instance Y, only one mate rule was fetched
2684 //FillDbAnonymPairWithInstancePair_FirstOnly(nearestAnonymPair);
2685 if (loadAllMateInfos)
2686 {
2687 FillDbAnonymPairWithInstancePairs(nearestAnonymPair);
2688 }
2689 else
2690 {
2691 FillDbAnonymPairWithInstancePair_FilterByMatrices(nearestAnonymPair);
2692 }
2693 dbGroup.HiddenAnonymPairs.Add(nearestAnonymPair);
2694 nearestAnonymPair.CountOfContexts = anonymPairs.Count;
2695 }
2696
2697 /* this was used until 2014-10-20. But it creates very similar groups, just in different contexts (and with different instances)
2698 for (int j = 0; j < anonymPairs.Count; j++)
2699 {
2700 DbAnonymPair dbAnonymPair = anonymPairs[j];
2701 FillDbAnonymPairWithInstancePairs(dbAnonymPair);
2702 }
2703 dbGroup.HiddenAnonymPairs = new EntitySet<DbAnonymPair>();
2704 dbGroup.HiddenAnonymPairs.AddRange(anonymPairs);
2705 */
2706 }
2707 }
2708
2709 Pdm.Models.ProfilingTools.Watches.Stop("FillDbGroupWithAnonymAndInstancePairs");
2710 }
2711
2712
2713 private void FillDbGroupWithAnonymAndInstancePairs_OnlyForParent(DbGroup dbGroup, BsInfo commonParent, bool useVariant)
2714 {
2715 dbGroup.HiddenAnonymPairs = new EntitySet<DbAnonymPair>();
2716
2717 IList<DbAnonymPair> anonymPairs;
2718 if (useVariant)
2719 {
2720 anonymPairs = FindAnonymousPathsForDbGroup_OnlyForParent_ByIdVariant(dbGroup, commonParent);
2721 }
2722 else
2723 {
2724 anonymPairs = FindAnonymousPathsForDbGroup_OnlyForParent_ById(dbGroup, commonParent);
2725 }
2726
2727
2728 if (anonymPairs != null)
2729 {
2730 for (int j = 0; j < anonymPairs.Count; j++)
2731 {
2732 DbAnonymPair dbAnonymPair = anonymPairs[j];
2733 FillDbAnonymPairWithInstancePairs(dbAnonymPair);
2734 }
2735 dbGroup.HiddenAnonymPairs.AddRange(anonymPairs);
2736 }
2737 }
2738
2739 private void FillDbAnonymPairWithInstancePairs(DbAnonymPair dbAnonymPair)
2740 {
2741 dbAnonymPair.HiddenInstancePairs = new EntitySet<DbInstancePair>();
2742 IList<DbInstancePair> dbInstances = FindFullPathsForAnonymousPath(dbAnonymPair);
2743 if (dbInstances != null)
2744 {
2745 dbAnonymPair.HiddenInstancePairs.AddRange(dbInstances);
2746 dbAnonymPair.CountOfInstancePairs = dbInstances.Count;
2747 }
2748 else
2749 {
2750 dbAnonymPair.CountOfInstancePairs = 0;
2751 }
2752 }
2753
2754 /// <summary>
2755 /// Fills the database anonym pair with a first instance pair.
2756 /// Because of speed, it searches only for a first InstancePair, even if there could be more InstancePairs for an anonymPair.
2757 /// </summary>
2758 /// <param name="dbAnonymPair">The database anonym pair.</param>
2759 private void FillDbAnonymPairWithInstancePair_FirstOnly(DbAnonymPair dbAnonymPair)
2760 {
2761 if (dbAnonymPair != null)
2762 {
2763 dbAnonymPair.HiddenInstancePairs = new EntitySet<DbInstancePair>();
2764
2765 DbInstancePair dbInstance = FindFullPathForAnonymousPath_FirstOnly(dbAnonymPair.AnonymPairId);
2766 if (dbInstance != null)
2767 {
2768 dbAnonymPair.HiddenInstancePairs.Add(dbInstance);
2769 }
2770 //get count of instancePairs
2771 dbAnonymPair.CountOfInstancePairs = FindCountOfFullPathsForAnonymousPaths(dbAnonymPair.AnonymPairId);
2772 }
2773 }
2774
2775 /// <summary>
2776 /// Fills the database anonym pair with a first instance pair.
2777 /// Because of speed, it searches only for a first InstancePair, even if there could be more InstancePairs for an anonymPair.
2778 /// </summary>
2779 /// <param name="dbAnonymPair">The database anonym pair.</param>
2780 private void FillDbAnonymPairWithInstancePair_FilterByMatrices(DbAnonymPair dbAnonymPair)
2781 {
2782 if (dbAnonymPair != null)
2783 {
2784 dbAnonymPair.HiddenInstancePairs = new EntitySet<DbInstancePair>();
2785 IList<DbInstancePair> dbInstances = FindFullPathsForAnonymousPath(dbAnonymPair.AnonymPairId);
2786 int countOfInstances = 0;
2787 if (dbInstances != null)
2788 {
2789 countOfInstances = dbInstances.Count;
2790 if (dbInstances.Count == 1)
2791 {
2792 //only one instance pair
2793 DbInstancePair dbInst = dbInstances[0];
2794 dbAnonymPair.HiddenInstancePairs.Add(dbInst);
2795 }
2796 else if (dbInstances.Count > 1)
2797 {
2798 //more instance pairs - take only pairs with unique matrices
2799 Dictionary<byte[], byte> tableUniqueMatrices = new Dictionary<byte[],byte>(new ByteArrayComparer());
2800 for (int i = 0; i < dbInstances.Count; i++)
2801 {
2802 DbInstancePair dbInst = dbInstances[i];
2803 byte[] byteArr = dbInst.MatrixOfTransformed;
2804 if (!tableUniqueMatrices.ContainsKey(byteArr))
2805 {
2806 tableUniqueMatrices[byteArr] = 1;
2807 dbAnonymPair.HiddenInstancePairs.Add(dbInst);
2808 }
2809 }
2810 }
2811 }
2812 //get count of instancePairs
2813 dbAnonymPair.CountOfInstancePairs = countOfInstances;
2814 }
2815 }
2816
2817 public IEnumerable<DbBso> FindDbBsoOfParts(IEnumerable<BsInfo> parts)
2818 {
2819 List<DbBso> dbBsoParts = new List<DbBso>();
2820
2821 if (parts != null)
2822 {
2823 foreach (BsInfo bsInfo in parts)
2824 {
2825 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(bsInfo);
2826 if (dbBso != null)
2827 {
2828 dbBsoParts.Add(dbBso);
2829 }
2830 }
2831 }
2832
2833 return dbBsoParts;
2834 }
2835
2836 public List<DbGroup> FindDbGroupsForTwoParts(BsInfo partA, BsInfo partB, bool includePartialMatches = false)
2837 {
2838 List<BsInfo> partAAsList = new List<BsInfo>();
2839 partAAsList.Add(partA);
2840 List<BsInfo> partBAsList = new List<BsInfo>();
2841 partBAsList.Add(partB);
2842
2843 return FindDbGroupsForTwoCollectionsOfParts(partAAsList, partBAsList, includePartialMatches);
2844 }
2845
2846 /// <summary>
2847 /// Returns Dbgroups that are related to given lists of parts. Does not include partial matches
2848 /// </summary>
2849 /// <param name="partsA"></param>
2850 /// <param name="partsB"></param>
2851 /// <returns></returns>
2852 public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts(List<BsInfo> partsA, List<BsInfo> partsB)
2853 {
2854 return FindDbGroupsForTwoCollectionsOfParts(partsA, partsB, true);
2855 }
2856
2857 public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts(List<BsInfo> partsA, List<BsInfo> partsB, bool includePartialMatches)
2858 {
2859 List<DbBso> dbBsoPartsA;
2860 List<DbBso> dbBsoPartsB;
2861 Dictionary<DbBso, DbBso> tableUsedOriginalBsos;
2862 FindDbBsosForTwoCollectionsOfParts(partsA, partsB, out dbBsoPartsA, out dbBsoPartsB, out tableUsedOriginalBsos);
2863
2864 bool partsDoesNotExist = ((partsA != null && partsA.Count > 0) && (dbBsoPartsA == null || dbBsoPartsA.Count == 0)) ||
2865 ((partsB != null && partsB.Count > 0) && (dbBsoPartsB == null || dbBsoPartsB.Count == 0));
2866
2867 //return null, if at least for one of the input list, no corresponding object in the database exists
2868 if (partsDoesNotExist)
2869 {
2870 return null;
2871 }
2872 List<DbGroup> groups = FindDbGroupsForTwoCollectionsOfParts(dbBsoPartsA, dbBsoPartsB, includePartialMatches);
2873 ModifyGroups_ReplaceDbBso(groups, tableUsedOriginalBsos);
2874
2875 return groups;
2876 }
2877
2878 /// <summary>
2879 /// This method is to be used when looking for a direct mate rules. It "fixes the version number" in resulting groups of mate rules.
2880 /// It replace actual DbBsos in groups of mate rules by query DbBsos.
2881 /// An example - we were looking for a mate rule applicable on a part 12$5. We have found only mate rule applicable on a part 12$1.
2882 /// Now we have to replace the part 12$1 by the part 12$5.
2883 /// </summary>
2884 /// <param name="groups">The groups.</param>
2885 /// <param name="tableUsedOriginalBsos">The table used original bsos.</param>
2886 private void ModifyGroups_ReplaceDbBso(List<DbGroup> groups, Dictionary<DbBso, DbBso> tableUsedOriginalBsos)
2887 {
2888 if (groups != null && tableUsedOriginalBsos != null)
2889 {
2890 for (int i = 0; i < groups.Count; i++)
2891 {
2892 DbGroup group = groups[i];
2893 DbBso bsoA = group.PartA;
2894 DbBso origBsoA, origBsoB;
2895 bool okA = tableUsedOriginalBsos.TryGetValue(group.PartA, out origBsoA);
2896 bool okB = tableUsedOriginalBsos.TryGetValue(group.PartB, out origBsoB);
2897 if (okA && okB &&
2898 (!group.PartA.Equals(origBsoB) || !group.PartB.Equals(origBsoB))) //if at least one of the dbBso must be replaced
2899 {
2900 group.ReplaceDbBso(group.PartA, origBsoA, group.PartB, origBsoB);
2901 }
2902 }
2903 }
2904 }
2905
2906 public void ClearCacheBsInfoDbBso()
2907 {
2908 if (_cacheBsInfoDbBso != null)
2909 {
2910 _cacheBsInfoDbBso.Clear();
2911 }
2912 }
2913
2914 /// <summary>
2915 /// Finds the database bsos for two collections of parts.
2916 /// </summary>
2917 /// <param name="partsA">The parts a.</param>
2918 /// <param name="partsB">The parts b.</param>
2919 /// <param name="dbBsoPartsA">The database bso parts a.</param>
2920 /// <param name="dbBsoPartsB">The database bso parts b.</param>
2921 /// <param name="tableUsedOriginalBsos">returns a table, where a key is a dbBso found in the database and a value is a dbBso, which we were looking for. Note that these two dbBsos can have different versions.</param>
2922 private void FindDbBsosForTwoCollectionsOfParts(IEnumerable<BsInfo> partsA, IEnumerable<BsInfo> partsB, out List<DbBso> dbBsoPartsA, out List<DbBso> dbBsoPartsB, out Dictionary<DbBso, DbBso> tableUsedOriginalBsos)
2923 {
2924 Pdm.Models.ProfilingTools.Watches.Start("FindDbBsosForTwoCollectionsOfParts");
2925
2926 //a key is the dbBso found in the database, a value is a dbBso, which we were looking for. Note that these two dbBsos can have different version
2927 tableUsedOriginalBsos = new Dictionary<DbBso, DbBso>();
2928
2929 dbBsoPartsA = new List<DbBso>();
2930 dbBsoPartsB = new List<DbBso>();
2931 if (_cacheBsInfoDbBso == null)
2932 {
2933 _cacheBsInfoDbBso = new Dictionary<BsInfo, DbBso>();
2934 }
2935
2936 foreach (BsInfo bsInfo in partsA)
2937 {
2938 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(bsInfo);
2939
2940 if (dbBso != null)
2941 {
2942 dbBsoPartsA.Add(dbBso);
2943 tableUsedOriginalBsos[dbBso] = new DbBso(bsInfo); //a key is the dbBso found in the database, a value is a dbBso, which we were looking for. Note that these two dbBsos can have different version
2944 }
2945 }
2946
2947 foreach (BsInfo bsInfo in partsB)
2948 {
2949 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(bsInfo);
2950
2951 if (dbBso != null)
2952 {
2953 dbBsoPartsB.Add(dbBso);
2954 tableUsedOriginalBsos[dbBso] = new DbBso(bsInfo); //a key is the dbBso found in the database, a value is a dbBso, which we were looking for. Note that these two dbBsos can have different version
2955 }
2956 }
2957
2958 Pdm.Models.ProfilingTools.Watches.Stop("FindDbBsosForTwoCollectionsOfParts");
2959 }
2960
2961 /// <summary>
2962 /// Returns all groups where PartA is among partsA and PartB is among partsB.
2963 /// </summary>
2964 /// <param name="partsA">Collection of A parts. If empty, disregards this parameter.</param>
2965 /// <param name="partsB">Collection of B parts. If empty, disregards this parameter.</param>
2966 /// <returns></returns>
2967 public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts(IEnumerable<DbBso> partsA, IEnumerable<DbBso> partsB, bool includePartialMatches)
2968 {
2969 Pdm.Models.ProfilingTools.Watches.Start("FindDbGroupsForTwoCollectionsOfParts");
2970
2971 var dbGroupList = from dbGroup in this.DbTouchAnalysis.TableGroups
2972 select dbGroup;
2973
2974 if (includePartialMatches)
2975 {
2976 dbGroupList = from dbGroup in dbGroupList
2977 where (partsA.Contains(dbGroup.PartA) || partsA.Contains(dbGroup.PartB)) ||
2978 (partsB.Contains(dbGroup.PartA) || partsB.Contains(dbGroup.PartB))
2979 select dbGroup;
2980 }
2981 else
2982 {
2983 dbGroupList = from dbGroup in dbGroupList
2984 where (partsA.Contains(dbGroup.PartA) && partsB.Contains(dbGroup.PartB)) ||
2985 (partsB.Contains(dbGroup.PartA) && partsA.Contains(dbGroup.PartB))
2986 select dbGroup;
2987 }
2988
2989 List<DbGroup> dbGroups = dbGroupList.ToList();
2990 if (dbGroups != null)
2991 {
2992 for (int i = 0; i < dbGroups.Count; i++)
2993 {
2994 dbGroups[i].SetInheritaceDistance(AncestralOrigin.Direct);
2995 }
2996 }
2997
2998 Pdm.Models.ProfilingTools.Watches.Stop("FindDbGroupsForTwoCollectionsOfParts");
2999
3000 return dbGroups;
3001 }
3002
3003
3004 #region find groups of mate rules using an inheritance
3005
3006 public List<DbGroup> LoadMateRulesFromDatabase_UseInheritance(SearchData searchData, SearchSettings searchSett)
3007 {
3008 CheckInheritanceTable();
3009
3010 List<DbGroup> dbGroups = FindDbGroupsForTwoCollectionsOfParts_UseInheritance(searchData.QueryParts, searchData.Parts, searchSett);
3011 for (int i = 0; i < dbGroups.Count; i++)
3012 {
3013 if (MateEngineState.Stopped) return null;
3014
3015 DbGroup dbGroup = dbGroups[i];
3016 FillDbGroupWithAnonymAndInstancePairs(dbGroup, searchData.CommonParent);
3017 }
3018 dbGroups = RemoveInvalidDbGroupFromList(dbGroups);
3019 return dbGroups;
3020 }
3021
3022 public List<DbGroup> LoadMateRulesFromDatabase_UseClassification(SearchData searchData, SearchSettings searchSett)
3023 {
3024 CheckInheritanceTable();
3025
3026 List<DbGroup> dbGroups = FindDbGroupsForTwoCollectionsOfParts_UseClassification(searchData.QueryParts, searchData.Parts);
3027 for (int i = 0; i < dbGroups.Count; i++)
3028 {
3029 if (MateEngineState.Stopped)
3030 {
3031 return null;
3032 }
3033 DbGroup dbGroup = dbGroups[i];
3034 FillDbGroupWithAnonymAndInstancePairs(dbGroup, searchData.CommonParent);
3035 }
3036 dbGroups = RemoveInvalidDbGroupFromList(dbGroups);
3037 return dbGroups;
3038 }
3039
3040 //public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts_UseInheritance(IEnumerable<BsInfo> partsA, IEnumerable<BsInfo> partsB)
3041 //{
3042 // List<DbBso> dbBsoPartsA;
3043 // List<DbBso> dbBsoPartsB;
3044 // FindDbBsosForTwoCollectionsOfParts(infosA, infosB, out dbBsoPartsA, out dbBsoPartsB);
3045
3046 // List<DbGroup> groups = FindDbGroupsForTwoCollectionsOfParts_UseInheritance(dbBsoPartsA, dbBsoPartsB);
3047 // return groups;
3048 //}
3049
3050
3051 /// <summary>
3052 /// Returns all groups where PartA is among partsA and PartB is among partsB.
3053 /// </summary>
3054 /// <param name="partsA">Collection of A parts. If empty, disregards this parameter.</param>
3055 /// <param name="partsB">Collection of B parts. If empty, disregards this parameter.</param>
3056 /// <returns></returns>
3057 /*
3058 * How the search for inherited mate rules works:
3059 * Generations of A: 0 (newest),...,N (oldest)
3060 * Generations of B: 0 (newest),...,M (oldest)
3061 * We test a following sequence of pairs:
3062 * 0-1, 1-0, 1-1;
3063 * 0-2, 2-0, 1-2, 2-1, 2-2;
3064 * 0-3, 3-0, 1-3, 3-1, 2-3, 3-2, 3-3;
3065 * etc.
3066 * In each "level", we expand the search by adding an older ancestor for both A and B.
3067 * The tested pair always contains one the currently oldest known ancestor.
3068 */
3069 public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts_UseInheritance(List<BsInfo> infosA, List<BsInfo> infosB, SearchSettings searchSett)
3070 {
3071 List<DbGroup> allGroups = new List<DbGroup>();
3072
3073 if (infosA == null || infosA.Count == 0 || infosB == null || infosB.Count == 0)
3074 {
3075 //2015-04-23 - if at least one of the list is empty, we can skip the rest
3076 return allGroups;
3077 }
3078
3079 DbInheritanceTable tableInheritanceA = new DbInheritanceTable(this);
3080 tableInheritanceA.AddRecordsAndFindFamilies(infosA);
3081 //tableInheritanceA.AddRecords
3082 DbInheritanceTable tableInheritanceB = new DbInheritanceTable(this);
3083 tableInheritanceB.AddRecordsAndFindFamilies(infosB);
3084
3085 Dictionary<BsInfoPair, byte> testedPairs = new Dictionary<BsInfoPair, byte>();
3086
3087 foreach (KeyValuePair<BsInfo, Family<DbBso>> inheritA in tableInheritanceA)
3088 {
3089 Family<DbBso> ancestorsA = inheritA.Value;
3090 if (ancestorsA == null)
3091 {
3092 continue;
3093 }
3094
3095 foreach (KeyValuePair<BsInfo, Family<DbBso>> inheritB in tableInheritanceB)
3096 {
3097 if (MateEngineState.Stopped)
3098 {
3099 return allGroups;
3100 }
3101
3102 Family<DbBso> ancestorsB = inheritB.Value;
3103 if (ancestorsB == null)
3104 {
3105 continue;
3106 }
3107
3108 //skip an already tested pair
3109 BsInfoPair infoPair = new BsInfoPair(inheritA.Key, inheritB.Key);
3110 if (testedPairs.ContainsKey(infoPair))
3111 {
3112 continue;
3113 }
3114 testedPairs[infoPair] = 1;
3115
3116 bool groupFound = false;
3117 bool ancestorFound;
3118
3119 List<DbGroup> groups = null;
3120
3121 DbBso ancA, ancB;
3122 ancA = ancB = null;
3123
3124 //find groups of mate rules applicable on the youngest ancestors of A and B
3125 int currentLevel;
3126 bool aStartsWithQuery = inheritA.Key.Equals(inheritA.Value[0].CreateBsInfo());
3127 bool bStartsWithQuery = inheritB.Key.Equals(inheritB.Value[0].CreateBsInfo());
3128
3129 int offsetA = aStartsWithQuery ? 0 : 1; //zero if the inheritA starts with the query part, 1 if it starts with an ancestor
3130 int offsetB = bStartsWithQuery ? 0 : 1; //zero if the inheritB starts with the query part, 1 if it starts with an ancestor
3131
3132 if (aStartsWithQuery && bStartsWithQuery)
3133 {
3134 //inheritA.Value[0] and inheritB.Value[0] contains the original parts, not their ancestors.
3135 //We want to skip searching of mate rules for this pair of parts.
3136 //currentLevel = 1; //15.4.2014 - this skips groups of mate rules applicable directly on the origA and origB (no inheritance). But I think, that if we have directly applicable gmr, we should use it!
3137 if (searchSett.SkipDirectMateRulesInInheritance)
3138 {
3139 currentLevel = 1; //this skips groups of mate rules applicable directly on the origA and origB (no inheritance).
3140 }
3141 else
3142 {
3143 currentLevel = 0; //if there is gmr applicable on the origA and origB, let's use it!
3144 }
3145 }
3146 else
3147 {
3148 //inheritA.Value[0] or inheritB.Value[0] contains an ancestor, not the original parts.
3149 //We must search for mate rules for this pair of parts
3150 currentLevel = 0;
3151 }
3152
3153 bool canExit = false;
3154 do
3155 {
3156 ancestorFound = false;
3157 DbBso lastAncA = GetAncestorForCurrentLevel(ancestorsA, currentLevel);
3158 DbBso lastAncB = GetAncestorForCurrentLevel(ancestorsB, currentLevel);
3159 ancestorFound = lastAncA != null || lastAncB != null;
3160 if (!ancestorFound) //no more ancestors => end the search
3161 {
3162 break;
3163 }
3164
3165 for (int i = 0; i <= currentLevel; i++) //here we include the combination lastAncA + lastAncB
3166 {
3167 //one of the ancestors of A + the oldest ancestor of B
3168 if (lastAncB != null && i < ancestorsA.Count && ancestorsA[i] != null)
3169 {
3170 ancA = ancestorsA[i];
3171 groups = FindDbGroupsForTwoParts(ancA, lastAncB);
3172 groupFound = groups != null && groups.Count > 0;
3173 if (groupFound)
3174 {
3175 SetInheritaceDistance(groups, ancA, lastAncB, i + offsetA, currentLevel + offsetB, AncestralOrigin.Inherited);
3176 ancB = lastAncB; //ancB will be replaced in the found group
3177 //TODO - optional - check, whether some of the groups is applicable on the original partA and partB (do they have the proper surfaces?)
3178 ModifyAndStoreGroups(allGroups, inheritA.Key, inheritB.Key, groups, ancA, ancB);
3179
3180 if (CanStopSearching(groupFound, ancestorFound, currentLevel, searchSett))
3181 {
3182 return allGroups;
3183 }
3184 }
3185 }
3186 }
3187
3188 for (int i = 0; i < currentLevel; i++) //here we EXCLUDE the combination lastAncA + lastAncB (hence the condition i < currentLevel)
3189 {
3190 //one of the ancestors of B + the oldest ancestor of A
3191 if (lastAncA != null && i < ancestorsB.Count && ancestorsB[i] != null)
3192 {
3193 ancB = ancestorsB[i];
3194 groups = FindDbGroupsForTwoParts(lastAncA, ancB);
3195 groupFound = groups != null && groups.Count > 0;
3196 if (groupFound)
3197 {
3198 SetInheritaceDistance(groups, lastAncA, ancB, currentLevel + offsetA, i + offsetB, AncestralOrigin.Inherited);
3199 ancA = lastAncA; //ancA will be replaced in the found group
3200 //TODO - optional - check, whether some of the groups is applicable on the original partA and partB (do they have the proper surfaces?)
3201 ModifyAndStoreGroups(allGroups, inheritA.Key, inheritB.Key, groups, ancA, ancB);
3202
3203 if (CanStopSearching(groupFound, ancestorFound, currentLevel, searchSett))
3204 {
3205 return allGroups;
3206 }
3207 }
3208 }
3209 }
3210
3211 canExit = CanStopSearching(groupFound, ancestorFound, currentLevel, searchSett);
3212 currentLevel++;
3213 //} while (!groupFound && ancestorFound); //break the loop if a group was found or there are no more ancestors to be tested
3214 } while (!canExit);
3215
3216 }
3217 }
3218 return allGroups;
3219 }
3220
3221 private void ModifyAndStoreGroups(List<DbGroup> allGroups, BsInfo infoA, BsInfo infoB, List<DbGroup> groups, DbBso ancA, DbBso ancB)
3222 {
3223 DbBso partA = new DbBso(infoA);
3224 DbBso partB = new DbBso(infoB);
3225 List<DbGroup> modifiedGroups = ChangeDbBsoInGroups(groups, partA, ancA, partB, ancB);
3226 if (modifiedGroups != null) allGroups.AddRange(modifiedGroups);
3227 }
3228
3229 private void SetInheritaceDistance(List<DbGroup> groups, DbBso partA, DbBso partB, int distanceA, int distanceB, AncestralOrigin origin)
3230 {
3231 if (groups != null)
3232 {
3233 for (int i = 0; i < groups.Count; i++)
3234 {
3235 DbGroup group = groups[i];
3236 if (group != null)
3237 {
3238 group.SetInheritaceDistance(partA, partB, distanceA, distanceB, origin);
3239 }
3240 }
3241 }
3242 }
3243
3244 private static bool CanStopSearching(bool groupFound, bool ancestorFound, int currentLevel, SearchSettings searchSett)
3245 {
3246 bool canExit = !ancestorFound || (groupFound && searchSett.Inheritance_StopTraversingOnFirstHit) || (searchSett.Inheritance_MaxLevelTraversing == currentLevel);
3247 return canExit;
3248 }
3249
3250 public List<DbGroup> FindDbGroupsForTwoCollectionsOfParts_UseClassification(List<BsInfo> infosA, List<BsInfo> infosB)
3251 {
3252 List<DbGroup> allGroups = new List<DbGroup>();
3253
3254 Dictionary<BsInfo, List<DbBso>> tableFamilyA = InitFamilyTable(infosA);
3255 Dictionary<BsInfo, List<DbBso>> tableFamilyB = InitFamilyTable(infosB);
3256
3257 foreach (KeyValuePair<BsInfo, List<DbBso>> familyA in tableFamilyA)
3258 {
3259 List<DbBso> membersA = familyA.Value;
3260 if (membersA == null)
3261 {
3262 continue;
3263 }
3264 BsInfo infoA = familyA.Key;
3265
3266 foreach (KeyValuePair<BsInfo, List<DbBso>> familyB in tableFamilyB)
3267 {
3268 if (MateEngineState.Stopped)
3269 {
3270 return allGroups;
3271 }
3272
3273 List<DbBso> membersB = familyB.Value;
3274 if (membersB == null)
3275 {
3276 continue;
3277 }
3278 BsInfo infoB = familyB.Key;
3279
3280 List<DbGroup> groups = FindFirstGroupsForTwoParts_UseClassification(allGroups, membersA, infoA, membersB, infoB, true);
3281 if (groups != null)
3282 {
3283 allGroups.AddRange(groups);
3284 }
3285 }
3286 }
3287 return allGroups;
3288 }
3289
3290 private List<DbGroup> FindFirstGroupsForTwoParts_UseClassification(List<DbGroup> allGroups, List<DbBso> membersA, BsInfo infoA, List<DbBso> membersB, BsInfo infoB, bool returnOnlyGmrUsingWorkFeatures)
3291 {
3292 //TODO - possible improvements:
3293 // - returns groups of all pairs, not only the first found.
3294 // - or returns the group with the biggest restriction
3295 // - or check, whether the target parts infoA and infoB have the surfaces used in mate rules
3296 GmrsFromClassificationSorter sorter = new GmrsFromClassificationSorter();
3297
3298 for (int i = 0; i < membersA.Count; i++)
3299 {
3300 DbBso memberA = membersA[i];
3301 for (int j = 0; j < membersB.Count; j++)
3302 {
3303 if (MateEngineState.Stopped)
3304 {
3305 return null;
3306 }
3307
3308 DbBso memberB = membersB[j];
3309
3310 //skip the pair of original parts
3311 bool skipOriginalPairOfParts = false; //15.4.2014 - search also for fmr applicable directly on the original pair of parts
3312 bool skipPair = skipOriginalPairOfParts && (!infoA.Equals(memberA.CreateBsInfo()) || !infoB.Equals(memberB.CreateBsInfo()));
3313
3314 if (!skipPair)
3315 {
3316 List<DbGroup> groups = FindDbGroupsForTwoParts(memberA, memberB);
3317 if (groups != null)
3318 {
3319 if (returnOnlyGmrUsingWorkFeatures && groups.Count > 0) //if we are looking only for gmrs using work features, filter found gmrs by their surfaces
3320 {
3321 List<DbGroup> preferedGmrs = new List<DbGroup>();
3322 for (int k = 0; k < groups.Count; k++)
3323 {
3324 DbGroup group = groups[k];
3325 if (group.UsesOnlyWorkFeatures())
3326 {
3327 preferedGmrs.Add(group);
3328 }
3329 }
3330 groups = preferedGmrs;
3331 }
3332
3333 if (groups.Count > 0)
3334 {
3335 sorter.Add(groups, memberA, memberB);
3336 //DbBso partA = new DbBso(infoA);
3337 //DbBso partB = new DbBso(infoB);
3338 //List<DbGroup> modifiedGroups = ChangeDbBsoInGroups(groups, partA, memberA, partB, memberB);
3339 //return modifiedGroups;
3340 }
3341 }
3342 }
3343 }
3344 }
3345
3346 sorter.SortByGmrsCount();
3347 GmrsFromClassification best = sorter.GetOneBestSet();
3348 if (best != null)
3349 {
3350 DbBso partA = new DbBso(infoA);
3351 DbBso partB = new DbBso(infoB);
3352 List<DbGroup> modifiedGroups = ChangeDbBsoInGroups(best.Gmrs, partA, best.MemberA, partB, best.MemberB);
3353
3354 if (modifiedGroups != null)
3355 {
3356 for (int i = 0; i < modifiedGroups.Count; i++)
3357 {
3358 modifiedGroups[i].SetInheritaceDistance(AncestralOrigin.Classificated);
3359 }
3360 }
3361
3362 return modifiedGroups;
3363 }
3364
3365 return null;
3366 }
3367
3368 private DbBso GetAncestorForCurrentLevel(Family<DbBso> ancestors, int currentLevel)
3369 {
3370 DbBso anc;
3371 if (currentLevel < ancestors.Count && ancestors[currentLevel] != null) //the ancestor corresponding to the current level was already found
3372 {
3373 //the ancestor was already found
3374 anc = ancestors[currentLevel];
3375 }
3376 else if (currentLevel >= ancestors.Count && (ancestors.Count == 0 || ancestors[ancestors.Count - 1] == null)) //the ancestor corresponding to the current level does not exist (we already had tried to find it)
3377 {
3378 //the ancestor does not exist
3379 anc = null;
3380 }
3381 else //try to find the next ancestor
3382 {
3383 //2014-10-20 - a whole family is created at once, we do not build it gradually. So if a family does not contain data for a current level, do not try to fetch them.
3384 //anc = GetAncestor(ancestors[ancestors.Count - 1]);
3385 //TODO - fill the ancestors correctly!
3386 //ancestors.Add(anc);
3387 anc = null;
3388 }
3389 return anc;
3390 }
3391
3392 private Dictionary<BsInfo, List<DbBso>> InitInheritanceTable(List<BsInfo> infos)
3393 {
3394 Dictionary<BsInfo, List<DbBso>> tableInheritance = new Dictionary<BsInfo, List<DbBso>>(infos.Count);
3395 for (int i = 0; i < infos.Count; i++)
3396 {
3397 BsInfo info = infos[i];
3398 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(info);
3399 if (dbBso == null)
3400 {
3401 dbBso = GetAncestor(info);
3402 }
3403 if (dbBso != null)
3404 {
3405 tableInheritance[info] = new List<DbBso>() { dbBso };
3406 }
3407 else
3408 {
3409 tableInheritance[info] = null;
3410 }
3411 }
3412 return tableInheritance;
3413 }
3414
3415 private Dictionary<BsInfo, List<DbBso>> InitFamilyTable(List<BsInfo> infos)
3416 {
3417 Dictionary<BsInfo, List<DbBso>> tableClassification = new Dictionary<BsInfo, List<DbBso>>(infos.Count);
3418 for (int i = 0; i < infos.Count; i++)
3419 {
3420
3421 BsInfo info = infos[i];
3422
3423 List<DbBso> family = FindDbBso_WithClassification(info);
3424 tableClassification[info] = family;
3425 }
3426 return tableClassification;
3427 }
3428
3429 private List<DbBso> FindDbBso_WithClassification(BsInfo info)
3430 {
3431 List<DbBso> family = null;
3432 //Get the classification of the info. First, try to get it from TA database,
3433 //and if a corresponding DbBso object does not exist, try BlueStar.
3434 string baseClass = null;
3435 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso(info);
3436 if (dbBso != null)
3437 {
3438 if (dbBso.Classification != null)
3439 {
3440 baseClass = dbBso.Classification.ClassName;
3441 }
3442 }
3443 else
3444 {
3445 string origin, classific;
3446 List<BSObjectLight> ancestorsBsos;
3447 List<BSObjectLight> descendants;
3448 AxServer.Instance.GetAncestors(Convert.ConvertBsInfoToBso(info), out ancestorsBsos, out descendants, out classific);
3449 if (!String.IsNullOrEmpty(classific))
3450 {
3451 baseClass = classific;
3452 }
3453 }
3454
3455 if (!String.IsNullOrWhiteSpace(baseClass))
3456 {
3457 family = FindDbBso_WithClassification(baseClass);
3458 }
3459 return family;
3460 }
3461
3462 private List<DbBso> FindDbBso_WithClassification(string baseClass)
3463 {
3464 var q = from bso in _dbTA.TableBlueStarObjects
3465 //where String.Equals(bso.Classification.ClassName, baseClass, StringComparison.OrdinalIgnoreCase)
3466 where String.Compare(bso.Classification.ClassName, baseClass, StringComparison.OrdinalIgnoreCase) == 0
3467 select bso;
3468 return q.ToList();
3469 }
3470
3471 private List<DbGroup> ChangeDbBsoInGroups(List<DbGroup> groups, DbBso partA, DbBso ancestorA, DbBso partB, DbBso ancestorB)
3472 {
3473 List<DbGroup> modifiedGroups = new List<DbGroup>(groups.Count);
3474 for (int i = 0; i < groups.Count; i++)
3475 {
3476 DbGroup group = groups[i];
3477 DbGroup clone = group.ShallowCopy();
3478 bool replaceOk = clone.ReplaceDbBso(ancestorA, partA, ancestorB, partB);
3479 System.Diagnostics.Debug.Assert(replaceOk, "Cannot replace the ancestors in a DbGroup.");
3480 modifiedGroups.Add(clone);
3481 }
3482 return modifiedGroups;
3483 }
3484
3485 /// <summary>
3486 /// For a given object, it tries to find its ancestor in the TA database.
3487 /// If the TA database does not contain a direct ancestor,
3488 /// it tries to use ancestors from BlueStar to skip ancestors missing in the TA database.
3489 /// For example, a father of the input dbBso is not in the TA database, but the grandfather is. We use the BlueStar
3490 /// to bridge this gap.
3491 /// It always returns a DbBso existing in the TA database or null.
3492 /// </summary>
3493 /// <param name="dbBso">The db bso.</param>
3494 /// <returns>a youngest ancestor existing in TA database, or null</returns>
3495 internal DbBso GetAncestor(DbBso dbBso)
3496 {
3497 if (dbBso == null)
3498 {
3499 return null;
3500 }
3501
3502 DbBso ancestor = null;
3503 if (dbBso.AncestorId != EMPTY_DB_INDEX)
3504 {
3505 var q = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.BsoId == dbBso.AncestorId);
3506 if ((ancestor = q as DbBso) != null)
3507 {
3508 return ancestor;
3509 }
3510 }
3511 BsInfo info = dbBso.CreateBsInfo();
3512 return GetAncestor(info);
3513 }
3514
3515 /// <summary>
3516 /// For a given object, it tries to find its ancestor in the TA database.
3517 /// If the TA database does not contain a direct ancestor,
3518 /// it tries to use ancestors from BlueStar to skip ancestors missing in the TA database.
3519 /// For example, a father of the input dbBso is not in the TA database, but the grandfather is. We use the BlueStar
3520 /// to bridge this gap.
3521 /// It always returns a DbBso existing in the TA database or null.
3522 /// </summary>
3523 /// <param name="dbBso">The db bso.</param>
3524 /// <returns>a youngest ancestor existing in TA database, or null</returns>
3525 internal List<DbBso> GetDirectDescendants(DbBso dbBso)
3526 {
3527 if (dbBso == null)
3528 {
3529 return null;
3530 }
3531
3532 List<DbBso> descendatns = null;
3533 if (dbBso.BsoId != EMPTY_DB_INDEX)
3534 {
3535 var q =
3536 from x in _dbTA.TableBlueStarObjects
3537 where x.AncestorId == dbBso.BsoId
3538 select x;
3539
3540 descendatns = q.ToList();
3541 return descendatns;
3542 }
3543 else
3544 {
3545 return null;
3546 }
3547 }
3548
3549 public List<DbBso> GetAllBsObjects()
3550 {
3551 if (_dbTA == null || _dbTA.TableBlueStarObjects == null)
3552 {
3553 return new List<DbBso>();
3554 }
3555 var bsoTable = _dbTA.TableBlueStarObjects;
3556 return bsoTable.ToList();
3557 }
3558
3559 internal DbBso GetAncestor(BsInfo info)
3560 {
3561 //use ancestor from BlueStar, find the newest ancestor stored in the TA database
3562 BSObjectLight bso = Convert.ConvertBsInfoToBso(info);
3563 bool ancestorInBSfound = true;
3564 DbBso dbBso = null;
3565 do
3566 {
3567 string baseClass;
3568 Family<BSObjectLight> ancestorsBsos = null;
3569 BSObjectLight ancestorBso = null;
3570 //BlueViewControls.AxService.FetchOriginAndClassification(bso, out origin, out baseClass);
3571 //BlueViewControls.AxService.GetAncestors(bso, out ancestorsBsos, out baseClass);
3572 bool sourceFound;
3573 _inheritanceSource.GetFamilyAndClassification(bso, out ancestorsBsos, out baseClass, out sourceFound);
3574 if (ancestorsBsos != null && ancestorsBsos.Ancestors != null && ancestorsBsos.Ancestors.Count > 0)
3575 {
3576 ancestorBso = ancestorsBsos.Ancestors[0];
3577 }
3578 if (ancestorBso != null && !string.IsNullOrEmpty(ancestorBso.ObjectID))
3579 {
3580 List<DbBso> ancestors = FindDbBso_ByObjectId_Variant(ancestorBso.ObjectID, ancestorBso.VariantID);
3581 dbBso = FindBestAncestorFromSetWithEqualObjectId(ancestors);
3582 if (dbBso != null) //we have found an ancestor existing in TA database
3583 {
3584 return dbBso;
3585 }
3586 else //we will try to get an older ancestor from the BlueStar
3587 {
3588 bso = ancestorBso;
3589 }
3590 }
3591 else
3592 {
3593 ancestorInBSfound = false;
3594 }
3595 } while (ancestorInBSfound);
3596 return null;
3597 }
3598
3599 #endregion
3600
3601 public int FetchGroupWithHighestId()
3602 {
3603 DbGroup highestIdGroup = this.DbTouchAnalysis.TableGroups.OrderByDescending(u => u.GroupId).FirstOrDefault();
3604
3605 return highestIdGroup.GroupId;
3606 }
3607
3608 /// <summary>
3609 /// Fetches common neighbors and all available details - contexts and instances.
3610 /// Touching instances are divided into configurations - all instances touching one instance of the query part are stored together in one list.
3611 /// </summary>
3612 /// <param name="part">The part.</param>
3613 /// <param name="contextAsm">The context asm.</param>
3614 /// <returns>common neighbors and all details</returns>
3615 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
3616 public TDitem FetchCommonNeighbors_WithInstances(BsInfo part, BsInfo contextAsm)
3617 {
3618 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3619 TDitem tdItem = new TDitem(partBso);
3620
3621 if (part != null)
3622 {
3623 if (contextAsm == null)
3624 {
3625 try
3626 {
3627 var myGroups = FindGroupsUsingPart(part);
3628
3629 if (myGroups != null)
3630 {
3631 IList<DbGroup> dbGroups = myGroups.ToList();
3632
3633 if (dbGroups != null)
3634 {
3635 foreach (DbGroup dbGroup in dbGroups)
3636 {
3637 bool queryPartIsInA;
3638 DbBso otherDbBso = dbGroup.GetOtherBso(part, out queryPartIsInA);
3639 if (otherDbBso != null)
3640 {
3641 BSObjectLight otherBso = otherDbBso.CreateBso();
3642 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
3643
3644 IList<DbAnonymPair> anonymPaths = FindAnonymousPathsForDbGroup(dbGroup);
3645
3646 if (anonymPaths != null)
3647 {
3648 foreach (DbAnonymPair anonym in anonymPaths)
3649 {
3650 BsInfo contextInfo = anonym.FirstCommonParent.CreateBsInfo();
3651 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
3652 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
3653
3654 IList<DbInstancePair> instances = FindFullPathsForAnonymousPath(anonym);
3655 if (instances != null)
3656 {
3657 foreach (DbInstancePair dbInstPair in instances)
3658 {
3659 string instA = dbInstPair.InstanceA;
3660 string instB = dbInstPair.InstanceB;
3661
3662
3663 string desA = BsInstanceId.BuildDesignator(contextInfo.CombinedId, dbInstPair.InstancePathA, otherBso.CombinedId, instA, BsOccurrenceId.EMPTY_INDEX);
3664 string desB = BsInstanceId.BuildDesignator(contextInfo.CombinedId, dbInstPair.InstancePathB, otherBso.CombinedId, instB, BsOccurrenceId.EMPTY_INDEX);
3665 string desTouching;
3666 string desItem;
3667 if (queryPartIsInA)
3668 {
3669 desItem = desA;
3670 desTouching = desB;
3671 }
3672 else
3673 {
3674 desItem = desB;
3675 desTouching = desA;
3676 }
3677
3678 BsInstanceId instItem = BsInstanceId.InitFromDesignator(desItem, CadObjectTypes.Part);
3679 BsInstanceId instTouching = BsInstanceId.InitFromDesignator(desTouching, CadObjectTypes.Part);
3680
3681 TDinstancesBsInst tdInstances = itemContext.GetExistingCreateNew(instItem);
3682 tdInstances.AddInstance(instTouching);
3683
3684 //AddIntoTable(key, instTouching, tableInstances);
3685 }
3686 }
3687 }
3688 }
3689 }
3690 }
3691 }
3692 }
3693 }
3694 catch (Exception ex)
3695 {
3696 PDMLog.Logger.Log(ex);
3697 }
3698 }
3699 }
3700 return tdItem;
3701 }
3702
3703 /// <summary>
3704 /// Fetches common neighbors and their contexts.
3705 /// </summary>
3706 /// <param name="part">The part.</param>
3707 /// <returns>common neighbors and their contexts</returns>
3708 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
3709 public TDitem FetchCommonNeighbors_WithContexts_Slow(BsInfo part)
3710 {
3711 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3712 TDitem tdItem = new TDitem(partBso);
3713
3714 if (part != null)
3715 {
3716 try
3717 {
3718 var myGroups = FindGroupsUsingPart(part);
3719
3720 if (myGroups != null)
3721 {
3722 IList<DbGroup> dbGroups = myGroups.ToList();
3723
3724 if (dbGroups != null)
3725 {
3726 foreach (DbGroup dbGroup in dbGroups)
3727 {
3728 bool queryPartIsInA;
3729 DbBso otherDbBso = dbGroup.GetOtherBso(part, out queryPartIsInA);
3730 if (otherDbBso != null)
3731 {
3732 BSObjectLight otherBso = otherDbBso.CreateBso();
3733 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
3734
3735 var contexts = from anonymPath in this.DbTouchAnalysis.TableAnonymPairs
3736 where anonymPath.GroupId == dbGroup.GroupId
3737 select anonymPath.FirstCommonParent;
3738
3739 if (contexts != null)
3740 {
3741 foreach (DbBso context in contexts)
3742 {
3743 BsInfo contextInfo = context.CreateBsInfo();
3744 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
3745 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
3746 }
3747 }
3748 }
3749 }
3750 }
3751 }
3752 }
3753 catch (Exception ex)
3754 {
3755 PDMLog.Logger.Log(ex);
3756 }
3757
3758 }
3759 return tdItem;
3760 }
3761
3762
3763 /// <summary>
3764 /// Fetches common neighbors and their contexts.
3765 /// Looks for items with exactly equal id, version and variant.
3766 /// </summary>
3767 /// <param name="part">The part.</param>
3768 /// <returns>common neighbors and their contexts</returns>
3769 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
3770 public TDitem FetchCommonNeighbors_WithContexts(BsInfo part, string bsoClassif, FamilyLevels familyLevel)
3771 {
3772 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3773 List<TDitem> tdItems = new List<TDitem>();
3774
3775 if (part != null)
3776 {
3777 if ((familyLevel & FamilyLevels.Exact) > 0)
3778 {
3779 TDitem tdItem = FetchCommonNeighbors_WithContexts_Exact_Fast(part); //2015-10-05
3780 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Exact);
3781 }
3782
3783 if ((familyLevel & FamilyLevels.Versions) > 0)
3784 {
3785 TDitem tdItem = FetchCommonNeighbors_WithContexts_Version_Fast(part); //2015-10-05
3786 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Versions);
3787 }
3788
3789 if ((familyLevel & FamilyLevels.Variants) > 0)
3790 {
3791 TDitem tdItem = FetchCommonNeighbors_WithContexts_Variant(part);
3792 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Variants);
3793 }
3794
3795 if ((familyLevel & FamilyLevels.Classification) > 0)
3796 {
3797 int classificationId;
3798 if (!String.IsNullOrWhiteSpace(bsoClassif) &&
3799 (classificationId = FindClassificationId(bsoClassif)) != DbManager.EMPTY_DB_INDEX)
3800 {
3801 TDitem tdItem = FetchCommonNeighbors_WithContexts_Classiffication(part, classificationId);
3802 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Classification);
3803 }
3804 }
3805 //default:
3806 // System.Diagnostics.Debug.Fail("FetchCommonNeighbors_WithContexts - an unsupported value - " + familyLevel.ToString());
3807 // break;
3808 }
3809
3810 TDitem result = TDitem.MergeList(tdItems, partBso);
3811 return result;
3812 }
3813
3814 private static void AddTDitemIntoList(List<TDitem> tdItems, TDitem tdItem, FamilyLevels familyLevel)
3815 {
3816 if (tdItem != null)
3817 {
3818 tdItem.SetFamilyLevelIntoTouchingItems(familyLevel);
3819 tdItems.Add(tdItem);
3820 }
3821 }
3822
3823 /// <summary>
3824 /// Fetches common neighbors and their contexts.
3825 /// Looks for items with exactly equal id, and variant, but different version.
3826 /// </summary>
3827 /// <param name="part">The part.</param>
3828 /// <returns>common neighbors and their contexts</returns>
3829 private TDitem FetchCommonNeighbors_WithContexts_Version(BsInfo part)
3830 {
3831 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3832 TDitem tdItem = new TDitem(partBso);
3833
3834 try
3835 {
3836 //var myGroups = FindGroupsUsingPart(part);
3837
3838 //if (myGroups != null)
3839 {
3840 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
3841 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
3842 where (part.Id == gr.PartA.ObjectId &&
3843 part.Version != gr.PartA.ObjectVersion &&
3844 part.Variant == gr.PartA.ObjectVariant) ||
3845 (part.Id == gr.PartB.ObjectId &&
3846 part.Version != gr.PartB.ObjectVersion &&
3847 part.Variant == gr.PartB.ObjectVariant)
3848 select new DbGroupAndContext(gr, context.FirstCommonParent);
3849
3850 //var list = neighsAndContexts.ToList();
3851 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
3852
3853 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Version);
3854 }
3855 }
3856 catch (Exception ex)
3857 {
3858 PDMLog.Logger.Log(ex);
3859 }
3860
3861 return tdItem;
3862 }
3863
3864 /// <summary>
3865 /// Fetches common neighbors and their contexts.
3866 /// Looks for items with exactly equal id, and variant, but different version.
3867 /// </summary>
3868 /// <param name="part">The part.</param>
3869 /// <returns>common neighbors and their contexts</returns>
3870 private TDitem FetchCommonNeighbors_WithContexts_Version_Fast(BsInfo part)
3871 {
3872 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3873 TDitem tdItem = new TDitem(partBso);
3874 if (part != null)
3875 {
3876
3877 try
3878 {
3879 List<int> dbBsoIds = FindDbBsos_WithDifferentVersion(part);
3880 if (dbBsoIds != null && dbBsoIds.Count > 0)
3881 {
3882 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
3883 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
3884 where (dbBsoIds.Contains(gr.PartAId) ||
3885 dbBsoIds.Contains(gr.PartBId))
3886 select new DbGroupAndContext(gr, context.FirstCommonParent);
3887
3888 //var list = neighsAndContexts.ToList();
3889 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
3890
3891 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Version);
3892 }
3893 }
3894 catch (Exception ex)
3895 {
3896 PDMLog.Logger.Log(ex);
3897 }
3898 }
3899 return tdItem;
3900 }
3901
3902 /// <summary>
3903 /// Fetches common neighbors and their contexts.
3904 /// Looks for items with exactly equal id, but different variant, and an arbitrary version.
3905 /// </summary>
3906 /// <param name="part">The part.</param>
3907 /// <returns>common neighbors and their contexts</returns>
3908 private TDitem FetchCommonNeighbors_WithContexts_Variant(BsInfo part)
3909 {
3910 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3911 TDitem tdItem = new TDitem(partBso);
3912
3913 try
3914 {
3915 //var myGroups = FindGroupsUsingPart(part);
3916
3917 //if (myGroups != null)
3918 {
3919 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
3920 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
3921 where (part.Id == gr.PartA.ObjectId &&
3922 part.Variant != gr.PartA.ObjectVariant) ||
3923 (part.Id == gr.PartB.ObjectId &&
3924 part.Variant != gr.PartB.ObjectVariant)
3925 select new DbGroupAndContext(gr, context.FirstCommonParent);
3926
3927 //var list = neighsAndContexts.ToList();
3928 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
3929
3930 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Variant);
3931 }
3932 }
3933 catch (Exception ex)
3934 {
3935 PDMLog.Logger.Log(ex);
3936 }
3937
3938 return tdItem;
3939 }
3940
3941 /// <summary>
3942 /// Fetches common neighbors and their contexts.
3943 /// </summary>
3944 /// <param name="part">The part.</param>
3945 /// <returns>common neighbors and their contexts</returns>
3946 private TDitem FetchCommonNeighbors_WithContexts_Exact(BsInfo part)
3947 {
3948 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3949 TDitem tdItem = new TDitem(partBso);
3950
3951 if (part != null)
3952 {
3953 try
3954 {
3955 //var myGroups = FindGroupsUsingPart(part);
3956
3957 //if (myGroups != null)
3958 {
3959 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
3960 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
3961 where (part.Id == gr.PartA.ObjectId &&
3962 part.Version == gr.PartA.ObjectVersion &&
3963 part.Variant == gr.PartA.ObjectVariant) ||
3964 (part.Id == gr.PartB.ObjectId &&
3965 part.Version == gr.PartB.ObjectVersion &&
3966 part.Variant == gr.PartB.ObjectVariant)
3967 select new DbGroupAndContext(gr, context.FirstCommonParent);
3968
3969 //var list = neighsAndContexts.ToList();
3970 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
3971
3972 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Exact);
3973 }
3974 }
3975 catch (Exception ex)
3976 {
3977 PDMLog.Logger.Log(ex);
3978 }
3979
3980 }
3981 return tdItem;
3982 }
3983
3984 /// <summary>
3985 /// Fetches common neighbors and their contexts.
3986 /// </summary>
3987 /// <param name="part">The part.</param>
3988 /// <returns>common neighbors and their contexts</returns>
3989 [System.Obsolete("2018-02-26 - maybe not used anywhere?")]
3990 private TDitem FetchCommonNeighbors_WithContexts_Exact_Fast(BsInfo part)
3991 {
3992 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
3993 TDitem tdItem = new TDitem(partBso);
3994
3995 if (part != null)
3996 {
3997 DbBso dbBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(part);
3998 if (dbBso != null && dbBso.BsoId != EMPTY_DB_INDEX)
3999 {
4000 try
4001 {
4002 IQueryable<DbGroupAndContext> neighsAndContexts =
4003 from gr in this.DbTouchAnalysis.TableGroups
4004 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4005 where (dbBso.BsoId == gr.PartAId || dbBso.BsoId == gr.PartBId)
4006 select new DbGroupAndContext(gr, context.FirstCommonParent);
4007
4008 //var list = neighsAndContexts.ToList();
4009 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4010
4011 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Exact);
4012 }
4013 catch (Exception ex)
4014 {
4015 PDMLog.Logger.Log(ex);
4016 }
4017 }
4018 }
4019 return tdItem;
4020 }
4021
4022 /// <summary>
4023 /// Fetches common neighbors and their contexts.
4024 /// </summary>
4025 /// <param name="part">The part.</param>
4026 /// <returns>common neighbors and their contexts</returns>
4027 private TDitem FetchCommonNeighbors_WithContexts_Classiffication(BsInfo part, int classificationId)
4028 {
4029 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
4030 TDitem tdItem = new TDitem(partBso);
4031
4032 if (part != null)
4033 {
4034 try
4035 {
4036 //var myGroups = FindGroupsUsingPart(part);
4037
4038 //if (myGroups != null)
4039 {
4040 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4041 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4042 where (classificationId == gr.PartA.ClassificationId ||
4043 classificationId == gr.PartB.ClassificationId)
4044 select new DbGroupAndContext(gr, context.FirstCommonParent);
4045
4046 //var list = neighsAndContexts.ToList();
4047 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4048
4049 FillTdItem(part, classificationId, tdItem, neighsAndContexts, ObjectAreCorrespondig_Classification);
4050 }
4051 }
4052 catch (Exception ex)
4053 {
4054 PDMLog.Logger.Log(ex);
4055 }
4056
4057 }
4058 return tdItem;
4059 }
4060
4061 private static void FillTdItem(BsInfo part, int partClassification, TDitem tdItem, IQueryable<DbGroupAndContext> neighsAndContexts, ObjectAreCorrespondigDelegate objCorresponds)
4062 {
4063 if (neighsAndContexts != null)
4064 {
4065 foreach (var item in neighsAndContexts)
4066 {
4067 //bool queryPartIsInA;
4068 if (objCorresponds(item.Group.PartA, part, partClassification))
4069 {
4070 DbBso otherDbBso = item.Group.PartB;
4071 if (otherDbBso != null)
4072 {
4073 BSObjectLight otherBso = otherDbBso.CreateBso();
4074 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4075
4076 BsInfo contextInfo = item.FirstCommonParent.CreateBsInfo();
4077 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4078 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4079 }
4080 }
4081
4082 if (objCorresponds(item.Group.PartB, part, partClassification))
4083 {
4084 DbBso otherDbBso = item.Group.PartA;
4085 if (otherDbBso != null)
4086 {
4087 BSObjectLight otherBso = otherDbBso.CreateBso();
4088 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4089
4090 BsInfo contextInfo = item.FirstCommonParent.CreateBsInfo();
4091 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4092 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4093 }
4094 }
4095 }
4096 }
4097 }
4098
4099 private static void FillTdItem(List<int> queryBsoIds, TDitem tdItem, IQueryable<DbGroupAndContext> neighsAndContexts)
4100 {
4101 if (neighsAndContexts != null)
4102 {
4103 foreach (var item in neighsAndContexts)
4104 {
4105 //bool queryPartIsInA;
4106 if (queryBsoIds.Contains(item.Group.PartAId))
4107 {
4108 DbBso otherDbBso = item.Group.PartB;
4109 if (otherDbBso != null)
4110 {
4111 BSObjectLight otherBso = otherDbBso.CreateBso();
4112 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4113
4114 BsInfo contextInfo = item.FirstCommonParent.CreateBsInfo();
4115 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4116 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4117 }
4118 }
4119
4120 if (queryBsoIds.Contains(item.Group.PartBId))
4121 {
4122 DbBso otherDbBso = item.Group.PartA;
4123 if (otherDbBso != null)
4124 {
4125 BSObjectLight otherBso = otherDbBso.CreateBso();
4126 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4127
4128 BsInfo contextInfo = item.FirstCommonParent.CreateBsInfo();
4129 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4130 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4131 }
4132 }
4133 }
4134 }
4135 }
4136
4137 /// <summary>
4138 /// Fetches common neighbors and their contexts and count of touches.
4139 /// </summary>
4140 /// <param name="part">The part.</param>
4141 /// <returns>common neighbors and their contexts and count of touches</returns>
4142 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
4143 public TDitem FetchCommonNeighbors_WithContextsAndCountOfTouches(BsInfo part)
4144 {
4145 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
4146 TDitem tdItem = new TDitem(partBso);
4147
4148 if (part != null)
4149 {
4150 try
4151 {
4152 var myGroups = FindGroupsUsingPart(part);
4153
4154 if (myGroups != null)
4155 {
4156 var neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4157 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4158 join instance in this.DbTouchAnalysis.TableInstancePairs on context.AnonymPairId equals instance.AnonymPairId
4159 where (part.Id == gr.PartA.ObjectId &&
4160 part.Variant == gr.PartA.ObjectVariant) ||
4161 (part.Id == gr.PartB.ObjectId &&
4162 part.Variant == gr.PartB.ObjectVariant)
4163 select new { gr, context.FirstCommonParent, instance.InstancePairId };
4164
4165 var list = neighsAndContexts.ToList();
4166
4167 if (list != null)
4168 {
4169 foreach (var item in list)
4170 {
4171 bool queryPartIsInA;
4172 DbBso otherDbBso = item.gr.GetOtherBso(part, out queryPartIsInA);
4173 if (otherDbBso != null)
4174 {
4175 BSObjectLight otherBso = otherDbBso.CreateBso();
4176 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4177
4178 BsInfo contextInfo = item.FirstCommonParent.CreateBsInfo();
4179 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4180 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso, 0);
4181 itemContext.IncCountOfAllTouches(1);
4182 }
4183 }
4184 }
4185 }
4186 }
4187 catch (Exception ex)
4188 {
4189 PDMLog.Logger.Log(ex);
4190 }
4191
4192 }
4193 return tdItem;
4194 }
4195
4196
4197 /// <summary>
4198 /// Fetches common neighbors, their contexts and number of touches.
4199 /// </summary>
4200 /// <param name="part">The part.</param>
4201 /// <returns>common neighbors and contexts and count of touches</returns>
4202 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
4203 public TDitem FetchCommonNeighbors_WithContextsAndCountOfTouches_Slow(BsInfo part)
4204 {
4205 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
4206 TDitem tdItem = new TDitem(partBso);
4207
4208 if (part != null)
4209 {
4210 try
4211 {
4212 var myGroups = FindGroupsUsingPart(part);
4213
4214 if (myGroups != null)
4215 {
4216 IList<DbGroup> dbGroups = myGroups.ToList();
4217
4218 if (dbGroups != null)
4219 {
4220 foreach (DbGroup dbGroup in dbGroups)
4221 {
4222 bool queryPartIsInA;
4223 DbBso otherDbBso = dbGroup.GetOtherBso(part, out queryPartIsInA);
4224 if (otherDbBso != null)
4225 {
4226 BSObjectLight otherBso = otherDbBso.CreateBso();
4227 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4228
4229 IList<DbAnonymPair> anonymPaths = FindAnonymousPathsForDbGroup(dbGroup);
4230
4231 if (anonymPaths != null)
4232 {
4233 foreach (DbAnonymPair anonym in anonymPaths)
4234 {
4235 int cInstances = FindCountOfFullPathsForAnonymousPaths(anonym.AnonymPairId);
4236 if (cInstances > 0)
4237 {
4238 BsInfo contextInfo = anonym.FirstCommonParent.CreateBsInfo();
4239 BSObjectLight contextBso = Convert.ConvertBsInfoToBso(contextInfo);
4240 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso, cInstances);
4241 }
4242 }
4243 }
4244 }
4245 }
4246 }
4247 }
4248 }
4249 catch (Exception ex)
4250 {
4251 PDMLog.Logger.Log(ex);
4252 }
4253
4254 }
4255 return tdItem;
4256 }
4257
4258
4259 /// <summary>
4260 /// Fetches only common neighbors, but not their contexts of instances.
4261 /// </summary>
4262 /// <param name="part">The part.</param>
4263 /// <param name="contextAsm">The context asm.</param>
4264 /// <returns>common neighbors</returns>
4265 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
4266 public TDitem FetchCommonNeighbors(BsInfo part, BsInfo contextAsm)
4267 {
4268 BSObjectLight partBso = Convert.ConvertBsInfoToBso(part);
4269 TDitem tdItem = new TDitem(partBso);
4270
4271 if (part != null)
4272 {
4273 if (contextAsm == null)
4274 {
4275 try
4276 {
4277 var myGroups = FindGroupsUsingPart(part);
4278
4279 if (myGroups != null)
4280 {
4281 IList<DbGroup> dbGroups = myGroups.ToList();
4282
4283 if (dbGroups != null)
4284 {
4285 foreach (DbGroup dbGroup in dbGroups)
4286 {
4287 bool queryPartIsInA;
4288 DbBso otherDbBso = dbGroup.GetOtherBso(part, out queryPartIsInA);
4289 if (otherDbBso != null)
4290 {
4291 BSObjectLight otherBso = otherDbBso.CreateBso();
4292 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4293 }
4294 }
4295 }
4296 }
4297 }
4298 catch (Exception ex)
4299 {
4300 PDMLog.Logger.Log(ex);
4301 }
4302 }
4303 }
4304 return tdItem;
4305 }
4306
4307 private IQueryable<DbGroup> FindGroupsUsingPart(BsInfo part)
4308 {
4309 //equals
4310 //var myGroups = from myGroup in this.DbTouchAnalysis.TableGroups
4311 // where (part.Id.Equals(myGroup.PartA.ObjectId) &&
4312 // part.Variant.Equals(myGroup.PartA.ObjectVariant)) ||
4313 // (part.Id.Equals(myGroup.PartB.ObjectId) &&
4314 // part.Variant.Equals(myGroup.PartB.ObjectVariant))
4315 // select myGroup;
4316
4317 //==
4318 var myGroups = from myGroup in this.DbTouchAnalysis.TableGroups
4319 where (part.Id == myGroup.PartA.ObjectId &&
4320 part.Variant == myGroup.PartA.ObjectVariant) ||
4321 (part.Id == myGroup.PartB.ObjectId &&
4322 part.Variant == myGroup.PartB.ObjectVariant)
4323 select myGroup;
4324
4325 return myGroups;
4326 }
4327
4328 private void AddIntoTable(string key, BsInstanceId touchInst, Dictionary<string, List<BsInstanceId>> tableInstances)
4329 {
4330 List<BsInstanceId> instances;
4331 if (!tableInstances.TryGetValue(key, out instances))
4332 {
4333 instances = new List<BsInstanceId>();
4334 tableInstances[key] = instances;
4335 }
4336 instances.Add(touchInst);
4337 }
4338
4339 /// <summary>
4340 /// Deletes all anonyms pairs where first common assembly is equal to a given commonParent.
4341 /// Also deletes all instance pairs
4342 /// </summary>
4343 /// <param name="commonParent">The assembly information.</param>
4344 public List<TwoInts> DeleteAnonymAndInstancePairsForContext(BsInfo commonParent)
4345 {
4346 List<TwoInts> anonyms = null;
4347 DbBso contextBso;
4348 if (commonParent != null && (contextBso = FindBsInfoInTableBsObjects_GetDbBso_UseIdVariantVersion(commonParent)) != null)
4349 {
4350 anonyms = FindAnonymousPathsForCommonParent(contextBso.BsoId);
4351 if (anonyms != null)
4352 {
4353 //delete all instances for all anonyms
4354 foreach (TwoInts item in anonyms)
4355 {
4356 DeleteInstancePairByAnonymPairId(item.RecordId);
4357 }
4358
4359 //delete all anonyms
4360 foreach (TwoInts item in anonyms)
4361 {
4362 DeleteAnonymousPairByPK(item.RecordId);
4363 }
4364 }
4365 }
4366 return anonyms;
4367 }
4368
4369 public void DeleteNonUpdatedSurfaces(int partBsoId, Dictionary<int, byte> tableUpdatedSurfaces)
4370 {
4371 List<int> surfacesIds = FindsSurfacesForPart(partBsoId);
4372 if (surfacesIds != null)
4373 {
4374 for (int i = 0; i < surfacesIds.Count; i++)
4375 {
4376 int surfId = surfacesIds[i];
4377
4378 if (!tableUpdatedSurfaces.ContainsKey(surfId))
4379 {
4380 DeleteSurfaceByPK(surfId);
4381 }
4382 }
4383 }
4384 }
4385
4386 private List<int> FindsSurfacesForPart(int partBsoId)
4387 {
4388 var surfaces = from surf in this.DbTouchAnalysis.TableSurfaceUsabilities
4389 where surf.PartId == partBsoId
4390 select surf.SurfaceId;
4391 return surfaces.ToList();
4392 }
4393
4394
4395 public void DeleteInstancePairByPK(int pk)
4396 {
4397 _dbTA.ExecuteCommand("DELETE FROM [TableInstancePairs] WHERE [InstancePairId] = {0}", pk);
4398 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4399 }
4400
4401 public void DeleteTrainSamples(int setId)
4402 {
4403 _dbTA.ExecuteCommand("DELETE FROM [TableTrainSamples] WHERE [TrainSetId] = {0}", setId);
4404 }
4405
4406 private void DeleteTrainSet(int setId)
4407 {
4408 _dbTA.ExecuteCommand("DELETE FROM [TableTrainSet] WHERE [TrainSetId] = {0}", setId);
4409 }
4410
4411 public void DeleteInstancePairByAnonymPairId(int anonymPairId)
4412 {
4413 _dbTA.ExecuteCommand("DELETE FROM [TableInstancePairs] WHERE [AnonymPairId] = {0}", anonymPairId);
4414 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4415 }
4416
4417 public void DeleteAnonymousPairByPK(int pk)
4418 {
4419 _dbTA.ExecuteCommand("DELETE FROM [TableAnonymPairs] WHERE [AnonymPairId] = {0}", pk);
4420 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4421 }
4422
4423 public void TruncateClassWeightsTable()
4424 {
4425 _dbTA.ExecuteCommand("TRUNCATE TABLE [TableClassWeights]");
4426 }
4427
4428 public void DeleteGroupByPK(int pk)
4429 {
4430 _dbTA.ExecuteCommand("DELETE FROM [TableGroups] WHERE [GroupId] = {0}", pk);
4431 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4432 }
4433
4434 public void DeleteSurfaceByPK(int pk)
4435 {
4436 _dbTA.ExecuteCommand("DELETE FROM [TableSurfaceUsability] WHERE [SurfaceId] = {0}", pk);
4437 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4438 }
4439
4440 public void DeleteMateRulesByPK(int pk)
4441 {
4442 _dbTA.ExecuteCommand("DELETE FROM [TableMateRules] WHERE [MateRuleId] = {0}", pk);
4443 //_dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
4444 }
4445
4446
4447 /// <summary>
4448 /// Checks groups given by groupId in the list removedAnonymPairs.
4449 /// If no anonymous pair exist for the group, the group and corresponding mate rules
4450 /// are deleted.
4451 /// </summary>
4452 /// <param name="removedAnonymPairs">The removed anonym pairs.</param>
4453 public void DeleteGroupsWithoutAnonymPairs(List<TwoInts> removedAnonymPairs)
4454 {
4455 if (removedAnonymPairs != null)
4456 {
4457 foreach (var item in removedAnonymPairs)
4458 {
4459 int groupId = item.ParentId;
4460 bool isEmptyGroup = AnonymousPathsForGroupIsEmpty(groupId);
4461 if (isEmptyGroup)
4462 {
4463 var mateRulesForGroups = from mateRule in DbTouchAnalysis.TableMateRules
4464 where mateRule.GroupId == groupId
4465 select mateRule;
4466 //delete mate rules
4467 List<DbMateRule> rules = mateRulesForGroups.ToList();
4468 DbTouchAnalysis.TableMateRules.DeleteAllOnSubmit(rules);
4469
4470 //delete the group
4471 DeleteGroupByPK(groupId);
4472 }
4473 }
4474 DbTouchAnalysis.SubmitChanges(ConflictMode.ContinueOnConflict);
4475 }
4476 }
4477
4478 /// <summary>
4479 /// Deletes given surfaces and all dependent mate rules from Mate DB.
4480 /// </summary>
4481 /// <param name="surfaceIds">The surface ids.</param>
4482 public void DeleteSurfacesAndDependentMateRules(List<int> surfaceIds)
4483 {
4484 if (surfaceIds != null && surfaceIds.Count > 0)
4485 {
4486 List<TwoInts> mateRulesIds = FindMateRulesUsingSurfaces(surfaceIds);
4487 Dictionary<int, byte> tableGroupIds = new Dictionary<int, byte>();
4488 if (mateRulesIds != null)
4489 {
4490 //delete mate rules
4491 for (int i = 0; i < mateRulesIds.Count; i++)
4492 {
4493 TwoInts mrId = mateRulesIds[i];
4494 DeleteMateRulesByPK(mrId.RecordId);
4495 tableGroupIds[mrId.ParentId] = 1;
4496 }
4497
4498 //check groups. Delete a group if it does not contain any mate rule.
4499 foreach (int groupId in tableGroupIds.Keys)
4500 {
4501 bool empty = MateRulesForGroupIsEmpty(groupId);
4502 if (empty)
4503 {
4504 List<int> anonymIds = FindAnonymousPathsForDbGroup(groupId);
4505 if (anonymIds != null)
4506 {
4507 //delete anonym paths and instance paths
4508 for (int i = 0; i < anonymIds.Count; i++)
4509 {
4510 int anonymId = anonymIds[i];
4511 DeleteInstancePairByAnonymPairId(anonymId);
4512 DeleteAnonymousPairByPK(anonymId);
4513 }
4514 }
4515 DeleteGroupByPK(groupId);
4516 }
4517 }
4518 }
4519
4520 //delete surfaces
4521 for (int i = 0; i < surfaceIds.Count; i++)
4522 {
4523 int surfId = surfaceIds[i];
4524 DeleteSurfaceByPK(surfId);
4525 }
4526 }
4527 }
4528
4529 private List<TwoInts> FindMateRulesUsingSurfaces(List<int> surfaceIds)
4530 {
4531 var myRules = from myRule in this.DbTouchAnalysis.TableMateRules
4532 where (surfaceIds.Contains(myRule.SurfaceAId) || surfaceIds.Contains(myRule.SurfaceBId))
4533 select new TwoInts { RecordId = myRule.MateRuleId, ParentId = myRule.GroupId };
4534
4535 return myRules.ToList();
4536 }
4537
4538 private List<int> FindMateRulesUsingSurface(int surfId)
4539 {
4540 var myRules = from myRule in this.DbTouchAnalysis.TableMateRules
4541 where (myRule.SurfaceAId == surfId || myRule.SurfaceBId == surfId)
4542 select myRule.MateRuleId;
4543
4544 return myRules.ToList();
4545 }
4546
4547 public List<DbAnonymPair> FindDbGroupsForAssembly(BsInfo asmInfo, out bool exactVersionFound)
4548 {
4549 List<DbAnonymPair> anonyms = null;
4550
4551 DbBso asmBso = FindBsInfoInTableBsObjects_NewestPrevious(asmInfo, out exactVersionFound);
4552 if (asmBso != null)
4553 {
4554 anonyms = FindAnonymousPathsForCommonParent_Object(asmBso.BsoId);
4555
4556 if (anonyms != null)
4557 {
4558 for (int i = 0; i < anonyms.Count; i++)
4559 {
4560 DbAnonymPair anonym = anonyms[i];
4561 FillDbAnonymPairWithInstancePairs(anonym);
4562 }
4563 }
4564 }
4565 return anonyms;
4566 }
4567
4568
4569 #region FetchCommonNeighbors_WithContexts from the project baseMateDbInterface
4570
4571 delegate bool ObjectAreCorrespondigDelegate2(DbBso dbBso, BSObject partInfo, int partClassificationId);
4572
4573 private bool ObjectAreCorrespondig_Exact2(DbBso dbBso, BSObject partInfo, int partClassificationId)
4574 {
4575 return partInfo.ObjectID == dbBso.ObjectId &&
4576 partInfo.UniqueRev == dbBso.ObjectVersion &&
4577 partInfo.VariantID == dbBso.ObjectVariant;
4578 }
4579
4580 private bool ObjectAreCorrespondig_Version2(DbBso dbBso, BSObject partInfo, int partClassificationId)
4581 {
4582 return partInfo.ObjectID == dbBso.ObjectId &&
4583 partInfo.UniqueRev != dbBso.ObjectVersion &&
4584 partInfo.VariantID == dbBso.ObjectVariant;
4585 }
4586
4587 private bool ObjectAreCorrespondig_Variant2(DbBso dbBso, BSObject partInfo, int partClassificationId)
4588 {
4589 return partInfo.ObjectID == dbBso.ObjectId &&
4590 partInfo.VariantID != dbBso.ObjectVariant;
4591 }
4592
4593 private bool ObjectAreCorrespondig_Classification2(DbBso dbBso, BSObject partInfo, int partClassificationId)
4594 {
4595 return partClassificationId == dbBso.ClassificationId;
4596 }
4597
4598 /// <summary>
4599 /// Fetches common neighbors and their contexts.
4600 /// Looks for items with exactly equal id, version and variant.
4601 /// </summary>
4602 /// <param name="part">The part.</param>
4603 /// <returns>common neighbors and their contexts</returns>
4604 public TDitem FetchCommonNeighbors_WithContexts(BSObject part, string bsoClassif, FamilyLevels familyLevel)
4605 {
4606 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts");
4607
4608 BSObjectLight partBso = new BSObjectLight(part);
4609 List<TDitem> tdItems = new List<TDitem>();
4610
4611 if (part != null)
4612 {
4613 EnterCriticalSection();
4614 try
4615 {
4616
4617 if ((familyLevel & FamilyLevels.Exact) > 0)
4618 {
4619 TDitem tdItem = FetchCommonNeighbors_WithContexts_Exact_Fast(part); //2015-10-05
4620 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Exact);
4621 }
4622
4623 if ((familyLevel & FamilyLevels.Versions) > 0)
4624 {
4625 TDitem tdItem = FetchCommonNeighbors_WithContexts_Version_Fast(part); //2015-10-05
4626 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Versions);
4627 }
4628
4629 if ((familyLevel & FamilyLevels.Variants) > 0)
4630 {
4631 TDitem tdItem = FetchCommonNeighbors_WithContexts_Variant_Fast(part);
4632 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Variants);
4633 }
4634
4635 if ((familyLevel & FamilyLevels.Classification) > 0)
4636 {
4637 int classificationId;
4638 if (!String.IsNullOrWhiteSpace(bsoClassif) &&
4639 (classificationId = FindClassificationId(bsoClassif)) != DbManager.EMPTY_DB_INDEX)
4640 {
4641 TDitem tdItem = FetchCommonNeighbors_WithContexts_Classiffication(part, classificationId);
4642 AddTDitemIntoList(tdItems, tdItem, FamilyLevels.Classification);
4643 }
4644 }
4645 }
4646 finally
4647 {
4648 LeaveCriticalSection();
4649 }
4650 //default:
4651 // System.Diagnostics.Debug.Fail("FetchCommonNeighbors_WithContexts - an unsupported value - " + familyLevel.ToString());
4652 // break;
4653 }
4654
4655 TDitem result = TDitem.MergeList(tdItems, partBso);
4656
4657 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts");
4658 return result;
4659 }
4660
4661 public void LeaveCriticalSection()
4662 {
4663 if (_runningQuery != null)
4664 _runningQuery.Set();
4665 }
4666
4667 public void EnterCriticalSection()
4668 {
4669 if (_runningQuery != null)
4670 _runningQuery.WaitOne(5000);
4671 }
4672
4673 /// <summary>
4674 /// Fetches common neighbors and their contexts.
4675 /// </summary>
4676 /// <param name="part">The part.</param>
4677 /// <returns>common neighbors and their contexts</returns>
4678 private TDitem FetchCommonNeighbors_WithContexts_Exact_Fast(BSObject part)
4679 {
4680 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Exact_Fast");
4681
4682 BSObjectLight partBso = new BSObjectLight(part);
4683 TDitem tdItem = new TDitem(partBso);
4684
4685 if (part != null)
4686 {
4687 DbBso dbBso = FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion(part);
4688 if (dbBso != null && dbBso.BsoId != EMPTY_DB_INDEX)
4689 {
4690 try
4691 {
4692 Watches.Start("FetchCommonNeighbors_WithContexts_Exact_Fast - query");
4693 IQueryable<DbGroupAndContext> neighsAndContexts =
4694 from gr in this.DbTouchAnalysis.TableGroups
4695 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4696 where (dbBso.BsoId == gr.PartAId || dbBso.BsoId == gr.PartBId)
4697 select new DbGroupAndContext(gr, context.FirstCommonParent);
4698
4699 //var list = neighsAndContexts.ToList();
4700 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4701
4702 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Exact2);
4703 Watches.Stop("FetchCommonNeighbors_WithContexts_Exact_Fast - query");
4704 }
4705 catch (Exception ex)
4706 {
4707 PDMLog.Logger.Log(ex);
4708 }
4709 }
4710 }
4711
4712 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Exact_Fast");
4713
4714 return tdItem;
4715 }
4716
4717 /// <summary>
4718 /// Fetches common neighbors and their contexts.
4719 /// </summary>
4720 /// <param name="parts">The parts.</param>
4721 /// <param name="mainItem">The main item.</param>
4722 /// <returns>
4723 /// common neighbors and their contexts
4724 /// </returns>
4725 public TDitem FetchCommonNeighborsOfSet_WithContexts_Exact(List<BSObject> parts, BSObject mainItem)
4726 {
4727 TDitem tdItem = new TDitem(new BSObjectLight(mainItem));
4728
4729 if (parts != null)
4730 {
4731 Watches.Start("DbManager.FetchCommonNeighborsOfSet_WithContexts_Exact");
4732
4733 Watches.Start("DbManager.FetchCommonNeighborsOfSet_WithContexts_Exact - get dbos");
4734 /*
4735 List<int> bsoIds = new List<int>();
4736 for (int i = 0; i < parts.Count; i++)
4737 {
4738 BSObject part = parts[i];
4739 if (part != null)
4740 {
4741 int bsoId = FindBsoInTableBsObjects_GetDbBsoId_UseIdVariantVersion(part);
4742 if (bsoId != EMPTY_DB_INDEX)
4743 {
4744 bsoIds.Add(bsoId);
4745 }
4746 }
4747 }
4748 */
4749 List<int> bsoIds = FindListBso_UseIdVariantVersion(parts);
4750
4751 Watches.Stop("DbManager.FetchCommonNeighborsOfSet_WithContexts_Exact - get dbos");
4752
4753 if (bsoIds?.Count > 0)
4754 {
4755 try
4756 {
4757 Watches.Start("FetchCommonNeighborsOfSet_WithContexts_Exact - query");
4758 IQueryable<DbGroupAndContext> neighsAndContexts =
4759 from gr in this.DbTouchAnalysis.TableGroups
4760 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4761 where (bsoIds.Contains(gr.PartAId) || bsoIds.Contains(gr.PartBId))
4762 select new DbGroupAndContext(gr, context.FirstCommonParent);
4763
4764 FillTdItem(bsoIds, tdItem, neighsAndContexts);
4765 Watches.Stop("FetchCommonNeighborsOfSet_WithContexts_Exact - query");
4766 }
4767 catch (Exception ex)
4768 {
4769 PDMLog.Logger.Log(ex);
4770 }
4771 }
4772
4773 Watches.Stop("DbManager.FetchCommonNeighborsOfSet_WithContexts_Exact");
4774 }
4775 return tdItem;
4776 }
4777
4778 /// <summary>
4779 /// Fetches common neighbors and their contexts.
4780 /// Looks for items with exactly equal id, and variant, but different version.
4781 /// </summary>
4782 /// <param name="part">The part.</param>
4783 /// <returns>common neighbors and their contexts</returns>
4784 private TDitem FetchCommonNeighbors_WithContexts_Version_Fast(BSObject part)
4785 {
4786 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Version_Fast");
4787
4788 BSObjectLight partBso = new BSObjectLight(part);
4789 TDitem tdItem = new TDitem(partBso);
4790 if (part != null)
4791 {
4792
4793 try
4794 {
4795 List<int> dbBsoIds = FindDbBsos_WithDifferentVersion(part);
4796 if (dbBsoIds != null && dbBsoIds.Count > 0)
4797 {
4798 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4799 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4800 where (dbBsoIds.Contains(gr.PartAId) ||
4801 dbBsoIds.Contains(gr.PartBId))
4802 select new DbGroupAndContext(gr, context.FirstCommonParent);
4803
4804 //var list = neighsAndContexts.ToList();
4805 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4806
4807 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Version2);
4808 }
4809 }
4810 catch (Exception ex)
4811 {
4812 PDMLog.Logger.Log(ex);
4813 }
4814 }
4815
4816 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Version_Fast");
4817
4818 return tdItem;
4819 }
4820
4821 /// <summary>
4822 /// Fetches common neighbors and their contexts.
4823 /// Looks for items with exactly equal id, but different variant, and an arbitrary version.
4824 /// </summary>
4825 /// <param name="part">The part.</param>
4826 /// <returns>common neighbors and their contexts</returns>
4827 private TDitem FetchCommonNeighbors_WithContexts_Variant(BSObject part)
4828 {
4829 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Variant");
4830
4831 BSObjectLight partBso = new BSObjectLight(part);
4832 TDitem tdItem = new TDitem(partBso);
4833
4834 try
4835 {
4836 //var myGroups = FindGroupsUsingPart(part);
4837
4838 //if (myGroups != null)
4839 {
4840 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Variant - query");
4841
4842 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4843 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4844 where (part.ObjectID == gr.PartA.ObjectId &&
4845 part.VariantID != gr.PartA.ObjectVariant) ||
4846 (part.ObjectID == gr.PartB.ObjectId &&
4847 part.VariantID != gr.PartB.ObjectVariant)
4848 select new DbGroupAndContext(gr, context.FirstCommonParent);
4849
4850#if DEBUG
4851 //just to force execution of the query
4852 var list = neighsAndContexts.ToList();
4853 int count = list.Count;
4854 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4855#endif
4856 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Variant - query");
4857
4858 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Variant2);
4859 }
4860 }
4861 catch (Exception ex)
4862 {
4863 PDMLog.Logger.Log(ex);
4864 }
4865
4866 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Variant");
4867
4868 return tdItem;
4869 }
4870
4871 /// <summary>
4872 /// Fetches common neighbors and their contexts.
4873 /// Looks for items with exactly equal id, but different variant, and an arbitrary version.
4874 /// </summary>
4875 /// <param name="part">The part.</param>
4876 /// <returns>common neighbors and their contexts</returns>
4877 private TDitem FetchCommonNeighbors_WithContexts_Variant_Fast(BSObject part)
4878 {
4879 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Variant_Fast");
4880
4881 BSObjectLight partBso = new BSObjectLight(part);
4882 TDitem tdItem = new TDitem(partBso);
4883
4884 try
4885 {
4886 //var myGroups = FindGroupsUsingPart(part);
4887 List<int> dbBsoIds = FindDbBsos_WithDifferentVariant(part);
4888
4889 if (dbBsoIds != null && dbBsoIds.Count > 0)
4890 {
4891 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Variant_Fast - query");
4892
4893 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4894 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4895 where (dbBsoIds.Contains(gr.PartAId) ||
4896 dbBsoIds.Contains(gr.PartBId))
4897 select new DbGroupAndContext(gr, context.FirstCommonParent);
4898
4899#if DEBUG
4900 //just to force execution of the query
4901 var list = neighsAndContexts.ToList();
4902 int count = list.Count;
4903 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4904#endif
4905 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Variant_Fast - query");
4906
4907 FillTdItem(part, DbManager.EMPTY_DB_INDEX, tdItem, neighsAndContexts, ObjectAreCorrespondig_Variant2);
4908 }
4909 }
4910 catch (Exception ex)
4911 {
4912 PDMLog.Logger.Log(ex);
4913 }
4914
4915 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Variant_Fast");
4916
4917 return tdItem;
4918 }
4919
4920 private TDitem FetchCommonNeighbors_WithContexts_Classiffication(BSObject part, int classificationId)
4921 {
4922 Watches.Start("DbManager.FetchCommonNeighbors_WithContexts_Classiffication");
4923
4924 BSObjectLight partBso = new BSObjectLight(part);
4925 TDitem tdItem = new TDitem(partBso);
4926
4927 if (part != null)
4928 {
4929 try
4930 {
4931 //var myGroups = FindGroupsUsingPart(part);
4932
4933 //if (myGroups != null)
4934 {
4935 IQueryable<DbGroupAndContext> neighsAndContexts = from gr in this.DbTouchAnalysis.TableGroups
4936 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
4937 where (classificationId == gr.PartA.ClassificationId ||
4938 classificationId == gr.PartB.ClassificationId)
4939 select new DbGroupAndContext(gr, context.FirstCommonParent);
4940
4941 //var list = neighsAndContexts.ToList();
4942 //List<DbGroupAndContext> list = neighsAndContexts.ToList();
4943
4944 FillTdItem(part, classificationId, tdItem, neighsAndContexts, ObjectAreCorrespondig_Classification2);
4945 }
4946 }
4947 catch (Exception ex)
4948 {
4949 PDMLog.Logger.Log(ex);
4950 }
4951
4952 }
4953 Watches.Stop("DbManager.FetchCommonNeighbors_WithContexts_Classiffication");
4954
4955 return tdItem;
4956 }
4957
4958 private static void FillTdItem(BSObject part, int partClassification, TDitem tdItem, IQueryable<DbGroupAndContext> neighsAndContexts, ObjectAreCorrespondigDelegate2 objCorresponds)
4959 {
4960 if (neighsAndContexts != null)
4961 {
4962 foreach (var item in neighsAndContexts)
4963 {
4964 //bool queryPartIsInA;
4965 if (objCorresponds(item.Group.PartA, part, partClassification))
4966 {
4967 DbBso otherDbBso = item.Group.PartB;
4968 if (otherDbBso != null)
4969 {
4970 BSObjectLight otherBso = otherDbBso.CreateBso();
4971 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4972
4973 BSObjectLight contextBso = item.FirstCommonParent.CreateBso();
4974 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4975 }
4976 }
4977
4978 if (objCorresponds(item.Group.PartB, part, partClassification))
4979 {
4980 DbBso otherDbBso = item.Group.PartA;
4981 if (otherDbBso != null)
4982 {
4983 BSObjectLight otherBso = otherDbBso.CreateBso();
4984 TDitemTouching tdItemTouching = tdItem.GetExistingOrCreateNew(otherBso);
4985
4986 BSObjectLight contextBso = item.FirstCommonParent.CreateBso();
4987 TDitemTouchingContext itemContext = tdItemTouching.GetExistingOrCreateNew(contextBso);
4988 }
4989 }
4990 }
4991 }
4992 }
4993
4994 /// <summary>
4995 /// Finds a given bs info in database by its id, variant and version.
4996 /// </summary>
4997 /// <param name="bso">The bs info.</param>
4998 /// <returns>dbBso or null</returns>
4999 public DbBso FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion(BSObject bso)
5000 {
5001 //search by id, variant, version
5002 var q = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.ObjectId == bso.ObjectID &&
5003 x.ObjectVariant == bso.VariantID &&
5004 x.ObjectVersion == bso.UniqueRev);
5005 DbBso dbBso = q;
5006 return dbBso;
5007 }
5008
5009 /// <summary>
5010 /// Finds a given bs info in database by its id, variant and version.
5011 /// </summary>
5012 /// <param name="bso">The bs info.</param>
5013 /// <returns>dbBso or null</returns>
5014 public int FindBsoInTableBsObjects_GetDbBsoId_UseIdVariantVersion(BSObject bso)
5015 {
5016 //search by id, variant, version
5017 var q = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.ObjectId == bso.ObjectID &&
5018 x.ObjectVariant == bso.VariantID &&
5019 x.ObjectVersion == bso.UniqueRev);
5020 if (q != null) return q.BsoId;
5021 else return EMPTY_DB_INDEX;
5022 }
5023
5024 /// <summary>
5025 /// Returns a list of DbBso.BsoId corresponding to given bsos.
5026 /// First, it tries to find an exact match for each bso (same objectId, variantId and version). If such dbBso is not found,
5027 /// it looks for matching objectId and variantId.
5028 /// </summary>
5029 /// <param name="bso">The bs info.</param>
5030 /// <returns>dbBso or null</returns>
5031 public List<int> FindListBso_UseIdVariantVersion(List<BSObject> bsos)
5032 {
5033 //search by id, variant, version
5034 //this throws a run-time exception "Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator."
5035 //var q = from data in _dbTA.TableBlueStarObjects.AsQueryable<DbBso>()
5036 // where bsos.Any(bso => (bso.ObjectID == data.ObjectId && bso.VariantID == data.ObjectVariant && bso.UniqueRev == data.ObjectVersion))
5037 // select data.BsoId;
5038
5039 //this works but it is slower than if I query for bso one by one
5040 //var q = from bso in bsos
5041 // from data in _dbTA.TableBlueStarObjects
5042 // where bso.ObjectID == data.ObjectId && bso.VariantID == data.ObjectVariant && bso.UniqueRev == data.ObjectVersion
5043 // select data.BsoId;
5044
5045 //this throws a run-time exception "Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator."
5046 //var q = from data in _dbTA.TableBlueStarObjects
5047 // from bso in bsos
5048 // where bso.ObjectID == data.ObjectId && bso.VariantID == data.ObjectVariant && bso.UniqueRev == data.ObjectVersion
5049 // select data.BsoId;
5050
5051 //I was not able to get all dbBsos with given objectId, variantId and version with a single linq to sql query.
5052 //Therefore, I look for all dbBsos with given objectId and then filter the result by variantId and version on a client side.
5053
5054 if (bsos == null) return null;
5055
5056 var q = from b in bsos select b.ObjectID;
5057 List<string> objectIds = q.ToList();
5058
5059 if (objectIds == null) return null;
5060
5061 //get all dbBsos with given objectIds
5062 var q2 = from dbo in _dbTA.TableBlueStarObjects
5063 where objectIds.Contains(dbo.ObjectId)
5064 select dbo;
5065 List<DbBso> dbBsos = q2.ToList();
5066
5067 if (dbBsos == null) return null;
5068
5069 //filter the result by variantId and version on a client side.
5070 List<int> dbBsoIds = new List<int>();
5071 for (int i = 0; i < dbBsos.Count; i++)
5072 {
5073 DbBso dbBso = dbBsos[i];
5074
5075 if (bsos.FirstOrDefault(x => x.ObjectID == dbBso.ObjectId && x.VariantID == dbBso.ObjectVariant && x.UniqueRev == dbBso.ObjectVersion) != null)
5076 {
5077 //first look for bsos with equal id, variant id and version
5078 dbBsoIds.Add(dbBso.BsoId);
5079 }
5080 else if (bsos.FirstOrDefault(x => x.ObjectID == dbBso.ObjectId && x.VariantID == dbBso.ObjectVariant) != null)
5081 {
5082 //if an exact version match is not found, look for equal id and variant id.
5083 dbBsoIds.Add(dbBso.BsoId);
5084 }
5085 }
5086
5087 return dbBsoIds;
5088 }
5089
5090 /// <summary>
5091 /// Finds a given bs info in database by its id, variant and version.
5092 /// </summary>
5093 /// <param name="bso">The bs info.</param>
5094 /// <returns>a list of DbBso.BsoId</returns>
5095 public List<int> FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion2(BSObject bso)
5096 {
5097 //search by id, variant, version
5098 var q = from dbBso in _dbTA.TableBlueStarObjects
5099 where dbBso.ObjectId == bso.ObjectID &&
5100 dbBso.ObjectVariant == bso.VariantID &&
5101 dbBso.ObjectVersion == bso.UniqueRev
5102 select dbBso.BsoId;
5103 return q.ToList();
5104 }
5105
5106 /// <summary>
5107 /// Finds a given bs info in database with id, variant and a different version.
5108 /// </summary>
5109 /// <param name="bso">The bs info.</param>
5110 /// <returns>a list of DbBso.BsoId</returns>
5111 public List<int> FindBsoInTableBsObjects_GetDbBso_UseIdVariant_DifferentVersion(BSObject bso)
5112 {
5113 var q = from dbBso in _dbTA.TableBlueStarObjects
5114 where dbBso.ObjectId == bso.ObjectID &&
5115 dbBso.ObjectVariant == bso.VariantID &&
5116 dbBso.ObjectVersion != bso.UniqueRev
5117 select dbBso.BsoId;
5118 return q.ToList();
5119 }
5120
5121 /// <summary>
5122 /// Finds a given bs info in database with id and variant.
5123 /// </summary>
5124 /// <param name="bso">The bs info.</param>
5125 /// <returns>a list of DbBso.BsoId</returns>
5126 public List<int> FindBsoInTableBsObjects_GetDbBso_UseIdVariant(BSObject bso)
5127 {
5128 var q = from dbBso in _dbTA.TableBlueStarObjects
5129 where dbBso.ObjectId == bso.ObjectID &&
5130 dbBso.ObjectVariant == bso.VariantID
5131 select dbBso.BsoId;
5132 return q.ToList();
5133 }
5134
5135 /// <summary>
5136 /// Finds a given bs info in database with id, variant and a different version.
5137 /// </summary>
5138 /// <param name="bso">The bs info.</param>
5139 /// <returns>a list of DbBso</returns>
5140 public List<DbBso> FindBsoInTableBsObjects_GetDbBso_UseIdVariant_DifferentVersion(DbBso bso)
5141 {
5142 var q = from dbBso in _dbTA.TableBlueStarObjects
5143 where dbBso.ObjectId == bso.ObjectId &&
5144 dbBso.ObjectVariant == bso.ObjectVariant &&
5145 dbBso.ObjectVersion != bso.ObjectVersion
5146 select dbBso;
5147 return q.ToList();
5148 }
5149
5150 /// <summary>
5151 /// Finds a given bs info in database with id and a different variant.
5152 /// </summary>
5153 /// <param name="bso">The bs info.</param>
5154 /// <returns>a list of DbBso.BsoId</returns>
5155 public List<int> FindBsoInTableBsObjects_GetDbBso_UseId_DifferentVariant(BSObject bso)
5156 {
5157 var q = from dbBso in _dbTA.TableBlueStarObjects
5158 where dbBso.ObjectId == bso.ObjectID &&
5159 dbBso.ObjectVariant != bso.VariantID
5160 select dbBso.BsoId;
5161 return q.ToList();
5162 }
5163
5164 public DbBso FindBsoInTableBsObjects_GetDbBso(int bsoId)
5165 {
5166 Table<DbBso> tb = _dbTA.TableBlueStarObjects;
5167 return tb.FirstOrDefault(x => x.BsoId == bsoId);
5168 }
5169
5170 /// <summary>
5171 /// Finds dbBsos with a given id and variant but with a different version!
5172 /// </summary>
5173 /// <param name="bso">The bs info.</param>
5174 /// <returns>dbBso or null</returns>
5175 public List<int> FindDbBsos_WithDifferentVersion(BSObject bso)
5176 {
5177 IQueryable<int> ids = from dbBso in _dbTA.TableBlueStarObjects
5178 where (bso.ObjectID == dbBso.ObjectId &&
5179 bso.UniqueRev != dbBso.ObjectVersion &&
5180 bso.VariantID == dbBso.ObjectVariant)
5181 select dbBso.BsoId;
5182 return ids.ToList();
5183 }
5184
5185 /// <summary>
5186 /// Finds dbBsos with a given id, but with a different variant!
5187 /// </summary>
5188 /// <param name="bso">The bs info.</param>
5189 /// <returns>dbBso or null</returns>
5190 public List<int> FindDbBsos_WithDifferentVariant(BSObject bso)
5191 {
5192 IQueryable<int> ids = from dbBso in _dbTA.TableBlueStarObjects
5193 where (bso.ObjectID == dbBso.ObjectId &&
5194 bso.VariantID != dbBso.ObjectVariant)
5195 select dbBso.BsoId;
5196 return ids.ToList();
5197 }
5198
5199 #endregion
5200
5201 #region from BaseDbManager
5202
5203 /// <summary>
5204 /// Searches for a face given by a name. It checks parts with equal objectId, variant, version,
5205 /// then with equal objectId, variant and then with equal objectId.
5206 /// </summary>
5207 /// <param name="bso">The bso.</param>
5208 /// <param name="surfaceName">Name of the surface.</param>
5209 /// <returns>x, y, z coords of a sample point or null</returns>
5210 public double[] FindFace_SimilarBso(BSObject bso, string surfaceName)
5211 {
5212 double[] samplePoint;
5213 List<int> partIds;
5214
5215 //find a surface for the exact id, variant, version
5216 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion2(bso);
5217 samplePoint = FindFirstFace(surfaceName, partIds);
5218
5219 if (samplePoint == null)
5220 {
5221 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariant_DifferentVersion(bso);
5222 samplePoint = FindFirstFace(surfaceName, partIds);
5223
5224 if (samplePoint == null)
5225 {
5226 partIds = FindBsoInTableBsObjects_GetDbBso_UseId_DifferentVariant(bso);
5227 samplePoint = FindFirstFace(surfaceName, partIds);
5228
5229#if USE_RELATED_ITEMS
5230 if (samplePoint == null)
5231 {
5232 partIds = FindAllRelatedItems_WithDifferentObjectId(bso);
5233 samplePoint = FindFirstFace(surfaceName, partIds);
5234 }
5235#endif
5236 }
5237 }
5238
5239 return samplePoint;
5240 }
5241
5242 private double[] FindFirstFace(string surfaceName, List<int> partIds)
5243 {
5244 if (partIds != null)
5245 {
5246 for (int i = 0; i < partIds.Count; i++)
5247 {
5248 int partId = partIds[i];
5249 var q = _dbTA.TableSurfaceUsabilities.FirstOrDefault(x => x.PartId == partId &&
5250 String.Compare(x.Surface, surfaceName, true) == 0);
5251 DbSurfaceUsability dbSurf = q;
5252 if (dbSurf != null)
5253 {
5254 double[] samplePoint = dbSurf.GetSamplePoint();
5255 return samplePoint;
5256 }
5257
5258 }
5259 }
5260 return null;
5261 }
5262
5263 /// <summary>
5264 /// Searches for faces given by a wildcard name. It checks parts with equal objectId, variant, version,
5265 /// then with equal objectId, variant and then with equal objectId.
5266 /// </summary>
5267 /// <param name="bso">The bso.</param>
5268 /// <param name="surfaceName">a wildcard name of faces.</param>
5269 /// <returns>a number of corresponding faces</returns>
5270 public int HasMatchingFace_SimilarBso(BSObject bso, string faceNameFilter, bool ignoreWorkfeatures = true)
5271 {
5272 int count = 0;
5273 List<int> partIds;
5274
5275 string dbSurfFilter = CreateDbPatern(faceNameFilter);
5276
5277 //find a surface for the exact id, variant, version
5278 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion2(bso);
5279 count = HasMatchingFaces(dbSurfFilter, partIds, ignoreWorkfeatures);
5280
5281 if (count == 0)
5282 {
5283 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariant_DifferentVersion(bso);
5284 count = HasMatchingFaces(dbSurfFilter, partIds, ignoreWorkfeatures);
5285
5286 if (count == 0)
5287 {
5288 partIds = FindBsoInTableBsObjects_GetDbBso_UseId_DifferentVariant(bso);
5289 count = HasMatchingFaces(dbSurfFilter, partIds, ignoreWorkfeatures);
5290
5291#if USE_RELATED_ITEMS
5292 if (count == 0)
5293 {
5294 partIds = FindAllRelatedItems_WithDifferentObjectId(bso);
5295 count = HasMatchingFaces(dbSurfFilter, partIds, ignoreWorkfeatures);
5296 }
5297#endif
5298 }
5299 }
5300
5301 return count;
5302 }
5303
5304 private int HasMatchingFaces(string faceNameFilter, List<int> partIds, bool ignoreWorkfeatures)
5305 {
5306 if (partIds != null)
5307 {
5308 for (int i = 0; i < partIds.Count; i++)
5309 {
5310 int partId = partIds[i];
5311
5312 var q = from surf in _dbTA.TableSurfaceUsabilities
5313 where surf.PartId == partId && SqlMethods.Like(surf.Surface, faceNameFilter)
5314 select surf;
5315
5316
5317 if (ignoreWorkfeatures)
5318 {
5319 int cNonWF = 0;
5320 foreach (DbSurfaceUsability s in q)
5321 {
5322 if (!IsWorkfeature(s.Type))
5323 {
5324 cNonWF++;
5325 }
5326 }
5327 return cNonWF;
5328 }
5329 else
5330 {
5331 return q.Count();
5332 }
5333 }
5334 }
5335 return 0;
5336 }
5337
5338 private static string CreateDbPatern(string s)
5339 {
5340 if (s != null)
5341 {
5342 s = s.Replace("_", @"\_");
5343 s = s.Replace('*', '%');
5344 s = s.Replace('?', '_');
5345 }
5346 return s;
5347 }
5348
5349 /// <summary>
5350 /// Searches for faces given by a wildcard name. It checks parts with equal objectId, variant, version,
5351 /// then with equal objectId, variant and then with equal objectId.
5352 /// </summary>
5353 /// <param name="bso">The bso.</param>
5354 /// <param name="surfaceName">a wildcard name of faces.</param>
5355 /// <returns>a list of corresponding faces</returns>
5356 public List<CadFace> FindMatchingFaces_SimilarBso(BSObject bso, string faceNameFilter, bool ignoreWorkfeatures)
5357 {
5358 List<int> partIds;
5359 List<CadFace> cadFaces = null;
5360
5361 string dbFaceFilter = CreateDbPatern(faceNameFilter);
5362
5363 //find a surface for the exact id, variant, version
5364 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariantVersion2(bso);
5365 cadFaces = GetMatchingFaces(dbFaceFilter, partIds, ignoreWorkfeatures);
5366 if (cadFaces == null || cadFaces.Count == 0)
5367 {
5368 partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariant_DifferentVersion(bso);
5369 cadFaces = GetMatchingFaces(dbFaceFilter, partIds, ignoreWorkfeatures);
5370
5371 if (cadFaces == null || cadFaces.Count == 0)
5372 {
5373 partIds = FindBsoInTableBsObjects_GetDbBso_UseId_DifferentVariant(bso);
5374 cadFaces = GetMatchingFaces(dbFaceFilter, partIds, ignoreWorkfeatures);
5375
5376#if USE_RELATED_ITEMS
5377 if (cadFaces == null || cadFaces.Count == 0)
5378 {
5379 partIds = FindAllRelatedItems_WithDifferentObjectId(bso);
5380 cadFaces = GetMatchingFaces(dbFaceFilter, partIds, ignoreWorkfeatures);
5381 }
5382#endif
5383 }
5384 }
5385
5386 return cadFaces;
5387 }
5388
5389 private List<CadFace> GetMatchingFaces(string faceNameFilter, List<int> partIds, bool ignoreWorkfeatures)
5390 {
5391 List<CadFace> faces = new List<CadFace>();
5392
5393 if (partIds != null)
5394 {
5395 for (int i = 0; i < partIds.Count; i++)
5396 {
5397 int partId = partIds[i];
5398 var q = from surf in _dbTA.TableSurfaceUsabilities
5399 where surf.PartId == partId && SqlMethods.Like(surf.Surface, faceNameFilter)
5400 select surf;
5401
5402 foreach (var surf in q)
5403 {
5404 //optionally, skip workfeatures
5405 if (!ignoreWorkfeatures || !IsWorkfeature(surf.Type))
5406 {
5407 double[] samplePoint = surf.GetSamplePoint();
5408 faces.Add(new CadFace(surf.Surface, samplePoint));
5409 }
5410 }
5411 }
5412 }
5413 return faces;
5414 }
5415
5416 private static bool IsWorkfeature(DbSurfaceTypes surfType)
5417 {
5418 return surfType == DbSurfaceTypes.None_WorkFeature ||
5419 surfType == DbSurfaceTypes.Plane_WorkFeature ||
5420 surfType == DbSurfaceTypes.Cylinder_WorkFeature;
5421 }
5422
5423
5424 #region related items
5425
5426 private List<int> FindAllRelatedItems_WithDifferentObjectId(BSObject bso)
5427 {
5428 CheckErp();
5429 List<int> relatedIds = new List<int>();
5430 List<BSObject> inheritItems = _erp.GetInheritInfo(bso, new List<Tuple<string, string>>());
5431 if (inheritItems != null)
5432 {
5433 for (int i = 0; i < inheritItems.Count; i++)
5434 {
5435 BSObject x = inheritItems[i];
5436 if (!String.Equals(x.ObjectID, bso.ObjectID, StringComparison.OrdinalIgnoreCase))
5437 {
5438 List<int> partIds = FindBsoInTableBsObjects_GetDbBso_UseIdVariant(x);
5439 if (partIds != null)
5440 {
5441 relatedIds.AddRange(partIds);
5442 }
5443 }
5444 }
5445 }
5446 return relatedIds;
5447 }
5448
5449 private void CheckErp()
5450 {
5451 if (_erp == null)
5452 {
5453 _erp = new Pdm.Caderps.CommonErp();
5454 }
5455 }
5456
5457 #endregion
5458
5459 #endregion
5460
5461 #region fetch common neighbors - only their BsInfo
5462
5463 /// <summary>
5464 /// Finds a given bs info in database by its id, variant and version.
5465 /// </summary>
5466 /// <param name="bso">The bs info.</param>
5467 /// <returns>a list of DbBso.BsoId</returns>
5468 public int FindBso_UseIdVariantVersion(BsInfo part)
5469 {
5470 //search by id, variant, version
5471 var q = from dbBso in _dbTA.TableBlueStarObjects
5472 where dbBso.ObjectId == part.Id &&
5473 dbBso.ObjectVariant == part.Variant &&
5474 dbBso.ObjectVersion == part.Version
5475 select dbBso.BsoId;
5476 return q.FirstOrDefault();
5477 }
5478
5479 /// <summary>
5480 /// Finds a given bs info in database with id, variant and a different version.
5481 /// </summary>
5482 /// <param name="bso">The bs info.</param>
5483 /// <returns>a list of DbBso.BsoId</returns>
5484 public List<int> FindBso_UseIdVariant_DifferentVersion(BsInfo part)
5485 {
5486 var q = from dbBso in _dbTA.TableBlueStarObjects
5487 where dbBso.ObjectId == part.Id &&
5488 dbBso.ObjectVariant == part.Variant &&
5489 dbBso.ObjectVersion != part.Version
5490 select dbBso.BsoId;
5491 return q.ToList();
5492 }
5493
5494 public int FindBso_UseIdVariant_NewestVersion(BsInfo part)
5495 {
5496 int partId = -1;
5497 var q = from dbBso in _dbTA.TableBlueStarObjects
5498 where dbBso.ObjectId == part.Id &&
5499 dbBso.ObjectVariant == part.Variant
5500 orderby dbBso.ObjectVersion
5501 select dbBso.BsoId;
5502
5503 List<int> ids = q.ToList();
5504 if (ids != null && ids.Count > 0)
5505 {
5506 partId = ids[ids.Count - 1];
5507 }
5508
5509 return partId;
5510 }
5511
5512 /// <summary>
5513 /// Finds a given bs info in database with id and variant.
5514 /// </summary>
5515 /// <param name="bso">The bs info.</param>
5516 /// <returns>a list of DbBso.BsoId</returns>
5517 public List<int> FindBso_UseIdVariant(BsInfo part)
5518 {
5519 var q = from dbBso in _dbTA.TableBlueStarObjects
5520 where dbBso.ObjectId == part.Id &&
5521 dbBso.ObjectVariant == part.Variant
5522 select dbBso.BsoId;
5523 return q.ToList();
5524 }
5525
5526 public int FindBso_UseId(BsInfo part)
5527 {
5528 var q = from dbBso in _dbTA.TableBlueStarObjects
5529 where dbBso.ObjectId == part.Id select dbBso.BsoId;
5530 return q.FirstOrDefault();
5531 }
5532
5533 /// <summary>
5534 /// Fetches common neighbors. Returns only list of BsInfos
5535 /// </summary>
5536 /// <param name="part">The part.</param>
5537 /// <returns>common neighbors</returns>
5538 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
5539 public List<BsInfo> FetchCommonNeighbors_Exact(BsInfo part)
5540 {
5541 List<BsInfo> neighbors = null;
5542 if (part != null)
5543 {
5544 int bsoId = FindBso_UseIdVariantVersion(part);
5545 if (bsoId > 0)
5546 {
5547 try
5548 {
5549 neighbors = GetCommonNeighborsOf(bsoId);
5550 }
5551 catch (Exception ex)
5552 {
5553 PDMLog.Logger.Log(ex);
5554 }
5555 }
5556 }
5557 return neighbors;
5558 }
5559
5560 /// <summary>
5561 /// Fetches common neighbors. Returns only list of BsInfos
5562 /// </summary>
5563 /// <param name="part">a list of parts.</param>
5564 /// <returns>common neighbors</returns>
5565 public List<BsInfo> FetchCommonNeighbors_UseIdVariant(List<BsInfo> parts)
5566 {
5567 Pdm.Models.ProfilingTools.Watches.Start("FetchCommonNeighbors_UseIdVariant");
5568 Dictionary<BsInfo, byte> tableNeighbors = new Dictionary<BsInfo, byte>();
5569 if (parts != null)
5570 {
5571 for (int i = 0; i < parts.Count; i++)
5572 {
5573 List<BsInfo> list = FetchCommonNeighbors_UseIdVariant(parts[i]);
5574 AddListToTable(list, tableNeighbors);
5575 }
5576 }
5577 Pdm.Models.ProfilingTools.Watches.Stop("FetchCommonNeighbors_UseIdVariant");
5578 return tableNeighbors.Keys.ToList();
5579 }
5580
5581 /// <summary>
5582 /// Fetches common neighbors. Returns only list of BsInfos
5583 /// </summary>
5584 /// <param name="part">The part.</param>
5585 /// <returns>common neighbors</returns>
5586 public List<BsInfo> FetchCommonNeighbors_UseIdVariant(BsInfo part)
5587 {
5588 Dictionary<BsInfo, byte> tableNeighbors = new Dictionary<BsInfo, byte>();
5589 if (part != null)
5590 {
5591 List<int> bsoIds = FindBso_UseIdVariant(part);
5592 GetCommonNeighborsOfList(tableNeighbors, bsoIds);
5593 }
5594 return tableNeighbors.Keys.ToList();
5595 }
5596
5597 /// <summary>
5598 /// Fetches common neighbors. Returns only list of BsInfos
5599 /// </summary>
5600 /// <param name="part">The part.</param>
5601 /// <returns>common neighbors</returns>
5602 [System.Obsolete("2016-12-15 - maybe not used anywhere?")]
5603 public List<BsInfo> FetchCommonNeighbors_UseIdVariant_DifferentVersion(BsInfo part)
5604 {
5605 Dictionary<BsInfo, byte> tableNeighbors = new Dictionary<BsInfo,byte>();
5606 if (part != null)
5607 {
5608 List<int> bsoIds = FindBso_UseIdVariant_DifferentVersion(part);
5609 GetCommonNeighborsOfList(tableNeighbors, bsoIds);
5610 }
5611 return tableNeighbors.Keys.ToList();
5612 }
5613
5614
5615 private void GetCommonNeighborsOfList(Dictionary<BsInfo, byte> tableNeighbors, List<int> bsoIds)
5616 {
5617 if (bsoIds != null && bsoIds.Count > 0)
5618 {
5619 try
5620 {
5621 for (int i = 0; i < bsoIds.Count; i++)
5622 {
5623 List<BsInfo> list = GetCommonNeighborsOf(bsoIds[i]);
5624 AddListToTable(list, tableNeighbors);
5625 }
5626 }
5627 catch (Exception ex)
5628 {
5629 PDMLog.Logger.Log(ex);
5630 }
5631 }
5632 }
5633
5634 public static void AddListToTable(List<BsInfo> list, Dictionary<BsInfo, byte> table)
5635 {
5636 if (list != null && list.Count > 0)
5637 {
5638 for (int i = 0; i < list.Count; i++)
5639 {
5640 table[list[i]] = 1;
5641 }
5642 }
5643 }
5644
5645 private List<BsInfo> GetCommonNeighborsOf(int bsoId)
5646 {
5647 List<BsInfo> neighbors = null;
5648 IQueryable<TwoRecs<int>> records =
5649 from gr in this.DbTouchAnalysis.TableGroups
5650 join context in this.DbTouchAnalysis.TableAnonymPairs on gr.GroupId equals context.GroupId
5651 where (bsoId == gr.PartAId || bsoId == gr.PartBId)
5652 select new TwoRecs<int>(gr.PartAId, gr.PartBId);
5653
5654 List<TwoRecs<int>> list = records.ToList();
5655 if (list != null && list.Count > 0)
5656 {
5657 neighbors = new List<BsInfo>();
5658
5659 for (int i = 0; i < list.Count; i++)
5660 {
5661 int neighId;
5662 TwoRecs<int> rec = list[i];
5663 if (rec.IdA == bsoId) neighId = rec.IdB;
5664 else neighId = rec.IdA;
5665
5666 DbBso dbBso = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.BsoId == neighId);
5667 if (dbBso != null)
5668 {
5669 BsInfo neighInfo = dbBso.CreateBsInfo();
5670 neighbors.Add(neighInfo);
5671 }
5672 }
5673 }
5674 return neighbors;
5675 }
5676
5677 private List<BsInfo> IdsToBsInfos(List<TwoRecs<int>> list, int bsoId)
5678 {
5679 List<BsInfo> neighbors = null;
5680
5681 if (list != null && list.Count > 0)
5682 {
5683 neighbors = new List<BsInfo>();
5684
5685 for (int i = 0; i < list.Count; i++)
5686 {
5687 int neighId;
5688 TwoRecs<int> rec = list[i];
5689 if (rec.IdA == bsoId) neighId = rec.IdB;
5690 else neighId = rec.IdB;
5691
5692 DbBso dbBso = _dbTA.TableBlueStarObjects.FirstOrDefault(x => x.BsoId == neighId);
5693 if (dbBso != null)
5694 {
5695 BsInfo neighInfo = dbBso.CreateBsInfo();
5696 neighbors.Add(neighInfo);
5697 }
5698 }
5699 }
5700 return neighbors;
5701 }
5702
5703 #endregion
5704
5705 /// <summary>
5706 /// Starts a thread, which prepares a connection to the MateDB.
5707 /// </summary>
5708 public static void ConnectToMateDB_Thread()
5709 {
5710 System.ComponentModel.BackgroundWorker bgw = new System.ComponentModel.BackgroundWorker();
5711 bgw.DoWork += new System.ComponentModel.DoWorkEventHandler(bgw_ConnectToMateDB);
5712 bgw.RunWorkerAsync();
5713 }
5714
5715 private static void bgw_ConnectToMateDB(object sender, System.ComponentModel.DoWorkEventArgs e)
5716 {
5717 CheckDbManager();
5718 }
5719
5720 public static void CheckDbManager()
5721 {
5722 if (_dbManager == null)
5723 {
5724 bool licenseServerAvailable = true; //TODO - 2016-04-13 - set this correctly
5725 _dbManager = new DbManager(InheritanceSourceBso.GetSourceType(licenseServerAvailable));
5726 }
5727 //TODO - 2016-09-26 - uncomment this and handle a case, when no mate DB is available. Probably load a setting from somewhere ?
5728 if (!_dbManager.ConnectToTouchAnalysisDB())
5729 {
5730 PDMLog.Logger.Log("Cannot connect to the mate rules database. Connection string: " + DbManager.ConnectionSettings.GetConnectionString());
5731 }
5732 }
5733
5734 public static void CheckDbManager(string connectionString)
5735 {
5736 if (_dbManager == null)
5737 {
5738 bool licenseServerAvailable = true; //TODO - 2016-04-13 - set this correctly
5739 _dbManager = new DbManager(InheritanceSourceBso.GetSourceType(licenseServerAvailable));
5740 }
5741 if (!_dbManager.ConnectToTouchAnalysisDB(connectionString))
5742 {
5743 PDMLog.Logger.Log("Cannot connect to the mate rules database. Connection string: " + DbManager.ConnectionSettings.GetConnectionString());
5744 }
5745 }
5746
5747 #region DBNormalizedFeatures
5748 /// <summary>
5749 /// Updates normalzied feature or insert into database new according to dataset.
5750 /// </summary>
5751 /// <param name="normFeatures">The values for normalizing current feature.</param>
5752 /// <param name="datasetName">Name of the dataset.</param>
5753 /// <returns></returns>
5754 public bool UpdateOrInsertDbNormalizedFeature(DbNormFeatures normFeatures, string datasetName)
5755 {
5756 bool insertNew = false;
5757 try
5758 {
5759 int trainSetId = DbManager.Instance.FindDbTrainSetId(datasetName);
5760 normFeatures.TrainSetId = trainSetId;
5761 Table<DbNormFeatures> tb = _dbTA.GetTable<DbNormFeatures>();
5762 DbNormFeatures oldNormFeatures = tb.FirstOrDefault(x => x.FeatureName == normFeatures.FeatureName
5763 && x.TrainSetId == trainSetId);
5764
5765 if (oldNormFeatures != null)
5766 {
5767 _dbTA.ExecuteCommand("DELETE FROM [TableNormFeatures] WHERE [TrainSetId] = {0}", trainSetId);
5768 _dbTA.SubmitChanges();
5769 }
5770
5771 insertNew = true;
5772 InsertDbNormFeatures(normFeatures);
5773
5774 _dbTA.SubmitChanges();
5775 return true;
5776 }
5777 catch (Exception ex)
5778 {
5779 PDMLog.Logger.Log(ex);
5780 PDMLog.Logger.Log("UpdateOrInsertDbNormalizedFeature: insertNew = " + insertNew + "; feat = " + normFeatures.ToString());
5781 return false;
5782 }
5783 }
5784
5785 /// <summary>
5786 /// Inserts into database normalized feature object.
5787 /// </summary>
5788 /// <param name="normFeatures">The normalized features object.</param>
5789 /// <returns></returns>
5790 private bool InsertDbNormFeatures(DbNormFeatures normFeatures)
5791 {
5792 try
5793 {
5794 Table<DbNormFeatures> tb = _dbTA.GetTable<DbNormFeatures>();
5795 tb.InsertOnSubmit(normFeatures);
5796 return true;
5797 }
5798 catch (Exception ex)
5799 {
5800 PDMLog.Logger.Log(ex);
5801 return false;
5802 }
5803 }
5804
5805 /// <summary>
5806 /// Loads the list of normalized features according to ID of train set.
5807 /// </summary>
5808 /// <param name="setId">The train set identifier.</param>
5809 /// <returns></returns>
5810 public List<DbNormFeatures> LoadNormFeatures(int setId)
5811 {
5812 try
5813 {
5814 Table<DbNormFeatures> tb = _dbTA.GetTable<DbNormFeatures>();
5815 var q = from normWeights in tb
5816 where normWeights.TrainSetId == setId
5817 select normWeights;
5818 return (List<DbNormFeatures>)q.ToList();
5819 }
5820 catch (Exception ex)
5821 {
5822 PDMLog.Logger.Log(ex);
5823 PDMLog.Logger.Log("Probably cannot access a table DbNormFeatures in MateDB.");
5824 return null;
5825 }
5826 }
5827 #endregion DBNormalizedFeatures
5828
5829 #region DBTrainSample
5830 /// <summary>
5831 /// Updates or insert train sample in database.
5832 /// </summary>
5833 /// <param name="sample">Train sample object.</param>
5834 /// <returns></returns>
5835 public bool UpdateOrInsertDbTrainSample(DbTrainSample sample)
5836 {
5837 bool insertNew = false;
5838 try
5839 {
5840 Table<DbTrainSample> tb = _dbTA.GetTable<DbTrainSample>();
5841 DbTrainSample oldSample = tb.FirstOrDefault(x => x.TrueClass == sample.TrueClass
5842 && x.BsoId == sample.BsoId && x.TrainSetId == sample.TrainSetId);
5843 if (oldSample == null)
5844 {
5845 insertNew = true;
5846 InsertDbTrainSample(sample);
5847 }
5848 else
5849 {
5850 insertNew = false;
5851 oldSample.CopyFrom(sample);
5852 }
5853 _dbTA.SubmitChanges();
5854 return true;
5855 }
5856 catch (Exception ex)
5857 {
5858 PDMLog.Logger.Log(ex);
5859 PDMLog.Logger.Log("DbTrainSample: insertNew = " + insertNew + "; set = " + sample.ToString());
5860 return false;
5861 }
5862 }
5863
5864 /// <summary>
5865 /// Inserts train sample into the database.
5866 /// </summary>
5867 /// <param name="sample">The sample.</param>
5868 /// <returns></returns>
5869 private bool InsertDbTrainSample(DbTrainSample sample)
5870 {
5871 try
5872 {
5873 Table<DbTrainSample> tb = _dbTA.GetTable<DbTrainSample>();
5874 tb.InsertOnSubmit(sample);
5875 return true;
5876 }
5877 catch (Exception ex)
5878 {
5879 PDMLog.Logger.Log(ex);
5880 return false;
5881 }
5882 }
5883
5884 /// <summary>
5885 /// Loads the list of all train sets.
5886 /// </summary>
5887 /// <returns>list of train sets</returns>
5888 public List<DbTrainSet> LoadTrainSets()
5889 {
5890 try
5891 {
5892 Table<DbTrainSet> tb = _dbTA.GetTable<DbTrainSet>();
5893 return tb.ToList();
5894 }
5895 catch (Exception ex)
5896 {
5897 PDMLog.Logger.Log(ex);
5898 PDMLog.Logger.Log("Probably cannot access a table DbTrainSet in MateDB.");
5899 return null;
5900 }
5901 }
5902
5903 /// <summary>
5904 /// Loads the train samples according to training set.
5905 /// </summary>
5906 /// <param name="setId">The training set identifier.</param>
5907 /// <returns></returns>
5908 public List<DbTrainSample> LoadTrainSamplesInSet(int setId)
5909 {
5910 try
5911 {
5912 Table<DbTrainSample> tb = _dbTA.GetTable<DbTrainSample>();
5913 var q = from trainSet in _dbTA.GetTable<DbTrainSample>()
5914 where trainSet.TrainSetId == setId
5915 select trainSet;
5916 return (List <DbTrainSample>)q.ToList();
5917 }
5918 catch (Exception ex)
5919 {
5920 PDMLog.Logger.Log(ex);
5921 PDMLog.Logger.Log("Probably cannot access a table DbTrainSet in MateDB.");
5922 return null;
5923 }
5924 }
5925
5926 /// <summary>
5927 /// Removes the train samples according to train set.
5928 /// </summary>
5929 /// <param name="setId">The train set identifier.</param>
5930 /// <returns></returns>
5931 public bool RemoveTrainSamples(int setId)
5932 {
5933 try
5934 {
5935 DeleteTrainSamples(setId);
5936 return true;
5937 }
5938 catch (Exception ex)
5939 {
5940 PDMLog.Logger.Log(ex);
5941 PDMLog.Logger.Log("Probably cannot access a table DbTrainSample in MateDB.");
5942 return false;
5943 }
5944 }
5945 #endregion DBTrainSample
5946
5947 #region DBTrainSet
5948 /// <summary>
5949 /// Updates or insert train set into database.
5950 /// </summary>
5951 /// <param name="name">The name of train set.</param>
5952 /// <returns></returns>
5953 public bool UpdateOrInsertDbTrainSet(string name)
5954 {
5955 bool insertNew = false;
5956 DbTrainSet set = new DbTrainSet(name);
5957 try
5958 {
5959 Table<DbTrainSet> tb = _dbTA.GetTable<DbTrainSet>();
5960 DbTrainSet oldSet = tb.FirstOrDefault(x => x.Name == set.Name);
5961 if (oldSet == null)
5962 {
5963 insertNew = true;
5964 InsertDbTrainSet(set);
5965 }
5966 else
5967 {
5968 insertNew = false;
5969 oldSet.CopyFrom(set);
5970 }
5971 _dbTA.SubmitChanges();
5972
5973 return true;
5974 }
5975 catch (Exception ex)
5976 {
5977 PDMLog.Logger.Log(ex);
5978 PDMLog.Logger.Log("UpdateOrInsertDbNormalizedFeature: insertNew = " + insertNew + "; set = " + set.ToString());
5979 return false;
5980 }
5981 }
5982
5983 /// <summary>
5984 /// Removes the train set according to train set ID.
5985 /// </summary>
5986 /// <param name="setId">Train set identifier.</param>
5987 /// <returns></returns>
5988 public bool RemoveTrainSet(int setId)
5989 {
5990 try
5991 {
5992 DeleteTrainSet(setId);
5993 return true;
5994 }
5995 catch (Exception ex)
5996 {
5997 PDMLog.Logger.Log(ex);
5998 PDMLog.Logger.Log("Probably cannot access a table DbTrainSet in MateDB.");
5999 return false;
6000 }
6001 }
6002
6003 /// <summary>
6004 /// Inserts train set into the database.
6005 /// </summary>
6006 /// <param name="set">The train set object.</param>
6007 /// <returns></returns>
6008 private bool InsertDbTrainSet(DbTrainSet set)
6009 {
6010 try
6011 {
6012 Table<DbTrainSet> tb = _dbTA.GetTable<DbTrainSet>();
6013 tb.InsertOnSubmit(set);
6014 return true;
6015 }
6016 catch (Exception ex)
6017 {
6018 PDMLog.Logger.Log(ex);
6019 return false;
6020 }
6021 }
6022
6023 /// <summary>
6024 /// Finds the train set ID according to set name.
6025 /// </summary>
6026 /// <param name="name">The train set name.</param>
6027 /// <returns></returns>
6028 public int FindDbTrainSetId(string name)
6029 {
6030 if (_dbTA == null)
6031 return Int32.MinValue;
6032 Table<DbTrainSet> tb = _dbTA.GetTable<DbTrainSet>();
6033
6034 DbTrainSet temp = null;
6035 try
6036 {
6037 temp = tb.FirstOrDefault(x => x.Name == name);
6038 }
6039 catch (Exception ex)
6040 {
6041 return -1;
6042 }
6043
6044 if (temp == null)
6045 return -1;
6046
6047 return temp.TrainSetId;
6048 }
6049 #endregion DBTrainSet
6050
6051 #region DBNeuralNetworks
6052 /// <summary>
6053 /// Finds the neural net according to ID and returns neural network object.
6054 /// </summary>
6055 /// <param name="netId">The neural net identifier.</param>
6056 /// <returns></returns>
6057 public DbNeuralNetworks FindNeuralNet(int netId)
6058 {
6059 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6060 DbNeuralNetworks net = tb.FirstOrDefault(x => x.NeuralNetworkId == netId);
6061 return net;
6062 }
6063
6064 /// <summary>
6065 /// Sets the neural net to active according to ID and set as inactive other neural
6066 /// nets.
6067 /// </summary>
6068 /// <param name="netId">The net identifier.</param>
6069 public void SetNeuralNetToActive(int netId)
6070 {
6071 // set active to false for last active layer
6072 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6073 DbNeuralNetworks lastActiveNetwork = tb.FirstOrDefault(x => x.Active == true);
6074 if (lastActiveNetwork != null)
6075 {
6076 lastActiveNetwork.Active = false;
6077 InsertDbNeuralNet(lastActiveNetwork);
6078 }
6079 DbNeuralNetworks newActiveNet = tb.FirstOrDefault(x => x.NeuralNetworkId == netId);
6080 if (newActiveNet != null)
6081 {
6082 newActiveNet.Active = true;
6083 InsertDbNeuralNet(newActiveNet);
6084 }
6085
6086 _dbTA.SubmitChanges();
6087 }
6088
6089 /// <summary>
6090 /// Finds the neural net identifier according to the name of net.
6091 /// </summary>
6092 /// <param name="name">The name of the neural networks.</param>
6093 /// <returns></returns>
6094 public int FindNeuralNetId(string name)
6095 {
6096 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6097 DbNeuralNetworks net = tb.FirstOrDefault(x => x.Name == name);
6098 return net.NeuralNetworkId;
6099 }
6100
6101 /// <summary>
6102 /// Finds the neural net with flag active set to true.
6103 /// </summary>
6104 /// <returns>active network</returns>
6105 public DbNeuralNetworks FindIdActiveNeuralNetwork()
6106 {
6107 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6108 DbNeuralNetworks net = tb.FirstOrDefault(x => x.Active == true);
6109 return net;
6110 }
6111
6112 /// <summary>
6113 /// Updates or insert neural network into database.
6114 /// </summary>
6115 /// <param name="networkRecord">The network record.</param>
6116 /// <param name="nnName">Name of the nn.</param>
6117 /// <returns></returns>
6118 public bool UpdateOrInsertNetwork(DbNeuralNetworks networkRecord, string nnName = "")
6119 {
6120 bool insertNew = false;
6121 try
6122 {
6123 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6124 DbNeuralNetworks oldNet = tb.FirstOrDefault(x => x.Name == networkRecord.Name);
6125 if (oldNet == null)
6126 {
6127 insertNew = true;
6128 InsertDbNeuralNet(networkRecord);
6129 }
6130 else
6131 {
6132 insertNew = false;
6133 oldNet.CopyFrom(networkRecord);
6134 }
6135 _dbTA.SubmitChanges();
6136
6137 return true;
6138 }
6139 catch (Exception ex)
6140 {
6141 PDMLog.Logger.Log(ex);
6142 PDMLog.Logger.Log("UpdateOrInsertNetwork: insertNew = " + insertNew + "; network name = " + nnName);
6143 return false;
6144 }
6145 }
6146 /// <summary>
6147 /// Inserts neural net into database.
6148 /// </summary>
6149 /// <param name="networkRecord">The network record.</param>
6150 /// <returns>true if insert is valid otherwise false</returns>
6151 private bool InsertDbNeuralNet(DbNeuralNetworks networkRecord)
6152 {
6153 try
6154 {
6155 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6156 tb.InsertOnSubmit(networkRecord);
6157 return true;
6158 }
6159 catch (Exception ex)
6160 {
6161 PDMLog.Logger.Log(ex);
6162 return false;
6163 }
6164 }
6165
6166 /// <summary>
6167 /// Loads list of the all neural networks.
6168 /// </summary>
6169 /// <returns>list of all networks</returns>
6170 public List<DbNeuralNetworks> LoadNeuralNetworks()
6171 {
6172 try
6173 {
6174 Table<DbNeuralNetworks> tb = _dbTA.GetTable<DbNeuralNetworks>();
6175 List<DbNeuralNetworks> nets = tb.ToList<DbNeuralNetworks>();
6176 return nets;
6177 }
6178 catch (Exception ex)
6179 {
6180 PDMLog.Logger.Log(ex);
6181 PDMLog.Logger.Log("Probably cannot access a table DbNeuralNetworks in MateDB.");
6182 return null;
6183 }
6184 }
6185 #endregion
6186
6187 #region DBClassWeights
6188 /// <summary>
6189 /// Updates or insert class weight.
6190 /// </summary>
6191 /// <param name="classname">The name of class.</param>
6192 /// <param name="weights">The weights.</param>
6193 /// <returns></returns>
6194 public bool UpdateOrInsertDbClassWeight(string classname, DbClassWeights weights)
6195 {
6196 bool insertNew = false;
6197 try
6198 {
6199 Table<DbClassWeights> tb = _dbTA.GetTable<DbClassWeights>();
6200 DbClassWeights oldWeights = tb.FirstOrDefault(x => x.Classname == classname && x.NeuralNetworkId == weights.NeuralNetworkId);
6201 if (oldWeights == null)
6202 {
6203 insertNew = true;
6204 InsertDbClassWeights(classname, weights);
6205 }
6206 else
6207 {
6208 insertNew = false;
6209 oldWeights.CopyFrom(classname, weights);
6210 }
6211 _dbTA.SubmitChanges(); //TODO - 2016-10-27 - submit batch of changes?
6212 return true;
6213 }
6214 catch (Exception ex)
6215 {
6216 PDMLog.Logger.Log(ex);
6217 PDMLog.Logger.Log("UpdateOrInsertDbClassWeights: insertNew = " + insertNew + "; feat = " + weights.ToString());
6218 return false;
6219 }
6220 }
6221
6222 /// <summary>
6223 /// Inserts the class weights into database.
6224 /// </summary>
6225 /// <param name="classname">The classname.</param>
6226 /// <param name="weights">The weights.</param>
6227 /// <returns></returns>
6228 private bool InsertDbClassWeights(string classname, DbClassWeights weights)
6229 {
6230 try
6231 {
6232 weights.Classname = classname;
6233 Table<DbClassWeights> table = _dbTA.GetTable<DbClassWeights>();
6234 table.InsertOnSubmit(weights);
6235 return true;
6236 }
6237 catch (Exception ex)
6238 {
6239 PDMLog.Logger.Log(ex);
6240 return false;
6241 }
6242 }
6243
6244 /// <summary>
6245 /// Loads the list of weights.
6246 /// </summary>
6247 /// <returns>list of weights</returns>
6248 public List<DbClassWeights> LoadWeights()
6249 {
6250 try
6251 {
6252 Table<DbNeuralNetworks> tbNetworks = _dbTA.GetTable<DbNeuralNetworks>();
6253 DbNeuralNetworks activeNetwork = tbNetworks.FirstOrDefault(x => x.Active == true);
6254 if (activeNetwork == null)
6255 return new List<DbClassWeights>();
6256 var q = from weights in _dbTA.GetTable<DbClassWeights>()
6257 where weights.NeuralNetworkId == activeNetwork.NeuralNetworkId
6258 select weights;
6259 // if there are not any results return empty list
6260 if (!q.Any())
6261 return new List<DbClassWeights>();
6262 return (List<DbClassWeights>)q.ToList();
6263 }
6264 catch (Exception ex)
6265 {
6266 PDMLog.Logger.Log(ex);
6267 PDMLog.Logger.Log("Probably cannot access a table DbClassWeights in MateDB.");
6268 return null;
6269 }
6270 }
6271
6272 #endregion DBClassWeights
6273
6274 #region DBFeatures
6275
6276 public bool UpdateOrInsertDbFeatures(int dbPartId, DbFeatures features)
6277 {
6278 bool insertNew = false;
6279 try
6280 {
6281 Table<DbFeatures> tb = _dbTA.GetTable<DbFeatures>();
6282 DbFeatures oldFeats = tb.FirstOrDefault(x => x.PartId == dbPartId);
6283 if (oldFeats == null)
6284 {
6285 insertNew = true;
6286 InsertDbFeatures(dbPartId, features);
6287 }
6288 else
6289 {
6290 insertNew = false;
6291 oldFeats.CopyFrom(features);
6292 }
6293 _dbTA.SubmitChanges(); //TODO - 2016-10-27 - submit batch of changes?
6294 return true;
6295 }
6296 catch (Exception ex)
6297 {
6298 PDMLog.Logger.Log(ex);
6299 PDMLog.Logger.Log("UpdateOrInsertDbFeatures: insertNew = " + insertNew + "; feat = " + features.ToString());
6300 return false;
6301 }
6302 }
6303
6304 private bool InsertDbFeatures(int dbPartId, DbFeatures features)
6305 {
6306 try
6307 {
6308 features.PartId = dbPartId;
6309 Table<DbFeatures> table = _dbTA.GetTable<DbFeatures>();
6310 table.InsertOnSubmit(features);
6311 return true;
6312 }
6313 catch (Exception ex)
6314 {
6315 PDMLog.Logger.Log(ex);
6316 return false;
6317 }
6318 }
6319
6320 public DbFeatures FindFeaturesOf(DbBso dbBso)
6321 {
6322 try
6323 {
6324 Table<DbFeatures> tb = _dbTA.GetTable<DbFeatures>();
6325 DbFeatures features = tb.FirstOrDefault(x => x.PartId == dbBso.BsoId);
6326 return features;
6327 }
6328 catch (Exception ex)
6329 {
6330 PDMLog.Logger.Log(ex);
6331 PDMLog.Logger.Log("Probably cannot access a table DbFeatures in MateDB.");
6332 return null;
6333 }
6334 }
6335
6336 public bool UpdateClassificationInDbFeatures(int dbPartId, byte mainClass, string classification)
6337 {
6338 try
6339 {
6340 Table<DbFeatures> table = _dbTA.GetTable<DbFeatures>();
6341 DbFeatures f = table.FirstOrDefault(x => x.PartId == dbPartId);
6342 if (f != null)
6343 {
6344 f.MainGeomClass = mainClass;
6345 f.AllGeomClasses = classification;
6346
6347 _dbTA.SubmitChanges();
6348
6349 return true;
6350 }
6351 }
6352 catch (Exception ex)
6353 {
6354 PDMLog.Logger.Log(ex);
6355 }
6356 return false;
6357 }
6358
6359 public bool UpdateOrInsertThumbnailHashes(BsInfo info, string hashIso, string hashBestFit)
6360 {
6361 int partId = FindBsInfoInTableBsObjects_CreateNewIfNotExist(info, false);
6362 try
6363 {
6364 Table<DbFeatures> tb = _dbTA.GetTable<DbFeatures>();
6365 DbFeatures fts = tb.FirstOrDefault(x => x.PartId == partId);
6366 if (fts != null)
6367 {
6368 fts.HashIso = hashIso;
6369 fts.HashBestFit = hashBestFit;
6370 _dbTA.SubmitChanges();
6371 }
6372 else
6373 {
6374 fts = new DbFeatures();
6375 fts.PartId = partId;
6376 fts.HashIso = hashIso;
6377 fts.HashBestFit = hashBestFit;
6378 tb.InsertOnSubmit(fts);
6379 _dbTA.SubmitChanges();
6380 }
6381
6382 return true;
6383 }
6384 catch (Exception ex)
6385 {
6386 PDMLog.Logger.Log(ex);
6387 return false;
6388 }
6389 }
6390
6391 public List<BaseSurface> FindBaseSurfacesForPart(BsInfo part)
6392 {
6393 List<BaseSurface> surfaces = null;
6394 int partId = FindBso_UseIdVariantVersion(part);
6395 if (partId == -1)
6396 {
6397 partId = FindBso_UseIdVariant_NewestVersion(part);
6398 }
6399
6400 if (partId != -1)
6401 {
6402 string[] surfaceNames;
6403 int[] usabilities;
6404 Point3D[] samplePoints;
6405 DbSurfaceTypes[] dbSurfTypes;
6406 BaseSurface[] geomSurfaces;
6407 int[] surfIds;
6408
6409 FindSurfaceUsabilitiesOfPart_inner(partId, out surfaceNames, out usabilities, out samplePoints, out dbSurfTypes, out geomSurfaces, out surfIds);
6410 if (geomSurfaces != null)
6411 {
6412 surfaces = geomSurfaces.ToList();
6413 }
6414 }
6415 return surfaces;
6416 }
6417
6418 #endregion
6419
6420 public void UpdateCadSystemOfAllObjectsFromBS()
6421 {
6422 if (ConnectToTouchAnalysisDB())
6423 {
6424 int batchSize = 100;
6425 int i = 0;
6426 int cTotal = 0;
6427 foreach (DbBso dbBso in _dbTA.TableBlueStarObjects)
6428 {
6429 cTotal++;
6430 if (string.IsNullOrEmpty(dbBso.CadSystem))
6431 {
6432 BsInfo bsInfo = dbBso.CreateBsInfo();
6433
6434 string baseClass;
6435 List<BSObjectLight> ancestorsBsos;
6436 List<BSObjectLight> descendants;
6437 AxServer.Instance.GetAncestors(Convert.ConvertBsInfoToBso(bsInfo), out ancestorsBsos, out descendants, out baseClass);
6438
6439 string cadSystem = AxServer.Instance.GetCadSystem(bsInfo.Id, bsInfo.Variant, bsInfo.Version, bsInfo.Type);
6440
6441
6442 //BlueViewControls.AxService.FetchOriginAndClassification(Convert.ConvertBsInfoToBso(bsInfo), out origin, out baseClass);
6443 int classifId = GetClassificationId(baseClass);
6444 dbBso.CadSystem = cadSystem;
6445 dbBso.ClassificationId = classifId;
6446
6447 i++;
6448 if (i == batchSize)
6449 {
6450 i = 0;
6451 _dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
6452 }
6453 }
6454 }
6455
6456 if (i > 0)
6457 {
6458 _dbTA.SubmitChanges(ConflictMode.ContinueOnConflict);
6459 }
6460 }
6461 }
6462 }
6463
6464 public struct TwoInts
6465 {
6466 public int RecordId { get; set; }
6467 public int ParentId { get; set; }
6468 }
6469
6470 public struct TwoRecs<T>
6471 {
6472 private T _idA;
6473 private T _idB;
6474
6475 public T IdA
6476 {
6477 get { return _idA; }
6478 set { _idA = value; }
6479 }
6480
6481 public T IdB
6482 {
6483 get { return _idB; }
6484 set { _idB = value; }
6485 }
6486
6487
6488 public TwoRecs(T idA, T idB)
6489 {
6490 _idA = idA;
6491 _idB = idB;
6492 }
6493 }
6494
6495 /// <summary>
6496 /// a not very smart way how to hash 3d transformation matrices. It is used for a comparison of matrices of dbInstancePairs.
6497 /// </summary>
6498 class ByteArrayComparer : IEqualityComparer<byte[]>
6499 {
6500 public bool Equals(byte[] x, byte[] y)
6501 {
6502 if (x == y)
6503 {
6504 return true;
6505 }
6506 else if (x != null && y != null)
6507 {
6508 if (x.Length != y.Length)
6509 {
6510 return false;
6511 }
6512 else
6513 {
6514 for (int i = 0; i < x.Length; i++)
6515 {
6516 if (x[i] != y[i])
6517 {
6518 return false;
6519 }
6520 }
6521 return true;
6522 }
6523 }
6524 else return false;
6525 }
6526
6527 public int GetHashCode(byte[] obj)
6528 {
6529 int sum = 0;
6530 for (int i = 0; i < obj.Length; i++)
6531 {
6532 sum += obj[i];
6533 }
6534 return sum;
6535 }
6536 }
6537
6538 static class ExceptionExtension
6539 {
6540 public static string SerializeForLog(this ChangeConflictException e, DataContext context)
6541 {
6542 StringBuilder builder = new StringBuilder();
6543
6544 using (StringWriter sw = new StringWriter(builder))
6545 {
6546 sw.WriteLine("Optimistic concurrency error:");
6547 sw.WriteLine(e.Message);
6548
6549 foreach (ObjectChangeConflict occ in context.ChangeConflicts)
6550 {
6551 Type objType = occ.Object.GetType();
6552 MetaTable metatable = context.Mapping.GetTable(objType);
6553 object entityInConflict = occ.Object;
6554
6555 sw.WriteLine("Table name: {0}", metatable.TableName);
6556
6557 var noConflicts =
6558 from property in objType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
6559 where property.CanRead &&
6560 property.CanWrite &&
6561 property.GetIndexParameters().Length == 0 &&
6562 !occ.MemberConflicts.Any(c => c.Member.Name != property.Name)
6563 orderby property.Name
6564 select property;
6565
6566 foreach (var property in noConflicts)
6567 {
6568 sw.WriteLine("\tMember: {0}", property.Name);
6569 sw.WriteLine("\t\tCurrent value: {0}",
6570 property.GetGetMethod().Invoke(occ.Object, new object[0]));
6571 }
6572
6573 sw.WriteLine("\t-- Conflicts Start Here --", metatable.TableName);
6574
6575 foreach (MemberChangeConflict mcc in occ.MemberConflicts)
6576 {
6577 sw.WriteLine("\tMember: {0}", mcc.Member.Name);
6578 sw.WriteLine("\t\tCurrent value: {0}", mcc.CurrentValue);
6579 sw.WriteLine("\t\tOriginal value: {0}", mcc.OriginalValue);
6580 sw.WriteLine("\t\tDatabase value: {0}", mcc.DatabaseValue);
6581 }
6582 }
6583
6584 sw.WriteLine();
6585 sw.WriteLine("Attempted SQL: ");
6586
6587 //TextWriter tw = context.Log;
6588
6589 //try
6590 //{
6591 // context.Log = sw;
6592 // context.SubmitChanges();
6593 //}
6594 //catch (ChangeConflictException)
6595 //{
6596 // // This is what we wanted.
6597 //}
6598 //catch
6599 //{
6600 // sw.WriteLine("Unable to recreate SQL!");
6601 //}
6602 //finally
6603 //{
6604 // context.Log = tw;
6605 //}
6606
6607 //sw.WriteLine();
6608
6609 //sw.WriteLine(e.SerializeForLog());
6610 }
6611
6612 return builder.ToString();
6613 }
6614 }
6615}