Exemple #1
0
        private static ServiceElement CreateEnglishUtf8PrimaryLanguageServiceElement()
        {
            ServiceElement englishUtf8PrimaryLanguage = LanguageBaseItem.CreateElementSequenceFromList(
                new LanguageBaseItem[] { LanguageBaseItem.CreateEnglishUtf8PrimaryLanguageItem() });

            return(englishUtf8PrimaryLanguage);
        }
Exemple #2
0
 public static string GetName(ServiceAttributeId id, Type[] attributeIdDefiningClasses,
                              LanguageBaseItem[] langBaseList, out LanguageBaseItem applicableLangBase)
 {
     if (attributeIdDefiningClasses == null)
     {
         throw new ArgumentNullException("attributeIdDefiningClasses");
     }
     //HACK if (langBaseList == null) {
     if (langBaseList == null)
     {
         throw new ArgumentNullException("langBaseList");
     }
     // Foreach: class that defines AttributeId enum.
     //    Foreach: AttributeId enum field in that class.
     //       Check whether its value matches the one being searched for, and return if so.
     //
     foreach (Type curDefiningType in attributeIdDefiningClasses)
     {
         //if (!(curDefiningType.IsSealed && curDefiningType.IsAbstract)) { }
         //----
         System.Reflection.FieldInfo[] fieldArr = curDefiningType.GetFields(
             // With Public, no permissions required, apparently.
             System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
         foreach (System.Reflection.FieldInfo curField in fieldArr)
         {
             if (curField.FieldType == typeof(ServiceAttributeId))
             {
                 // A multi-language attribute or a just a normal one?
                 Object[] dotnetAtttrs = curField.GetCustomAttributes(typeof(StringWithLanguageBaseAttribute), false);
                 if (dotnetAtttrs.Length != 0)
                 {
                     System.Diagnostics.Debug.Assert(dotnetAtttrs.Length == 1,
                                                     "Not that it's a problem for us at all, but that Attribute should only be applied once.");
                     string name = _GetNameIfMatchesMultiLang(id, curField, langBaseList, out applicableLangBase);
                     if (name != null)
                     {
                         return(name);
                     }
                 }
                 else
                 {
                     // No just a normal Attribute, not language base offsetting.
                     string name = _GetNameIfMatches(id, curField);
                     if (name != null)
                     {
                         applicableLangBase = null;
                         return(name);
                     }
                 } //else
             }
         }         //foreach
     }             //foreach
     // Not found.
     applicableLangBase = null;
     return(null);
 }
Exemple #3
0
        public String GetPrimaryMultiLanguageStringAttributeById(ServiceAttributeId id)
        {
            LanguageBaseItem lang = this.GetPrimaryLanguageBaseItem();

            if (lang == null)
            {
                lang = LanguageBaseItem.CreateEnglishUtf8PrimaryLanguageItem();
            }
            return(GetMultiLanguageStringAttributeById(id, lang));
        }
Exemple #4
0
        /// <summary>
        /// Returns the attribute with the given ID and natural language.
        /// </summary>
        /// -
        /// <param name="id">The id of the service attribute to locate, as a
        /// <see cref="T:InTheHand.Net.Bluetooth.ServiceAttributeId"/>.</param>
        /// <param name="language">
        /// Which multi-language version of the string attribute to locate.
        /// </param>
        /// -
        /// <returns>A <see cref="T:InTheHand.Net.Bluetooth.ServiceAttribute"/> holding
        /// the attribute with the specified ID and language.
        /// Is never <see langword="null"/>.
        /// </returns>
        /// -
        /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">
        /// There is no attribute with the given Id with the given language base in the record.
        /// </exception>
        public ServiceAttribute GetAttributeById(ServiceAttributeId id, LanguageBaseItem language)
        {
            if (language == null)
            {
                throw new ArgumentNullException("language");
            }
            ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
            ServiceAttribute   attr     = GetAttributeById(actualId);

            System.Diagnostics.Debug.Assert(attr != null);
            return(attr);
        }
Exemple #5
0
        //--------------------------------------------------------------
        /// <summary>
        /// Determines whether a TextString service attribute with the specified ID
        /// and natural language
        /// is in the List.
        /// </summary>
        /// -
        /// <param name="id">The id of the service attribute to locate, as a
        /// <see cref="T:InTheHand.Net.Bluetooth.ServiceAttributeId"/>.</param>
        /// <param name="language">
        /// Which multi-language version of the string attribute to locate.
        /// </param>
        /// -
        /// <returns>true if item is found in the record; otherwise, false. </returns>
        public bool Contains(ServiceAttributeId id, LanguageBaseItem language)
        {
            if (language == null)
            {
                throw new ArgumentNullException("language");
            }
            ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
            ServiceAttribute   tmp;
            bool found = TryGetAttributeById(actualId, out tmp);

            return(found && (tmp.Value.ElementType == ElementType.TextString));
        }
Exemple #6
0
        public String GetMultiLanguageStringAttributeById(ServiceAttributeId id, LanguageBaseItem language)
        {
            if (language == null)
            {
                throw new ArgumentNullException("language");
            }
            ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
            ServiceAttribute   attr     = GetAttributeById(actualId);
            ServiceElement     element  = attr.Value;
            // (No need to check that element is of type TextString, that's handled inside the following).
            String str = element.GetValueAsString(language);

            return(str);
        }
Exemple #7
0
        /// <summary>
        /// Get the value of the <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>,
        /// when it is encoded as specified by the given IETF Charset identifer.
        /// </summary>
        /// -
        /// <remarks>
        /// Note that a strict decoding of the string is carried out
        /// (except on the NETCF where it is not supported).
        /// Thus if the value is not in the specified encoding, or has been
        /// encoded incorrectly, then an error will occur.
        /// </remarks>
        /// -
        /// <returns>
        /// A <see cref="T:System.String"/> holding the value of the
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>
        /// from the service element.
        /// </returns>
        /// -
        /// <exception cref="T:System.InvalidOperationException">
        /// The service element is not of type
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>.
        /// </exception>
        /// <exception cref="T:System.Text.DecoderFallbackException">
        /// If the value in the service element is not a valid string in the given encoding.
        /// </exception>
        public String GetValueAsString(LanguageBaseItem languageBase)
        {
            if (languageBase == null)
            {
                throw new ArgumentNullException("languageBase");
            }
            Encoding enc = languageBase.GetEncoding();

#if !PocketPC
            if (_strictStringDecoding)
            {
                enc = (Encoding)enc.Clone();                          //not in NETCFv1
                enc.DecoderFallback = new DecoderExceptionFallback(); // not in NETCF.
                // Not intended for encoding, but set it anyway.
                enc.EncoderFallback = new EncoderExceptionFallback(); // not in NETCF.
            }
#endif
            return(GetValueAsString(enc));
        }
Exemple #8
0
        //--------------------------------------------------------------

        /// <summary>
        /// Gets the list of LanguageBaseAttributeId items in the service record.
        /// </summary>
        /// -
        /// <remarks>
        /// See also <see cref="M:InTheHand.Net.Bluetooth.ServiceRecord.GetPrimaryLanguageBaseItem"/>.
        /// </remarks>
        /// -
        /// <returns>
        /// An array of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>.
        /// An array of length zero is returned if the service record contains no such attribute.
        /// </returns>
        /// -
        /// <seealso cref="M:InTheHand.Net.Bluetooth.ServiceRecord.GetPrimaryLanguageBaseItem"/>
        public LanguageBaseItem[] GetLanguageBaseList()
        {
            if (!Contains(InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList))
            {
                return(new LanguageBaseItem[0]);
            }
            ServiceAttribute attr = GetAttributeById(InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList);

            if (attr.Value.ElementType != ElementType.ElementSequence)
            {
                return(new LanguageBaseItem[0]);
            }
            LanguageBaseItem[] langList;
            try {
                langList = LanguageBaseItem.ParseListFromElementSequence(attr.Value);
            } catch (System.Net.ProtocolViolationException) {
                return(new LanguageBaseItem[0]);
            }
            return(langList);
        }
Exemple #9
0
 _GetNameIfMatchesMultiLang(ServiceAttributeId id, System.Reflection.FieldInfo curField,
                            LanguageBaseItem[] langBaseList, out LanguageBaseItem applicableLangBase)
 {
     foreach (LanguageBaseItem curBaseItem in langBaseList)
     {
         ServiceAttributeId baseOffset = curBaseItem.AttributeIdBase;
         ServiceAttributeId realId     = id;
         unchecked { realId -= baseOffset; }
         // (Theorically 'unchecked' above could allow wrong results but
         // only 0, 1, and 2, have "[StringWithLanguageBaseAttribute]",
         // and it would be an odd record that could produce those
         // integers for wrong reasons).
         string fieldName = _GetNameIfMatches(realId, curField);
         if (fieldName != null)
         {
             applicableLangBase = curBaseItem;
             return(fieldName);
         }
     }//foreach
     applicableLangBase = null;
     return(null);
 }
Exemple #10
0
        //--------------------
        //

        /// <summary>
        /// Gets the list of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>
        /// items in the service record.
        /// </summary>
        /// -
        /// <param name="elementSequence">
        /// A <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> holding the
        /// data from the
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList"/>
        /// attribute.
        /// </param>
        /// -
        /// <returns>
        /// An array of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>.
        /// An array length zero is returned if the service record contains no such attribute.
        /// </returns>
        /// -
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="elementSequence"/> is not of type
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementType.ElementSequence"/>.
        /// </exception>
        /// <exception cref="T:System.Net.ProtocolViolationException">
        /// The element sequence contains incorrectly formatted or invalid content,
        /// for example it contains the wrong element data types, or doesn't contain
        /// the elements in groups of three as required.
        /// </exception>
        public static LanguageBaseItem[] ParseListFromElementSequence(ServiceElement elementSequence)
        {
            if (elementSequence.ElementType != ElementType.ElementSequence)
            {
                throw new ArgumentException(ErrorMsgLangBaseListParseNotSequence);
            }
#if V1
            IList elementList = elementSequence.GetValueAsElementList();
#else
            IList <ServiceElement> elementList = elementSequence.GetValueAsElementList();
#endif
            int       numElements     = elementList.Count;
            const int ElementsPerItem = 3;
            if (numElements == 0 || (numElements % ElementsPerItem) != 0)
            {
                throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotInThrees);
            }
            int numItems             = numElements / ElementsPerItem;
            LanguageBaseItem[] items = new LanguageBaseItem[numItems];
            for (int i = 0; i < numItems; ++i)
            {
                // Casts are for the non-Generic version.
                ServiceElement e1Lang   = (ServiceElement)elementList[i * ElementsPerItem];
                ServiceElement e2EncId  = (ServiceElement)elementList[i * ElementsPerItem + 1];
                ServiceElement e3BaseId = (ServiceElement)elementList[i * ElementsPerItem + 2];
                if (e1Lang.ElementType != ElementType.UInt16 || e2EncId.ElementType != ElementType.UInt16 || e3BaseId.ElementType != ElementType.UInt16)
                {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotU16);
                }
                if ((UInt16)e3BaseId.Value == 0)
                {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseBaseInvalid);
                }
                LanguageBaseItem item = new LanguageBaseItem(
                    (UInt16)e1Lang.Value, (UInt16)e2EncId.Value, (UInt16)e3BaseId.Value);
                items[i] = item;
            }
            return(items);
        }
        //--------------------

        /// <summary>
        /// Create a data element for the 
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList"/>
        /// attribute
        /// from the list of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>
        /// </summary>
        /// -
        /// <param name="list">
        /// An array of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>.
        /// </param>
        /// -
        /// <returns>
        /// A <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> holding the 
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList"/>
        /// element, to be added to a generally the 
        /// <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/>.
        /// </returns>
        public static ServiceElement CreateElementSequenceFromList(LanguageBaseItem[] list)
        {
#if !  V1
            IList<ServiceElement> children = new List<ServiceElement>();
#else
            IList children = new ArrayList();
#endif
            foreach (LanguageBaseItem item in list) {
                //String lang = item.NaturalLanguage;
                //UInt16 langNumerical = GetLanguageIdStringAsBytes(lang);
                UInt16 langNumerical = item.NaturalLanguageAsUInt16;
                children.Add(new ServiceElement(ElementType.UInt16,
                    (UInt16)langNumerical));
                children.Add(new ServiceElement(ElementType.UInt16,
                    (UInt16)item.EncodingId));
                children.Add(new ServiceElement(ElementType.UInt16,
                    (UInt16)item.AttributeIdBase));
            }
            return new ServiceElement(ElementType.ElementSequence,
                children);
        }
        //--------------------
        //

        /// <summary>
        /// Gets the list of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>
        /// items in the service record.
        /// </summary>
        /// -
        /// <param name="elementSequence">
        /// A <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> holding the 
        /// data from the 
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList"/>
        /// attribute.
        /// </param>
        /// -
        /// <returns>
        /// An array of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>.  
        /// An array length zero is returned if the service record contains no such attribute.
        /// </returns>
        /// -
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="elementSequence"/> is not of type 
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementType.ElementSequence"/>.
        /// </exception>
        /// <exception cref="T:System.Net.ProtocolViolationException">
        /// The element sequence contains incorrectly formatted or invalid content,
        /// for example it contains the wrong element data types, or doesn't contain
        /// the elements in groups of three as required.
        /// </exception>
        public static LanguageBaseItem[] ParseListFromElementSequence(ServiceElement elementSequence)
        {
            if (elementSequence.ElementType != ElementType.ElementSequence) {
                throw new ArgumentException(ErrorMsgLangBaseListParseNotSequence);
            }
#if V1
            IList  elementList = elementSequence.GetValueAsElementList();
#else
            IList<ServiceElement> elementList = elementSequence.GetValueAsElementList();
#endif
            int numElements = elementList.Count;
            const int ElementsPerItem = 3;
            if (numElements == 0 || (numElements % ElementsPerItem) != 0) {
                throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotInThrees);
            }
            int numItems = numElements / ElementsPerItem;
            LanguageBaseItem[] items = new LanguageBaseItem[numItems];
            for (int i = 0; i < numItems; ++i) {
                // Casts are for the non-Generic version.
                ServiceElement e1Lang = (ServiceElement)elementList[i * ElementsPerItem];
                ServiceElement e2EncId = (ServiceElement)elementList[i * ElementsPerItem + 1];
                ServiceElement e3BaseId = (ServiceElement)elementList[i * ElementsPerItem + 2];
                if (e1Lang.ElementType != ElementType.UInt16 || e2EncId.ElementType != ElementType.UInt16 || e3BaseId.ElementType != ElementType.UInt16) {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotU16);
                }
                if ((UInt16)e3BaseId.Value == 0) {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseBaseInvalid);
                }
                LanguageBaseItem item = new LanguageBaseItem(
                        (UInt16)e1Lang.Value, (UInt16)e2EncId.Value, (UInt16)e3BaseId.Value);
                items[i] = item;
            }
            return items;
        }
        private static void DumpString(System.IO.TextWriter writer, int depth, ServiceElement element, LanguageBaseItem langBase)
        {
            if (langBase != null)
            {
                try {
                    String value = element.GetValueAsString(langBase);
                    writer.WriteLine("{0}: [{1}] '{2}'", element.ElementType, langBase.NaturalLanguage, value);
                } catch (NotSupportedException ex) {
                    System.Diagnostics.Debug.Assert(ex.Message != null);
                    System.Diagnostics.Debug.Assert(ex.Message.StartsWith("Unrecognized character encoding"));
                    writer.WriteLine("{0}: Failure: {1}", element.ElementType, ex.Message);
                }
            }
            else
            {
                try {
                    String hack = element.GetValueAsStringUtf8();
                    if (hack.IndexOf((char)0) != -1)
                    {
                        throw new
#if !WinCE
                              System.Text.DecoderFallbackException
#else
                              // NETCF doesn't support DecoderFallbackException this what the docs say.
                              ArgumentException
#endif
                                  ("EEEEE contains nulls!  UTF-16?!");
                    }
                    writer.WriteLine("{0} (guessing UTF-8): '{1}'", element.ElementType, hack);
                } catch (
                    // TODO ! What exception thrown by UTF8Encoding on NETCF?
#if !WinCE
                    System.Text.DecoderFallbackException
#else
                    // NETCF doesn't support DecoderFallbackException this what the docs say.
                    ArgumentException
#endif
                    ) {
                    writer.WriteLine("{0} (Unknown/bad encoding):", element.ElementType);
                    var arr = (byte[])element.Value;
                    var str = BitConverter.ToString(arr);
                    WritePrefix(writer, depth); // On another line.
                    writer.WriteLine("Length: {0}, >>{1}<<", arr.Length, str);
                }//try
            }
        }
 public String GetMultiLanguageStringAttributeById(ServiceAttributeId id, LanguageBaseItem language)
 {
     if (language == null) { throw new ArgumentNullException("language"); }
     ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
     ServiceAttribute attr = GetAttributeById(actualId);
     ServiceElement element = attr.Value;
     // (No need to check that element is of type TextString, that's handled inside the following).
     String str = element.GetValueAsString(language);
     return str;
 }
Exemple #15
0
     _GetNameIfMatchesMultiLang(ServiceAttributeId id, System.Reflection.FieldInfo curField,
     LanguageBaseItem[] langBaseList, out LanguageBaseItem applicableLangBase)
 {
     foreach (LanguageBaseItem curBaseItem in langBaseList) {
         ServiceAttributeId baseOffset = curBaseItem.AttributeIdBase;
         ServiceAttributeId realId = id;
         realId -= baseOffset;
         string fieldName = _GetNameIfMatches(realId, curField);
         if (fieldName != null) {
             applicableLangBase = curBaseItem;
             return fieldName;
         }
     }//foreach
     applicableLangBase = null;
     return null;
 }
        /// <summary>
        /// Get the value of the <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>,
        /// when it is encoded as specified by the given IETF Charset identifer.
        /// </summary>
        /// -
        /// <remarks>
        /// Note that a strict decoding of the string is carried out 
        /// (except on the NETCF where it is not supported). 
        /// Thus if the value is not in the specified encoding, or has been
        /// encoded incorrectly, then an error will occur.
        /// </remarks>
        /// -
        /// <returns>
        /// A <see cref="T:System.String"/> holding the value of the 
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>
        /// from the service element.
        /// </returns>
        /// -
        /// <exception cref="T:System.InvalidOperationException">
        /// The service element is not of type 
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementTypeDescriptor.TextString"/>.
        /// </exception>
        /// <exception cref="T:System.Text.DecoderFallbackException">
        /// If the value in the service element is not a valid string in the given encoding.
        /// </exception>
        public String GetValueAsString(LanguageBaseItem languageBase)
        {
            if (languageBase == null) {
                throw new ArgumentNullException("languageBase");
            }
            Encoding enc = languageBase.GetEncoding();
#if ! PocketPC
            if (m_strictStringDecoding) {
                enc = (Encoding)enc.Clone(); //not in NETCFv1
                enc.DecoderFallback = new DecoderExceptionFallback(); // not in NETCF.
                // Not intended for encoding, but set it anyway.
                enc.EncoderFallback = new EncoderExceptionFallback(); // not in NETCF.
            }
#endif
            return GetValueAsString(enc);
        }
Exemple #17
0
 public static string GetName(ServiceAttributeId id, Type[] attributeIdDefiningClasses,
     LanguageBaseItem[] langBaseList, out LanguageBaseItem applicableLangBase)
 {
     if (attributeIdDefiningClasses == null) {
         throw new ArgumentNullException("attributeIdDefiningClasses");
     }
     //HACK if (langBaseList == null) {
     if (langBaseList == null) {
         throw new ArgumentNullException("langBaseList");
     }
     // Foreach: class that defines AttributeId enum.
     //    Foreach: AttributeId enum field in that class.
     //       Check whether its value matches the one being searched for, and return if so.
     //
     foreach (Type curDefiningType in attributeIdDefiningClasses) {
         //if (!(curDefiningType.IsSealed && curDefiningType.IsAbstract)) { }
         //----
         System.Reflection.FieldInfo[] fieldArr = curDefiningType.GetFields(
             // With Public, no permissions required, apparently.
             System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
         foreach (System.Reflection.FieldInfo curField in fieldArr) {
             if (curField.FieldType == typeof(ServiceAttributeId)) {
                 // A multi-language attribute or a just a normal one?
                 Object[] dotnetAtttrs = curField.GetCustomAttributes(typeof(StringWithLanguageBaseAttribute), false);
                 if (dotnetAtttrs.Length != 0) {
                     System.Diagnostics.Debug.Assert(dotnetAtttrs.Length == 1,
                         "Not that it's a problem for us at all, but that Attribute should only be applied once.");
                     string name = _GetNameIfMatchesMultiLang(id, curField, langBaseList, out applicableLangBase);
                     if (name != null) {
                         return name;
                     }
                 } else {
                     // No just a normal Attribute, not language base offsetting.
                     string name = _GetNameIfMatches(id, curField);
                     if (name != null) {
                         applicableLangBase = null;
                         return name;
                     }
                 }//else
             }
         }//foreach
     }//foreach
     // Not found.
     applicableLangBase = null;
     return null;
 }
 //--------------------------------------------------------------
 /// <summary>
 /// Determines whether a TextString service attribute with the specified ID 
 /// and natural language 
 /// is in the List.
 /// </summary>
 /// -
 /// <param name="id">The id of the service attribute to locate, as a 
 /// <see cref="T:InTheHand.Net.Bluetooth.ServiceAttributeId"/>.</param>
 /// <param name="language">
 /// Which multi-language version of the string attribute to locate.
 /// </param>
 /// -
 /// <returns>true if item is found in the record; otherwise, false. </returns>
 public bool Contains(ServiceAttributeId id, LanguageBaseItem language)
 {
     if (language == null) { throw new ArgumentNullException("language"); }
     ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
     ServiceAttribute tmp;
     bool found = TryGetAttributeById(actualId, out tmp);
     return found && (tmp.Value.ElementType == ElementType.TextString);
 }
        private static void DumpString(System.IO.TextWriter writer, int depth, ServiceElement element, LanguageBaseItem langBase)
        {
            if (langBase != null) {
                try {
                    String value = element.GetValueAsString(langBase);
                    writer.WriteLine("{0}: [{1}] '{2}'", element.ElementType, langBase.NaturalLanguage, value);
                } catch (NotSupportedException ex) {
                    System.Diagnostics.Debug.Assert(ex.Message != null);
                    System.Diagnostics.Debug.Assert(ex.Message.StartsWith("Unrecognized character encoding"));
                    writer.WriteLine("{0}: Failure: {1}", element.ElementType, ex.Message);
                }
            } else {
                try {
                    String hack = element.GetValueAsStringUtf8();
                    writer.WriteLine("{0} (guessing UTF-8): '{1}'", element.ElementType, hack);
                } catch (
                    // TODO ! What exception thrown by UTF8Encoding on NETCF?
#if ! WinCE
                    System.Text.DecoderFallbackException
#else
                    // NETCF doesn't support DecoderFallbackException this what the docs say.
                    ArgumentException
#endif
                ) {
                    writer.WriteLine("{0} (Unknown/bad encoding):", element.ElementType);
                }//try
            }
        }
 /// <summary>
 /// Returns the attribute with the given ID and natural language.
 /// </summary>
 /// -
 /// <param name="id">The id of the service attribute to locate, as a 
 /// <see cref="T:InTheHand.Net.Bluetooth.ServiceAttributeId"/>.</param>
 /// <param name="language">
 /// Which multi-language version of the string attribute to locate.
 /// </param>
 /// -
 /// <returns>A <see cref="T:InTheHand.Net.Bluetooth.ServiceAttribute"/> holding 
 /// the attribute with the specified ID and language.
 /// Is never <see langword="null"/>.
 /// </returns>
 /// -
 /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">
 /// There is no attribute with the given Id with the given language base in the record.
 /// </exception>
 public ServiceAttribute GetAttributeById(ServiceAttributeId id, LanguageBaseItem language)
 {
     if (language == null) { throw new ArgumentNullException("language"); }
     ServiceAttributeId actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
     ServiceAttribute attr = GetAttributeById(actualId);
     System.Diagnostics.Debug.Assert(attr != null);
     return attr;
 }