home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / Database / OTC_EOFBetaExamples_V1.0 / EOFramework / Querying / QueryController.m < prev    next >
Encoding:
Text File  |  1994-07-31  |  16.5 KB  |  543 lines

  1. /*--------------------------------------------------------------------------
  2.  *
  3.  *     You may freely copy, distribute, and reuse the code in this example.
  4.  *     SHL Systemhouse disclaims any warranty of any kind, expressed or  
  5.  *    implied, as to its fitness for any particular use.
  6.  *
  7.  *
  8.  *    QueryController
  9.  *
  10.  *    Inherits From:        NSObject
  11.  *
  12.  *    Conforms To:        None.
  13.  *
  14.  *    Declared In:        QueryController.h
  15.  *
  16.  *
  17.  *------------------------------------------------------------------------*/
  18. #import "QueryController.h"
  19. #import "EOQualifierContentsCategory.h"
  20.  
  21.  
  22.  
  23.  
  24. @implementation QueryController
  25.  
  26.  
  27. /*--------------------------------------------------------------------------
  28.  *    Model file reading and preparation for query building
  29.  *------------------------------------------------------------------------*/
  30. - _setUpForModelFile: (NSString *)aFilepath
  31. {
  32.     id model = [[EOModel allocWithZone: NULL]
  33.                 initWithContentsOfFile: aFilepath];
  34.  
  35.     /*----------------------------------------------------------------------
  36.      *    create adaptor with specifics contained in the model (server, etc.)
  37.      *--------------------------------------------------------------------*/
  38.     if (adaptor) [adaptor release];
  39.     adaptor = [[EOAdaptor adaptorWithModel: model] retain];
  40.     [model release];
  41.  
  42.     /*----------------------------------------------------------------------
  43.       *    set up database pieces to allow transactions, qualifiers, etc.
  44.      *--------------------------------------------------------------------*/
  45.     if (database) [database release];
  46.     database = [[EODatabase allocWithZone: [self zone]]
  47.                     initWithAdaptor: adaptor];
  48.  
  49.     if (dbContext) [dbContext release];
  50.     dbContext = [[EODatabaseContext alloc] initWithDatabase: database];
  51.     
  52.     if (dbChannel) [dbChannel release];
  53.     dbChannel = [[EODatabaseChannel alloc] initWithDatabaseContext: dbContext];
  54.  
  55.     /*----------------------------------------------------------------------
  56.      *    open the channel and turn on debug to see SQL in console
  57.      *--------------------------------------------------------------------*/
  58.     if (! [dbChannel openChannel]) {
  59.         NSLog(@"database channel could not be opened.");
  60.     }
  61.     [[dbChannel adaptorChannel] setDebugEnabled:YES];
  62.  
  63.     entity = nil;
  64.  
  65.     [self clearQualifier:nil];
  66.     [[qualifierBrowser matrixInColumn:0] renewRows:0 cols:0];
  67.     [[qualifierBrowser matrixInColumn:0] sizeToCells];
  68.     [qualifierBrowser display];
  69.     return self;
  70. }
  71.  
  72.  
  73. /*--------------------------------------------------------------------------
  74.  *    IconWell delegate method
  75.  *------------------------------------------------------------------------*/
  76. - dragSource:dragSource didDropOnIconWell:sender
  77. {
  78.     [modelPath setStringValue: (const char *)[sender path]];
  79.     [self _setUpForModelFile: [NSString stringWithCString:
  80.         (char *)[sender path]]];
  81.  
  82.     [[browser loadColumnZero] display];
  83.     [window makeKeyAndOrderFront: self];
  84.  
  85.     return self;
  86. }
  87.  
  88.  
  89. /*--------------------------------------------------------------------------
  90.  *    Application delegation
  91.  *------------------------------------------------------------------------*/
  92. - appDidInit: sender
  93. {
  94.     qualifier = nil;
  95.     dataSource = nil;
  96.     controller = nil;
  97.     dbContext = nil;
  98.     dbChannel = nil;
  99.  
  100.     [qualifierOperation setEmptySelectionEnabled:YES];
  101.     [qualifierOperation selectCellAt:-1:-1];
  102.     [window makeKeyAndOrderFront: self];
  103.     return self;
  104. }
  105.  
  106.  
  107. /*--------------------------------------------------------------------------
  108.  *    Query Actions
  109.  *------------------------------------------------------------------------*/
  110. - performQuery:sender
  111. {
  112.     id             selection = [[NSMutableArray allocWithZone:NULL] init];
  113.     id            selectedCells = [[List alloc] init];
  114.     int            countSelected, iterator;
  115.     const char     *cString;
  116.     
  117.     /*----------------------------------------------------------------------
  118.      *    get attribute names to be selected and browsed
  119.      *--------------------------------------------------------------------*/
  120.     [[browser matrixInColumn:1] getSelectedCells:selectedCells];
  121.     countSelected = [selectedCells count];
  122.  
  123.     if (countSelected == 0) {
  124.         [selectedCells free];
  125.         selectedCells = [[browser matrixInColumn:1] cellList];
  126.         countSelected = [selectedCells count];
  127.     }
  128.     
  129.     /*----------------------------------------------------------------------
  130.      *    transfer info from a NS3.2 list to a NS3.3NSArray
  131.      *--------------------------------------------------------------------*/
  132.     for (iterator = 0; iterator < countSelected; iterator++) {
  133.         cString = [(Cell *)[selectedCells objectAt: iterator] stringValue];
  134.         [(NSMutableArray *)selection addObject:
  135.                 [NSString stringWithCString: cString]];
  136.     }
  137.  
  138.     /*----------------------------------------------------------------------
  139.      *    assure current entity
  140.      *--------------------------------------------------------------------*/
  141.     cString = [(Cell *)[[browser matrixInColumn:0] selectedCell] stringValue];
  142.     entity = [[adaptor model] entityNamed:
  143.                 [NSString stringWithCString: cString]];
  144.  
  145.     /*----------------------------------------------------------------------
  146.      *    if qualifier is not defined, create an unqualified fetch.
  147.      *--------------------------------------------------------------------*/
  148.     if (qualifier == nil)
  149.         qualifier = [entity qualifier];
  150.  
  151.     /*----------------------------------------------------------------------
  152.      *    call method to handle fetch and reporting thru NXTableView
  153.      *--------------------------------------------------------------------*/
  154.     [self fetchAndDisplay:selection inEntity:entity
  155.                 withQualifier:qualifier];
  156.  
  157.     return self;
  158. }
  159.  
  160.  
  161. - (void) fetchAndDisplay:(NSArray *)attributes inEntity:(EOEntity *)anEntity
  162.     withQualifier:(EOQualifier *)aQualifier
  163. {
  164.     unsigned int    count, iterator;
  165.  
  166.     [resultWindow disableDisplay];
  167.  
  168.     /*----------------------------------------------------------------------
  169.      *    if not the first query, we need to change dataSources.  The entity
  170.      *    may be different from the previous query.
  171.      *--------------------------------------------------------------------*/
  172.     if (dataSource) [dataSource release];
  173.  
  174.     dataSource = [[EODatabaseDataSource allocWithZone: [self zone]]
  175.                     initWithEntity: anEntity databaseChannel: dbChannel];
  176.  
  177.     /*----------------------------------------------------------------------
  178.      *    get a new controller with the new dataSource
  179.      *--------------------------------------------------------------------*/
  180.     controller = [[EOController allocWithZone: [self zone]]
  181.             initWithDataSource: dataSource];
  182.  
  183.     /*----------------------------------------------------------------------
  184.      *    delete all current columns in the table view
  185.      *--------------------------------------------------------------------*/
  186.     count = [resultTable columnCount];
  187.     for (iterator = count; iterator > 0; iterator--)
  188.         [resultTable removeColumnAt: iterator-1];
  189.     [(NXTableView *)resultTable setDataSource:nil];
  190.  
  191.     /*----------------------------------------------------------------------
  192.      *    iterate through the desired select attributes and build columns for
  193.      *    each in the tableView.
  194.      *--------------------------------------------------------------------*/
  195.     count = [attributes count];
  196.     for (iterator = 0; iterator < count; iterator ++) {
  197.         id    association;
  198.         id    attribute = [anEntity attributeNamed:
  199.             [attributes objectAtIndex:iterator]];
  200.  
  201.         [resultTable addColumn:attribute withTitle:
  202.             [[(EOAttribute *)attribute name] cString]];
  203.  
  204.     /*----------------------------------------------------------------------
  205.      *    create a new association for each of these attribute/column pairs
  206.      *--------------------------------------------------------------------*/
  207.         association = [[EOColumnAssociation allocWithZone: [self zone]]
  208.             initWithController:controller key: [(EOAttribute *)attribute name]
  209.             destination:[resultTable columnAt:iterator]];
  210.  
  211.         [association setTableView:resultTable];
  212.         [controller addAssociation: association];
  213.         [association release];
  214.     }
  215.  
  216.     /*----------------------------------------------------------------------
  217.      *    set the qualifier for the fetch.
  218.      *--------------------------------------------------------------------*/
  219.     [dataSource setQualifier: aQualifier];
  220.  
  221.     /*----------------------------------------------------------------------
  222.      *    Start a transaction, do the fetch, rollback the transaction (a fetch
  223.      *    doesn't need to commit anything) have the values filled to the
  224.      *    tableView via the columnAssociations.
  225.      *--------------------------------------------------------------------*/
  226.     [dbContext beginTransaction];
  227.  
  228.     if (! [controller fetch])
  229.         NSLog(@"controller fetch failed.");
  230.  
  231.     [dbContext rollbackTransaction];
  232.  
  233.     /*----------------------------------------------------------------------
  234.      *    Redisplay everything...
  235.      *--------------------------------------------------------------------*/
  236.     [resultWindow reenableDisplay];
  237.     [controller redisplay];
  238.     [resultWindow makeKeyAndOrderFront:self];
  239.     return;
  240. }
  241.     
  242.     
  243. - (int) browser:aBrowser fillMatrix:aMatrix inColumn:(int)aColumn
  244. {
  245.     int            iterator = 0, entryCount = 0;
  246.     id            contents = nil;
  247.     id            enumerator, current;
  248.  
  249.     /*----------------------------------------------------------------------
  250.      *    Fill qualifier browser with the attributes of the selected entity;
  251.      *    this is the same list as in the second column of the first browser.
  252.      *--------------------------------------------------------------------*/
  253.     if (aBrowser == qualifierBrowser) {
  254.         id selectedEntity;
  255.  
  256.         iterator = 0;
  257.         if ([browser selectedColumn] < 0) 
  258.             return 0;
  259.  
  260.         selectedEntity = [NSString stringWithCString: 
  261.             [(Cell *)[[browser matrixInColumn:0] selectedCell]
  262.              stringValue]];
  263.         contents = [[[adaptor model] entityNamed: selectedEntity] attributes];
  264.         entity = nil;
  265.  
  266.         entryCount = [contents count];
  267.         [aMatrix renewRows: entryCount cols: 1];
  268.  
  269.         enumerator = [contents objectEnumerator];
  270.         while (current = [enumerator nextObject]) {
  271.  
  272.             [[[aMatrix cellAt: iterator++ : 0] 
  273.                 setStringValue: [[(EOAttribute *)current name] cString]]
  274.                 setLeaf:  YES];
  275.         }
  276.         return entryCount;
  277.     }
  278.  
  279.     /*----------------------------------------------------------------------
  280.      *    The main entity attribute browser with two columns.  One selects the
  281.      *    entity for the query the other the attributes to be selected.  Note
  282.      *    that since we're using the EODatabaseAdaptor (instead of the
  283.      *    EOChannelAdaptor, we actually select the entire object, but only these
  284.      *    fields will be associated with the tableView.
  285.      *
  286.      *    Reset query qualifiers for new entity
  287.      *--------------------------------------------------------------------*/
  288.     [qualifier release];
  289.     [qualifierText setStringValue: ""];
  290.     [queryText setStringValue: ""];
  291.  
  292.     if (aColumn == 0) 
  293.         contents = [[adaptor model] entities];
  294.  
  295.     else if (aColumn == 1) {
  296.         id selectedEntity;
  297.  
  298.         selectedEntity = [NSString stringWithCString: 
  299.             [(Cell *)[[aBrowser matrixInColumn:0] selectedCell] stringValue]];
  300.         contents = [[[adaptor model] entityNamed: selectedEntity] attributes];
  301.         entity = nil;
  302.     }
  303.  
  304.     entryCount = [contents count];
  305.     [aMatrix renewRows: entryCount cols: 1];
  306.  
  307.     enumerator = [contents objectEnumerator];
  308.     while (current = [enumerator nextObject]) {
  309.  
  310.         [[[aMatrix cellAt: iterator : 0] 
  311.             setStringValue: [[(EOEntity *)current name] cString]]
  312.             setLeaf:  aColumn == 1 ];
  313.         iterator++;
  314.     }
  315.  
  316.     if (aColumn ==     1)
  317.         [[qualifierBrowser loadColumnZero] display];
  318.  
  319.     return entryCount;
  320. }
  321.  
  322.  
  323. - selectOperation:sender
  324. {
  325.     int selectedOp;
  326.     id    opString = nil;
  327.     int    selection;
  328.  
  329.     selectedOp = [[qualifierOperation selectedCell] tag];
  330.  
  331.     if (selectedOp == 0) opString = @"<";
  332.     else if (selectedOp == 1) opString = @"<=";
  333.     else if (selectedOp == 2) opString = @">";
  334.     else if (selectedOp == 3) opString = @">=";
  335.     else if (selectedOp == 4) opString = @"=";
  336.     else if (selectedOp == 5) opString = @"<>";
  337.     
  338.     
  339.     [qualifierText setStringValue: 
  340.         [[NSString stringWithFormat:@"%s%s ",
  341.         [(TextField *)qualifierText stringValue],
  342.             [opString cString]] cString]];
  343.  
  344.     selection = strlen([(TextField *)qualifierText stringValue]);
  345.     [qualifierText selectText:nil];
  346.  
  347.  
  348.     return self;
  349. }
  350.  
  351.  
  352. - selectAttribute:sender
  353. {
  354.     id            selectedCell;
  355.     EOAttribute    *newAttribute;
  356.  
  357.     if (entity == nil) {
  358.         const char     *entityName;
  359.  
  360.         entityName = [(Cell *)[[browser matrixInColumn: 0]
  361.                                 selectedCell] stringValue];
  362.         entity = [[adaptor model] entityNamed:
  363.                 [NSString stringWithCString: entityName]];
  364.     }
  365.  
  366.     if (selectedCell = [qualifierBrowser selectedCell]) {
  367.         id    newString;
  368.  
  369.         newAttribute = [entity attributeNamed:
  370.             [NSString stringWithCString:[(Cell *)selectedCell stringValue]]];
  371.  
  372.     /*----------------------------------------------------------------------
  373.      *    Get the name internal to the database; if it is a column, get the
  374.       *    column name, otherwise, it is a complex value (a flattened attribute)
  375.      *    so get the description.
  376.      *--------------------------------------------------------------------*/
  377.         newString = [NSString stringWithFormat: @"%s%s ",
  378.             [(TextField *)qualifierText stringValue],     
  379.             [newAttribute columnName] ?     
  380.                 [(NSString *)[newAttribute columnName] cString] :
  381.                 [(NSString *)[newAttribute definition] cString]];
  382.  
  383.         [qualifierText setStringValue: [newString cString]];
  384.         [qualifierText selectText: nil];
  385.  
  386.     }
  387.  
  388.     return self;
  389. }
  390.  
  391.  
  392. - replaceQualifier: sender
  393. {
  394.     if (qualifier) [qualifier release];
  395.  
  396.     if (entity == nil) {
  397.         const char     *entityName;
  398.  
  399.         entityName = [(Cell *)[[browser matrixInColumn: 0]
  400.                                 selectedCell] stringValue];
  401.         if (! entityName) {
  402.             NXRunAlertPanel("Query Builder",
  403.                 "A model file must be present before a query is possible.",
  404.                 NULL, NULL, NULL);
  405.             return nil;
  406.         }
  407.  
  408.         entity = [[adaptor model] entityNamed:
  409.                 [NSString stringWithCString: entityName]];
  410.     }
  411.  
  412.     qualifier = [[EOQualifier allocWithZone:[self zone]]
  413.         initWithEntity:entity
  414.         qualifierFormat: [NSString stringWithCString:
  415.             [(TextField *)qualifierText stringValue]]];
  416.     
  417.     if ([negator state]) [qualifier negate];
  418.  
  419.     [negator setState: 0];
  420.     [queryText setStringValue:[[qualifier contents] cString]];
  421.     [qualifierText setStringValue:""];
  422.     [qualifierText selectText: nil];
  423.     [qualifierOperation selectCellAt:-1:-1];
  424.  
  425.  
  426.     return self;
  427. }
  428.  
  429.  
  430. - appendAND: sender
  431. {
  432.     id newQualifier;
  433.  
  434.     if (entity == nil) {
  435.         const char     *entityName;
  436.  
  437.         entityName = [(Cell *)[[browser matrixInColumn: 0]
  438.                                 selectedCell] stringValue];
  439.         if (! entityName) {
  440.             NXRunAlertPanel("Query Builder",
  441.                 "A model file must be present before a query is possible.",
  442.                 NULL, NULL, NULL);
  443.             return nil;
  444.         }
  445.  
  446.         entity = [[adaptor model] entityNamed:
  447.                 [NSString stringWithCString: entityName]];
  448.     }
  449.  
  450.  
  451.     newQualifier = [[EOQualifier allocWithZone:[self zone]]
  452.         initWithEntity:entity
  453.         qualifierFormat: [NSString stringWithCString:
  454.             [(TextField *)qualifierText stringValue]]];
  455.  
  456.     /*----------------------------------------------------------------------
  457.      *    If the qualifier is to be negated...
  458.      *--------------------------------------------------------------------*/
  459.     if ([negator state]) [newQualifier negate];
  460.  
  461.     /*----------------------------------------------------------------------
  462.      *    AND the new qualifier with the previous one
  463.      *--------------------------------------------------------------------*/
  464.     [qualifier     conjoinWithQualifier: newQualifier];
  465.  
  466.     [newQualifier release];
  467.  
  468.     [negator setState: 0];
  469.     [queryText setStringValue:[[qualifier contents] cString]];
  470.     [qualifierText setStringValue:""];
  471.     [qualifierText selectText: nil];
  472.     [qualifierOperation selectCellAt:-1:-1];
  473.  
  474.  
  475.     return self;
  476. }
  477.  
  478.  
  479. - appendOR: sender
  480. {
  481.     id newQualifier;
  482.  
  483.     if (entity == nil) {
  484.         const char     *entityName;
  485.  
  486.         entityName = [(Cell *)[[browser matrixInColumn: 0]
  487.                                 selectedCell] stringValue];
  488.         if (! entityName) {
  489.             NXRunAlertPanel("Query Builder",
  490.                 "A model file must be present before a query is possible.",
  491.                 NULL, NULL, NULL);
  492.             return nil;
  493.         }
  494.  
  495.         entity = [[adaptor model] entityNamed:
  496.                 [NSString stringWithCString: entityName]];
  497.     }
  498.  
  499.  
  500.     newQualifier = [[EOQualifier allocWithZone:[self zone]]
  501.         initWithEntity:entity
  502.         qualifierFormat: [NSString stringWithCString:
  503.             [(TextField *)qualifierText stringValue]]];
  504.  
  505.     /*----------------------------------------------------------------------
  506.      *    If the qualifier is to be negated...
  507.      *--------------------------------------------------------------------*/
  508.     if ([negator state]) [newQualifier negate];
  509.  
  510.     /*----------------------------------------------------------------------
  511.      *    OR the new qualifier with the previous one.
  512.      *--------------------------------------------------------------------*/
  513.     [qualifier     disjoinWithQualifier: newQualifier];
  514.  
  515.     [newQualifier release];
  516.  
  517.     [negator setState: 0];
  518.     [queryText setStringValue:[[qualifier contents] cString]];
  519.     [qualifierText setStringValue:""];
  520.     [qualifierText selectText: nil];
  521.     [qualifierOperation selectCellAt:-1:-1];
  522.  
  523.  
  524.     return self;
  525. }
  526.  
  527.  
  528. - clearQualifier: sender
  529. {
  530.     [qualifier release];
  531.     qualifier = nil;
  532.     [negator setState: 0];
  533.     [queryText setStringValue:""];
  534.     [qualifierText setStringValue:""];
  535.     [qualifierText selectText:nil];
  536.     [qualifierOperation selectCellAt:-1:-1];
  537.  
  538.     return self;
  539. }
  540.  
  541.  
  542. @end
  543.