├── LICENSE ├── README.md ├── examples ├── 0-classes_and_objects.sh ├── 1-methods_and_attributes.sh ├── 2-inheritance.sh ├── 3-decoration.sh ├── 4-traits.sh ├── 5-cloning.sh ├── 6-exceptions.sh ├── 7-magic_globals.sh └── 8-overriding_defaults.sh ├── lib ├── Console │ └── Console └── String │ ├── String │ └── example.sh └── ooengine /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ooengine 2 | ======== 3 | 4 | Intuitive pseudo object orientation for bash (Shell Script) 5 | 6 | Project maintainance: 7 | -------------------------------------- 8 | This was more of an experiment whether I can get some of OO greatness into bash scripts. 9 | I'm not planning to continue any of it at the moment. 10 | But feel free to fork it if you are interested! 11 | 12 | 13 | Features: 14 | -------------------------------------- 15 | 1. "Classes" containing "methods". 16 | 2. Created objects saved in variables. 17 | 3. Public / private attributes. 18 | 4. Inheritance (extending classes). 19 | 5. Traits (multiple inheritance). 20 | 6. Object cloning. 21 | 7. Exceptions - throw and catch them. 22 | 23 | As intuitive as possible (it's still bash though). 24 | 25 | Crash course: 26 | -------------------------------------- 27 | 1. 'Classes' are functions, prefixed with 'class::'. 28 | 2. 'Methods' are functions within classes, prefixed with 'method::'. 29 | 3. 'Objects' are created by calling new [Class name], save it's return value into a variable. 30 | 31 | Example: 32 | -------------------------------------- 33 | 34 | ```shell 35 | #!/bin/bash 36 | source ooengine || exit 1 37 | 38 | # A simple base class named 'TestClass'. 39 | class::TestClass() { 40 | 41 | # Public attribute, 'get' and 'set'-able. 42 | public attributePublic "optional default value" 43 | 44 | # Private attribute, only internal 'get' and 'set'-able. 45 | private attributePrivate "optional default value" 46 | 47 | # Public method, reachable with any reference. 48 | method::publicTestMethod() { 49 | echo "Do something here." 50 | # Call private method. 51 | $this internalTestMethod 52 | } 53 | 54 | # Public getter method for private attribute 'attributePrivate'. 55 | method::getAttributePrivate() { 56 | $this get attributePrivate 57 | } 58 | 59 | # Public setter method for private attribute 'attributePrivate'. 60 | method::setAttributePrivate() { 61 | $this set attributePrivate "$1" 62 | } 63 | 64 | # Private method, only internal reachable with $this reference. 65 | __method::internalTestMethod() { 66 | echo "Or do something here." 67 | } 68 | } 69 | 70 | # Create an object of the class. 71 | testObject=$(new TestClass) 72 | 73 | # Call a method. 74 | $testObject publicTestMethod 75 | 76 | # Get a public attribute. 77 | value=$($testObject get attributePublic) 78 | echo $value 79 | 80 | # Set a public attribute. 81 | $testObject set attributePublic "New value" 82 | 83 | # Get a private attribute. 84 | # echo $($testObject get attributePrivate) # This would fail. 85 | value=$($testObject getAttributePrivate) 86 | echo $value 87 | 88 | # Set a private attribute. 89 | # $testObject set attributePrivate # This would fail. 90 | $testObject setAttributePrivate "New value" 91 | 92 | # Destruct the object. 93 | $testObject destruct 94 | ``` 95 | 96 | More? 97 | -------------------------------------- 98 | Please have a look at the examples in ./examples directory! 99 | 100 | 101 | Packed libraries 102 | -------------------------------------- 103 | - Console (Incomplete) - Console/IO help functions. 104 | - String (Incomplete) - String class. 105 | - Array (Incomplete) 106 | - MySQL (Incomplete) 107 | - ... 108 | 109 | Using libraries 110 | -------------------------------------- 111 | 112 | Use libraries by importing them: 113 | 114 | ```shell 115 | import String # (searches for $librarypath/String/String) 116 | import String/StringManipulation # (searches for $librarypath/String/StringManipulation) 117 | ``` 118 | 119 | Use own library directories: 120 | 121 | ```shell 122 | add ./mylibraries 123 | import MyLibrary 124 | import MyLibrary/SubClass 125 | ``` 126 | -------------------------------------------------------------------------------- /examples/0-classes_and_objects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 0: Classes and objects. 6 | 7 | # This is the most possible simplistic "class". 8 | class::YourClassName() { 9 | : # With classes you define how an object of it looks like. 10 | } 11 | 12 | # Create a new object based on the defined class. 13 | yourObject=$(new YourClassName) 14 | 15 | # $yourObject now contains a reference to the new object. 16 | # This variable can be passed around however you like. 17 | 18 | # You can destruct an object and its contents by calling the "destruct" method. 19 | # Syntax: $yourObject [method] [parameters ...] 20 | $yourObject destruct 21 | 22 | 23 | class::SomeOtherClass() { 24 | $this # Within a class there's always the $this global available. 25 | # It points to the current object itsself. 26 | # Syntax: $this [method] [parameters ...] 27 | } -------------------------------------------------------------------------------- /examples/1-methods_and_attributes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 1: Simple methods and attributes. 6 | 7 | # A simple base class named 'TestClass'. 8 | class::TestClass() { 9 | 10 | # Public attribute, 'get' and 'set'-able. 11 | public attributePublic "optional default value" 12 | 13 | # Private attribute, only internal 'get' and 'set'-able. 14 | private attributePrivate "optional default value" 15 | 16 | # Public method, reachable with any reference. 17 | method::publicTestMethod() { 18 | echo "Do something here." 19 | # Call private method. 20 | $this internalTestMethod 21 | } 22 | 23 | # Public getter method for private attribute 'attributePrivate'. 24 | method::getAttributePrivate() { 25 | $this get attributePrivate 26 | } 27 | 28 | # Public setter method for private attribute 'attributePrivate'. 29 | method::setAttributePrivate() { 30 | $this set attributePrivate "$1" 31 | } 32 | 33 | # Private method, only internal reachable with $this reference. 34 | __method::internalTestMethod() { 35 | echo "Or do something here." 36 | } 37 | } 38 | 39 | # Create an object of the class. 40 | testObject=$(new TestClass) 41 | 42 | 43 | # Call a method. 44 | $testObject publicTestMethod 45 | 46 | 47 | # Get a public attribute. 48 | value=$($testObject get attributePublic) 49 | echo $value 50 | 51 | # Set a public attribute. 52 | $testObject set attributePublic "New value" 53 | 54 | 55 | # Get a private attribute. 56 | # echo $($testObject get attributePrivate) # This would fail. 57 | value=$($testObject getAttributePrivate) 58 | echo $value 59 | 60 | # Set a private attribute. 61 | # $testObject set attributePrivate # This would fail. 62 | $testObject setAttributePrivate "New value" -------------------------------------------------------------------------------- /examples/2-inheritance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 2: Class inheritance of methods and attributes. 6 | 7 | # 'Animal' base class. 8 | class::Animal() { 9 | # All animals should be able to eat. 10 | method::eat() { 11 | echo "nom nom nom.." 12 | } 13 | } 14 | 15 | # 'Dog' class, extends 'Animal'. 16 | class::Dog::extends::Animal() { 17 | # Only dogs are able to bark. 18 | method::bark() { 19 | echo "Woof woof" 20 | } 21 | } 22 | 23 | # 'Cat' class, extends 'Animal'. 24 | class::Cat::extends::Animal() { 25 | # Cats are able to purr. 26 | method::purr() { 27 | echo "purrrrrr" 28 | } 29 | } 30 | 31 | # 'PurringCat' class, extends 'Cat'. 32 | class::PurringCat::extends::Cat() { 33 | # This cat purrs while eating. 34 | method::eat() { 35 | # Call inherited purring method. 36 | $this purr 37 | # Call the parents eat method. 38 | $parent eat 39 | } 40 | } 41 | 42 | 43 | # Create an animal. 44 | someAnimal=$(new Animal) 45 | # An animal is able to eat. 46 | $someAnimal eat 47 | 48 | # Create a dog. 49 | someDog=$(new Dog) 50 | # Dogs are also able to eat as they inherit it from animals. 51 | $someDog eat 52 | # But dogs are additionally able to bark. 53 | $someDog bark 54 | 55 | # Create a cat. 56 | someCat=$(new Cat) 57 | # Cats are as well able to eat and to purr. 58 | $someCat eat 59 | $someCat purr 60 | 61 | # Create a purring cat. 62 | aPurringCat=$(new PurringCat) 63 | # This cat always purrs while eating. 64 | $aPurringCat eat -------------------------------------------------------------------------------- /examples/3-decoration.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 3: Class decoration, for injecting methods and attributes. 6 | 7 | # 'Animal' base class. 8 | class::Animal() { 9 | # All animals should be able to eat. 10 | method::eat() { 11 | echo "nom nom nom.." 12 | } 13 | } 14 | 15 | # 'AnimalMovement' class, decorates 'Animal'. 16 | class::AnimalMovement::decorates::Animal() { 17 | # All animals should be able to move. 18 | method::move() { 19 | echo "moving.." 20 | } 21 | } 22 | 23 | # 'Dog' class, extends 'Animal'. 24 | class::Dog::extends::Animal() { 25 | # Only dogs are able to bark. 26 | method::bark() { 27 | echo "Woof woof" 28 | } 29 | } 30 | 31 | # 'DogSnarling' class, decorates 'Dog'. 32 | class::DogSnarling::decorates::Dog() { 33 | # Dogs should be able to snarl. 34 | method::snarl() { 35 | echo "grrrrrrr" 36 | } 37 | } 38 | 39 | # Create an animal. 40 | someAnimal=$(new Animal) 41 | # An animal is able to eat. 42 | $someAnimal eat 43 | # By decoration, animals are also able to move. 44 | $someAnimal move 45 | 46 | # Create a dog. 47 | someDog=$(new Dog) 48 | # Dogs are also able to eat as they inherit it from animals. 49 | $someDog eat 50 | # But dogs are additionally able to bark. 51 | $someDog bark 52 | # By inherited decoration, dogs are also able to move. 53 | $someDog move 54 | # By decoration, dogs are able to snarl. 55 | $someDog snarl -------------------------------------------------------------------------------- /examples/4-traits.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 4: Traits, makes multiple inheritance possible. 6 | 7 | # 'Printer' trait class. 8 | trait::Printer() { 9 | # Prints text without newline. 10 | method::out.print() { 11 | echo -ne "$@" 12 | } 13 | # Prints text with newline. 14 | method::out.println() { 15 | echo -e "$@" 16 | } 17 | } 18 | 19 | # 'SayHello' class. 20 | class::SayHello() { 21 | 22 | # Use 'Printer' trait class. 23 | use Printer 24 | 25 | method::do() { 26 | # We inherited the 'out.println' method from 'Printer' class. 27 | $this out.println "Hello!" 28 | } 29 | } 30 | 31 | # 'Exiter' trait class. 32 | trait::Exiter() { 33 | 34 | # Use 'Printer' trait class. 35 | use Printer 36 | 37 | # Successfully exits. 38 | method::exit() { 39 | $this out.println "Successfully exiting!" 40 | exit 0 41 | } 42 | # Exits with failure. 43 | method::die() { 44 | $this out.println "Exiting with failure!" 45 | exit 1 46 | } 47 | } 48 | 49 | # 'SayGoodbye' class. 50 | class::SayGoodbye() { 51 | 52 | # Use 'Printer' trait class. 53 | use Printer 54 | # Also use 'Exiter' trait class. 55 | use Exiter 56 | 57 | method::do() { 58 | # We inherited the 'out.println' method from 'Printer' trait class. 59 | $this out.println "Goodbye!" 60 | # Now exit, with inherited exit method from 'Exiter' trait class. 61 | $this exit 62 | } 63 | } 64 | 65 | helloer=$(new SayHello) 66 | goodbyer=$(new SayGoodbye) 67 | 68 | $helloer do 69 | $goodbyer do -------------------------------------------------------------------------------- /examples/5-cloning.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 5: Object cloning. 6 | 7 | class::Human() { 8 | 9 | private name $__OBJECT 10 | 11 | method::setName() { 12 | $this set name "$1" 13 | echo "Hello my ID is $__OBJECT, but you gave me the name $1, thank you!" 14 | } 15 | 16 | method::tellName() { 17 | local name=$($this get name) 18 | echo "My name is $name and my ID was $__OBJECT!" 19 | } 20 | 21 | } 22 | 23 | # Create a guy called daniel. 24 | daniel=$(new Human) 25 | $daniel setName "Daniel" 26 | $daniel tellName 27 | 28 | # Create some other guy as base. 29 | danielsClone=$(new Human) 30 | 31 | # Clone daniel. 32 | $daniel clone $danielsClone 33 | 34 | # Now we got two daniels! 35 | $danielsClone tellName 36 | 37 | # Let's kill the clone before this goes crazy. 38 | $danielsClone destruct -------------------------------------------------------------------------------- /examples/6-exceptions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 6: Exception handling, simplistic throwing and catching. 6 | 7 | # A class throwing an exception. 8 | class::fooClass() { 9 | 10 | ## 11 | # Throwing Exceptions: 12 | method::letsThrowIt() { 13 | # This will throw the default exception class named 'Exception'. 14 | # Uncatched exceptions will call toString and exit execution. 15 | throw Exception "Okay, I threw it on purpose!" 16 | # Syntax: throw [Exception] [exception parameters] ... 17 | } 18 | 19 | } 20 | 21 | # A custom exception handler. 22 | exceptionHandler() { 23 | # Print error message with call stack. 24 | $exception printStack 1>&2 25 | # Exiting with failure, is what the default handler would do. 26 | # exit 1 27 | } 28 | 29 | ## 30 | # Catching Exceptions: 31 | ## 32 | fooObject=$(new fooClass) 33 | 34 | # Define a try block, everything what happens can be catched. 35 | try() { 36 | $fooObject letsThrowIt 37 | } 38 | catch Exception exceptionHandler 39 | # The catch function will call the try block, catch the specified 40 | # Exception and pass it to your custom exception handler. 41 | 42 | 43 | ## 44 | # Default Exceptions: 45 | # 46 | # There are some default exceptions you can make use of. 47 | defaultExceptions() { 48 | throw IllegalArgumentException "Some function arguments where wrong!" 49 | throw UnknownLibraryException "Internal exception for unknown libraries." 50 | throw UndefinedMethodException "Internal exception for undefined methods." 51 | throw UndefinedClassException "Internal exception for undefined classes." 52 | throw UndefinedAttributeException "Internal exception for undefined attributes." 53 | } 54 | 55 | ## 56 | # Custom Exceptions: 57 | # 58 | # Custom Exceptions should extend from 'Exception'. 59 | class::ErrorCodeException::extends::Exception() { 60 | 61 | # The public message attribute will be inherited from 'Exception'. 62 | # public message 63 | 64 | # Lets add an error code. 65 | public code 66 | 67 | ## 68 | # Override the default setParameters method of 'Exception' to 69 | # save out error code. 70 | method::setParameters() { 71 | $this set message "$1" 72 | $this set code "$2" 73 | } 74 | 75 | ## 76 | # Override the default toString method, to add the code to the output. 77 | method::toString() { 78 | local message=$($this get message) 79 | local code=$($this get code) 80 | echo "$__CLASS (code: $code): $message" 81 | } 82 | } 83 | 84 | # Throw a custom exception: 85 | throw ErrorCodeException "Let's throw this custom exception!" 444 86 | # It will be catched by the default exception handler for 'Exception'. -------------------------------------------------------------------------------- /examples/7-magic_globals.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 7: Magic globals, funky stuff. 6 | 7 | class::someParentClass() { 8 | : 9 | } 10 | 11 | class::someClass::extends::someParentClass() { 12 | 13 | private test1 14 | private test2 15 | private test3 16 | public test4 17 | public test5 18 | 19 | method::getClassName() { 20 | # The $__CLASS global contains the name of the objects class. 21 | echo "Class name: $__CLASS" 22 | } 23 | 24 | method::getBaseName() { 25 | # The $__BASE global contains the objects class parent name. 26 | echo "Parent name: $__BASE" 27 | } 28 | 29 | method::getObjectId() { 30 | # The $__OBJECT global contains the unique object ID. 31 | echo "Object ID: $__OBJECT" 32 | } 33 | 34 | method::listAttributes() { 35 | # The global $__ATTRIBUTES array contains the objects attibutes. 36 | local attribute 37 | local attribute_info 38 | for attribute in ${__ATTRIBUTES[@]} 39 | do 40 | # Each attribute is saved as [private|publish]:[attribute name]. 41 | attribute_info=(${attribute/:/ }) 42 | echo "There is a ${attribute_info[0]} attribute called '${attribute_info[1]}'" 43 | done 44 | } 45 | } 46 | 47 | someObject=$(new someClass) 48 | 49 | $someObject getClassName 50 | 51 | $someObject getBaseName 52 | 53 | $someObject getObjectId 54 | 55 | $someObject listAttributes -------------------------------------------------------------------------------- /examples/8-overriding_defaults.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ../ooengine || exit 1 4 | 5 | # Example 8: Overriding default Class methods. 6 | 7 | class::OverrideAllTheThingsClass() { 8 | 9 | ## 10 | # Overrides standard attribute getter. 11 | method::get() { 12 | # ... do something before ... 13 | 14 | # Call the standard get method. 15 | $parent get "$@" 16 | 17 | # ... or afterwards ... 18 | } 19 | 20 | ## 21 | # Overrides standard attribute setter. 22 | method::set() { 23 | # ... do something before ... 24 | 25 | # Call the standard set method. 26 | $parent set "$@" 27 | 28 | # ... or afterwards ... 29 | } 30 | 31 | ## 32 | # Overrides default toString method. 33 | method::toString() { 34 | # ... do something before ... 35 | 36 | # You may call the standard toString method. 37 | $parent toString 38 | 39 | # ... or afterwards ... 40 | } 41 | 42 | ## 43 | # Overrides default destructor. 44 | method::destruct() { 45 | # ... do something before ... 46 | 47 | # Call the standard destruct method. 48 | $parent destruct 49 | 50 | # ... or - no wait, don't do something 51 | # after deconstructing your self! 52 | } 53 | 54 | ## 55 | # Overrides standard clone method. 56 | method::clone() { 57 | # ... do something before ... 58 | 59 | # Call the standard clone method. 60 | $parent clone $@ 61 | 62 | # ... or afterwards ... 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /lib/Console/Console: -------------------------------------------------------------------------------- 1 | ## 2 | # 'Console' trait. 3 | # 4 | trait::Console() { 5 | 6 | ## 7 | # 'println' method. 8 | # Prints text to console ending with newline. 9 | method::println() { 10 | if (( $# <= 1 )); then 11 | printf "%s\n" "$@" 12 | else 13 | throw IllegalArgumentException "Too few arguments $#" 14 | fi 15 | } 16 | 17 | ## 18 | # 'println' method. 19 | # Prints text to console. 20 | method::print() { 21 | if (( $# <= 1 )); then 22 | printf "%s" "$@" 23 | else 24 | throw IllegalArgumentException "Too few arguments $#" 25 | fi 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /lib/String/String: -------------------------------------------------------------------------------- 1 | import Console 2 | 3 | ## 4 | # 'String' class. 5 | # 6 | class::String() { 7 | 8 | use Console 9 | 10 | # The string itself. 11 | public string "" 12 | 13 | ## 14 | # Overrides the default 'set' method. 15 | # 16 | # String is the only attribute, so always set the string. 17 | # 18 | # @param $1 19 | # The string to set. 20 | method::set() { 21 | $parent set string "$1" 22 | } 23 | 24 | ## 25 | # Overrides the default 'get' method. 26 | # 27 | # String is the only attribute, so only return the string. 28 | # 29 | # @return 30 | # The string. 31 | method::get() { 32 | $parent get string 33 | } 34 | 35 | ## 36 | # 'toString' method. 37 | # 38 | # Returns the string itself. 39 | # 40 | # @return 41 | # The string. 42 | method::toString() { 43 | $this get 44 | } 45 | 46 | ## 47 | # 'length' method. 48 | # 49 | # Returns the length of the string. 50 | # 51 | # @return 52 | # The strings length 53 | method::length() { 54 | local string=$($this toString) 55 | $this println "${#string}" 56 | } 57 | 58 | ## 59 | # 'isEmpty' method. 60 | # 61 | # Returns whether the string is empty. 62 | # 63 | # @return 64 | # Whether the string is empty. 65 | method::isEmpty() { 66 | if (( $($this length) == 0 )); then 67 | $this println true 68 | else 69 | $this println false 70 | fi 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /lib/String/example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ../.. 3 | source ooengine || exit 1 4 | 5 | import String 6 | 7 | # Create a String object. 8 | aString=$(new String) 9 | 10 | # Set the string itsself. 11 | $aString set "This is a String!" 12 | 13 | # Get the string. 14 | $aString toString 15 | 16 | # Get the strings length. 17 | $aString length 18 | 19 | # Check whether the string is empty. 20 | if $($aString isEmpty); then 21 | echo "String is empty!" 22 | else 23 | echo "String is not empty!" 24 | fi -------------------------------------------------------------------------------- /ooengine: -------------------------------------------------------------------------------- 1 | ## 2 | # ooengine - Object oriented bash engine 3 | # 4 | # AUTHOR: Patrick Drotleff 5 | # USAGE: source ./ooengine 6 | # See ./examples/ for further documentation. 7 | 8 | ## 9 | # Default 'Class' all other classes automatically extend from. 10 | class::Class() { 11 | 12 | ## 13 | # Standard attribute getter. 14 | method::get() { 15 | __attribute_get "$1" 16 | } 17 | 18 | ## 19 | # Standard attribute setter. 20 | method::set() { 21 | __attribute_set "$1" "$2" 22 | } 23 | 24 | ## 25 | # Default toString method. 26 | method::toString() { 27 | echo "$__OBJECT" 28 | } 29 | 30 | ## 31 | # Default destructor. 32 | method::destruct() { 33 | __destruct 34 | } 35 | 36 | ## 37 | # Standard clone method. 38 | method::clone() { 39 | __clone "$3" 40 | } 41 | 42 | } 43 | 44 | ## 45 | # Default 'Exception'. 46 | class::Exception() { 47 | 48 | # Error message attribute. 49 | public message 50 | 51 | # The saved callstack. 52 | public callStack 53 | 54 | ## 55 | # Default parameter setter. 56 | method::setParameters() { 57 | $this set message "$1" 58 | } 59 | 60 | ## 61 | # Default toString method. 62 | method::toString() { 63 | local message=$($this get message) 64 | echo "$__CLASS: $message" 65 | } 66 | 67 | ## 68 | # Prints the exceptions callstack. 69 | method::printStack() { 70 | $this toString 71 | $this get callStack 72 | } 73 | 74 | } 75 | 76 | # Default exceptions. 77 | class::IllegalArgumentException::extends::Exception() { :; } 78 | class::UnknownLibraryException::extends::Exception() { :; } 79 | class::UndefinedMethodException::extends::Exception() { :; } 80 | class::UndefinedClassException::extends::Exception() { :; } 81 | class::UndefinedAttributeException::extends::Exception() { :; } 82 | class::ShellErrorException::extends::Exception() { :; } 83 | 84 | # Frame stack array, and pointer to the next position. 85 | # Contains object references in called order. 86 | declare -a __FRAME_STACK 87 | __FRAME_STACK_POINTER=0 88 | 89 | # Object and attributes value container. 90 | declare -A __OBJECTS 91 | 92 | # Array of library sources. 93 | declare -a __SOURCES=("./lib") 94 | 95 | # Array of current exception handlers. 96 | declare -A __EXCEPTION_HANDLERS 97 | __EXCEPTION_HANDLERS['Exception']="__default_exception_handler" 98 | trap "throw ShellErrorException 'A shell error occurred.'" ERR 99 | 100 | ## 101 | # Adds a path as library source. 102 | add() { 103 | __SOURCES=("$1" ${__SOURCES[@]}) 104 | } 105 | 106 | ## 107 | # Imports a given library. 108 | # 109 | # @param $1 110 | # The library name to import. 111 | # A simple "Name" will be included with Name/Name. 112 | # A sublibrary "Name/SubName" will be included with Name/SubName. 113 | import() { 114 | local sourcepath 115 | local dirname=$(dirname $1) 116 | local basename=$(basename $1) 117 | if [[ $dirname == "." ]]; then 118 | dirname=$basename 119 | fi 120 | for sourcepath in ${__SOURCES[@]} 121 | do 122 | if [[ -f "$sourcepath/$dirname/$basename" ]]; then 123 | source "$sourcepath/$dirname/$basename" 124 | return 0 125 | fi 126 | done 127 | throw UnknownLibraryException "Could not find the requested library." 128 | } 129 | 130 | ## 131 | # Returns a callable, new object reference. 132 | # 133 | # @param $1 134 | # The Class name to construct the object of. 135 | new() { 136 | echo "__call $1 $(date +%s%N)" 137 | } 138 | 139 | ## 140 | # Executes the try() block and manage exception handlers. 141 | # 142 | # @param $1 143 | # Name of the exception class to catch. 144 | # @param $2 145 | # The exception handler function to pass the exception to. 146 | catch() { 147 | if __function_exists "try"; then 148 | # Save previous handler for this exception. 149 | local old_handler=${__EXCEPTION_HANDLERS[$1]} 150 | # Set new handler. 151 | __EXCEPTION_HANDLERS[$1]=$2 152 | 153 | # Try the try block. 154 | try 155 | 156 | # Restore previous handler for this exception. 157 | __EXCEPTION_HANDLERS[$1]=$old_handler 158 | 159 | # Remove previous try block. 160 | unset -f try 161 | else 162 | throw Exception "No try block to execute found." 163 | fi 164 | } 165 | 166 | ## 167 | # Throws the given exception and calls the current handler. 168 | # 169 | # @param $1 170 | # Name of the exception class to throw. 171 | throw() { 172 | local exception_class=$1 173 | shift 1 174 | 175 | # Create and fill exception. 176 | local exception=$(new $exception_class) 177 | $exception set callStack "$(__call_stack)" 178 | $exception setParameters "$@" 179 | 180 | # Call the responsible handler. 181 | local handler=${__EXCEPTION_HANDLERS[$exception_class]} 182 | if [[ -n $handler ]]; then 183 | $handler "$exception" 184 | else 185 | ${__EXCEPTION_HANDLERS[Exception]} "$exception" 186 | fi 187 | } 188 | 189 | ## 190 | # Calls a method of an object. 191 | # 192 | # @param $1 193 | # The methods Class. 194 | # @param $2 195 | # The object reference. 196 | # @param $3 197 | # The methods name. 198 | __call() { 199 | local class=$1 200 | local object=$2 201 | local method=$3 202 | shift 3 203 | 204 | # Save frame to stack. 205 | __frame_push 206 | 207 | # Enter the class. 208 | __enter $class $object 209 | 210 | # Call the method. 211 | if __function_exists "method::$method"; then 212 | method::$method "$@" 213 | else 214 | throw UndefinedMethodException "Method '$method' of class '$class' not defined." 215 | fi 216 | 217 | # Leave the class. 218 | __leave 219 | 220 | # Rebuild frame from stack. 221 | __frame_pop 222 | } 223 | 224 | ## 225 | # Handles inner parent calls through $parent. 226 | # 227 | # @param $1 228 | # The objects parent Class. 229 | # @param $2 230 | # The object reference. 231 | # @param $3 232 | # The methods name. 233 | __parent_call() { 234 | local base=$1 235 | local object=$2 236 | local method=$3 237 | shift 3 238 | 239 | # Save frame to stack. 240 | __frame_push 241 | 242 | # Enter the parent. 243 | __enter $base $object 244 | 245 | # Call the method. 246 | __inner_call "$method" "$@" 247 | 248 | # Leave the class. 249 | __leave 250 | 251 | # Rebuild frame from stack. 252 | __frame_pop 253 | } 254 | 255 | ## 256 | # Handles inner calls through $this. 257 | # 258 | # @param $1 259 | # The methods name. 260 | __inner_call() { 261 | local method=$1 262 | shift 1 263 | __INNERCALL=true 264 | if __function_exists "method::$method"; then 265 | # Public function call. 266 | method::$method "$@" 267 | elif __function_exists "__method::$method"; then 268 | # Private function call. 269 | __method::$method "$@" 270 | else 271 | throw UndefinedMethodException "Method '$method' of class '$class' not defined." 272 | fi 273 | __INNERCALL=false 274 | } 275 | 276 | ## 277 | # Enters (sets up methods and attributes of) an object. 278 | # 279 | # @param $1 280 | # The methods Class. 281 | # @param $2 282 | # The object reference. 283 | __enter() { 284 | # Set inner globals. 285 | __CLASS=$1 286 | __OBJECT=$2 287 | __ATTRIBUTES=() 288 | 289 | # Attribute discovery. 290 | private() { __attribute_init $__OBJECT "$1" "private" "$2"; } 291 | public() { __attribute_init $__OBJECT "$1" "public" "$2"; } 292 | 293 | # Get the base class. 294 | local class_function=$(__get_functions "class::$__CLASS::extends::*") 295 | __BASE=${class_function:$((${#__CLASS} + 18))} 296 | 297 | # All base classes automatically extend from 'Class'. 298 | __resolve "class" "Class" 299 | if [[ -z $__BASE && $__CLASS != "Class" ]]; then 300 | __BASE="Class" 301 | fi 302 | 303 | # Provide trait resolving function. 304 | use() { __resolve "trait" "$1"; } 305 | 306 | # Resolve the target class. 307 | __resolve "class" $__CLASS $__BASE 308 | 309 | # Set $this and $parent. 310 | this="__inner_call" 311 | parent="__parent_call $__BASE $__OBJECT" 312 | 313 | unset -f use 314 | unset -f private 315 | unset -f public 316 | } 317 | 318 | ## 319 | # Resolves extensions, decorations of a construct. 320 | # 321 | # @param $1 322 | # Construct type. 323 | # @param $2 324 | # Construct name. 325 | # @param $3 326 | # Optional base name. 327 | __resolve() { 328 | local type=$1 329 | local name=$2 330 | local base=$3 331 | 332 | # Get the function. 333 | local function="$(__get_functions "$type::$name")" 334 | if [[ -z $function ]]; then 335 | function="$(__get_functions "$type::$name::extends::*")" 336 | fi 337 | 338 | # Get the base. 339 | if [[ -z $base ]]; then 340 | base=${function:$((${#type} + ${#name} + 13))} 341 | fi 342 | 343 | # Resolve the base. 344 | if [[ -n $base ]]; then 345 | __resolve $type $base 346 | fi 347 | 348 | # Call class function. 349 | if __function_exists "$function"; then 350 | $function 351 | else 352 | __leave 353 | throw UndefinedClassException "Class ($type) '$name' not defined." 354 | fi 355 | 356 | # Search and resolve decorator classes. 357 | $(__get_functions "*::decorates::$name") 358 | } 359 | 360 | ## 361 | # Leaves an entered class 362 | __leave() { 363 | # Remove methods. 364 | unset -f $(__get_functions "method::*") 365 | 366 | # Remove inner globals. 367 | unset __CLASS 368 | unset __OBJECT 369 | unset __BASE 370 | unset __ATTRIBUTES 371 | unset this 372 | unset parent 373 | } 374 | 375 | ## 376 | # Handles object destruction. 377 | __destruct() { 378 | # Unset all attributes. 379 | local attribute 380 | local attribute_info 381 | for attribute in ${__ATTRIBUTES[@]}; do 382 | attribute_info=(${attribute/:/ }) 383 | unset __OBJECTS["$__OBJECT,${attribute_info[1]},${attribute_info[0]}"] 384 | done 385 | } 386 | 387 | ## 388 | # Clones an object to an existing reference. 389 | # 390 | # @param $1 391 | # The clones object reference. 392 | __clone() { 393 | local object=$1 394 | if [[ -z $object || "$object" != ?(+|-)+([0-9]) ]]; then 395 | throw IllegalArgumentException "Expected object reference, '$object' given." 396 | fi 397 | # Copy all attributes. 398 | local attribute 399 | local attribute_info 400 | for attribute in ${__ATTRIBUTES[@]}; do 401 | attribute_info=(${attribute/:/ }) 402 | __OBJECTS["$object,${attribute_info[1]},${attribute_info[0]}"]=${__OBJECTS[$__OBJECT,${attribute_info[1]},${attribute_info[0]}]} 403 | done 404 | } 405 | 406 | ## 407 | # Default exception handler. 408 | # 409 | # @param $1 410 | __default_exception_handler() { 411 | # Print error message with call stack. 412 | $exception printStack 1>&2 413 | # Exit with failure. 414 | exit 1 415 | } 416 | 417 | ## 418 | # Saves the current frame to stack. 419 | __frame_push() { 420 | if [[ -n $__CLASS ]]; then 421 | # Push frame to stack. 422 | __FRAME_STACK[$__FRAME_STACK_POINTER]="__enter $__CLASS $__OBJECT" 423 | let __FRAME_STACK_POINTER+=1 424 | # Leave current object. 425 | __leave 426 | fi 427 | } 428 | 429 | ## 430 | # Reenters the pervious frame from stack. 431 | __frame_pop() { 432 | if [[ $__FRAME_STACK_POINTER -gt 0 ]]; then 433 | # Get frame from stack. 434 | let __FRAME_STACK_POINTER-=1 435 | # Reenter previous object. 436 | ${__FRAME_STACK[$__FRAME_STACK_POINTER]} 437 | unset __FRAME_STACK[$__FRAME_STACK_POINTER] 438 | fi 439 | } 440 | 441 | ## 442 | # Initializes an attribute. 443 | # 444 | # @param $1 445 | # The object reference. 446 | # @param $2 447 | # The attribute name. 448 | # @param $3 449 | # The attribute type. 450 | # @param $4 451 | # The default value. 452 | __attribute_init() { 453 | # Add attribute to list. 454 | __ATTRIBUTES=(${__ATTRIBUTES[@]} "$3:$2") 455 | # Save default value. 456 | if [[ -z ${__OBJECTS["$1,$2,$3"]} ]]; then 457 | if [[ -n $4 ]]; then 458 | __OBJECTS["$1,$2,$3"]="$4" 459 | else 460 | __OBJECTS["$1,$2,$3"]="<<[NONE]>>" 461 | fi 462 | fi 463 | } 464 | 465 | ## 466 | # Sets the value of an attribute. 467 | # 468 | # @param $1 469 | # The attribute name. 470 | # @param $2 471 | # The value to set. 472 | __attribute_set() { 473 | local type 474 | if [[ -n ${__OBJECTS["$__OBJECT,$1,public"]} ]]; then 475 | type="public" 476 | else 477 | if [[ -n ${__OBJECTS["$__OBJECT,$1,private"]} && $__INNERCALL == true ]]; then 478 | type="private" 479 | fi 480 | fi 481 | if [[ -n $type ]]; then 482 | if [[ -n $2 ]]; then 483 | __OBJECTS["$__OBJECT,$1,$type"]=$2 484 | else 485 | __OBJECTS["$__OBJECT,$1,$type"]="<<[NONE]>>" 486 | fi 487 | else 488 | throw UndefinedAttributeException "Attribute '$1' not defined." 489 | fi 490 | } 491 | 492 | ## 493 | # Gets the value of an attribute. 494 | # 495 | # @param $1 496 | # The attribute name. 497 | __attribute_get() { 498 | local value 499 | if [[ -n ${__OBJECTS["$__OBJECT,$1,public"]} ]]; then 500 | value=${__OBJECTS["$__OBJECT,$1,public"]} 501 | else 502 | if [[ -n ${__OBJECTS["$__OBJECT,$1,private"]} && $__INNERCALL == true ]]; then 503 | value=${__OBJECTS["$__OBJECT,$1,private"]} 504 | else 505 | throw UndefinedAttributeException "Attribute '$1' not defined." 506 | fi 507 | fi 508 | if [[ $value != "<<[NONE]>>" && -n $value ]]; then 509 | echo "$value" 510 | fi 511 | } 512 | 513 | ## 514 | # Checks whether a function exists. 515 | # 516 | # @param $1 517 | # The function name. 518 | __function_exists() { 519 | if [[ -n $(type -t "$1") ]]; then 520 | return 0 521 | else 522 | return 1 523 | fi 524 | } 525 | 526 | ## 527 | # Returns the current call stack. 528 | __call_stack() { 529 | local frames=${#BASH_LINENO[@]} 530 | local frame=0 531 | for ((frame=frames-2; frame>=0; frame--)); do 532 | local base_source=${BASH_SOURCE[frame+1]} 533 | if [[ $(basename $base_source) != "ooengine" ]]; then 534 | printf " %-20s :%s \t %25s \n" "${BASH_SOURCE[frame+1]}" "${BASH_LINENO[frame]}" "${FUNCNAME[frame+1]}" 535 | fi 536 | done 537 | } 538 | 539 | ## 540 | # Returns a list of existing functions by pattern. 541 | # 542 | # @param $1 543 | # The pattern to match the name with. 544 | __get_functions() { 545 | compgen -A function -X \!$1 546 | } --------------------------------------------------------------------------------