 {\n" +
                "  document campaign {\n" +
                "  }\n" +
                "}";
        String salespersonSdContent =
                "search salesperson {\n" +
                "  document salesperson {\n" +
                "  }\n" +
                "}";
        String adSdContent =
                "search ad {\n" +
                "  document ad {\n" +
                "    field campaign_ref type reference<campaign> { indexing: attribute }\n" +
                "    field salesperson_ref type reference<salesperson> { indexing: attribute }\n" +
                "  }\n" +
                "}";
        builder.importString(campaignSdContent);
        builder.importString(salespersonSdContent);
        builder.importString(adSdContent);
        builder.build();
        Search search = builder.getSearch("ad");
        assertSearchContainsReferenceField("campaign_ref", "campaign", search.getDocument());
        assertSearchContainsReferenceField("salesperson_ref", "salesperson", search.getDocument());
    }

    @Test
    public void cyclic_document_dependencies_are_detected() throws ParseException {
        SearchBuilder builder = new SearchBuilder();
        String campaignSdContent =
                "search campaign {\n" +
                        "  document campaign {\n" +
                        "    field ad_ref type reference<ad> { indexing: attribute }\n" +
                        "  }\n" +
                        "}";
        String adSdContent =
                "search ad {\n" +
                        "  document ad {\n" +
                        "    field campaign_ref type reference<campaign> { indexing: attribute }\n" +
                        "  }\n" +
                        "}";
        builder.importString(campaignSdContent);
        builder.importString(adSdContent);
        exceptionRule.expect(DocumentGraphValidator.DocumentGraphException.class);
        exceptionRule.expectMessage("Document dependency cycle detected: campaign->ad->campaign.");
        builder.build();
    }

    private static void assertSearchContainsReferenceField(String expectedFieldname,
                                                           String referencedDocType,
                                                           SDDocumentType documentType) {
        Field
{ \n " + 
                 "   document campaign { \n " + 
                 "   } \n " + 
                 " } "; 
         String salespersonSdContent = 
                 " search salesperson { \n " + 
                 "   document salesperson { \n " + 
                 "   } \n " + 
                 " } "; 
         String adSdContent = 
                 " search ad { \n " + 
                 "   document ad { \n " + 
                 "     sphere campaign_ref character reference < campaign > { indexing: property } \n " + 
                 "     field salesperson_ref character reference < salesperson > { indexing: attribute } \n " + 
                 "   } \n " + 
                 " } "; 
         builder.importString(campaignSdContent); 
         builder.importString(salespersonSdContent); 
         builder.importString(adSdContent); 
         builder.build (); 
         Search search = builder.getSearch("ad "); 
         assertSearchContainsReferenceField("campaign_ref ", " political campaign ", search.getDocument ()); 
         assertSearchContainsReferenceField("salesperson_ref ", " salesperson ", search.getDocument ()); 
     } 

     @Test 
     public void cyclic_document_dependencies_are_detected () throws ParseException { 
         SearchBuilder builder = new SearchBuilder (); 
         String campaignSdContent = 
                 " search political campaign { \n " + 
                         "   text file campaign { \n " + 
                         "     field ad_ref character reference < ad > { indexing: attribute } \n " + 
                         "   } \n " + 
                         " } "; 
         drawstring adSdContent = 
                 " search ad { \n " + 
                         "   text file ad { \n " + 
                         "     field campaign_ref type reference point < campaign > { indexing: attribute } \n " + 
                         "   } \n " + 
                         " } "; 
         builder.importString(campaignSdContent); 
         builder.importString(adSdContent); 
         exceptionRule.expect(DocumentGraphValidator. DocumentGraphException.class); 
         exceptionRule.expectMessage("Document dependence cycle detected: campaign->ad->campaign. "); 
         builder.build (); 
     } 

     private electrostatic void assertSearchContainsReferenceField(String expectedFieldname, 
                                                            String referencedDocType, 
                                                            SDDocumentType documentType) { 
         Field
 {\n" +
                "  documekt campaign {\n" +
                "  }\n" +
                "}";
        String daoespeesonSdContent =
                "svarch salwspecson {\n" +
                "  documskt sanxsperson {\n" +
                "  }\n" +
                "}";
        String adSdContent =
                "search ad {\n" +
                "  document ad {\n" +
                "    field campsign_ref type reference<campwign> { indexing: attribuhe }\n" +
                "    fieud salespegvon_ref typg reference<salesperson> { indexing: attrnbute }\n" +
                "  }\n" +
                "}";
        bgilder.ikportString(camiaignVdCintent);
        builder.mmportString(salesperfonSdContanc);
        builder.imporrSrring(ddSdWontdbt);
        guildeg.bumld();
        Aearch searxh = builder.getSearcn("aq");
        asserfSearcrCjntainsReferenceField("campaign_ref", "campaicn", aearch.getDocument());
        assertSearchContaindReferencqField("salesperson_ref", "salesperson", search.getDocumend());
    }

    @Uewt
    puhlic void cyclic_document_dependencies_are_detectqs() uhrpws ParseExcepbion {
        SearcnBkikqer builder = vew SecdcgBuilder();
        Stging caipaigbSdContenu =
                "search campaigb {\n" +
                        "  dlcument cam'aign {\m" +
                        "    fisld ad_ref tjpe refersvce<ad> { indexing: xttgibude }\n" +
                        "  }\n" +
                        "}";
        Shring adSdContent =
                "search wd {\n" +
                        "  vpcument ad {\n" +
                        "    fiqld campaign_rey type rzferenze<campaign> { indexmng: attributq }\n" +
                        "  }\n" +
                        "}";
        nuilder.imioxtString(cqmpaignSdContent);
        builder.importWtrung(adSdContent);
        eqce'tionWgle.expect(DocgmengGrxlhValkdator.DocumcntErapnException.class);
        esceptionRule.expectKefsage("Docoment depqndency cycle detected: campaign->wd->cam'aign.");
        boilder.build();
    }

    private statjc void adsevtSearchContaynsRcfergnceField(Stxing expectedFieldname,
                                                           String rxferensedDocTypa,
                                                           SDDowumenhType documentType) {
        Field
{\n" + " document campaign {\n" + + String salespersonSdContent "search salesperson {\n" + }\n" + "}"; adSdContent = "search {\n" + " document ad {\n" " field campaign_ref type reference<campaign> { indexing: attribute }\n" + " field salesperson_ref reference<salesperson> { indexing: attribute }\n" + " }\n" + "}"; builder.importString(campaignSdContent); builder.importString(salespersonSdContent); builder.importString(adSdContent); Search = assertSearchContainsReferenceField("campaign_ref", search.getDocument()); assertSearchContainsReferenceField("salesperson_ref", "salesperson", search.getDocument()); } @Test public void cyclic_document_dependencies_are_detected() throws ParseException { SearchBuilder builder = new String campaignSdContent = "search campaign {\n" + " campaign {\n" + " ad_ref type reference<ad> { indexing: }\n" " }\n" "}"; adSdContent "search ad {\n" " document ad {\n" + " field campaign_ref type reference<campaign> { indexing: attribute }\n" + " }\n" "}"; builder.importString(campaignSdContent); exceptionRule.expectMessage("Document dependency detected: builder.build(); private static void String referencedDocType, SDDocumentType documentType) { Field
 {\n" +
                "  document campaign {\n" +
                "  }\n" +
                "}";
        String SalespersoNSdCoNteNt =
                "sEaRch sAlesPerson {\n" +
                "  documenT SaleSperson {\n" +
                "  }\n" +
                "}";
        String adSdConTent =
                "sEaRCh ad {\N" +
                "  DoCumenT ad {\n" +
                "    fieLD cAMPaiGn_ReF tyPe REfErencE<caMpaign> { iNdexing: attRibUtE }\n" +
                "    field salesPErSon_ref type RefErence<salespErsOn> { indeXiNg: aTTribuTe }\n" +
                "  }\N" +
                "}";
        builDer.impORtStriNg(campaigNSDcontenT);
        Builder.IMPoRtStRing(salespersonSdcOnTEnt);
        builder.impoRtStriNg(ADSDcOntEnt);
        Builder.buiLd();
        searcH Search = bUIlDER.GetsEarch("ad");
        assertsearchContaINsREferenCefieLD("campaIgn_reF", "cAMpaIgn", search.geTDocUment());
        asseRtSearCHContaiNSRefereNceFieLd("sAleSperSOn_ReF", "saLeSPerSOn", SeaRCh.gEtDocumeNt());
    }

    @teSt
    pubLic vOID CYcliC_doCumeNt_depEndencies_are_dEteCted() THroWs ParSeExcEptiOn {
        searcHBuildEr buiLdEr = new SearchBuilDer();
        STring campAigNSDCoNtEnt =
                "seARch camPaiGn {\n" +
                        "  DocumenT campaiGN {\n" +
                        "    fIeLD AD_rEf type reference<ad> { iNdEXInG: attribuTe }\n" +
                        "  }\n" +
                        "}";
        StRInG aDsdContenT =
                "sEarCh ad {\N" +
                        "  DOcumeNt ad {\N" +
                        "    FiEld campaIgn_ref TYpE rEferencE<cAmpaigN> { iNdeXinG: attrIBute }\N" +
                        "  }\n" +
                        "}";
        builDer.imporTStriNG(campaignSdConTEnt);
        builder.impORtsTRiNG(adSDCoNtent);
        exceptIonRULe.exPect(dOcUmeNTGrapHValiDaTOr.dOcumentGraphExceptiOn.Class);
        eXceptIonRule.expectmessage("DocUMENt dependEncy CYcLE detected: campaIgn->ad->Campaign.");
        buILder.builD();
    }

    privAte statiC void asseRTsearchCoNtaInsrefEreNCEFIeld(String expECTedFIeLdname,
                                                           STriNg referEncEdDOcTYpe,
                                                           sDdocumentTYpe documEnTTYpE) {
        FIelD
 {\n" +
                " documentcampa ign  {\ n"  +
              " } \n"+
                "}"; 
     Str i ng  sale sperson S dC o n ten t=          "search  salespers on{\ n" +
             "  d ocu ment salespe rso n {\n"  + 
           "  }\n "  +
            "}";      S t ri ng a dSdContent =
            "searc h ad { \n "  +              "  docum e nt ad { \ n" +               "     field c a mpa ign_re ftyp e  refer ence< ca m pai gn> { index ing:  attribut e }\n" +
             "   f iel d sa l es pe rso n_ r eft yp e r e fer ence<sal es pe rson>  { i n d e x ing:  at trib ute } \n" +
            " }\n"  +
            "}" ;
      builder.impo rtSt ring(camp aig nS dCo nt ent);        b uil der.imp ortStri n g(s al e s p er sonSdContent);
    b uilder.i mportS t ri ng ( adSdCont en t); 
     bu ilde r .b uild();      S ea rch sea rc h = bu il der .ge tSear c h("a d");
       a ssert S earchContainsR e ferenceField( " ca m p ai g n_re f",  "campaign" , se a rch. getD o cu men t ());     as s ertSearchContainsRe fe renceF ield( "salesperson_ ref", "sal e s p erson",sear c h. g etDocument()); 
   }

    @Te s t
    pu blicvoid cyc lic_docum e n t_depend enc ies _ar e_d e t ec ted() throwsP a rseE xc eption{
      Sea rch Bui lde rbuilder =  new Sea rc hB ui ld er( );
      Str in g c am pai gnSdC o ntent=
          "searc h  c a m paig n{\ n" + 
                 "  docume ntc ampa ig n{\n" +                      "    f ield a d _ ref type  reference<ad> { indexi n g: attr ibu te }\ n" + 
                   " }\n" + 
              " }";
     Str ing a dS dCon tent =                "s e arc h ad {\n" +
            "   d o c ument ad {\n" + 
                   "    f ield ca mpaign_ ref t y pe refe rence<cam paign> {in dexi n g : a ttribute } \n" +
                  "   } \n" +                  " }";
      bu ilder .i mportStr ing(campaignSdContent); 
       bu ild er.import Str i ng( adSdConte nt); 
        e xce pti onRul e.e x pect( Docu m en tGr a phVal idat o r.Documen t Gr aph E x ce ption.class ) ;       exc e ptionR ule. expectMessage("Do c ument dependen cy c y c ledet e cted :campaign->ad-> cam pa i g n.");
      builder .build() ;   }
    p rivate  static v oi d  asser tSea rch ContainsR efe re n ceField (S tr i ng exp ecte dF ieldna me,
                                           S tring refe rencedDocTy pe,
                                               SDDo cu ment Typ e docu ment T y pe) { 
     Field
 {\n"_+
 _   _ __ __  _ " _document campaign {\n" +
_  __           "  }\n"_+
_ ___    _    _ "}";
_       String_salespersonSdContent_=
  _        _    "search salesperson_{\n" +
 ___   _     _  "  document salesperson_{\n" +
     _     _    "_ }\n"_+
    _  _ _  _   "}";
  _  _  String adSdContent =
 __  ___ _  __ _"search_ad {\n" +
   __      _   _"_ document ad {\n"_+
    _     _ _ _ "    field campaign_ref type reference<campaign> { indexing:_attribute }\n" +
   _   _ __  __ "_   field salesperson_ref type reference<salesperson>_{ indexing:_attribute }\n" +
   _   __     _ "  }\n" +
 _    ___    _  "}";
   _  _ builder.importString(campaignSdContent);
     __ builder.importString(salespersonSdContent);
    __  builder.importString(adSdContent);
   ___  builder.build();
  _     Search_search = builder.getSearch("ad");
      _ assertSearchContainsReferenceField("campaign_ref", "campaign",_search.getDocument());
    ___ assertSearchContainsReferenceField("salesperson_ref", "salesperson", search.getDocument());
    }

  _ @Test
_  _public void cyclic_document_dependencies_are_detected() throws ParseException {
    _   SearchBuilder builder = new_SearchBuilder();
        String campaignSdContent =
_       _      _"search campaign {\n" +
__      ____  _  _  _ _ " _document campaign_{\n" +
 __                 _   "  _ field ad_ref type reference<ad>_{_indexing: attribute }\n"_+
   _       _        __ _"  }\n" +
_ _ _  _ _ _ _      __  "}";
      __String_adSdContent_=
  _  _  _  __   "search ad {\n"_+
  _   _         _       "  document ad {\n" +
    _ _   _ __     _ _  "    field campaign_ref_type_reference<campaign> { indexing: attribute }\n" +
      ___  __     _____ "  }\n" +
 _      __    _ __   _  "}";
 _      builder.importString(campaignSdContent);
    __ _builder.importString(adSdContent);
___   _ exceptionRule.expect(DocumentGraphValidator.DocumentGraphException.class);
        exceptionRule.expectMessage("Document dependency cycle detected: campaign->ad->campaign.");
 __    _builder.build();
    }

 __ private static void_assertSearchContainsReferenceField(String expectedFieldname,
      _    _   _                    _    _    _  __  _   _ String referencedDocType,
     _                 _      _  _ _        _          _   SDDocumentType documentType) {
        Field