diff --git a/Apps/EOModelEditor/AdaptorsPanel.h b/Apps/EOModelEditor/AdaptorsPanel.h new file mode 100644 index 0000000..8a48ea3 --- /dev/null +++ b/Apps/EOModelEditor/AdaptorsPanel.h @@ -0,0 +1,48 @@ +#ifndef __AdaptorsPanel_H_ +#define __AdaptorsPanel_H_ + +/* + AdaptorsPanel.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include + + +@interface AdaptorsPanel : NSObject +{ + NSWindow *_window; + NSBrowser *brws_adaptors; + NSButton *btn_ok; + NSButton *btn_cancel; + NSBox *_box; + NSTextField *_label; +} + +-(NSString *)runAdaptorsPanel; + +@end + + +#endif // __AdaptorsPanel_H + diff --git a/Apps/EOModelEditor/AdaptorsPanel.m b/Apps/EOModelEditor/AdaptorsPanel.m new file mode 100644 index 0000000..e1b6e21 --- /dev/null +++ b/Apps/EOModelEditor/AdaptorsPanel.m @@ -0,0 +1,173 @@ +/** + AdaptorsPanel.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include "AdaptorsPanel.h" +#include + +#include + +static NSArray *_adaptorNames; + +@implementation AdaptorsPanel + +- (void) dealloc +{ + DESTROY(_window); + DESTROY(_adaptorNames); + /* released by window + _label + brws_adaptors + btn_ok + btn_cancel + */ + [super dealloc]; +} + +- (id) init +{ + if ((self = [super init])) + { + NSRect fr1, fr2; + _adaptorNames = RETAIN([EOAdaptor availableAdaptorNames]); + /* redo all these numbers so buttons and labels are on the right? */ + _window = [[NSWindow alloc] + initWithContentRect: NSMakeRect(200,200,200,300) + styleMask: NSBorderlessWindowMask | NSTitledWindowMask + backing: NSBackingStoreBuffered + defer: YES]; + [_window setTitle: @"Select adaptor"]; + [_window setReleasedWhenClosed:NO]; + + brws_adaptors = [[NSBrowser alloc] initWithFrame: NSMakeRect(5,30,190,240)]; + [brws_adaptors setDelegate: self]; + [brws_adaptors addColumn]; + [brws_adaptors setTitle: @"Available adaptors" ofColumn: 0]; + [brws_adaptors setAllowsEmptySelection: NO]; + [brws_adaptors setTarget:self]; + [brws_adaptors setDoubleAction:@selector(ok:)]; + + btn_ok = [[NSButton alloc] initWithFrame: NSMakeRect(5,5,50,20)]; + [btn_ok setTitle: @"ok"]; + [btn_ok setTarget: self]; + [btn_ok setAction: @selector(ok:)]; + + btn_cancel = [[NSButton alloc] initWithFrame: NSMakeRect(60,5,50,20)]; + [btn_cancel setTitle: @"cancel"]; + [btn_cancel setTarget: self]; + [btn_cancel setAction: @selector(cancel:)]; + + [[_window contentView] addSubview: brws_adaptors]; + [[_window contentView] addSubview: btn_ok]; + [[_window contentView] addSubview: btn_cancel]; + + [_window setInitialFirstResponder:brws_adaptors]; + [brws_adaptors setNextResponder:btn_ok]; + [btn_ok setNextResponder:btn_cancel]; +// hmm.. this seems to cause an infinate loop in the responder chain somehow +// when in the modal loop. +// [btn_cancel setNextResponder:brws_adaptors]; + + [btn_ok setKeyEquivalent:@"\r"]; + [btn_ok setImage:[NSImage imageNamed:@"common_ret"]]; + [btn_ok setAlternateImage:[NSImage imageNamed:@"common_retH"]]; + [btn_ok setImagePosition:NSImageRight]; + [btn_ok sizeToFit]; + + fr1 = [btn_ok frame]; + fr2 = [btn_cancel frame]; + + fr1.size.width = fr2.size.width = fr1.size.width > fr2.size.width + ? fr1.size.width + : fr2.size.width; + fr1.size.height = fr2.size.height = fr1.size.height > fr2.size.height + ? fr1.size.height + : fr2.size.height; + fr2.origin.x = NSMaxX(fr1) + 8; + + [btn_ok setFrame:fr1]; + [btn_cancel setFrame:fr2]; + + fr2 = [brws_adaptors frame]; + fr2.origin.y = NSMaxY(fr1) + 8; + [brws_adaptors setFrame:fr2]; + + RELEASE(_label); + RELEASE(brws_adaptors); + RELEASE(btn_ok); + RELEASE(btn_cancel); + + } + return self; +} + +- (NSString *) runAdaptorsPanel +{ + NSString *selection; + + if ([NSApp runModalForWindow:_window] == NSRunAbortedResponse) + { + selection = nil; + [_window orderOut:self]; + } + else + { + selection = [[brws_adaptors selectedCell] stringValue]; + [_window orderOut:self]; + } + return selection; +} + +/* button actions */ + +- (void) ok: (id)sender +{ + [NSApp stopModalWithCode:NSRunStoppedResponse]; +} + +- (void) cancel: (id)sender +{ + [NSApp stopModalWithCode:NSRunAbortedResponse]; +} + +/* NSBrowser delegate stuff */ + +- (int) browser:(id)sender numberOfRowsInColumn:(int)column +{ + return [_adaptorNames count]; +} + +- (void)browser:(NSBrowser*)sender + willDisplayCell:(NSBrowserCell*)cell + atRow:(int)row + column:(int)column +{ + [cell setLeaf:YES]; + [cell setTitle: [_adaptorNames objectAtIndex:row]]; +} + + + +@end + diff --git a/Apps/EOModelEditor/COPYING b/Apps/EOModelEditor/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/Apps/EOModelEditor/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Apps/EOModelEditor/CodeGenerator.h b/Apps/EOModelEditor/CodeGenerator.h new file mode 100644 index 0000000..42a2ba0 --- /dev/null +++ b/Apps/EOModelEditor/CodeGenerator.h @@ -0,0 +1,49 @@ +/** + CodeGenerator.h + Created by David Wetzel on 16.11.2008. + + This file is part of DBModeler. + + +DBModeler is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +DBModeler is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with DBModeler; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#import +#import + +#ifndef CodeGenerator_h +#define CodeGenerator_h + +@interface NSString (GeneratorAddtions) + +- (NSString *)initialCapitalString; +- (NSString *)initialLowercaseString; + +@end + +@interface CodeGenerator : NSObject +{ + NSString * _generatedClassPath; + NSString * _subclassPath; + NSString * _superclassName; + EOModel * _model; +} + +- (void) generate; + +@end + +#endif diff --git a/Apps/EOModelEditor/CodeGenerator.m b/Apps/EOModelEditor/CodeGenerator.m new file mode 100644 index 0000000..7a6749f --- /dev/null +++ b/Apps/EOModelEditor/CodeGenerator.m @@ -0,0 +1,737 @@ +/** + CodeGenerator.m + Created by David Wetzel on 16.11.2008. + + This file is part of EOModelEditor. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#import "CodeGenerator.h" +#import +#import +#import +#import + +#import +#import + + +#import + + + +@implementation NSString (GeneratorAddtions) + +// those 2 methods are from EOGenerator + +/*- + * Copyright (c) 2002-2006 Carl Lindberg and Mike Gentry + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +- (NSString *)initialCapitalString +{ + NSRange firstLetterRange; + NSString *firstLetterString; + NSString *restOfString; + + if ([self length] == 0) return self; + + firstLetterRange = [self rangeOfComposedCharacterSequenceAtIndex:0]; + firstLetterString = [[self substringWithRange:firstLetterRange] uppercaseString]; + restOfString = [self substringFromIndex:NSMaxRange(firstLetterRange)]; + + return [firstLetterString stringByAppendingString:restOfString]; +} + + +- (NSString *)initialLowercaseString +{ + NSRange firstLetterRange; + NSString *firstLetterString; + NSString *restOfString; + + if ([self length] == 0) return self; + + firstLetterRange = [self rangeOfComposedCharacterSequenceAtIndex:0]; + firstLetterString = [[self substringWithRange:firstLetterRange] lowercaseString]; + restOfString = [self substringFromIndex:NSMaxRange(firstLetterRange)]; + + return [firstLetterString stringByAppendingString:restOfString]; +} + + +@end + + +@implementation CodeGenerator + + +- (id) init +{ + self = [super init]; +// if (self != nil) { +// NSUserDefaults *defs; +// +// defs = [NSUserDefaults standardUserDefaults]; +// _generatedClassPath = [defs stringForKey:GENERATED_CLASS_PATH]; +// _subclassPath = [defs stringForKey:SUBCLASS_PATH]; +// _superclassName = [defs stringForKey:SUPERCLASS_NAME]; +// +// } + return self; +} + +- (NSString*) copyright +{ + return @""; +} + +/* + those are NOT added as '@class XXX;' lines to the _MyClass.h EO file. + */ + +- (NSSet*) knownBaseClassNames +{ + return [NSSet setWithObjects:@"NSArray", @"NSNumber", @"NSDecimalNumber", @"NSCalendarDate", + @"NSData", @"NSString", nil]; +} + +- (NSMutableString*) interfacePrologueForEntity:(EOEntity*) entity +{ + NSMutableString * cs = [NSMutableString string]; + NSString * copy = [self copyright]; + NSString * className = [entity className]; + + [cs appendFormat:@"// _%@.h\n", className]; + + if ((copy != nil) && ([copy length])) { + [cs appendString:copy]; + } + + [cs appendString:@"//\n"]; + [cs appendString:@"// Created by EOModelEditor.\n"]; + [cs appendFormat:@"// DO NOT EDIT. Make changes to %@.h instead.\n\n", className]; + [cs appendFormat:@"#ifndef ___%@_h_\n#define ___%@_h_\n\n", className, className]; + [cs appendString:@"#import \n\n"]; + + return cs; +} + +- (NSMutableString*) superclassPrologueForEntity:(EOEntity*) entity +{ + NSMutableString * cs = [NSMutableString string]; + NSString * copy = [self copyright]; + NSString * className = [entity className]; + + [cs appendFormat:@"// _%@.m\n", className]; + + if ((copy != nil) && ([copy length])) { + [cs appendString:copy]; + } + + [cs appendString:@"//\n"]; + [cs appendString:@"// Created by EOModelEditor.\n"]; + [cs appendFormat:@"// DO NOT EDIT. Make changes to %@.m instead.\n\n", className]; + [cs appendFormat:@"#import \"_%@.h\"\n", className]; + + return cs; +} + +- (NSString*) superInterfaceEpilogueForEntity:(EOEntity*) entity +{ + NSMutableString * cs = [NSMutableString string]; + NSString * className = [entity className]; + +// [cs appendString:@"// \n"]; + [cs appendFormat:@"#endif //___%@_h_\n", className]; + + return cs; +} + +- (NSString*) superclassEpilogueForEntity:(EOEntity*) entity +{ + return @"@end\n"; +} + + +- (BOOL) updateNeededForFileAtPath:(NSString*) aPath content:(NSString*)aString canOverwrite:(BOOL) overwrite +{ + NSFileManager * fileManager = [NSFileManager defaultManager]; + + if ([fileManager fileExistsAtPath:aPath]) { + NSString * myStr = [NSString stringWithContentsOfFile:aPath + encoding:NSUTF8StringEncoding + error:NULL]; + + if ([myStr isEqual:aString]) { + return NO; + } + + if (overwrite) { + return YES; + } + } + + return YES; +} + +void addToUsedClasses(NSMutableArray * mutArray,NSSet * knownNames, NSArray * otherArray) +{ + NSEnumerator * enumer = [otherArray objectEnumerator]; + NSString * className = nil; + id currentObj = nil; + + while ((currentObj = [enumer nextObject])) { + + if ([currentObj isKindOfClass:[NSString class]]) { + className = currentObj; + } else if ([currentObj isKindOfClass:[EORelationship class]]) { + className = [[(EORelationship*) currentObj destinationEntity] className]; + } else if ([currentObj isKindOfClass:[EOAttribute class]]) { + className = [(EOAttribute*) currentObj valueClassName]; + } + + if ((className) && ((([mutArray containsObject:className] == NO)) && ((!knownNames) || (([knownNames containsObject:className] == NO))))) { + [mutArray addObject:className]; + } + } + +} + +- (NSString*) classDummysForEntity:(EOEntity*) entity +{ + NSSet * knownNames = [self knownBaseClassNames]; + NSMutableString * ms = [NSMutableString string]; + NSEnumerator * enumer = nil; + NSString * className = nil; + + NSArray * classNonScalarAttributes = [[entity classNonScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToOneRelationships = [[entity classToOneRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToManyRelationships = [[entity classToManyRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSMutableArray * mutArray = [NSMutableArray array]; + + addToUsedClasses(mutArray, knownNames, classNonScalarAttributes); + addToUsedClasses(mutArray, knownNames, classToOneRelationships); + addToUsedClasses(mutArray, knownNames, classToManyRelationships); + + enumer = [mutArray objectEnumerator]; + + while ((className = [enumer nextObject])) { + [ms appendFormat:@"@class %@;\n", className]; + } + + [ms appendFormat:@"\n"]; + + return ms; +} + +- (NSString*) superIncludesForEntity:(EOEntity*) entity +{ + NSSet * knownNames = [self knownBaseClassNames]; + NSMutableString * ms = [NSMutableString string]; + NSEnumerator * enumer = nil; + NSString * className = nil; + + NSArray * classNonScalarAttributes = [[entity classNonScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToOneRelationships = [[entity classToOneRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToManyRelationships = [[entity classToManyRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSMutableArray * mutArray = [NSMutableArray array]; + + addToUsedClasses(mutArray, knownNames, classNonScalarAttributes); + addToUsedClasses(mutArray, knownNames, classToOneRelationships); + addToUsedClasses(mutArray, knownNames, classToManyRelationships); + + enumer = [mutArray objectEnumerator]; + + while ((className = [enumer nextObject])) { + [ms appendFormat:@"#import \"%@.h\"\n", className]; + } + + [ms appendFormat:@"\n"]; + + return ms; +} + + +- (NSString*) superInterfaceForEntity:(EOEntity*) entity +{ + + NSMutableString * cs = [NSMutableString string]; + NSArray * classScalarAttributes = [[entity classScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classNonScalarAttributes = [[entity classNonScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToOneRelationships = [[entity classToOneRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToManyRelationships = [[entity classToManyRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + EOAttribute * eoAttr = nil; + EORelationship * eoRel = nil; + NSEnumerator * enumer = [classScalarAttributes objectEnumerator]; + NSString * className = [entity className]; + + + [cs appendString:[self classDummysForEntity:entity]]; + + [cs appendFormat:@"@interface _%@ : EOCustomObject \n{\n", className]; + + while ((eoAttr = [enumer nextObject])) { + [cs appendFormat:@" %@ _%@;\n", [eoAttr cScalarTypeString], [eoAttr name]]; + } + + enumer = [classNonScalarAttributes objectEnumerator]; + + while ((eoAttr = [enumer nextObject])) { + [cs appendFormat:@" %@ *_%@;\n", [eoAttr valueClassName], [eoAttr name]]; + } + + enumer = [classToOneRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [cs appendFormat:@" %@ *_%@;\n", [[eoRel destinationEntity] className], [eoRel name]]; + } + + enumer = [classToManyRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [cs appendFormat:@" %@ *_%@s;\n", [[eoRel destinationEntity] className], [eoRel name]]; + } + + [cs appendFormat:@"}\n\n"]; + + + enumer = [classScalarAttributes objectEnumerator]; + + + while ((eoAttr = [enumer nextObject])) { + [cs appendFormat:@"- (void) set%@:(%@) aValue;\n", [[eoAttr name] initialCapitalString], + [eoAttr cScalarTypeString]]; + [cs appendFormat:@"- (%@) %@;\n\n", [eoAttr cScalarTypeString], [eoAttr name]]; + } + + enumer = [classNonScalarAttributes objectEnumerator]; + + while ((eoAttr = [enumer nextObject])) { + [cs appendFormat:@"- (void) set%@:(%@ *) aValue;\n", [[eoAttr name] initialCapitalString], + [eoAttr valueClassName]]; + [cs appendFormat:@"- (%@ *) %@;\n\n", [eoAttr valueClassName], [eoAttr name]]; + } + + enumer = [classToOneRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [cs appendFormat:@"- (void) set%@:(%@ *) aValue;\n", [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className]]; + [cs appendFormat:@"- (%@ *) %@;\n\n", [[eoRel destinationEntity] className], [eoRel name]]; + } + + enumer = [classToManyRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [cs appendFormat:@"- (NSArray *) %@;\n\n", [eoRel name]]; + [cs appendFormat:@"- (void) addTo%@:(%@ *) aValue;\n", [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className]]; + [cs appendFormat:@"- (void) removeFrom%@:(%@ *) aValue;\n", [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className]]; + } + + [cs appendFormat:@"@end\n\n"]; + + return cs; +} + +- (NSArray*) retainableAttributesInEntity:(EOEntity*) entity +{ + NSArray * classNonScalarAttributes = [[entity classNonScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToOneRelationships = [[entity classToOneRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToManyRelationships = [[entity classToManyRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSMutableArray * mutArray = [NSMutableArray array]; + NSEnumerator * enumer; + EORelationship * eoRel; + EOAttribute * eoAttr; + + enumer = [classNonScalarAttributes objectEnumerator]; + + while ((eoAttr = [enumer nextObject])) { + [mutArray addObject:[[eoAttr name] initialLowercaseString]]; + } + + enumer = [classToOneRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [mutArray addObject:[[eoRel name] initialLowercaseString]]; + } + + enumer = [classToManyRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + [mutArray addObject:[[eoRel name] initialLowercaseString]]; + } + + + return mutArray; +} + +- (NSString*) deallocForAttributes:(NSArray*) attrs +{ + NSMutableString * cs = [NSMutableString string]; + NSEnumerator * enumer = [attrs objectEnumerator]; + NSString * anIvar = nil; + + [cs appendFormat:@"\n- (void) dealloc\n{\n"]; + + while ((anIvar = [enumer nextObject])) { + [cs appendFormat:@" [_%@ release];\n", anIvar]; + } + + [cs appendFormat:@"\n [super dealloc];\n}\n\n"]; + + return cs; +} + +- (NSString*) superclassGettersAndSettersForEntity:(EOEntity*) entity +{ + + NSMutableString * cs = [NSMutableString string]; + NSArray * classScalarAttributes = [[entity classScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classNonScalarAttributes = [[entity classNonScalarAttributes] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToOneRelationships = [[entity classToOneRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + NSArray * classToManyRelationships = [[entity classToManyRelationships] + sortedArrayUsingSelector:@selector(eoCompareOnName:)]; + + EOAttribute * eoAttr = nil; + EORelationship * eoRel = nil; + NSEnumerator * enumer = [classScalarAttributes objectEnumerator]; + + enumer = [classScalarAttributes objectEnumerator]; + + + while ((eoAttr = [enumer nextObject])) { + NSString * lowStr = [[eoAttr name] initialLowercaseString]; + + [cs appendFormat:@"- (void) set%@:(%@) aValue\n{\n if ((_%@ == aValue)) {\n return;\n }\n\n", + [[eoAttr name] initialCapitalString], + [eoAttr cScalarTypeString], lowStr]; + + [cs appendFormat:@" [self willChange];\n _%@ = aValue;\n}\n\n", + lowStr]; + + [cs appendFormat:@"- (%@) %@\n{\n return _%@;\n}\n\n", [eoAttr cScalarTypeString], [eoAttr name], lowStr]; + } + + enumer = [classNonScalarAttributes objectEnumerator]; + + while ((eoAttr = [enumer nextObject])) { + NSString * lowStr = [[eoAttr name] initialLowercaseString]; + + [cs appendFormat:@"- (void) set%@:(%@ *) aValue\n{\n if ((_%@ == aValue)) {\n return;\n }\n\n", + [[eoAttr name] initialCapitalString], + [eoAttr valueClassName], lowStr]; + + [cs appendFormat:@" [self willChange];\n ASSIGN(_%@, aValue);\n}\n\n", + lowStr, lowStr]; + [cs appendFormat:@"- (%@ *) %@\n{\n return _%@;\n}\n\n", [eoAttr valueClassName], [eoAttr name], lowStr]; + } + + + if ([classToOneRelationships count]) { + [cs appendString:@"// to-one relationships\n\n"]; + } + + enumer = [classToOneRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + NSString * lowStr = [[eoRel name] initialLowercaseString]; + + [cs appendFormat:@"- (void) set%@:(%@ *) aValue\n{\n if ((_%@ == aValue)) {\n return;\n }\n\n", + [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className], lowStr]; + + [cs appendFormat:@" [self willChange];\n ASSIGN(_%@, aValue);\n}\n\n", + lowStr, lowStr]; + [cs appendFormat:@"- (%@ *)%@\n{\n return _%@;\n}\n\n", [[eoRel destinationEntity] className], [eoRel name], lowStr]; + } + + enumer = [classToManyRelationships objectEnumerator]; + + while ((eoRel = [enumer nextObject])) { + NSString * lowStr = [[eoRel name] initialLowercaseString]; + + [cs appendFormat:@"- (NSArray *) %@\n{\n", + [eoRel name]]; + [cs appendFormat:@" return _%@;\n}\n\n", + lowStr]; + + [cs appendFormat:@"- (void) addTo%@:(%@ *) aValue\n{\n", [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className]]; + + [cs appendFormat:@" [self willChange];\n [_%@ addObject:aValue];\n}\n\n", + lowStr]; + + [cs appendFormat:@"- (void) removeFrom%@:(%@ *) aValue\n{\n", [[eoRel name] initialCapitalString], + [[eoRel destinationEntity] className]]; + [cs appendFormat:@" [self willChange];\n [_%@ removeObject:aValue];\n}\n\n", + lowStr]; + } + + + return cs; +} + +- (NSString*) superclassForEntity:(EOEntity*) entity +{ + NSMutableString * cs = [NSMutableString string]; + NSString * className = [entity className]; + + NSArray * retainableAttrs = [self retainableAttributesInEntity:entity]; + + [cs appendFormat:@"@implementation _%@\n", className]; + + [cs appendString:[self deallocForAttributes:retainableAttrs]]; + + [cs appendString:[self superclassGettersAndSettersForEntity:entity]]; + + + return cs; +} + + +- (void) generateSuperInterfaceFileForEntity:(EOEntity*) entity +{ + NSMutableString * codeString = [self interfacePrologueForEntity:entity]; + NSString * path = _generatedClassPath; + + NSString * className = [entity className]; + NSString * currentPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"_%@.h", + className]]; + + [codeString appendString:[self superInterfaceForEntity:entity]]; + + [codeString appendString:[self superInterfaceEpilogueForEntity:entity]]; + + if ([self updateNeededForFileAtPath:currentPath + content:codeString + canOverwrite:YES]) { + + [codeString writeToFile:currentPath + atomically:NO + encoding:NSUTF8StringEncoding + error:NULL]; + + } +} + +- (void) generateSubInterfaceFileForEntity:(EOEntity*) entity +{ + NSMutableString * codeString = [NSMutableString string]; + NSString * path = _subclassPath; + NSString * className = [entity className]; + NSString * currentPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.h", + className]]; + + [codeString appendFormat:@"// %@.h\n\n", className]; + [codeString appendFormat:@"#ifndef __%@_h_\n#define __%@_h_\n\n", className, className]; + [codeString appendFormat:@"#import \"_%@.h\"\n\n", className]; + + [codeString appendFormat:@"@interface %@: _%@\n", className, className]; + [codeString appendString:@"{\n // Custom instance variables go here\n}\n\n"]; + [codeString appendString:@"// Business logic methods go here\n\n@end\n"]; + [codeString appendFormat:@"\n#endif //__%@_h_\n", className]; + + if ([self updateNeededForFileAtPath:currentPath + content:codeString + canOverwrite:NO]) { + + [codeString writeToFile:currentPath + atomically:NO + encoding:NSUTF8StringEncoding + error:NULL]; + + } +} + +- (void) generateSuperclassFileForEntity:(EOEntity*) entity +{ + NSMutableString * codeString = [self superclassPrologueForEntity:entity]; + NSString * path = _generatedClassPath; + + + NSString * className = [entity className]; + NSString * currentPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"_%@.m", + className]]; + + [codeString appendString:[self superIncludesForEntity:entity]]; + [codeString appendString:[self superclassForEntity:entity]]; + + [codeString appendString:[self superclassEpilogueForEntity:entity]]; + + if ([self updateNeededForFileAtPath:currentPath + content:codeString + canOverwrite:YES]) { + + [codeString writeToFile:currentPath + atomically:NO + encoding:NSUTF8StringEncoding + error:NULL]; + + } +} + +- (void) generateSubclassFileForEntity:(EOEntity*) entity +{ + NSMutableString * codeString = [NSMutableString string]; + NSString * path = _subclassPath; + NSString * className = [entity className]; + NSString * currentPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.m", + className]]; + + [codeString appendFormat:@"// %@.m\n\n#import \"%@.h\"\n\n", className, className]; + [codeString appendFormat:@"@implementation %@\n\n", className]; + [codeString appendString:@"- (void)dealloc\n{\n [super dealloc];\n}\n\n"]; + [codeString appendString:@"// Business logic methods go here\n\n@end\n"]; + + if ([self updateNeededForFileAtPath:currentPath + content:codeString + canOverwrite:NO]) { + + [codeString writeToFile:currentPath + atomically:NO + encoding:NSUTF8StringEncoding + error:NULL]; + + } +} + +- (BOOL) getPaths +{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + BOOL ok = NO; + + [panel setTitle:@"Select path for super classes"]; + [panel setCanCreateDirectories:YES]; + [panel setCanChooseFiles:NO]; + [panel setCanChooseDirectories:YES]; + + if ([panel runModal] == NSOKButton) + { + NSURL * url = [panel directoryURL]; + + [_generatedClassPath release]; + _generatedClassPath = [[url path] retain]; + + [panel setTitle:@"Select path for sub classes"]; + if ([panel runModal] == NSOKButton) + { + NSURL * suburl = [panel directoryURL]; + + [_subclassPath release]; + _subclassPath = [[suburl path] retain]; + + ok = YES; + } + } + + return ok; +} + +- (void) generate +{ + NSEnumerator * entityEnumer = nil; + EOEntity * currentEntity = nil; + + _model = [[[NSDocumentController sharedDocumentController] currentDocument] eomodel]; + + if (!_model) { + return; + } + + if ([self getPaths]) { + + entityEnumer = [[_model entities] objectEnumerator]; + + while ((currentEntity = [entityEnumer nextObject])) { + [self generateSuperInterfaceFileForEntity:currentEntity]; + [self generateSuperclassFileForEntity:currentEntity]; + [self generateSubInterfaceFileForEntity:currentEntity]; + [self generateSubclassFileForEntity:currentEntity]; + } + } +} + +- (void) dealloc +{ + [_generatedClassPath release]; + [_subclassPath release]; + //[_superclassName release]; + //[_model release]; + + [super dealloc]; +} + +@end diff --git a/Apps/EOModelEditor/ConsistencyChecker.h b/Apps/EOModelEditor/ConsistencyChecker.h new file mode 100644 index 0000000..dee53af --- /dev/null +++ b/Apps/EOModelEditor/ConsistencyChecker.h @@ -0,0 +1,35 @@ +/** + ConsistencyChecker.h + + Author: Matt Rice + Date: Jul 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#ifdef NeXT_Foundation_LIBRARY +#include +#else +#include +#endif + +@class NSNotification; + +@interface ConsistencyChecker : NSObject +@end diff --git a/Apps/EOModelEditor/ConsistencyChecker.m b/Apps/EOModelEditor/ConsistencyChecker.m new file mode 100644 index 0000000..aac02e8 --- /dev/null +++ b/Apps/EOModelEditor/ConsistencyChecker.m @@ -0,0 +1,437 @@ +/** + ConsistencyChecker.m + + Author: Matt Rice + Date: 2005, 2006 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include "ConsistencyChecker.h" +#include "Preferences.h" + +#include + +#include +#include +#include +#include + +#ifdef NeXT_Foundation_LIBRARY +#include +#else +#include +#endif + +#import "EOMEDocument.h" + +#define MY_PRETTY NSMutableAttributedString \ + mutableAttributedStringWithBoldSubstitutionsWithFormat + +static NSMutableArray *successText; +static EOMEDocument *doc; + +@implementation ConsistencyChecker ++(void) initialize +{ + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(beginConsistencyCheck:) + name:EOMCheckConsistencyBeginNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(endConsistencyCheck:) + name:EOMCheckConsistencyEndNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(modelConsistencyCheck:) + name:EOMCheckConsistencyForModelNotification + object:nil]; + + successText = [[NSMutableArray alloc] initWithCapacity:8]; +} + ++ (void) beginConsistencyCheck:(NSNotification *)notif +{ +} + ++ (void) endConsistencyCheck:(NSNotification *)notif +{ + unsigned i,c; + doc = [notif object]; + for (i = 0, c = [successText count]; i < c; i++) + { + [doc appendConsistencyCheckSuccessText:[successText objectAtIndex:i]]; + } + doc = nil; + [successText removeAllObjects]; +} +/* helper functions */ +static void pass(BOOL flag, NSAttributedString *as) +{ + if (flag) + { + [successText addObject:as]; + } + else + [doc appendConsistencyCheckErrorText: as]; +} + +static BOOL isInvalid(NSString *str) +{ + return (str == nil) || ([str length] == 0) ? YES : NO; +} + ++ (void) attributeDetailsCheckForModel:(EOModel *)model +{ + NSArray *ents = [model entities]; + unsigned i, c; + BOOL flag = YES; + + for (i = 0, c = [ents count]; i < c; i++) + { + EOEntity *entity = [ents objectAtIndex:i]; + NSArray *arr = [entity attributes]; + unsigned j, d; + + for (j = 0, d = [arr count]; j < d; j++) + { + EOAttribute *attrib = [arr objectAtIndex:j]; + NSString *className = [attrib valueClassName]; + + if ([[attrib className] isEqualToString:@"NSNumber"]) + { + if (isInvalid([attrib externalType])) + { + pass(NO,[MY_PRETTY: @"Fail: %@ of type 'NSNumber has no external type\n",[(EOAttribute *)attrib name]]); + flag = NO; + } + } + + /* TODO check whether NSCalendarDate/NSData require valueFactory...*/ + if ((!isInvalid(className)) + && (![className isEqual:@"NSString"] + && ![className isEqual:@"NSNumber"] + && ![className isEqual:@"NSDecimalNumber"] + && ![className isEqual:@"NSDate"] + && ![className isEqual:@"NSData"]) + && (isInvalid([attrib valueFactoryMethodName]))) + { + pass(NO,[MY_PRETTY: @"Fail: attribute '%@' of type '%@' requires a value factory method name\n",[(EOAttribute *)attrib name], className]); + flag = NO; + } + } + /* relationship primary key propagation */ + arr = [entity relationships]; + for (j = 0, d = [arr count]; j < d; j++) + { + EORelationship *rel = [arr objectAtIndex:j]; + + if ([rel propagatesPrimaryKey] == YES) + { + NSArray *attribs = [rel sourceAttributes]; + NSArray *pkAttribs = [[rel entity] primaryKeyAttributes]; + unsigned k, e; + id pkey; + BOOL ok = YES; + + for (k = 0, e = [pkAttribs count]; ok == YES && k < e; k++) + { + pkey = [pkAttribs objectAtIndex:k]; + ok = [attribs containsObject:pkey]; + } + + if (ok == NO) + { + pass(NO,[MY_PRETTY: @"Fail: relationship '%@' propagates primary key but its source attributes does not contain the source entity's primary key attributes\n",[(EORelationship *)rel name]]); + flag = NO; + } + + ok = YES; + attribs = [rel destinationAttributes]; + pkAttribs = [[rel destinationEntity] primaryKeyAttributes]; + + for (k = 0, e = [pkAttribs count]; ok == YES && k < e; k++) + { + pkey = [pkAttribs objectAtIndex:k]; + ok = [attribs containsObject:pkey]; + } + + if (ok == NO) + { + pass(NO, [MY_PRETTY: @"Fail: relationship '%@' propagates primary key but its destination attributes does not contain the destination entity's primary key attributes\n",[(EORelationship *)rel name]]); + flag = NO; + } + } + } + } + if (flag == YES) + pass(YES, [MY_PRETTY: @"Success: attribute detail check\n"]); +} + ++ (void) entityStoredProcedureCheckForModel:(EOModel *)model +{ + /* TODO */ +} + ++ (void) storedProcedureCheckForModel:(EOModel *)model +{ + /* TODO */ +} + ++ (void) inheritanceCheckForModel:(EOModel *)model +{ + BOOL flag = YES; + NSArray *ents = [model entities]; + unsigned i,c; + + for (i = 0, c = [ents count]; i < c; i++) + { + EOEntity *ent = [ents objectAtIndex:i]; + NSArray *subEnts = [ent subEntities]; + unsigned j, d; + + for (j = 0, d = [subEnts count]; j < d; j++) + { + EOEntity *subEnt = [subEnts objectAtIndex:j]; + NSArray *arr = [ent attributes]; + NSArray *subArr = [subEnt attributes]; + unsigned k, e; + + for (k = 0, e = [arr count]; k < e; k++) + { + EOAttribute *attrib = [arr objectAtIndex:k]; + + if (![subArr containsObject:[(EOAttribute *)attrib name]]) + { + pass(NO, [MY_PRETTY: @"FAIL: sub entity '%@' missing parent's '%@' attribute",[(EOEntity *)subEnt name], [(EOAttribute *)attrib name]]); + flag = NO; + } + } + + arr = [ent relationships]; + for (k = 0, e = [arr count]; k < e; k++) + { + EORelationship *rel = [arr objectAtIndex:k]; + EORelationship *subRel = [subEnt relationshipNamed:[(EORelationship *)rel name]]; + + if (!subRel || ![[rel definition] isEqual:[subRel definition]]) + { + pass(NO, [MY_PRETTY: @"FAIL: sub entity '%@' missing relationship '%@' or definitions do not match", [(EOEntity *)subEnt name], [(EORelationship *)rel name]]); + flag = NO; + } + } + + arr = [ent primaryKeyAttributes]; + subArr = [subEnt primaryKeyAttributes]; + if (![arr isEqual:subArr]) + { + pass(NO, [MY_PRETTY: @"FAIL: sub entity '%@' and parent entities primary keys do not match", [(EOEntity *)subEnt name]]); + flag = NO; + } + if ([[subEnt externalName] isEqual:[ent externalName]] + && (![subEnt restrictingQualifier] || ![ent restrictingQualifier])) + { + pass(NO, [MY_PRETTY: @"FAIL: sub entity '%@' and parent entity in same table must contain a restricting qualifier", [(EOEntity *)subEnt name]]); + flag = NO; + } + } + } + + if (flag == YES) + { + pass(YES, [MY_PRETTY: @"Success: inheritance check"]); + } +} + ++ (void) relationshipCheckForModel:(EOModel *)model +{ + /* TODO */ + NSArray *ents = [model entities]; + unsigned i, c; + BOOL flag = YES; + + for (i = 0, c = [ents count]; i < c; i++) + { + EOEntity *ent = [ents objectAtIndex:i]; + NSArray *arr = [ent relationships]; + unsigned j, d; + + for (j = 0, d = [arr count]; j < d; j++) + { + id rel = [arr objectAtIndex:j]; + + if (![[rel joins] count]) + { + pass(NO,[MY_PRETTY: @"Fail: relationship '%@' does not contain a join\n", [(EORelationship *)rel name]]); + flag = NO; + } + + if ([rel isToMany] == NO) + { + NSArray *pkAttribs = [[rel destinationEntity] primaryKeyAttributes]; + NSArray *attribs = [rel destinationAttributes]; + + if (![pkAttribs isEqual:attribs]) + { + pass(NO, [MY_PRETTY: @"Fail: destination attributes of relationship '%@' are not the destination entity primary keys\n",[(EORelationship *)rel name]]); + flag = NO; + } + } + + if ([rel propagatesPrimaryKey]) + { + NSArray *pkAttribs = [[rel entity] primaryKeyAttributes]; + NSArray *attribs = [rel sourceAttributes]; + unsigned k, e; + BOOL ok = YES; + + for (k = 0, e = [pkAttribs count]; ok == YES && k < e; k++) + { + ok = [attribs containsObject: [pkAttribs objectAtIndex:k]]; + } + + if (ok == NO) + { + pass(NO, [MY_PRETTY: @"Fail: relationship '%@' propagates primary keys but does not contain source entities primary key attributes\n", [(EORelationship *)rel name]]); + flag = NO; + } + + pkAttribs = [[rel destinationEntity] primaryKeyAttributes]; + attribs = [rel destinationAttributes]; + + for (k = 0, e = [pkAttribs count]; ok == YES && k < e; k++) + { + ok = [attribs containsObject: [pkAttribs objectAtIndex:k]]; + } + + if (ok == NO) + { + pass(NO, [MY_PRETTY: @"Fail: relationship '%@' propagates primary keys but does not contain destination entities primary key attributes\n", [(EORelationship *)rel name]]); + flag = NO; + } + + if ([[rel inverseRelationship] propagatesPrimaryKey]) + { + pass(NO,[MY_PRETTY: @"Fail: both relationship '%@' and inverse relationship '%@' should not propagate primary keys\n", [(EORelationship *)rel name], [(EORelationship *)[rel inverseRelationship] name]]); + flag = NO; + } + } + } + } + if (flag == YES) + pass(YES, [MY_PRETTY: @"Success: relationship check\n"]); +} + ++ (void) primaryKeyCheckForModel:(EOModel *)model +{ + NSArray *ents = [model entities]; + unsigned i,c; + BOOL flag = YES; + + for (i = 0, c = [ents count]; i < c; i++) + { + EOEntity *entity = [ents objectAtIndex:i]; + NSArray *arr = [entity primaryKeyAttributes]; + + if (![arr count]) + { + pass(NO,[MY_PRETTY: @"Fail: Entity '%@' does not have a primary key.\n", [(EOEntity *)entity name]]); + flag = NO; + } + } + if (flag == YES) + pass(YES, [MY_PRETTY:@"Success: primary key check\n"]); +} + ++ (void) externalNameCheckForModel:(EOModel *)model +{ + NSArray *ents = [model entities]; + NSArray *arr; + unsigned i, c, j, d; + BOOL flag = YES; + + for (i = 0,c = [ents count]; i < c; i++) + { + EOEntity *entity = [ents objectAtIndex:i]; + NSString *extName = [entity externalName]; + if (isInvalid(extName)) + { + pass(NO,[MY_PRETTY: @"Fail: Entity '%@' does not have an external name\n", + [(EOEntity *)entity name]]); + flag = NO; + } + arr = [entity attributes]; + for (j = 0, d = [arr count]; j + Date: Jul 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#ifdef NeXT_Foundation_LIBRARY +#include +#else +#include +#endif + +#ifdef NeXT_GUI_LIBRARY +#include +#else +#include +#endif + +@class NSPanel; +@class NSButton; +@class NSTextView; + +@interface ConsistencyResults : NSObject +{ + IBOutlet NSPanel *_panel; + IBOutlet NSButton *okButton; + IBOutlet NSButton *cancelButton; + IBOutlet NSTextView *results; + BOOL successful; +} ++ (id) sharedConsistencyPanel; +- (int) showConsistencyCheckResults:(id)sender cancelButton:(BOOL)useCancel +showOnSuccess:(BOOL)flag; +@end diff --git a/Apps/EOModelEditor/ConsistencyResults.m b/Apps/EOModelEditor/ConsistencyResults.m new file mode 100644 index 0000000..544f951 --- /dev/null +++ b/Apps/EOModelEditor/ConsistencyResults.m @@ -0,0 +1,104 @@ +/** + ConsistencyResults.m + + Author: Matt Rice + Date: Jul 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include + +#ifdef NeXT_GUI_LIBRARY +#include +#else +#include +#include +#include +#include +#include +#include +#endif + +#include + +static ConsistencyResults *_sharedResults; + +@implementation ConsistencyResults ++ (id) sharedConsistencyPanel; +{ + if (!_sharedResults) + _sharedResults = [[self allocWithZone:NSDefaultMallocZone()] init]; + + return _sharedResults; +} + +- (id) init +{ + self = [super init]; + [NSBundle loadGSMarkupNamed:@"ConsistencyResults" owner:self]; + successful = YES; + return self; +} + +- (int) showConsistencyCheckResults:(id)sender cancelButton:(BOOL)useCancel +showOnSuccess:(BOOL)flag +{ + int foo = NSRunStoppedResponse; + + [cancelButton setEnabled:useCancel]; + if (!flag && successful) + { + } + else + { + foo = [NSApp runModalForWindow:_panel]; + } + /* reset this.. */ + successful = YES; + return foo; +} + +- (void) appendConsistencyCheckErrorText:(NSAttributedString *)errorText +{ + successful = NO; + [[results textStorage] appendAttributedString:errorText]; +} + +- (void) appendConsistencyCheckSuccessText:(NSAttributedString *)successText +{ + [[results textStorage] appendAttributedString:successText]; +} + +- (void) cancel:(id)sender +{ + [NSApp abortModal]; + [_panel orderOut:self]; + [results setString:@""]; +} + +- (void) ok:(id)sender +{ + [NSApp stopModal]; + [_panel orderOut:self]; + [results setString:@""]; +} + +@end diff --git a/Apps/EOModelEditor/DataBrowser.h b/Apps/EOModelEditor/DataBrowser.h new file mode 100644 index 0000000..2406424 --- /dev/null +++ b/Apps/EOModelEditor/DataBrowser.h @@ -0,0 +1,54 @@ +/** + DataBrowser.h EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#ifndef __DataBrowser_h +#define __DataBrowser_h + +#import +#import +@class TableViewController; +@class EOEditingContext; + +@interface DataBrowser : NSObject +{ + IBOutlet NSWindow * _window; + IBOutlet NSTextField * _entityNameField; + IBOutlet NSTextField * _fetchLimitText; + IBOutlet NSTextField * _qualifierText; + IBOutlet NSTableView * _tableView; + EOEntity * _currentEntity; + TableViewController *_tableViewController; + EOEditingContext *_editingContext; +} + ++ (DataBrowser *) sharedBrowser; + +- (void) setEntity:(EOEntity*) aValue; + +@end + +#endif diff --git a/Apps/EOModelEditor/DataBrowser.m b/Apps/EOModelEditor/DataBrowser.m new file mode 100644 index 0000000..b01042e --- /dev/null +++ b/Apps/EOModelEditor/DataBrowser.m @@ -0,0 +1,198 @@ +/** + DataBrowser.h EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#import "DataBrowser.h" +#import +#import "TableViewController.h" +#import + +static DataBrowser *sharedDataBrowser = nil; + +@implementation DataBrowser + +- (NSWindow*) _window +{ + return _window; +} + ++ (DataBrowser *) sharedBrowser; +{ + if (!sharedDataBrowser) + sharedDataBrowser = [[self alloc] init]; + + [[sharedDataBrowser _window] makeKeyAndOrderFront:nil]; + + return sharedDataBrowser; +} + +- (id) init +{ + if (sharedDataBrowser) + { + [[NSException exceptionWithName:NSInternalInconsistencyException + reason: @"singleton initialized multiple times" + userInfo:nil] raise]; + return nil; + } + self = [super init]; + + [NSBundle loadGSMarkupNamed: @"DataBrowser" owner: self]; + + [_window setFrameUsingName:NSStringFromClass([self class])]; + + _tableViewController = [TableViewController new]; + [_tableView setDataSource:_tableViewController]; + [_tableView setDelegate:_tableViewController]; + + + return self; +} + +- (void) removeTableColumns +{ + NSArray * columns = [_tableView tableColumns]; + NSEnumerator * colEnumer = [[NSArray arrayWithArray:columns] objectEnumerator]; + NSTableColumn * column; + + while ((column = [colEnumer nextObject])) { + if ([[column identifier] isEqual:@"_#number"] == NO) { + [_tableView removeTableColumn:column]; + } + } + +} + +- (void) setEntity:(EOEntity*) aValue +{ + ASSIGN(_currentEntity, aValue); + + if (_currentEntity) { + NSEnumerator * attributeEnumer = [[_currentEntity attributes] objectEnumerator]; + EOAttribute * currentAttribute = nil; + + [_tableViewController setRepresentedObject:[NSArray array]]; + [_tableView reloadData]; + + [self removeTableColumns]; + [_entityNameField setStringValue:[_currentEntity name]]; + + while ((currentAttribute = [attributeEnumer nextObject])) { + NSString * attributeName = [currentAttribute name]; + NSTableColumn * column = [[NSTableColumn alloc] initWithIdentifier:attributeName]; + + [[column headerCell] setStringValue:attributeName]; + [column setEditable:NO]; + + [_tableView addTableColumn:column]; + RELEASE(column); + } + + } + +} + +- (void) dealloc +{ + sharedDataBrowser = nil; + + DESTROY(_tableViewController); + DESTROY(_currentEntity); + DESTROY(_editingContext); + + [super dealloc]; +} + +- (void) awakeFromGSMarkup +{ +} + +- (IBAction) fetch:(id) sender +{ + EOFetchSpecification *fetchSpec; + EOQualifier *qual = nil; + NSArray *results; + NSMutableArray *keyPaths = [NSMutableArray array]; + NSEnumerator *attributeEnumer = [[_currentEntity attributes] objectEnumerator]; + EOAttribute *attribute; + + + while ((attribute = [attributeEnumer nextObject])) { + [keyPaths addObject:[attribute name]]; + } + + [[EOModelGroup defaultGroup] addModel:[_currentEntity model]]; + + NS_DURING { + + if (!_editingContext) { + ASSIGN(_editingContext, [EOEditingContext new]); + RELEASE(_editingContext); + [_editingContext setInvalidatesObjectsWhenFreed:YES]; + } else { + [_editingContext invalidateAllObjects]; + } + + + + fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:[_currentEntity name] + qualifier:qual + sortOrderings:nil]; + + [fetchSpec setRawRowKeyPaths:keyPaths]; + + results = [_editingContext objectsWithFetchSpecification:fetchSpec]; + + [_tableViewController setRepresentedObject:results]; + [_tableView reloadData]; + + } NS_HANDLER { + NSRunCriticalAlertPanel (@"Problem fetching from Database", + @"%@", + @"Ok", + nil, + nil, + localException); + } NS_ENDHANDLER; + + [[EOModelGroup defaultGroup] removeModel:[_currentEntity model]]; + +} + +- (BOOL)windowShouldClose:(id)sender +{ + [_window endEditingFor:self]; + + [_window saveFrameUsingName:NSStringFromClass([self class])]; + + [_window setDelegate:nil]; + [_window orderOut:self]; + [self performSelector:@selector(release) withObject:self afterDelay:0.001]; + + return YES; +} + +@end diff --git a/Apps/EOModelEditor/EOAdditions.h b/Apps/EOModelEditor/EOAdditions.h new file mode 100644 index 0000000..529684f --- /dev/null +++ b/Apps/EOModelEditor/EOAdditions.h @@ -0,0 +1,36 @@ +#ifndef __EOAdditions_H_ +#define __EOAdditions_H_ + +/* + EOAdditions.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +/* these use NSNumbers because they are used in key value coding. */ +@interface EOAttribute (ModelerAdditions) +- (NSNumber *) isPrimaryKey; +- (void) setIsPrimaryKey:(NSNumber *)flag; +- (NSNumber *) isClassProperty; +- (void) setIsClassProperty:(NSNumber *)flag; +@end + +#endif // __EOAdditions_H_ diff --git a/Apps/EOModelEditor/EOAdditions.m b/Apps/EOModelEditor/EOAdditions.m new file mode 100644 index 0000000..a00632d --- /dev/null +++ b/Apps/EOModelEditor/EOAdditions.m @@ -0,0 +1,190 @@ +/** + EOAdditions.m + + Author: Matt Rice + Date: 2005, 2006 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include +#include +#include + +#ifdef NeXT_Foundation_LIBRARY +#include +#else +#include +#include +#endif + +#include + +/* this is all stuff for key value coding.. */ +static inline NSNumber * isClassProperty(id self) +{ + return [NSNumber numberWithBool: + [[[self entity] classProperties] containsObject:self]]; +} + +static inline void setIsClassProperty(id self, NSNumber *flag) +{ + BOOL isProp = [flag boolValue]; + NSArray *props = [[self entity] classProperties]; + + if (isProp) + { + if (!props) + { + if (![[self entity] setClassProperties: [NSArray arrayWithObject:self]]) + NSLog(@"invalid class property"); + } + else if (![props containsObject:self]) + { + [[self entity] setClassProperties: [props arrayByAddingObject:self]]; + } + } + else + { + if ([props containsObject:self]) + { + NSMutableArray *newProps = [NSMutableArray arrayWithArray:props]; + [newProps removeObject: self]; + [[self entity] setClassProperties: newProps]; + } + } +} + +@implementation EOAttribute (ModelerAdditions) + +- (NSNumber *) isPrimaryKey +{ + BOOL flag = [[[self entity] primaryKeyAttributes] containsObject:self]; + return [NSNumber numberWithBool: flag]; +} + +- (void) setIsPrimaryKey:(NSNumber *)flag +{ + BOOL isKey = [flag boolValue]; + NSArray *pka = [[self entity] primaryKeyAttributes]; + + if (isKey) + { + if (!pka) + { + [[self entity] + setPrimaryKeyAttributes: [NSArray arrayWithObject:self]]; + } + else if (![pka containsObject:self]) + { + [[self entity] + setPrimaryKeyAttributes: [pka arrayByAddingObject:self]]; + } + } + else + { + if ([pka containsObject:self]) + { + NSMutableArray *newPks = [NSMutableArray arrayWithArray:pka]; + [newPks removeObject: self]; + [[self entity] setPrimaryKeyAttributes: newPks]; + + } + } +} + +- (NSNumber *) isClassProperty +{ + id flag = isClassProperty(self); + + return flag; +} + +- (void) setIsClassProperty:(NSNumber *)flag +{ + setIsClassProperty(self, flag); +} + +- (NSNumber *) isUsedForLocking +{ + BOOL flag; + + flag = [[[self entity] attributesUsedForLocking] containsObject:self]; + + return [NSNumber numberWithBool:flag]; +} + +- (void) setIsUsedForLocking:(NSNumber *)flag +{ + BOOL yn = [flag boolValue]; + NSArray *la = RETAIN([[self entity] attributesUsedForLocking]); + + if (yn) + { + + if (la == nil) + { + [[self entity] + setAttributesUsedForLocking:[NSArray arrayWithObject:self]]; + } + else if (![la containsObject:self]) + { + [[self entity] + setAttributesUsedForLocking:[la arrayByAddingObject:self]]; + } + } + else + { + if ([la containsObject:self]) + { + NSMutableArray *newLA = [NSMutableArray arrayWithArray:la]; + [newLA removeObject:self]; + [[self entity] setAttributesUsedForLocking:newLA]; + } + } +} + +- (NSNumber *)allowNull +{ + BOOL flag = [self allowsNull]; + return [NSNumber numberWithBool:flag]; +} + +- (void) setAllowNull:(NSNumber *)flag +{ + [self setAllowsNull:[flag boolValue]]; +} + +@end + + +@implementation EORelationship (ModelerAdditions) +- (NSNumber *) isClassProperty +{ + id flag = isClassProperty(self); + return flag; +} + +- (void) setIsClassProperty:(NSNumber *)flag +{ + setIsClassProperty(self, flag); +} + +@end + diff --git a/Apps/EOModelEditor/EOMEDocument.h b/Apps/EOModelEditor/EOMEDocument.h new file mode 100644 index 0000000..1747abf --- /dev/null +++ b/Apps/EOModelEditor/EOMEDocument.h @@ -0,0 +1,74 @@ +/** + EOMEDocument.h EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of DBModeler. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#ifndef __EOMEDocument_h +#define __EOMEDocument_h + +#include +#include +#include +#include + + +GDL2MODELER_EXPORT NSString *EOMCheckConsistencyBeginNotification; +GDL2MODELER_EXPORT NSString *EOMCheckConsistencyEndNotification; +GDL2MODELER_EXPORT NSString *EOMCheckConsistencyForModelNotification; +GDL2MODELER_EXPORT NSString *EOMConsistencyModelObjectKey; + +@class TableViewController; + +@interface EOMEDocument : GSMarkupDocument +{ + IBOutlet NSOutlineView * _outlineView; + IBOutlet NSTableView * _topTableView; + IBOutlet NSTableView * _bottomTableView; + IBOutlet NSTableView * _storedProcedureTableView; + IBOutlet NSPopUpButton * _topVisibleColumnsPopUp; + IBOutlet NSPopUpButton * _bottomVisibleColumnsPopUp; + IBOutlet NSPopUpButton * _storedProcVisibleColumnsPopUp; + IBOutlet NSPopUpButton * _storedProcDirectionUp; + IBOutlet NSTabView * _tabView; + EOModel * _eomodel; + id _outlineSelection; + TableViewController * _topTableViewController; + TableViewController * _bottomTableViewController; + TableViewController * _procTableViewController; + NSArray * _entityNames; + NSArray * _selectedObjects; +} + +- (id) selectedObject; +- (id) outlineSelection; +- (EOModel*) eomodel; +- (void) setEomodel:(EOModel*) model; + +- (void) setAdaptor:(id)sender; + +@end + + +#endif diff --git a/Apps/EOModelEditor/EOMEDocument.m b/Apps/EOModelEditor/EOMEDocument.m new file mode 100644 index 0000000..f7264b3 --- /dev/null +++ b/Apps/EOModelEditor/EOMEDocument.m @@ -0,0 +1,899 @@ +/** + EOMEDocument.m EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#import "EOMEDocument.h" +#import "EOMEEOAccessAdditions.h" +#import "TableViewController.h" +#import "SQLGenerator.h" +#import "AdaptorsPanel.h" +#import "CodeGenerator.h" +#import +#import "DataBrowser.h" + +static NSString * entitiesItem = @"Entities"; +static NSString * storedProceduresItem = @"Procedures"; + +/** Notification sent when beginning consistency checks. + * The notifications object is the EOModelerDocument. + * The receiver should call -appendConsistencyCheckErrorText: + * on the notifications object for any consistency check failures */ +NSString *EOMCheckConsistencyBeginNotification = +@"EOMCheckConsistencyBeginNotification"; + +/** Notification sent when ending consistency checks. + * The notifications object is the EOModelerDocument. + * The receiver should call -appendConsistencyCheckSuccessText: + * on the notifications object for any consistency checks that passed. */ +NSString *EOMCheckConsistencyEndNotification = +@"EOMCheckConsistencyEndNotification"; + +/** Notification sent when beginning EOModel consistency checks. + * The notifications object is the EOModelerDocument. + * The receiver should call -appendConsistencyCheckErrorText: + * on the notifications object for any consistency check failures + * the userInfo dictionary contains an EOModel instance for the + * EOMConsistencyModelObjectKey key. */ +NSString *EOMCheckConsistencyForModelNotification = +@"EOMCheckConsistencyForModelNotification"; +NSString *EOMConsistencyModelObjectKey = @"EOMConsistencyModelObjectKey"; + +@implementation EOMEDocument + ++ (void) initialize +{ +// [entitiesItem retain]; +// [storedProceduresItem retain]; +} + + +- (void) dealloc +{ + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + // stop observing + [self setSelectedObjects:nil]; + + DESTROY(_outlineSelection); + DESTROY(_eomodel); + DESTROY(_topTableViewController); + DESTROY(_bottomTableViewController); + DESTROY(_procTableViewController); + DESTROY(_entityNames); + DESTROY(_selectedObjects); + + [super dealloc]; +} + +- (EOModel*) eomodel +{ + return _eomodel; +} + +- (void) setEomodel:(EOModel*) model +{ + ASSIGN(_eomodel, model); +} + +- (NSString *)windowNibName +{ + // Implement this to return a nib to load OR implement -makeWindowControllers to manually create your controllers. + return @"EOMEDocument"; +} + +- (NSButtonCell*) _cellWithImageNamed:(NSString*) aName +{ + NSButtonCell *cell = [[NSButtonCell alloc] initImageCell:nil]; + [cell setButtonType:NSSwitchButton]; + [cell setImagePosition:NSImageOnly]; + [cell setBordered:NO]; + [cell setBezeled:NO]; + [cell setAlternateImage:[NSImage imageNamed:aName]]; + [cell setControlSize: NSSmallControlSize]; + [cell setEditable:NO]; + + return AUTORELEASE(cell); +} + +- (void) initTopColumns +{ + NSTableColumn * column; + NSButtonCell * cell; + + column = [_topTableView tableColumnWithIdentifier:@"isPrimaryKey"]; + if (column) { + cell = [self _cellWithImageNamed:@"Key_On"]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } + column = [_topTableView tableColumnWithIdentifier:@"isClassProperty"]; + if (column) { + cell = [self _cellWithImageNamed:@"ClassProperty_On"]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } + column = [_topTableView tableColumnWithIdentifier:@"allowNull"]; + if (column) { + cell = [self _cellWithImageNamed:@"AllowsNull_On"]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } + + column = [_topTableView tableColumnWithIdentifier:@"isUsedForLocking"]; + if (column) { + cell = [self _cellWithImageNamed:@"Locking_On"]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } + +} + +- (void) initBottomColumns +{ + NSTableColumn * column; + NSButtonCell * cell; + + column = [_bottomTableView tableColumnWithIdentifier:@"isToMany"]; + if (column) { + cell = [self _cellWithImageNamed:@"toMany"]; + [cell setImage:[NSImage imageNamed:@"toOne"]]; + [cell setImageDimsWhenDisabled:NO]; + [cell setEnabled:NO]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } + column = [_bottomTableView tableColumnWithIdentifier:@"isClassProperty"]; + if (column) { + cell = [self _cellWithImageNamed:@"ClassProperty_On"]; + [column setEditable: NO]; + [column setDataCell:cell]; + + } +} + +- (void) initStoredProcedureColumns +{ + NSTableColumn * column; + NSButtonCell * cell; + + column = [_storedProcedureTableView tableColumnWithIdentifier:@"parameterDirection"]; + if (column) { + cell = [_storedProcDirectionUp cell]; + [column setEditable: NO]; + [column setDataCell:cell]; + } +} + + +- (void) updateItemsInPopUp:(NSPopUpButton*) popUpB forEOClass:(Class) eoclass tableView:(NSTableView*) tableView +{ + NSDictionary * columnDict = [eoclass allColumnNames]; + NSArray * sortedTags = [[columnDict allKeys] sortedArrayUsingSelector:@selector(compare:)]; + NSEnumerator * enumer = [sortedTags objectEnumerator]; + NSString * currentKey = nil; + NSDictionary * currentDict = nil; + NSMenu * menu = [popUpB menu]; + + [popUpB removeAllItems]; + + NSMenuItem * item = [NSMenuItem alloc]; + + [item initWithTitle:@"" + action:NULL + keyEquivalent:@""]; + + [item setTag:1000]; + [item setImage:[NSImage imageNamed:@"NSAddTemplate"]]; // @"gear" + [menu addItem:item]; + [item release]; + + // [[[NSImage imageNamed:@"NSAddTemplate"] TIFFRepresentation] writeToFile:@"/tmp/NSAddTemplate.tiff" atomically:NO]; + + while ((currentKey = [enumer nextObject])) { + currentDict = [columnDict objectForKey:currentKey]; + NSTableColumn * col = [tableView tableColumnWithIdentifier:[currentDict objectForKey:@"key"]]; + + item = [NSMenuItem alloc]; + + [item initWithTitle:[currentDict objectForKey:@"name"] + action:NULL + keyEquivalent:@""]; + + [item setTag:[currentKey integerValue]]; + if ([col isHidden]) { + [item setState:NSOffState]; + } else { + [item setState:NSOnState]; + } + + [menu addItem:item]; + + [item release]; + + } + +} + +- (void) makeCornerViews +{ + NSView * cornerView = [_topTableView cornerView]; + + [[_topVisibleColumnsPopUp cell] setArrowPosition:NSPopUpNoArrow]; + [_topVisibleColumnsPopUp setFrame:[cornerView frame]]; + [_topVisibleColumnsPopUp setImagePosition:NSImageOnly]; + [_topVisibleColumnsPopUp setBezelStyle:NSShadowlessSquareBezelStyle]; + + [_topTableView setCornerView:_topVisibleColumnsPopUp]; + + // bottom table view + + cornerView = [_bottomTableView cornerView]; + + [[_bottomVisibleColumnsPopUp cell] setArrowPosition:NSPopUpNoArrow]; + [_bottomVisibleColumnsPopUp setFrame:[cornerView frame]]; + [_bottomVisibleColumnsPopUp setImagePosition:NSImageOnly]; + [_bottomVisibleColumnsPopUp setBezelStyle:NSShadowlessSquareBezelStyle]; + + [_bottomTableView setCornerView:_bottomVisibleColumnsPopUp]; + + // stored proc table view + + cornerView = [_storedProcedureTableView cornerView]; + + [[_storedProcVisibleColumnsPopUp cell] setArrowPosition:NSPopUpNoArrow]; + [_storedProcVisibleColumnsPopUp setFrame:[cornerView frame]]; + [_storedProcVisibleColumnsPopUp setImagePosition:NSImageOnly]; + [_storedProcVisibleColumnsPopUp setBezelStyle:NSShadowlessSquareBezelStyle]; + + [_storedProcedureTableView setCornerView:_storedProcVisibleColumnsPopUp]; + +} + +- (void) awakeFromGSMarkup +{ + //NSImage * smartImage = [NSImage imageNamed:@"gear"]; + +// [[smartImage TIFFRepresentation] writeToFile:@"/tmp/NSSmartBadgeTemplate.tiff" atomically:NO]; + + [_outlineView setHeaderView:nil]; + + [self makeCornerViews]; + [self updateItemsInPopUp:_topVisibleColumnsPopUp + forEOClass:[EOAttribute class] + tableView:_topTableView]; + + [self updateItemsInPopUp:_bottomVisibleColumnsPopUp + forEOClass:[EORelationship class] + tableView:_bottomTableView]; + + [self updateItemsInPopUp:_storedProcVisibleColumnsPopUp + forEOClass:[EOStoredProcedure class] + tableView:_storedProcedureTableView]; + +// [_storedProcDirectionUp setBezelStyle: NSRegularSquareBezelStyle]; + [_storedProcDirectionUp setBordered: NO]; + + + [self initTopColumns]; + [self initBottomColumns]; + [self initStoredProcedureColumns]; + + + _topTableViewController = [TableViewController new]; + _bottomTableViewController = [TableViewController new]; + _procTableViewController = [TableViewController new]; + + [_topTableView setDataSource:_topTableViewController]; + [_topTableView setDelegate:_topTableViewController]; + + [_bottomTableView setDataSource:_bottomTableViewController]; + [_bottomTableView setDelegate:_bottomTableViewController]; + + [_storedProcedureTableView setDataSource:_procTableViewController]; + [_storedProcedureTableView setDelegate:_procTableViewController]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(outlineViewSelectionDidChange:) + name:NSOutlineViewSelectionDidChangeNotification + object:_outlineView]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(outlineViewItemWillCollapse:) + name:NSOutlineViewItemWillCollapseNotification + object:_outlineView]; + + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(tableViewSelectionDidChange:) + name:NSTableViewSelectionDidChangeNotification + object:_topTableView]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(tableViewSelectionDidChange:) + name:NSTableViewSelectionDidChangeNotification + object:_bottomTableView]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(tableViewSelectionDidChange:) + name:NSTableViewSelectionDidChangeNotification + object:_storedProcedureTableView]; + +} + + +- (void) setSelectedObjects:(NSArray*) aValue +{ + + [self stopObserving]; + + ASSIGN(_selectedObjects, aValue); + + [self startObserving]; + + // we will probably have the definition of EOModelerSelectionChanged somewhere else + // so we just use a string for now + [[NSNotificationCenter defaultCenter] postNotificationName:@"EOModelerSelectionChanged" + object:self]; +} + +- (NSArray*) selectedObjects +{ + return _selectedObjects; +} + +- (void) startObserving +{ + if ((_selectedObjects) && ([_selectedObjects count])) { + NSEnumerator * objEnumer = [_selectedObjects objectEnumerator]; + id currentObj = nil; + + while ((currentObj = [objEnumer nextObject])) { + NSEnumerator * keyEnumer = [[currentObj observerKeys] objectEnumerator]; + NSString * currentKey; + while ((currentKey = [keyEnumer nextObject])) { + [currentObj addObserver:self + forKeyPath:currentKey + options:(NSKeyValueObservingOptionNew | + NSKeyValueObservingOptionOld) + context:NULL]; + + } + } + } +} + +- (void) stopObserving +{ + if ((_selectedObjects) && ([_selectedObjects count])) { + NSEnumerator * objEnumer = [_selectedObjects objectEnumerator]; + id currentObj = nil; + + while ((currentObj = [objEnumer nextObject])) { + NSEnumerator * keyEnumer = [[currentObj observerKeys] objectEnumerator]; + NSString * currentKey; + while ((currentKey = [keyEnumer nextObject])) { + [currentObj removeObserver:self + forKeyPath:currentKey]; + + } + } + } +} + + +- (void) setOutlineSelection:(id) aValue +{ + ASSIGN(_outlineSelection, aValue); + + if ([_outlineSelection class] == [EOStoredProcedure class]) { + [_tabView selectTabViewItemAtIndex:1]; + + [_procTableViewController setRepresentedObject:[(EOStoredProcedure*)_outlineSelection arguments]]; + NSLog(@"%s:%@",__PRETTY_FUNCTION__, [(EOStoredProcedure*)_outlineSelection arguments]); + [_storedProcedureTableView reloadData]; + + } else { + [_tabView selectTabViewItemAtIndex:0]; + + [_topTableViewController setRepresentedObject:[_outlineSelection attributes]]; + [_topTableView reloadData]; + + [_bottomTableViewController setRepresentedObject:[_outlineSelection relationships]]; + [_bottomTableView reloadData]; + } + + if (!aValue) { + [self setSelectedObjects:[NSArray arrayWithObject:_eomodel]]; + } else { + [self setSelectedObjects:[NSArray arrayWithObject:aValue]]; + } +} + +- (id) outlineSelection +{ + return _outlineSelection; +} + +- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError +{ + NSLog(@"%s:%@", __PRETTY_FUNCTION__, typeName); + + NS_DURING { + + [_eomodel writeToFile: [absoluteURL path]]; + + } NS_HANDLER { + + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[localException reason] + forKey:NSLocalizedDescriptionKey]; + + *outError = [NSError errorWithDomain:@"EOModel" + code:1 + userInfo:userInfo]; + return NO; + } NS_ENDHANDLER; + + return YES; +} + + +//- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError +//{ +// NSLog(@"%s:%@", __PRETTY_FUNCTION__, typeName); + // Insert code here to write your document to data of the specified type. If the given outError != NULL, + // ensure that you set *outError when returning nil. + + // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or + // -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead. + + // For applications targeted for Panther or earlier systems, + // you should use the deprecated API -dataRepresentationOfType:. + // In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead. + +// return nil; +//} + +//- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError +//{ +// NSLog(@"%s:%@", __PRETTY_FUNCTION__, typeName); +// +// // Insert code here to read your document from the given data of the specified type. If the given outError != NULL, ensure that you set *outError when returning NO. +// +// // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. +// +// // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. +// // In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead. +// +// return YES; +//} + + +- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError +{ + NSString * newUSLStr = nil; + ASSIGN(_eomodel, [EOModel modelWithContentsOfFile: [absoluteURL path]]); + ASSIGN(_entityNames,[_eomodel entityNames]); + + return YES; +} + +#pragma mark - +#pragma mark Outline + +- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item +{ + if (!item) { + // top level entities and storedProcedures + return 2; + } + + if ((item == entitiesItem)) { + return [[_eomodel entityNames] count]; + } + + if ((item == storedProceduresItem)) { + return [[_eomodel storedProcedureNames] count]; + } + + return 0; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item +{ + if (!item) { + return YES; + } + if (((item == entitiesItem)) || ((item == storedProceduresItem))) { + return YES; + } + + return NO; +} + +- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item +{ + if (!item) { + if ((index == 0)) { + return entitiesItem; + } + if ((index == 1)) { + return storedProceduresItem; + } + } + + if ((item == entitiesItem)) { + return [[_eomodel entityNames] objectAtIndex:index]; + } + + if ((item == storedProceduresItem)) { + return [[_eomodel storedProcedureNames] objectAtIndex:index]; + } + + + return nil; +} + +- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item +{ + + if (!item) { + // top level entities and storedProcedures +// return @"EOModel"; + return nil; + } + if ((item == entitiesItem)) { + return entitiesItem; + } + + if ((item == storedProceduresItem)) { + return storedProceduresItem; + } +// +// NSLog(@"%s (%d)", __PRETTY_FUNCTION__, [outlineView rowForItem:item]); +// +// if ([item respondsToSelector:@selector(name)]) { +// return [item name]; +// } +// + + return item; + + +// return nil; +} + +#pragma mark - + +- (NSString*) pathForOutlineSelection +{ + NSMutableArray * myArray = [NSMutableArray array]; + id parentItem = [_outlineView itemAtRow:[_outlineView selectedRow]]; + + if ((parentItem)) { + + [myArray addObject:parentItem]; + + while (YES) { + parentItem = [_outlineView parentForItem:parentItem]; + if (parentItem) { + [myArray insertObject:parentItem atIndex:0]; + } else { + break; + } + } + } + + return [myArray componentsJoinedByString:@"."]; +} + + +/// KVC + +- (id) eomObjectForKeyPath:(NSString*) path +{ + NSString * newPath = nil; + + if (([path hasPrefix:entitiesItem]) && ([path length] > ([entitiesItem length] + 1))) { + newPath = [path substringFromIndex:[entitiesItem length]+1]; + return [_eomodel entityNamed:newPath]; + } else if ((([path hasPrefix:storedProceduresItem]) && ([path length] > ([storedProceduresItem length] + 1)))) { + newPath = [path substringFromIndex:[storedProceduresItem length]+1]; + return [_eomodel storedProcedureNamed:newPath]; + } + + return nil; +} + +#pragma mark - +#pragma mark delegates + +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + id newSelection = nil; + + newSelection = [self eomObjectForKeyPath:[self pathForOutlineSelection]]; + + [self setOutlineSelection:newSelection]; + +} + +- (void)outlineViewItemWillCollapse:(NSNotification *)notification +{ + NSOutlineView * outlineView = [notification object]; + NSUInteger index = 0; + NSInteger intIndex = 0; + NSString * collapseObj = [[notification userInfo] objectForKey:@"NSObject"]; + + intIndex = [outlineView rowForItem:collapseObj]; + if (intIndex > -1) { + index = intIndex; + } + + [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex: index] + byExtendingSelection:NO]; + +} + +- (void)tableViewSelectionDidChange:(NSNotification *) notification +{ + NSArray * selectedObjects = nil; + + if (([notification object] == _topTableView)) { + selectedObjects = [_topTableViewController selectedObjects]; + + if ([selectedObjects count] > 0) { + [self setSelectedObjects:selectedObjects]; + + [_bottomTableView selectRowIndexes:[NSIndexSet indexSet] + byExtendingSelection:NO]; + } + } + + if (([notification object] == _bottomTableView)) { + selectedObjects = [_bottomTableViewController selectedObjects]; + + if ([selectedObjects count] > 0) { + [self setSelectedObjects:selectedObjects]; + + [_topTableView selectRowIndexes:[NSIndexSet indexSet] + byExtendingSelection:NO]; + } + } + + if (([notification object] == _storedProcedureTableView)) { + selectedObjects = [_procTableViewController selectedObjects]; + + if ([selectedObjects count] > 0) { + [self setSelectedObjects:selectedObjects]; + } + } + +} + +- (IBAction) tableViewClicked:(NSTableView*) tv +{ + // NSLog(@"%s:%@",__PRETTY_FUNCTION__, tv); +} + +#pragma mark - +#pragma mark Pop ups + +- (IBAction) visibleColumnsChanged:(id) sender +{ + NSMenuItem * item = [sender selectedItem]; + NSDictionary * dict = nil; + NSString * identifier = nil; + NSTableColumn * col = nil; + + if (sender == _topVisibleColumnsPopUp) { + dict = [[EOAttribute allColumnNames] objectForKey:[NSNumber numberWithInteger:[item tag]]]; + identifier = [dict objectForKey:@"key"]; + col = [_topTableView tableColumnWithIdentifier:identifier]; + } + + if (sender == _bottomVisibleColumnsPopUp) { + dict = [[EORelationship allColumnNames] objectForKey:[NSNumber numberWithInteger:[item tag]]]; + identifier = [dict objectForKey:@"key"]; + col = [_bottomTableView tableColumnWithIdentifier:identifier]; + } + + if (sender == _storedProcVisibleColumnsPopUp) { + dict = [[EOStoredProcedure allColumnNames] objectForKey:[NSNumber numberWithInteger:[item tag]]]; + identifier = [dict objectForKey:@"key"]; + col = [_storedProcedureTableView tableColumnWithIdentifier:identifier]; + } + + + if (([item state] == NSOnState)) { + [item setState:NSOffState]; + [col setHidden:YES]; + } else { + [item setState:NSOnState]; + [col setHidden:NO]; + } +} + +- (IBAction) directionChanged:(id) sender +{ + NSMenuItem * item = [_storedProcDirectionUp selectedItem]; + NSLog(@"%s:%d", __PRETTY_FUNCTION__, [item tag]); +} + +#pragma mark - +#pragma mark Menu Items +- (void) showInspector:(id)sender +{ + [EOMInspectorController showInspector]; +} + +- (void) generateSQL:(id)sender +{ + [[SQLGenerator sharedGenerator] openSQLGeneratorForDocument:self]; +} + + +- (void) setAdaptor:(id)sender +{ + NSString *adaptorName; + EOAdaptor *adaptor; + AdaptorsPanel *adaptorsPanel = [[AdaptorsPanel alloc] init]; + + adaptorName = [adaptorsPanel runAdaptorsPanel]; + RELEASE(adaptorsPanel); + + if (!adaptorName) + return; + + [_eomodel setAdaptorName: adaptorName]; + adaptor = [EOAdaptor adaptorWithName: adaptorName]; + [_eomodel setConnectionDictionary:[adaptor runLoginPanel]]; + +} + +- (void)createTemplates:(id)sender +{ + CodeGenerator * codeGen = [[CodeGenerator new] autorelease]; + + [codeGen generate]; + +} + +- (void)addAttribute:(id)sender +{ + EOAttribute *attrb; + EOEntity *entity; + EOStoredProcedure *sProc = nil; + NSMutableArray *attributes; + NSUInteger count; + + if ((!_outlineSelection) || + (([_outlineSelection class] != [EOEntity class]) && ([_outlineSelection class] != [EOStoredProcedure class]))) { + return; + } + + if (([_outlineSelection class] == [EOStoredProcedure class])) { + sProc = (EOStoredProcedure*) _outlineSelection; + attributes = (NSMutableArray*)[sProc arguments]; + if (!attributes) { + attributes = [NSMutableArray array]; + } else { + attributes = [NSMutableArray arrayWithArray:attributes]; + } + + NSLog(@"%s:%@",__PRETTY_FUNCTION__, attributes); + } else { + entity = (EOEntity*) _outlineSelection; + attributes = (NSMutableArray*) [entity attributes]; + } + + count = [attributes count]; + + attrb = [[EOAttribute alloc] init]; + [attrb setName: [NSString stringWithFormat: @"Attribute%d", count]]; + [attrb setColumnName: [attrb name]]; + [attrb setValueClassName: @"NSString"]; + [attrb setExternalType: @""]; + + if (sProc) { + [attributes addObject:attrb]; + [sProc setArguments:attributes]; + [_procTableViewController setRepresentedObject:[sProc arguments]]; + [_storedProcedureTableView reloadData]; + }else { + [entity addAttribute:attrb]; + [_topTableView reloadData]; + } + + RELEASE(attrb); + +} + +- (IBAction)addProcedure:(id)sender +{ + EOStoredProcedure * sProc; + NSUInteger count; + count = [[_eomodel storedProcedureNames] count]; + + sProc = [[EOStoredProcedure alloc] initWithName:[NSString stringWithFormat:@"Procedure%d", count]]; + + [_eomodel addStoredProcedure:sProc]; + RELEASE(sProc); + + [_outlineView reloadData]; +} + +- (IBAction)dataBrowser:(id)sender +{ + EOEntity * entity = [self outlineSelection]; + + if ((entity) && ([entity class] == [EOEntity class])) { + DataBrowser * sharedBrowser = [DataBrowser sharedBrowser]; + + [sharedBrowser setEntity:entity]; + + } + +} + +#pragma mark - +#pragma mark key value observing + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + if ([object isKindOfClass:[EOAttribute class]]) { + // optimize this? + [_topTableView reloadData]; + [_storedProcedureTableView reloadData]; + } + + if ([object isKindOfClass:[EORelationship class]]) { + [_bottomTableView reloadData]; + } + + if ([object isKindOfClass:[EOEntity class]]) { + [_outlineView reloadData]; + } + + if ([object isKindOfClass:[EOStoredProcedure class]]) { + [_outlineView reloadData]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:@"EOModelerSelectionChanged" + object:self]; + + // NSLog(@"%s: %@, %@, %@", __PRETTY_FUNCTION__, keyPath, object, change); +} + +@end diff --git a/Apps/EOModelEditor/EOMEEOAccessAdditions.h b/Apps/EOModelEditor/EOMEEOAccessAdditions.h new file mode 100644 index 0000000..0bdad05 --- /dev/null +++ b/Apps/EOModelEditor/EOMEEOAccessAdditions.h @@ -0,0 +1,94 @@ +/** + EOMEEOAccessAdditions.h EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of DBModeler. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#ifndef __EOMEEOAccessAdditions_h +#define __EOMEEOAccessAdditions_h + +#import + +@interface EOMEEOAccessAdditions:NSObject +{ +} + ++ (void)initialize; +@end + +@interface EOAttribute (EOMEEOAccessAdditions) + ++ (NSDictionary*) defaultColumnNames; + ++ (NSDictionary*) allColumnNames; + +- (NSArray*) observerKeys; + +@end + +@interface EORelationship (EOMEEOAccessAdditions) ++ (NSDictionary*) allColumnNames; + +- (NSArray*) defaultColumnNames; + +- (NSArray*) observerKeys; + +- (NSArray*) sourceAttributeNames; + +- (NSString*) humanReadableSourceAttributes; + +- (NSArray*) destinationAttributeNames; + +- (NSString*) humanReadableDestinationAttributes; + +- (EOJoin*) joinFromAttributeNamed:(NSString*) atrName; + +- (EOJoin*) joinToAttributeNamed:(NSString*) atrName; + + +@end + +@interface EOEntity (EOMEEOAccessAdditions) + +- (NSArray*) attributeNames; +- (NSArray*) observerKeys; + +@end + +@interface EOStoredProcedure (EOMEEOAccessAdditions) + ++ (NSDictionary*) allColumnNames; + +- (NSArray*) observerKeys; + +@end + +@interface EOModel (EOMEEOAccessAdditions) + +- (NSArray*) observerKeys; + +@end + + +#endif diff --git a/Apps/EOModelEditor/EOMEEOAccessAdditions.m b/Apps/EOModelEditor/EOMEEOAccessAdditions.m new file mode 100644 index 0000000..d6d1c8a --- /dev/null +++ b/Apps/EOModelEditor/EOMEEOAccessAdditions.m @@ -0,0 +1,385 @@ +/** + EOMEEOAccessAdditions.m EOMEDocument Class + + Copyright (C) Free Software Foundation, Inc. + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with EOModelEditor; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + **/ + +#import "EOMEEOAccessAdditions.h" + +NSMutableArray *DefaultEntityColumns; +NSMutableArray *DefaultAttributeColumns; +NSMutableArray *DefaultRelationshipColumns; + +static NSDictionary * defaultEOAttributeColumnNamesDict = nil; +static NSDictionary * allEOAttributeColumnNamesDict = nil; +static NSDictionary * allEORelationshipColumnNamesDict = nil; +static NSDictionary * allEOStoredProcedureColumnNamesDict = nil; + +static NSArray * EOAttributeObserverKeys = nil; +static NSArray * EORelationshipObserverKeys = nil; +static NSArray * EOStoredProcedureObserverKeys = nil; +static NSArray * EOEOModelObserverKeys = nil; + +struct column_info { + NSString *key; + NSInteger tag; + NSString *name; + BOOL isDefault; +}; + +static struct column_info attribute_columns[] = { + {@"isPrimaryKey", 0, @"Primary key", YES}, + {@"isClassProperty", 1, @"Class property", YES}, + {@"allowNull", 2, @"Allows null", YES}, + {@"isUsedForLocking", 3, @"Locking", YES}, + {@"name", 4, @"Name", YES}, + {@"columnName", 5, @"Column name", YES}, + {@"valueClassName", 6, @"Value class name", YES}, + {@"externalType", 7, @"External Type", YES}, + {@"width", 8, @"Width", YES}, + {@"definition", 9, @"Definition", NO}, + {@"precision", 10, @"Precision", NO}, + {@"readFormat", 11, @"Read format", NO}, + {@"scale", 12, @"Scale", NO}, + {@"valueType", 13, @"Value type", NO}, + {@"writeFormat", 14, @"Write format", NO}, + {nil, 1000, nil, NO} +}; + +static struct column_info relationship_columns[]= { + {@"isToMany", 0, @"Cardinality", YES}, + {@"isClassProperty", 1, @"Class property", YES}, + {@"name", 2, @"Name", YES}, + {@"destinationEntity.name", 3, @"Destination Entity", YES}, + {@"humanReadableSourceAttributes", 4, @"Source Attribute", YES}, + {@"humanReadableDestinationAttributes",5, @"Destination Attribute", YES}, + {@"definition", 6, @"Definition", NO}, + {nil, 1000, nil, NO} +}; + +static struct column_info entity_columns[] = { + {@"name", 0, @"Name", YES}, + {@"className", 1, @"Class name", YES}, + {@"externalName", 2, @"External name", YES}, + {@"externalQuery", 4, @"External query", NO}, + {@"parentEntity.name", 5, @"Parent", NO}, + {nil, 1000, nil, NO} +}; + +static struct column_info procedure_columns[] = { + {@"name", 0, @"Name", YES}, + {@"parameterDirection", 1, @"Direction", YES}, + {@"columnName", 2, @"Column name", YES}, + {@"valueClassName", 3, @"Value class name",NO}, + {@"externalType", 4, @"External type", NO}, + {@"width", 5, @"Width", NO}, + {@"precision", 6, @"Precision", NO}, + {@"scale", 7, @"Scale", NO}, + {@"valueType", 8, @"Value type", NO}, + {nil, 1000, nil, NO} +}; + +@implementation EOMEEOAccessAdditions + ++ (void)initialize +{ + if (DefaultRelationshipColumns) { + // nothing to do + return; + } + + NSLog(@"%s", __PRETTY_FUNCTION__); + + DefaultRelationshipColumns = [[NSMutableArray alloc] init]; + + // _sharedDefaultColumnProvider = [[self alloc] init]; + // _aspectsAndKeys = [[NSMutableDictionary alloc] init]; +} + ++ (NSDictionary*) defaultColumnNamesForDict:(struct column_info*) staticDict onlyDefault:(BOOL) onlyDefault +{ + NSInteger i = 0; + NSMutableDictionary * mDict = [NSMutableDictionary new]; + + for (i = 0; staticDict[i].key != nil; i++) + { + if ((onlyDefault == NO) || (staticDict[i].isDefault == YES)) + { + NSDictionary * sDict = [NSDictionary dictionaryWithObjectsAndKeys:staticDict[i].name, @"name", + staticDict[i].key, @"key", nil]; + + [mDict setObject: sDict + forKey: [NSNumber numberWithInteger:staticDict[i].tag]]; + } + } + + return mDict; +} + ++ (NSArray*) keysFromDict:(struct column_info*) staticDict +{ + NSMutableArray * mArray = [NSMutableArray array]; + NSInteger i = 0; + + for (i = 0; staticDict[i].key != nil; i++) + { + [mArray addObject:staticDict[i].key]; + } + return mArray; +} + +@end + + +@implementation EOAttribute (EOMEEOAccessAdditions) + + ++ (NSDictionary*) defaultColumnNames +{ + if (!defaultEOAttributeColumnNamesDict) { + defaultEOAttributeColumnNamesDict = [EOMEEOAccessAdditions defaultColumnNamesForDict:&attribute_columns[0] + onlyDefault:YES]; + } + return defaultEOAttributeColumnNamesDict; +} + ++ (NSDictionary*) allColumnNames +{ + if (!allEOAttributeColumnNamesDict) { + allEOAttributeColumnNamesDict = [EOMEEOAccessAdditions defaultColumnNamesForDict:&attribute_columns[0] + onlyDefault:NO]; + } + return allEOAttributeColumnNamesDict; +} + +- (NSArray*) observerKeys +{ + if (!EOAttributeObserverKeys) { + NSMutableArray * mutArray; + NSArray * tmpArray = [NSArray arrayWithArray:[EOMEEOAccessAdditions + keysFromDict:&attribute_columns[0]]]; + + mutArray = [NSMutableArray arrayWithArray:tmpArray]; + + tmpArray = [NSArray arrayWithObjects:@"isReadOnly", + @"allowsNull", + @"parameterDirection", + nil]; + + [mutArray addObjectsFromArray:tmpArray]; + + EOAttributeObserverKeys = mutArray; + [EOAttributeObserverKeys retain]; + } + return EOAttributeObserverKeys; +} + +@end + +@implementation EORelationship (EOMEEOAccessAdditions) + ++ (NSDictionary*) allColumnNames +{ + if (!allEORelationshipColumnNamesDict) { + allEORelationshipColumnNamesDict = [EOMEEOAccessAdditions defaultColumnNamesForDict:&relationship_columns[0] + onlyDefault:NO]; + } + return allEORelationshipColumnNamesDict; +} + +- (NSArray*) observerKeys +{ + if (!EORelationshipObserverKeys) { + EORelationshipObserverKeys = [NSArray arrayWithObjects:@"toMany", + @"classProperty", + @"name", + @"destinationEntity", + @"definition", + @"joins", + @"joinSemantic", + @"isMandatory", + @"numberOfToManyFaultsToBatchFetch", + @"deleteRule", + @"ownsDestination", + @"propagatesPrimaryKey", + nil]; + [EORelationshipObserverKeys retain]; + } + return EORelationshipObserverKeys; +} + +- (NSArray*) sourceAttributeNames +{ + NSMutableArray * mArray = [NSMutableArray array]; + NSEnumerator * enumer = [[self sourceAttributes] objectEnumerator]; + EOAttribute * currentAttr = nil; + + while ((currentAttr = [enumer nextObject])) { + [mArray addObject:[currentAttr name]]; + } + + return mArray; +} + +- (NSString*) humanReadableSourceAttributes +{ + return [[self sourceAttributeNames] componentsJoinedByString:@", "]; +} + +- (NSArray*) destinationAttributeNames +{ + NSMutableArray * mArray = [NSMutableArray array]; + NSEnumerator * enumer = [[self destinationAttributes] objectEnumerator]; + EOAttribute * currentAttr = nil; + + while ((currentAttr = [enumer nextObject])) { + [mArray addObject:[currentAttr name]]; + } + + return mArray; +} + + +- (NSString*) humanReadableDestinationAttributes +{ + return [[self destinationAttributeNames] componentsJoinedByString:@", "]; +} + +- (EOJoin*) joinFromAttributeNamed:(NSString*) atrName +{ + NSArray * joins = [self joins]; + NSEnumerator * enumer; + EOJoin * currentJoin; + + if ([joins count] < 1) { + return nil; + } + + enumer = [joins objectEnumerator]; + + while ((currentJoin = [enumer nextObject])) { + if (([[[currentJoin sourceAttribute] name] isEqual:atrName])) { + return currentJoin; + } + } + + return nil; +} + +- (EOJoin*) joinToAttributeNamed:(NSString*) atrName +{ + NSArray * joins = [self joins]; + NSEnumerator * enumer; + EOJoin * currentJoin; + + if ([joins count] < 1) { + return nil; + } + + enumer = [joins objectEnumerator]; + + while ((currentJoin = [enumer nextObject])) { + if (([[[currentJoin destinationAttribute] name] isEqual:atrName])) { + return currentJoin; + } + } + + return nil; +} + + +@end + +@implementation EOEntity (EOMEEOAccessAdditions) + +- (NSArray*) attributeNames +{ + NSMutableArray * mArray = [NSMutableArray array]; + NSEnumerator * enumer = [[self attributes] objectEnumerator]; + EOAttribute * currentAttr = nil; + + while ((currentAttr = [enumer nextObject])) { + [mArray addObject:[currentAttr name]]; + } + + return mArray; +} + +- (NSArray*) observerKeys +{ + if (!EORelationshipObserverKeys) { + EORelationshipObserverKeys = [NSArray arrayWithObjects:@"externalName", + @"className", + @"name", + @"maxNumberOfInstancesToBatchFetch", + @"externalQuery", + nil]; + [EORelationshipObserverKeys retain]; + } + return EORelationshipObserverKeys; +} + + +@end + +@implementation EOStoredProcedure (EOMEEOAccessAdditions) + ++ (NSDictionary*) allColumnNames +{ + if (!allEOStoredProcedureColumnNamesDict) { + allEOStoredProcedureColumnNamesDict = [EOMEEOAccessAdditions defaultColumnNamesForDict:&procedure_columns[0] + onlyDefault:NO]; + } + return allEOStoredProcedureColumnNamesDict; +} + +- (NSArray*) observerKeys +{ + if (!EOStoredProcedureObserverKeys) { + EOStoredProcedureObserverKeys = [NSArray arrayWithObjects:@"externalName", + @"name", + @"parameterDirection", + nil]; + [EOStoredProcedureObserverKeys retain]; + } + return EOStoredProcedureObserverKeys; +} + + +@end + +@implementation EOModel (EOMEEOAccessAdditions) + +- (NSArray*) observerKeys +{ + if (!EOEOModelObserverKeys) { + EOEOModelObserverKeys = [NSArray arrayWithObjects:@"connectionDictionary", + @"userInfo", + nil]; + [EOEOModelObserverKeys retain]; + } + return EOEOModelObserverKeys; +} + +@end diff --git a/Apps/EOModelEditor/EOModelEditorApp.h b/Apps/EOModelEditor/EOModelEditorApp.h new file mode 100644 index 0000000..71081a3 --- /dev/null +++ b/Apps/EOModelEditor/EOModelEditorApp.h @@ -0,0 +1,40 @@ +/* + EOModelEditorApp.h + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EOModelEditorApp_h +#define __EOModelEditorApp_h + +#include + +@class EOMEDocument; + +@interface EOModelEditorApp : NSApplication +{ + +} + +- (EOMEDocument *) activeDocument; + +@end + +#endif diff --git a/Apps/EOModelEditor/EOModelEditorApp.m b/Apps/EOModelEditor/EOModelEditorApp.m new file mode 100644 index 0000000..dde5aaf --- /dev/null +++ b/Apps/EOModelEditor/EOModelEditorApp.m @@ -0,0 +1,126 @@ +/* + EOModelEditorApp.m + + Author: David Wetzel + Date: 2010 + + This file is part of EOModelEditor. + + EOModelEditor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + EOModelEditor is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#import "EOModelEditorApp.h" +#import "EOMEEOAccessAdditions.h" +#import +#import +#import "AdaptorsPanel.h" +#import "EOMEDocument.h" + +@implementation EOModelEditorApp + +/* + on Interface Builder the DocumentController is created by loading the NIB after it has been added to. + We don't have a NIB file so we have to do this manually -- dw + */ + +- (void)finishLaunching +{ + //NSDocumentController * dc = [NSDocumentController sharedDocumentController]; + + // [dc retain]; + [EOMEEOAccessAdditions class]; + + [super finishLaunching]; +} + +- (void)orderFrontStandardAboutPanel:(id)sender +{ + NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:@"Credits", @"Credits.rtf", + @"Version", @"0.1 (2010)", nil]; + + [self orderFrontStandardAboutPanelWithOptions: dict]; + +} + +- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender +{ + return NO; +} + +- (void) newDocumentWithModel:(EOModel *)newModel +{ + EOMEDocument *newModelerDoc; + NSError *outError = nil; + NSDocumentController * sharedDocController = [NSDocumentController sharedDocumentController]; + + + newModelerDoc = [sharedDocController openUntitledDocumentAndDisplay:YES + error:&outError]; + + if (newModelerDoc) { + [newModelerDoc setEomodel:newModel]; + } + +} + +- (void) newFromDatabase:(id)sender +{ + NSString *adaptorName; + AdaptorsPanel *adaptorsPanel = [[AdaptorsPanel alloc] init]; + + adaptorName = [adaptorsPanel runAdaptorsPanel]; + RELEASE(adaptorsPanel); + + if (adaptorName) + { + NS_DURING { + EOAdaptor *adaptor; + EOAdaptorChannel *channel; + EOAdaptorContext *ctxt; + EOModel *newModel; + NSDictionary *connDict; + + adaptor = [EOAdaptor adaptorWithName:adaptorName]; + connDict = [adaptor runLoginPanel]; + + if (connDict) + { + [adaptor setConnectionDictionary:connDict]; + ctxt = [adaptor createAdaptorContext]; + channel = [ctxt createAdaptorChannel]; + [channel openChannel]; + newModel = [channel describeModelWithTableNames:[channel describeTableNames]]; + [newModel setConnectionDictionary:[adaptor connectionDictionary]]; + [newModel setName: [[adaptor connectionDictionary] objectForKey:@"databaseName"]]; + [channel closeChannel]; + [self newDocumentWithModel:newModel]; + } + } NS_HANDLER { + NSRunCriticalAlertPanel (@"Problem creating model from Database", + @"%@", + @"Ok", + nil, + nil, + localException); + } NS_ENDHANDLER; + } +} + +- (EOMEDocument *) activeDocument +{ + return (EOMEDocument *) [[NSDocumentController sharedDocumentController] currentDocument]; +} + +@end diff --git a/Apps/EOModelEditor/EOModelEditorInfo.plist b/Apps/EOModelEditor/EOModelEditorInfo.plist new file mode 100644 index 0000000..0ba8d2e --- /dev/null +++ b/Apps/EOModelEditor/EOModelEditorInfo.plist @@ -0,0 +1,63 @@ +{ + ApplicationDescription = "GDL2 EOModel editor"; + ApplicationIcon = EOModelEditor; + ApplicationName = EOModelEditor; + ApplicationRelease = "1.0.0 (Alpha)"; + ApplicationURL = "http://mediawiki.gnustep.org/index.php/EOModelEditor"; + Authors = ("David Wetzel"); + Copyright = "Copyright \U00A9 2005, 2006 Free Software Foundation"; + CopyrightDescription = "Released under the GNU GPL. See COPYING for details."; + + CFBundleGetInfoString = "1.0.0 \U00A9 Free Software Foundation"; + CFBundleShortVersionString = "1.0.0"; + + GSMainMarkupFile = ""; + NSExecutable = EOModelEditor; + NSIcon = EOModelEditor.tiff; + CFBundleIconFile = "EOModelEditor"; + CFBundleIdentifier = "org.gnustep.eomodeleditor"; + + NSRole = "Editor"; + CFBundleDocumentTypes = ( + /* { + CFBundleTypeName = "EOModel Format"; + NSHumanReadableName = "EOModel Format"; + CFBundleTypeRole = Editor; + CFBundleTypeExtensions = ("eomodel", "eomodeld"); + CFBundleTypeIconFile = "EOModel"; + CFBundleTypeOSTypes = ("EOMO"); + XXLSItemContentTypes = ("org.gnustep.eomodeleditor.document"); + XXXNSExportableAs = ("NSTIFFPboardType"); + NSDocumentClass = "EOMEDocument"; + },*/ + { + CFBundleTypeIconFile = "EOModel"; + CFBundleTypeName = "EOModel Format"; + CFBundleTypeExtensions = ("eomodeld"); + CFBundleTypeRole = Editor; + CFBundleTypeOSTypes = ("EOMO"); + LSItemContentTypes = ("org.gnustep.eomodeleditor.document"); + LSIsAppleDefaultForType = "true"; + LSTypeIsPackage = "true"; + NSDocumentClass = "EOMEDocument"; + } + ); + + UTExportedTypeDeclarations = ( + { + UTTypeIdentifier = "org.gnustep.eomodeleditor.document"; + UTTypeDescription = "EOModel Format"; + UTTypeIconFile = "EOModel.icns"; + UTTypeConformsTo = ("com.apple.package"); + + UTTypeTagSpecification = { + "com.apple.ostype" = "EOMO"; + "public.filename-extension" = "eomodeld"; + "public.mime-type" = "document/eomodel"; + }; + } + ); + + NSMainNibFile = ""; + NSPrincipalClass = EOModelEditorApp; +} diff --git a/Apps/EOModelEditor/GNUmakefile b/Apps/EOModelEditor/GNUmakefile new file mode 100644 index 0000000..e1a8ec0 --- /dev/null +++ b/Apps/EOModelEditor/GNUmakefile @@ -0,0 +1,90 @@ +# +# EOModelEditor makefile for GNUstep Database Library. +# +# Copyright (C) 2005,2006 Free Software Foundation, Inc. +# +# Author: Matt Rice +# +# This file is part of the GNUstep Database Library. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; see the file COPYING.LIB. +# If not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +include ../../common.make +include $(GNUSTEP_MAKEFILES)/common.make + +APP_NAME = EOModelEditor + +EOModelEditor_NEEDS_GUI = yes +EOModelEditor_SUBPROJECTS=Inspectors + +ifeq ($(GUI_LIB),apple) +EOModelEditor_APPLICATION_ICON = EOModelEditor.icns +else +EOModelEditor_APPLICATION_ICON = EOModelEditor.tiff +endif + +ADDITIONAL_INCLUDE_DIRS+=-I../ +ADDITIONAL_NATIVE_LIB_DIRS+=../EOAccess ../EOControl ../EOInterface ../EOModeler +ADDITIONAL_NATIVE_LIBS += EOAccess EOControl EOInterface EOModeler Renaissance + +$(APP_NAME)_RESOURCE_FILES = \ + Resources/ModelDrag.tiff \ + Resources/SQLGenerator.gsmarkup \ + Resources/EOMEDocument.gsmarkup \ + Resources/EOModelEditorInfo.plist \ + Resources/Key_Diagram.tiff \ + Resources/Key_Header.tiff \ + Resources/toOne.tiff \ + Resources/toMany.tiff \ + Resources/Key_On.tiff \ + Resources/gear.tiff \ + Resources/Locking_Diagram.tiff \ + Resources/Locking_Header.tiff \ + Resources/Locking_On.tiff \ + Resources/ClassProperty_Diagram.tiff \ + Resources/ClassProperty_Header.tiff \ + Resources/ClassProperty_On.tiff \ + Resources/Preferences.gorm \ + Resources/EOModelEditor.tiff \ + Resources/EOModelEditor.icns \ + Resources/EOModel.icns \ + Resources/AllowsNull_On.tiff \ + Resources/dimple.tiff \ + Resources/nodimple.tiff \ + Resources/AllowsNull_Header.tiff \ + Resources/Menu-Cocoa.gsmarkup \ + Resources/Menu-GNUstep.gsmarkup \ + Resources/Credits.rtf \ + Resources/ConsistencyResults.gsmarkup \ + Resources/DataBrowser.gsmarkup + +$(APP_NAME)_OBJC_FILES = \ + main.m \ + EOModelEditorApp.m \ + TableViewController.m \ + EOMEEOAccessAdditions.m \ + EOMEDocument.m \ + AdaptorsPanel.m \ + EOAdditions.m \ + SQLGenerator.m \ + ConsistencyResults.m \ + Preferences.m \ + ConsistencyChecker.m \ + CodeGenerator.m \ + DataBrowser.m + +include $(GNUSTEP_MAKEFILES)/application.make diff --git a/Apps/EOModelEditor/Inspectors/AdvancedAttributeInspector.gsmarkup b/Apps/EOModelEditor/Inspectors/AdvancedAttributeInspector.gsmarkup new file mode 100644 index 0000000..6170689 --- /dev/null +++ b/Apps/EOModelEditor/Inspectors/AdvancedAttributeInspector.gsmarkup @@ -0,0 +1,44 @@ + + + + + + + + + +