Exemplo n.º 1
0
		internal static ITsString ExtractNonLIFTResidue(TsStringAccessor tsa)
		{
			if (tsa.Length < 29)
				return tsa.UnderlyingTsString;
			ITsStrBldr tsb = tsa.UnderlyingTsString.GetBldr();
			int idx = tsb.Text.IndexOf("<lift-residue");
			if (idx >= 0)
			{
				int idxEnd = tsb.Text.IndexOf("</lift-residue>", idx + 14);
				if (idxEnd >= 0)
					tsb.Replace(idx, idxEnd + 15, null, null);
			}
			return tsb.GetString();
		}
Exemplo n.º 2
0
		/// <summary>
		/// Scan ImportResidue for XML looking string inserted by LIFT import.  If any is found,
		/// move it from ImportResidue to LiftResidue.
		/// </summary>
		/// <returns>string containing any LIFT import residue found in ImportResidue</returns>
		public static string ExtractLIFTResidue(FdoCache cache, int hvo, int flidImportResidue,
			int flidLiftResidue)
		{
			TsStringAccessor tsa = new TsStringAccessor(cache, hvo, flidImportResidue);
			if (tsa.UnderlyingTsString == null || tsa.Length < 13)
				return null;
			int idx = tsa.Text.IndexOf("<lift-residue");
			if (idx >= 0)
			{
				string sLiftResidue = tsa.Text.Substring(idx);
				int idx2 = sLiftResidue.IndexOf("</lift-residue>");
				if (idx2 >= 0)
				{
					idx2 += 15;
					if (sLiftResidue.Length > idx2)
						sLiftResidue = sLiftResidue.Substring(0, idx2);
				}
				if (flidLiftResidue != 0)
				{
					int cch = sLiftResidue.Length;
					ITsStrBldr tsb = tsa.UnderlyingTsString.GetBldr();
					tsb.Replace(idx, idx + cch, null, null);
					tsa.UnderlyingTsString = tsb.GetString();	// remove from ImportResidue
					cache.SetUnicodeProperty(hvo, flidLiftResidue, sLiftResidue);
				}
				return sLiftResidue;
			}
			else
			{
				return null;
			}
		}
Exemplo n.º 3
0
		/// <summary>
		///
		/// </summary>
		/// <param name="source"></param>
		/// <param name="fConcatenateIfBoth">If true, and if source and dest both have values that are not
		/// equal, concatenate source on end of dest. Otherwise ignore source if dest has a value.</param>
		public void MergeString(TsStringAccessor source, bool fConcatenateIfBoth)
		{
			if (source == null)
				return;

			string text = null;
			if (UnderlyingTsString != null)
				text = UnderlyingTsString.Text;
			string sourceText = null;
			if (source.UnderlyingTsString != null)
				sourceText = source.UnderlyingTsString.Text;

			if ((text == null
				|| text == string.Empty)
				&& (sourceText != null
				&& sourceText != string.Empty))
			{
				UnderlyingTsString = source.UnderlyingTsString;
			}
			else if (!fConcatenateIfBoth)
			{
				return;
			}
			else if ((text != null
				&& text != string.Empty)
				&& sourceText != null
				&& sourceText != string.Empty
				&& !UnderlyingTsString.Equals(source.UnderlyingTsString))
			{
				// concatenate
				ITsStrBldr tsb = UnderlyingTsString.GetBldr();
				tsb.Replace(tsb.Length, tsb.Length, " ", null);
				tsb.ReplaceTsString(tsb.Length, tsb.Length, source.UnderlyingTsString);
				UnderlyingTsString = tsb.GetString();
			}
		}
Exemplo n.º 4
0
		/// <summary>
		///
		/// </summary>
		/// <param name="source"></param>
		public void MergeString(TsStringAccessor source)
		{
			MergeString(source, false);
		}
Exemplo n.º 5
0
		/// <summary>
		/// Calculate the WritingSystemHvo for a CmBaseAnnotation.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvoObject"></param>
		/// <param name="beginOffset"></param>
		/// <param name="flid"></param>
		/// <returns></returns>
		public static int GetAnnotationWritingSystem(FdoCache cache, int hvoObject, int beginOffset,
			int flid)
		{
			if (flid == (int)StTxtPara.StTxtParaTags.kflidContents)
			{
				TsStringAccessor tsa = new TsStringAccessor(cache, hvoObject, flid);
				ITsString tss = tsa.UnderlyingTsString;
				if (beginOffset >= 0 && beginOffset < tss.Length)
				{
					ITsTextProps ttp = tss.get_PropertiesAt(beginOffset);
					int nVar;
					int ws = ttp.GetIntPropValues((int)FwTextPropType.ktptWs, out nVar);
					if (ws > 0)
						return ws;
				}
			}
			return cache.DefaultVernWs;
		}
Exemplo n.º 6
0
		private object GetCustomFieldValue(CmObject target, string property)
		{
			try
			{
				string sClass = m_cache.MetaDataCacheAccessor.GetClassName((uint)target.ClassID);
				uint flid = m_cache.MetaDataCacheAccessor.GetFieldId(sClass, property, true);
				if (flid == 0)
					return null;
				int type = m_cache.MetaDataCacheAccessor.GetFieldType(flid);
				string sView;
				switch (type)
				{
					case (int)CellarModuleDefns.kcptString:
					case (int)CellarModuleDefns.kcptBigString:
						TsStringAccessor tsa = new TsStringAccessor(m_cache, target.Hvo, (int)flid);
						return tsa;
					case (int)CellarModuleDefns.kcptMultiUnicode:
					case (int)CellarModuleDefns.kcptMultiBigUnicode:
						sView = sClass + '_' + property;
						MultiUnicodeAccessor mua = new MultiUnicodeAccessor(m_cache, target.Hvo, (int)flid, sView);
						return mua;
					case (int)CellarModuleDefns.kcptMultiString:
					case (int)CellarModuleDefns.kcptMultiBigString:
						sView = sClass + '_' + property;
						MultiStringAccessor msa = new MultiStringAccessor(m_cache, target.Hvo, (int)flid, sView);
						return msa;
				}
			}
			catch
			{
			}
			return null;
		}
Exemplo n.º 7
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Merges object into this object.
		/// if fLoseNoStringData is false:
		/// For atomic properties, if this object has something in the property, the source
		/// property is ignored. For sequence properties, the objects in the source will be
		/// moved and appended to the properties in this object. Any references to the
		/// source object will be transferred to this object. The source object is deleted
		/// at the end of this method (objSrc.DeleteUnderlyingObject() call).
		/// String properties are copied from the source if the destination (this) has no value
		/// and the source has a value.
		///
		/// if fLoseNoStringData is true, the above is modified as follows:
		/// 1. If a string property has a value in both source and destination, and the values
		/// are different, append the source onto the destination.
		/// 2. If an atomic object property has a value in both source and destination,
		/// recursively merge the value in the source with the value in the destination.
		/// </summary>
		/// <param name="objSrc">Object whose properties will be merged into this object's properties</param>
		/// <remarks>
		/// NB: The given object will be deleted in this method, so don't expect it to be valid, afterwards.
		/// </remarks>
		/// <param name="fLoseNoStringData"></param>
		/// ------------------------------------------------------------------------------------
		public virtual void MergeObject(ICmObject objSrc, bool fLoseNoStringData)
		{
			Debug.Assert(m_cache != null);
			// We don't allow merging items of different classes.
			Debug.Assert(ClassID == objSrc.ClassID);
			if (ClassID != objSrc.ClassID)
				return;

			IFwMetaDataCache mdc = m_cache.MetaDataCacheAccessor;
			PropertyInfo[] myProperties = GetType().GetProperties();
			PropertyInfo[] srcProperties = objSrc.GetType().GetProperties();
			string fieldname;
			// Process all the fields in the source.
			foreach(uint flid in DbOps.GetFieldsInClassOfType(mdc, ClassID, FieldType.kgrfcptAll))
			{
				/* These values will also be returned because they are for most of CmObject's flids.
				 * I think it will do this for each superclass, so there could be some repeats on them.
				 *
				 * pvuFields->Push(101);	// kflidCmObject_Guid
				 * pvuFields->Push(102);	// kflidCmObject_Class
				 * pvuFields->Push(103);	// kflidCmObject_Owner
				 * pvuFields->Push(104);	// kflidCmObject_OwnFlid
				 * pvuFields->Push(105);	// kflidCmObject_OwnOrd
				 * //pvuFields->Push(106);	// kflidCmObject_UpdStmp
				 * //pvuFields->Push(107);	// kflidCmObject_UpdDttm
				 *
				*/
				if (flid < 1000)
					continue; // Do nothing for the CmObject flids.
				if (flid >= (int)SpecialTagValues.ktagMinVp)
					continue;	// Do nothing for virtual properties.

				int nType = mdc.GetFieldType(flid);
				fieldname = mdc.GetFieldName(flid);
					//|| fieldname == "DateModified"
					//|| nType == (int)FieldType.kcptTime // This is handled by a separate connection, so it can time out, if another transaction is open.
				if (fieldname == "DateCreated"
					|| nType == (int)FieldType.kcptImage // FDO does not support this one.
					|| nType == (int)FieldType.kcptGenDate) // FDO does not support setter for gendate.
					continue; // Don't mess with this one.

				// Set suffixes on some of the types.
				switch (nType)
				{
					case (int)FieldType.kcptOwningAtom: // 23
					{
						fieldname += "OA";
						break;
					}
					case (int)FieldType.kcptReferenceAtom: // 24
					{
						fieldname += "RA";
						break;
					}
					case (int)FieldType.kcptOwningCollection: // 25
					{
						fieldname += "OC";
						break;
					}
					case (int)FieldType.kcptReferenceCollection: // 26
					{
						fieldname += "RC";
						break;
					}
					case (int)FieldType.kcptOwningSequence: // 27
					{
						fieldname += "OS";
						break;
					}
					case (int)FieldType.kcptReferenceSequence: // 28
					{
						fieldname += "RS";
						break;
					}
				}
				Object myCurrentValue = null;
				MethodInfo mySetMethod = null;
				Object srcCurrentValue = null;

				PropertyInfo pi = this.GetType().GetProperty(fieldname);
				if (pi != null)
				{
					myCurrentValue = pi.GetGetMethod().Invoke(this, null);
					mySetMethod = pi.GetSetMethod();
					srcCurrentValue = objSrc.GetType().GetProperty(fieldname).GetGetMethod().Invoke(objSrc, null);
				}
				else
				{
					// We must have a custom field, and it needs special treatment.
					Debug.Assert(m_cache.GetIsCustomField(flid));
					mySetMethod = null;
					string classname = mdc.GetOwnClsName(flid);
					string sView = classname + "_" + fieldname;
					switch (nType)
					{
					case (int)FieldType.kcptString:
					case (int)FieldType.kcptBigString:
						myCurrentValue = new TsStringAccessor(m_cache, m_hvo, (int)flid);
						srcCurrentValue = new TsStringAccessor(objSrc.Cache, objSrc.Hvo, (int)flid);
						break;
					case (int)FieldType.kcptMultiString:
					case (int)FieldType.kcptMultiBigString:
						myCurrentValue = new MultiStringAccessor(m_cache, m_hvo,
							(int)flid, sView);
						srcCurrentValue = new MultiStringAccessor(objSrc.Cache, objSrc.Hvo,
							(int)flid, sView);
						break;
					case (int)FieldType.kcptMultiUnicode:
					case (int)FieldType.kcptMultiBigUnicode:
						myCurrentValue = new MultiUnicodeAccessor(m_cache, m_hvo,
							(int)flid, sView);
						srcCurrentValue = new MultiUnicodeAccessor(objSrc.Cache, objSrc.Hvo,
							(int)flid, sView);
						break;
					}
				}
				if (srcCurrentValue == null)
					continue; // Nothing to merge.
				Debug.Assert(srcCurrentValue != null);

				/*
				 * NOTE: Each of the cases (except the exception, which can't be tested)
				 * is tested in the MergeObjectsTests class in the unit tests.
				 * If any additions are made, or if some currently unused cases are enabled,
				 * be sure to add them (or enable them) to that class, as well.
				 */
				switch (nType)
				{
					default:
						throw new ApplicationException("Unrecognized data type for merging: " + nType.ToString());

						/* 0 -> 9 */
					case (int)FieldType.kcptBoolean: // 1
					{
						// Can't be null, so we have to live with default of 0 (false).
						// 0 gets replaced with source data, if 1 (true).
						bool myBool = (bool)myCurrentValue;
						bool srcBool = (bool)srcCurrentValue;
						if (!myBool && srcBool)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcCurrentValue});
						}
						break;
					}
						//
					case (int)FieldType.kcptInteger: // 2 Fall through
					// Setter not implemented in FDO. case (int)FieldType.kcptGenDate: // 8
					{
						// Can't be null, so we have to live with default of 0.
						// Zero gets replaced with source data, if greater than 0.
						int myInt = (int)myCurrentValue;
						int srcInt = (int)srcCurrentValue;
						if (myInt == 0 && srcInt > 0)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcCurrentValue});
						}
						break;
					}
					case (int)FieldType.kcptTime: // 5
					{
						// If it is DateCreated, we won't even be here,
						// since we will have already skipped it.
						bool resetTime = false;
						DateTime srcTime = DateTime.Now;
						// If it is DateModified, always set it to 'now'.
						if (fieldname == "DateModified")
						{
							// Already using 'Now'.
							resetTime = true;
						}
						else
						{
						// Otherwise, a later source will replace an older target.
						DateTime myTime = (DateTime)myCurrentValue;
							srcTime = (DateTime)srcCurrentValue;
							resetTime = (myTime < srcTime);
						if (myTime < srcTime)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcTime});
						}
						}
						if (resetTime)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcTime});
						}
						break;
					}
					case (int)FieldType.kcptGuid: // 6
					{
						// May be null.
						Guid myGuidValue = (Guid)myCurrentValue;
						Guid srcGuidValue = (Guid)srcCurrentValue;
						if (myGuidValue == Guid.Empty && srcGuidValue != Guid.Empty)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcGuidValue});
							mySetMethod.Invoke(objSrc, new object[] {Guid.Empty});
						}
						break;
					}
					//case (int)FieldType.kcptImage: // 7 Fall through.
					case (int)FieldType.kcptBinary: // 8
					{
						if (myCurrentValue == null)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcCurrentValue});
						}
						break;
					}

					/* 13 -> 20 */
					case (int)FieldType.kcptString: // 13 Fall through
					case (int)FieldType.kcptBigString: // 17
					{
						if (MergeStringProp((int)flid, nType, objSrc, fLoseNoStringData, myCurrentValue, srcCurrentValue))
							break;
						TsStringAccessor myTsa = myCurrentValue as TsStringAccessor;
						myTsa.MergeString(srcCurrentValue as TsStringAccessor, fLoseNoStringData);
						break;
					}

					case (int)FieldType.kcptMultiString: // 14 Fall through.
					case (int)FieldType.kcptMultiBigString: // 18
					{
						if (MergeStringProp((int)flid, nType, objSrc, fLoseNoStringData, myCurrentValue, srcCurrentValue))
							break;
						MultiStringAccessor myMsa = myCurrentValue as MultiStringAccessor;
						myMsa.MergeAlternatives(srcCurrentValue as MultiStringAccessor, fLoseNoStringData);
						break;
					}

					case (int)FieldType.kcptUnicode: // 15 Fall through.
					case (int)FieldType.kcptBigUnicode: // 19
					{
						if (MergeStringProp((int)flid, nType, objSrc, fLoseNoStringData, myCurrentValue, srcCurrentValue))
							break;
						string myUCurrent = myCurrentValue as string;
						string srcUValue = srcCurrentValue as string;
						if ((myUCurrent == null || myUCurrent == String.Empty)
							&& srcUValue != String.Empty)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcUValue});
						}
						else if (fLoseNoStringData
							&& myUCurrent != null && myUCurrent != String.Empty
							&& srcUValue != null && srcUValue != String.Empty
							&& srcUValue != myUCurrent)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {myUCurrent + ' ' + srcUValue});
						}
						break;
					}

					case (int)FieldType.kcptMultiUnicode: // 16 Fall through
					case (int)FieldType.kcptMultiBigUnicode: // 20 This one isn't actually used yet, but I hope it is the same as the small MultiUnicode
					{
						if (MergeStringProp((int)flid, nType, objSrc, fLoseNoStringData, myCurrentValue, srcCurrentValue))
							break;
						MultiUnicodeAccessor myMua = myCurrentValue as MultiUnicodeAccessor;
						myMua.MergeAlternatives(srcCurrentValue as MultiUnicodeAccessor, fLoseNoStringData);
						break;
					}

					/* 23 -> 28 */
					case (int)FieldType.kcptOwningAtom:
					case (int)FieldType.kcptReferenceAtom: // 24
					{
						ICmObject srcObj = srcCurrentValue as ICmObject;
						ICmObject currentObj = myCurrentValue as ICmObject;
						if (myCurrentValue == null)
						{
							Debug.Assert(mySetMethod != null);
							mySetMethod.Invoke(this, new object[] {srcObj});
							break;
						}
						else if (fLoseNoStringData && nType == (int)FieldType.kcptOwningAtom && srcObj != null
							&& currentObj.GetType() == srcObj.GetType())
						{
							// merge the child objects.
							currentObj.MergeObject(srcObj, true);
						}
						break;
					}

					case (int)FieldType.kcptOwningCollection: // 25 Fall through, since the collection class knows how to merge itself properly.
					case (int)FieldType.kcptReferenceCollection: // 26
					{
						PropertyInfo piCol = FdoVector<ICmObject>.HvoArrayPropertyInfo(srcCurrentValue);
						MethodInfo myAddMethod = FdoCollection<ICmObject>.AddIntMethodInfo(myCurrentValue);
						foreach (int hvo in (int[])piCol.GetGetMethod().Invoke(srcCurrentValue, null))
						{
							myAddMethod.Invoke(myCurrentValue, new object[] { hvo });
						}
						break;
					}

					case (int)FieldType.kcptOwningSequence: // 27 Fall through, since the collection class knows how to merge itself properly.
					case (int)FieldType.kcptReferenceSequence: // 28
					{
						PropertyInfo piCol = FdoVector<ICmObject>.HvoArrayPropertyInfo(srcCurrentValue);
						MethodInfo myAppendMethod = FdoSequence<ICmObject>.AppendIntMethodInfo(myCurrentValue);
						foreach (int hvo in (int[])piCol.GetGetMethod().Invoke(srcCurrentValue, null))
						{
							myAppendMethod.Invoke(myCurrentValue, new object[] { hvo });
						}
						break;
					}
				}
			}

			// Now move all incoming references.
			CmObject.ReplaceReferences(m_cache, objSrc, this);
			objSrc.DeleteUnderlyingObject();
		}