text: import uuid
  
  from office365.runtime.queries.create_entity_query import CreateEntityQuery
  from office365.runtime.queries.service_operation_query import ServiceOperationQuery
  from office365.runtime.resource_path_service_operation import ResourcePathServiceOperation
  from office365.sharepoint.base_entity_collection import BaseEntityCollection
  from office365.sharepoint.fields.field import Field
  from office365.sharepoint.fields.field_creation_information import FieldCreationInformation
  from office365.sharepoint.fields.field_type import FieldType
  from office365.sharepoint.fields.xmlSchemaFieldCreationInformation import XmlSchemaFieldCreationInformation
  
  
  class FieldCollection(BaseEntityCollection):
      """Represents a collection of Field resource."""
  
      def __init__(self, context, resource_path=None, parent=None):
          super(FieldCollection, self).__init__(context, Field, resource_path, parent)
  
      def add_url_field(self, title, description=None):
          """
          Adds Url field
  
          :param str title:
          :param str or None description:
          :return:
          """
          create_field_info = FieldCreationInformation(title=title,
                                                       description=description,
                                                       field_type_kind=FieldType.URL)
          return self.add(create_field_info)
  
      def add_lookup_field(self, title, lookup_list_id, lookup_field_name, allow_multiple_values=False):
          """
          Adds Lookup field
  
          :param bool allow_multiple_values:
          :param str lookup_field_name:
          :param str lookup_list_id:
          :param str title:
          """
          if allow_multiple_values:
              field_schema = '''
                          <Field Type="LookupMulti" Mult="TRUE" DisplayName="{title}" Required="FALSE" Hidden="TRUE" \
                          ShowField="{lookup_field_name}" List="{{{lookup_list_id}}}" StaticName="{title}" Name="{title}">
                          </Field>
                          '''.format(title=title, lookup_field_name=lookup_field_name, lookup_list_id=lookup_list_id)
              target_field = self.create_field_as_xml(field_schema)
          else:
              create_field_info = FieldCreationInformation(title=title,
                                                           lookup_list_id=lookup_list_id,
                                                           lookup_field_name=lookup_field_name,
                                                           field_type_kind=FieldType.Lookup)
              target_field = self.add_field(create_field_info)
          return target_field
  
      def add_choice_field(self, title, values, multiple_values=False):
          """
          Adds Choice field
  
          :param bool multiple_values:
          :param list[str] values:
          :param str title:
          """
          fld_type = FieldType.MultiChoice if multiple_values else FieldType.Choice
          create_field_info = FieldCreationInformation(title, fld_type)
          [create_field_info.Choices.add(choice) for choice in values]
          return self.add_field(create_field_info)
  
      def add_user_field(self):
          pass
  
      def add_dependent_lookup_field(self, displayName, primaryLookupField, lookupField):
          """Adds a secondary lookup field to a field (2) collection.
          A reference (3) to the SP.Field that was added is returned.
          :param str lookupField: Name of the field (2) from the target list (1) to include data from.
          :param Field primaryLookupField: Main lookup field to associate the dependent lookup field with.
              A dependent lookup field will include data from the list item referred to from the instance of the main
              lookup field.
          :param str displayName: Title of the added field
          """
          return_field = Field(self.context)
          self.add_child(return_field)
          parameters = {
              "displayName": displayName,
              "primaryLookupField": primaryLookupField,
              "lookupField": lookupField
          }
          qry = ServiceOperationQuery(self, "AddDependentLookupField", None, parameters, None, return_field)
          self.context.add_query(qry)
          return return_field
  
      def add(self, field_create_information):
          """Adds a fields to the fields collection.
  
          :type field_create_information: office365.sharepoint.fields.field_creation_information.FieldCreationInformation
          """
          field = Field.create_field_from_type(self.context, field_create_information)
          self.add_child(field)
          qry = CreateEntityQuery(self, field, field)
          self.context.add_query(qry)
          return field
  
      def add_field(self, parameters):
          """Adds a fields to the fields collection.
  
          :type parameters: office365.sharepoint.fields.field_creation_information.FieldCreationInformation
          """
          field = Field(self.context)
          self.add_child(field)
          qry = ServiceOperationQuery(self, "AddField", None, parameters, "parameters", field)
          self.context.add_query(qry)
          return field
  
      def create_taxonomy_field(self, name, ssp_id, term_set_id, anchor_id="00000000-0000-0000-0000-000000000000",
                                field_id=None, text_field_id=None, web_id=None, list_id=None):
  
          target_field = Field(self.context)
          field_params = {
              "name": name,
              "ssp_id": ssp_id,
              "term_set_id": term_set_id,
              "anchor_id": anchor_id,
              "field_id": field_id,
              "text_field_id": text_field_id,
              "list_id": list_id,
              "web_id": web_id,
              "target_field": target_field
          }
          if field_id is None:
              field_params["field_id"] = str(uuid.uuid1())
  
          def _create_taxonomy_field_inner():
              from office365.sharepoint.lists.list import List
              if isinstance(self._parent, List):
                  parent_list = self._parent
  
                  def _list_loaded():
                      field_params["web_id"] = parent_list.parent_web.properties["Id"]
                      field_params["list_id"] = parent_list.properties["Id"]
                      self._build_taxonomy_field_query(**field_params)
  
                  self._parent.ensure_properties(["Id", "ParentWeb"], _list_loaded)
              else:
  
                  def _web_loaded():
                      field_params["web_id"] = self.context.web.properties["Id"]
                      self._build_taxonomy_field_query(**field_params)
  
                  self.context.web.ensure_property("Id", _web_loaded)
  
          if text_field_id is None:
              text_field_name = "{name}".format(name=uuid.uuid4().hex)
              text_field_schema = '''
              <Field Type="Note" DisplayName="{name}_0" Hidden="TRUE" CanBeDeleted="TRUE" ShowInViewForms="FALSE"
                     StaticName="{text_field_name}" Name="{text_field_name}">
              </Field>
              '''.format(name=name, text_field_name=text_field_name)
              text_field = self.create_field_as_xml(text_field_schema)
  
              def _after_text_field_created(resp):
                  field_params["text_field_id"] = text_field.properties["Id"]
                  _create_taxonomy_field_inner()
  
              self.context.after_execute(_after_text_field_created, True)
          else:
              _create_taxonomy_field_inner()
  
          return target_field
  
      def _build_taxonomy_field_query(self, name, ssp_id, term_set_id, anchor_id,
                                      field_id=None, text_field_id=None, web_id=None, list_id=None,
                                      target_field=None):
          """
  
          :param str text_field_id: Text Field Id
          :param str web_id: Web Id
          :param str list_id: List Id
          :param str field_id: Field Id
          :type name: str
          :type ssp_id: str
          :type term_set_id: str
          :type anchor_id: str
          :type target_field: Field
          """
  
          list_attr = 'List="{{{list_id}}}"'.format(list_id=list_id) if list_id is not None else ""
  
          schema_xml = '''
  <Field Type="TaxonomyFieldType" DisplayName="{name}" {list_attr}
         WebId="{web_id}" Required="FALSE" EnforceUniqueValues="FALSE"
         ID="{{{field_id}}}" StaticName="{name}" Name="{name}">
      <Default/>
      <Customization>
          <ArrayOfProperty>
              <Property>
                  <Name>SspId</Name>
                  <Value xmlns:q1="http://www.w3.org/2001/XMLSchema" p4:type="q1:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{ssp_id}
                  </Value>
              </Property>
              <Property>
                  <Name>GroupId</Name>
              </Property>
              <Property>
                  <Name>TermSetId</Name>
                  <Value xmlns:q2="http://www.w3.org/2001/XMLSchema" p4:type="q2:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{term_set_id}
                  </Value>
              </Property>
              <Property>
                  <Name>AnchorId</Name>
                  <Value xmlns:q3="http://www.w3.org/2001/XMLSchema" p4:type="q3:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{anchor_id}
                  </Value>
              </Property>
              <Property>
                  <Name>UserCreated</Name>
                  <Value xmlns:q4="http://www.w3.org/2001/XMLSchema" p4:type="q4:boolean"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
                  </Value>
              </Property>
              <Property>
                  <Name>Open</Name>
                  <Value xmlns:q5="http://www.w3.org/2001/XMLSchema" p4:type="q5:boolean"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">true
                  </Value>
              </Property>
              <Property>
                  <Name>TextField</Name>
                  <Value xmlns:q6="http://www.w3.org/2001/XMLSchema" p4:type="q6:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{{{text_field_id}}}
                  </Value>
              </Property>
              <Property>
                  <Name>IsPathRendered</Name>
                  <Value xmlns:q7="http://www.w3.org/2001/XMLSchema" p4:type="q7:boolean"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
                  </Value>
              </Property>
              <Property>
                  <Name>IsKeyword</Name>
                  <Value xmlns:q8="http://www.w3.org/2001/XMLSchema" p4:type="q8:boolean"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
                  </Value>
              </Property>
              <Property>
                  <Name>TargetTemplate</Name>
              </Property>
              <Property>
                  <Name>CreateValuesInEditForm</Name>
                  <Value xmlns:q9="http://www.w3.org/2001/XMLSchema" p4:type="q9:boolean"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
                  </Value>
              </Property>
              <Property>
                  <Name>FilterAssemblyStrongName</Name>
                  <Value xmlns:q10="http://www.w3.org/2001/XMLSchema" p4:type="q10:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy,
                      Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
                  </Value>
              </Property>
              <Property>
                  <Name>FilterClassName</Name>
                  <Value xmlns:q11="http://www.w3.org/2001/XMLSchema" p4:type="q11:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy.TaxonomyField
                  </Value>
              </Property>
              <Property>
                  <Name>FilterMethodName</Name>
                  <Value xmlns:q12="http://www.w3.org/2001/XMLSchema" p4:type="q12:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">GetFilteringHtml
                  </Value>
              </Property>
              <Property>
                  <Name>FilterJavascriptProperty</Name>
                  <Value xmlns:q13="http://www.w3.org/2001/XMLSchema" p4:type="q13:string"
                         xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">FilteringJavascript
                  </Value>
              </Property>
          </ArrayOfProperty>
      </Customization>
  </Field>
  '''.format(list_id=list_id, name=name, list_attr=list_attr, web_id=web_id, field_id=field_id, ssp_id=ssp_id,
             term_set_id=term_set_id, anchor_id=anchor_id, text_field_id=text_field_id)
  
          field_schema = XmlSchemaFieldCreationInformation(schema_xml)
          self._create_field_as_xml_query(field_schema, target_field)
  
      def create_field_as_xml(self, schema_xml):
          """
          :type schema_xml: str
          """
          field = Field(self.context)
          field_schema = XmlSchemaFieldCreationInformation(schema_xml)
          self._create_field_as_xml_query(field_schema, field)
          return field
  
      def _create_field_as_xml_query(self, schema_xml, field):
          """
          :type field: Field
          :type schema_xml: XmlSchemaFieldCreationInformation
          """
          self.add_child(field)
          qry = ServiceOperationQuery(self, "CreateFieldAsXml", None, schema_xml, "parameters", field)
          self.context.add_query(qry)
          return field
  
      def get_by_id(self, _id):
          """Gets the fields with the specified ID."""
          return Field(self.context, ResourcePathServiceOperation("getById", [_id], self.resource_path))
  
      def get_by_internal_name_or_title(self, name_title):
          """Returns the first field (2) in the collection based on the internal name or the title specified
          by the parameter.
  
          :param str name_title:  The title or internal name to look up the field (2) by.
          """
          return Field(self.context,
                       ResourcePathServiceOperation("getByInternalNameOrTitle", [name_title], self.resource_path))
  
      def get_by_title(self, title):
          """Returns the first fields object in the collection based on the title of the specified fields.
  
          :type title: str
          """
          return Field(self.context,
                       ResourcePathServiceOperation("getByTitle", [title], self.resource_path))
  