--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry exported="true" kind="con" path="org.eclipse.fx.ide.jdt.core.JAVAFX_CONTAINER"/>
+ <classpathentry kind="lib" path="lib/javax/jcr/jcr/2.0/jcr-2.0.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/derby/derby/10.12.1.1/derby-10.12.1.1.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-api/2.14.5/jackrabbit-api-2.14.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-bundle/2.14.5/jackrabbit-bundle-2.14.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-core/2.14.5/jackrabbit-core-2.14.5.jar" sourcepath="C:/usr/local/src/Apache_Jackrabbit/jackrabbit-2.14.5/jackrabbit-core/src/main/java"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-data/2.14.5/jackrabbit-data-2.14.5.jar" sourcepath="C:/usr/local/src/Apache_Jackrabbit/jackrabbit-2.14.5/jackrabbit-core/src/main/java"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-jcr-commons/2.14.5/jackrabbit-jcr-commons-2.14.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-spi/2.14.5/jackrabbit-spi-2.14.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/jackrabbit/jackrabbit-spi-commons/2.14.5/jackrabbit-spi-commons-2.14.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/lucene/lucene-core/3.6.0/lucene-core-3.6.0.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/tika/tika-core/1.17/tika-core-1.17.jar"/>
+ <classpathentry kind="lib" path="lib/org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar"/>
+ <classpathentry kind="lib" path="lib/org/slf4j/slf4j-simple/1.6.6/slf4j-simple-1.6.6.jar"/>
+ <classpathentry kind="lib" path="lib/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar"/>
+ <classpathentry kind="lib" path="lib/commons-dbcp/commons-dbcp/1.3/commons-dbcp-1.3.jar"/>
+ <classpathentry kind="lib" path="lib/commons-io/commons-io/2.6/commons-io-2.6.jar"/>
+ <classpathentry kind="lib" path="lib/commons-pool/commons-pool/1.5.4/commons-pool-1.5.4.jar"/>
+ <classpathentry kind="lib" path="lib/concurrent/concurrent/1.3.4/concurrent-1.3.4.jar"/>
+ <classpathentry kind="lib" path="lib/log4j/log4j/1.2.17/log4j-1.2.17.jar"/>
+ <classpathentry kind="lib" path="lib/xalan/serializer/2.7.1/serializer-2.7.1.jar"/>
+ <classpathentry kind="lib" path="lib/xalan/xalan/2.7.1/xalan-2.7.1.jar"/>
+ <classpathentry kind="lib" path="lib/xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar"/>
+ <classpathentry kind="lib" path="lib/org/apache/derby/derby/10.12.1.1/derbyclient.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+bin
+derby.log
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Moxkiriya7</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+encoding//src/com/wiki/standalone/moxkiriya/resources/defaultstylesheet.css=UTF-8
+encoding/license=UTF-8
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.7
--- /dev/null
+<?xml version="1.0" encoding="ASCII"?>
+<anttasks:AntTask xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:anttasks="http://org.eclipse.fx.ide.jdt/1.0" buildDirectory="${project}/build">
+ <deploy>
+ <application name="Wall-E"/>
+ <info/>
+ </deploy>
+ <signjar/>
+</anttasks:AntTask>
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 <https://www.gnu.org/licenses/>.
+
+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:
+
+ <program> Copyright (C) <year> <name of author>
+ 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
+<https://www.gnu.org/licenses/>.
+
+ 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
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Main routine.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+
+package com.wiki.standalone.moxkiriya;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.ResourceBundle;
+
+import com.wiki.standalone.moxkiriya.dialog.ConfigSettingsDialog;
+import com.wiki.standalone.moxkiriya.dialog.DialogBase.CloseType;
+import com.wiki.standalone.moxkiriya.dialog.SelectPartyDialog;
+
+import javafx.application.Application;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+
+/**
+ * Application Main.
+ *
+ *
+ */
+public class Main extends Application {
+ /** primary stage. */
+ private Stage primaryStage_ = null;
+
+ /** Setting Manager */
+ private SettingManager settingManager_ = null;
+
+ /** Resource Bundle */
+ private ResourceBundle resources_;
+
+ /** Resource Manager */
+ public static ResourceManager resourceManagr_ = new ResourceManager();
+
+ /** Wiki Main window */
+ private WikiMainWindow wikiMainWindow_;
+
+ /**
+ * Main routine for this Application.
+ * @param args
+ */
+ public static void main(String[] args) {
+ launch(args);
+ }
+
+ @Override
+ public void start(Stage primaryStage) {
+ primaryStage_ = primaryStage;
+ settingManager_ = SettingManager.getInstance();
+ resources_ = ResourceBundle.getBundle("com.wiki.standalone.moxkiriya.resources.moxkiriya");
+
+ try {
+ WikiMainWindow.CloseType closeType = WikiMainWindow.CloseType.EXIT;
+
+ do {
+ String AppRoot = null;
+ String wikiroot = null;
+ String selectedParty = loadSelectedParty();
+
+ if(selectedParty != null) {
+ AppRoot = settingManager_.get(SettingManager.SETINGKEY_MOXKIRIYAROOT);
+ wikiroot = settingManager_.get(SettingManager.SETTINGSKEY_WIKIROOT);
+ }
+
+ if( (AppRoot == null)
+ || (wikiroot == null)) {
+ /*
+ * selectPartyを未設定の場合
+ */
+ Stage stage = new Stage(StageStyle.UNDECORATED);
+ stage.initOwner(primaryStage);
+ showConfigSettingsDialog(stage, selectedParty);
+ }
+
+ /*
+ * Show a wiki main window.
+ */
+ closeType = showWikiMainWindow();
+
+ if(closeType == WikiMainWindow.CloseType.RESTART) {
+ wikiMainWindow_.closeSession();
+ }
+ } while(closeType != WikiMainWindow.CloseType.EXIT);
+ } catch(Exception e) {
+ e.printStackTrace();
+ } finally {
+ if(wikiMainWindow_ != null) {
+ wikiMainWindow_.closeSession();
+ }
+ primaryStage_.hide();
+ }
+ }
+
+ /**
+ * Show wiki main window.
+ * @throws Exception
+ */
+ private WikiMainWindow.CloseType showWikiMainWindow() throws Exception {
+ WikiMainWindow.CloseType closeType = WikiMainWindow.CloseType.EXIT;
+ String appRoot = settingManager_.get(SettingManager.SETINGKEY_MOXKIRIYAROOT);
+
+ if(appRoot != null) {
+ File wikirootPath = new File(appRoot + "/" + WikiEngine.WIKIROOT_DIRECTORY);
+
+ if (wikirootPath != null) {
+ wikirootPath.mkdirs();
+
+ wikiMainWindow_ = new WikiMainWindow(primaryStage_, resources_);
+
+ /*
+ * wikirootに MainPageを構築する。
+ */
+ wikiMainWindow_.buildWikiMainTree(wikirootPath);
+
+ /*
+ * 外部リンクアイコン画像をApprootにアップロードする。
+ */
+ wikiMainWindow_.uploadResourcefile(appRoot + "/icon/Icon_External_Link.png",
+ "icon/Icon_External_Link.png");
+
+ closeType = wikiMainWindow_.show();
+ }
+ }
+
+ return closeType;
+ }
+
+ /**
+ * Load default party.
+ * @return String
+ * @throws Exception
+ */
+ private String loadSelectedParty() throws Exception {
+ String selectedParty = settingManager_.getSelectedParty();
+
+ if( (selectedParty != null)
+ && (selectedParty.isEmpty() == true)) {
+ ArrayList<String> partyList = settingManager_.getPartyList();
+
+ if(partyList.isEmpty() != true) {
+ SelectPartyDialog dialog = new SelectPartyDialog();
+ if(dialog.showDialog(primaryStage_, resources_) == CloseType.OK) {
+ String path = settingManager_.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+ settingManager_.savePartyConfig(path);
+ selectedParty = settingManager_.getSelectedParty();
+ }
+ else {
+ selectedParty = "";
+ }
+ }
+ }
+
+ return selectedParty;
+ }
+
+
+ /**
+ * WikiConfigSettingDialogを表示する。
+ * @param primaryStage
+ * @param selectedParty
+ * @throws Exception
+ */
+ private void showConfigSettingsDialog(Stage stage, String selectedParty) throws Exception {
+ ConfigSettingsDialog dialog = new ConfigSettingsDialog(selectedParty);
+ dialog.showDialog(stage, resources_);
+
+ Hashtable<String, String> settingsTable = dialog.getSettingsTable();
+ String path = settingManager_.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+
+ if( (selectedParty == null)
+ || (selectedParty.isEmpty() == true)) {
+ selectedParty = dialog.getPartyName();
+ }
+
+ if(selectedParty.isEmpty() != true) {
+ settingManager_.putParty(selectedParty, dialog.getDefaultPartyCheckValue());
+ settingManager_.savePartyConfig(path);
+ settingManager_.saveSettingConfig(path, selectedParty, settingsTable);
+ settingManager_.loadSettingFiles(path);
+ }
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Page data structure.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.regex.Pattern;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.version.Version;
+
+import com.wiki.standalone.moxkiriya.util.FileIO;
+
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+
+/**
+ * Page data structure.
+ *
+ */
+public class PageData {
+ /** JCR node */
+ private Node node_ = null;
+
+ /** Base version */
+ private Version baseVersion_ = null;
+
+ /** namespace: Main, File, or Category. */
+ private SimpleStringProperty namespace_ = new SimpleStringProperty("");
+
+ /** page title */
+ private SimpleStringProperty title_ = new SimpleStringProperty("");
+
+ /** content */
+ private SimpleStringProperty content_ = new SimpleStringProperty("");;
+
+ /** date */
+ private SimpleStringProperty date_ = new SimpleStringProperty("");;
+
+ /** check in Page list view */
+ private SimpleBooleanProperty check_ = new SimpleBooleanProperty(false);
+
+ /** categories */
+ private ArrayList<String> categories_ = new ArrayList<String>();
+
+ /** file data */
+ private FileData fileData_ = null;
+
+ /**
+ * Constructor.
+ */
+ public PageData() {
+ }
+
+ /**
+ * Constructor.
+ * @throws Exception
+ */
+ public PageData(Node node) throws Exception {
+ setNode(node);
+ }
+
+ /**
+ * Node getter.
+ * @return Node
+ */
+ public Node getNode() {
+ return node_;
+ }
+
+ /**
+ * node setter
+ * @param node
+ * @throws Exception
+ */
+ public void setNode(Node node) throws Exception {
+ try {
+ node_ = node;
+
+ namespace_.setValue(node.getProperty(WikiRepository.PROPERTY_NAMESPACE).getString());
+ title_.setValue(node.getProperty(WikiRepository.PROPERTY_TITLE).getString());
+ content_.setValue(node.getProperty(WikiRepository.PROPERTY_CONTENT).getString());
+
+ Value[] categories = node.getProperty(WikiRepository.PROPERTY_category).getValues();
+ for(Value category: categories) {
+ addCategory(category.getString());
+ }
+
+ Node fileNode = node.getNode(WikiRepository.NODE_FILE);
+ if(fileNode != null) {
+ fileData_ = new FileData(fileNode);
+ }
+ } catch(PathNotFoundException e) {
+ // Ignore exception.
+ }
+ }
+
+ /**
+ * UUID property getter.
+ * @return StringProperty
+ */
+ public StringProperty uuidProperty() {
+ SimpleStringProperty property = new SimpleStringProperty();
+
+ try {
+ property.setValue(node_.getProperty(Property.JCR_UUID).getString());
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ }
+
+ return property;
+ }
+
+ /**
+ * Check property getter.
+ * @return BooleanProperty
+ */
+ public BooleanProperty checkProperty() {
+ return check_;
+ }
+
+ /**
+ * Namespace getter.
+ * @return String
+ */
+ public String getNamespace() {
+ return namespace_.getValue();
+ }
+
+ /**
+ * Namespace setter.
+ * @param namespace
+ */
+ public void setNamespace(String namespace) {
+ namespace_.setValue(namespace);
+ }
+
+ /**
+ * Title getter.
+ * @return String
+ */
+ public String getTitle() {
+ return title_.getValue();
+ }
+
+ /**
+ * Title setter.
+ * @param title
+ */
+ public void setTitle(String title) {
+ title_.setValue(title);
+ }
+
+ /**
+ * titleProperty getter.
+ * @return StringProperty
+ */
+ public StringProperty titleProperty() {
+ return title_;
+ }
+
+ /**
+ * Content getter.
+ * @return String
+ */
+ public String getContent() {
+ return content_.getValue();
+ }
+
+ /**
+ * Content setter.
+ * @param title
+ */
+ public void setContent(String content) {
+ content_.setValue(content);
+ categories_ = extractCategoriesFromContent(content);
+ }
+
+ /**
+ * Introduction getter.
+ * Introduction is the first part of the page.
+ * The part is extracted until the following conditions are satisfied.
+ * <ul>
+ * <li>Up to the first heading.</li>
+ * <li>255 characters</li>
+ * <li>3 lines</li>
+ * </ul>
+ * @return String
+ * @throws Exception
+ */
+ public String getIntroduction() throws Exception {
+ BufferedReader buffreader = FileIO.bufferedReader(new StringReader(content_.getValue()));
+ String line;
+ StringBuffer buf = new StringBuffer("");
+ int lineCount = 0;
+ int charCount = 0;
+ Pattern hnPattern = Pattern.compile("^={2,6}[^=]+={2,6}$");
+
+ while((line = buffreader.readLine()) != null) {
+ if(hnPattern.matcher(line).matches() == true) {
+ break;
+ }
+ else if(charCount + line.length() > 255) {
+ buf.append(line.substring(0, 255 - charCount));
+ charCount = 255;
+ break;
+ }
+ else {
+ buf.append(line + "\n");
+ charCount += line.length() + 1;
+ lineCount++;
+
+ if(lineCount >= 3) {
+ break;
+ }
+ }
+ }
+
+ String intro = buf.toString();
+
+ return intro.replaceAll("<", "<").replaceAll(">", ">");
+ }
+
+ /**
+ * contentProperty getter.
+ * @return StringProperty
+ */
+ public StringProperty introductionProperty() {
+ String introduction = "";
+ try {
+ introduction = getIntroduction();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return new SimpleStringProperty(introduction);
+ }
+
+ /**
+ * dateProperty getter.
+ * @return StringProperty
+ */
+ public StringProperty dateProperty() {
+ String date = "";
+ try {
+ date = baseVersion_.getCreated().getTime().toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return new SimpleStringProperty(date);
+ }
+
+ /**
+ * Base version setter.
+ * @param baseVersion
+ */
+ public void setBaseVersion(Version baseVersion) {
+ baseVersion_ = baseVersion;
+ }
+
+ /**
+ * Categories getter.
+ * @return ArrayList<String>
+ */
+ public ArrayList<String> getCategories() {
+ return categories_;
+ }
+
+ /**
+ * Categories setter.
+ * @param category
+ */
+ public void addCategory(String category) {
+ categories_.add(category);
+ }
+
+ /**
+ * File data getter.
+ * @return FileData
+ */
+ public FileData getFileData() {
+ return fileData_;
+ }
+
+ /**
+ * Content setter.
+ * @param title
+ * @throws Exception
+ */
+ public void setFileData(File file) throws Exception {
+ fileData_ = new FileData(file);
+ }
+
+ /**
+ * content から Categories を抽出する。
+ * @param content
+ * @return ArrayList<String>
+ */
+ private ArrayList<String> extractCategoriesFromContent(String content) {
+ ArrayList<String> categories = new ArrayList<String>();
+ char[] charArrayContent = content.toCharArray();
+ int count = 0;
+
+ while(count < charArrayContent.length) {
+ if(charArrayContent[count] == '<') {
+ String sub = content.substring(count);
+
+ if(content.startsWith("<code>")) {
+ count += extractCategoriesSkipElem(sub, "<code>", "</code>");
+ }
+ else if(sub.startsWith("<pre>")) {
+ count += extractCategoriesSkipElem(sub, "<pre>", "</pre>");
+ }
+ else {
+ count++;
+ }
+ }
+ else if(charArrayContent[count] == '[') {
+ if(content.startsWith("[[Category:", count)) {
+ count += "[[Category:".length();
+ int startCount = count;
+
+ while(count < charArrayContent.length) {
+ count++;
+ if(charArrayContent[count] == ']') {
+ if(content.startsWith("]]", count) == true) {
+ int endCount = count;
+
+ String category = content.substring(startCount, endCount);
+ categories.add(category);
+ count += "]]".length();
+ break;
+ }
+ }
+ }
+ }
+ else {
+ count++;
+ }
+ }
+ else {
+ count++;
+ }
+ }
+
+ return categories;
+ }
+
+ /**
+ * Categories抽出中の指定された要素{<pre>, <code>}をスキップする。
+ * @param content
+ * @param startElem
+ * @param endElem
+ * @return int
+ */
+ private int extractCategoriesSkipElem(String content, String startElem, String endElem) {
+ char[] charArrayContent = content.toCharArray();
+ int count = 0;
+
+ while(count < content.length()) {
+ count++;
+ if(charArrayContent[count] == '<') {
+ String sub = content.substring(count);
+ if(sub.startsWith(endElem) == true) {
+ count += endElem.length();
+ break;
+ }
+ else if(sub.startsWith(startElem) == true) {
+ count += extractCategoriesSkipElem(sub, startElem, endElem);
+ }
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * File data structure.
+ */
+ public class FileData {
+ /** Node */
+ private Node node_ = null;
+
+ /** Mime type */
+ private String mimeType_;
+
+ /** Data within the file.*/
+ private InputStream inputStream_;
+
+ /** Timestamp of the file. */
+ private Calendar lastModified_;
+
+ /** character encoding. */
+ private String encoding_;
+
+ /**
+ * Constructor.
+ * @param file
+ * @throws Exception
+ */
+ public FileData(File file) throws Exception {
+ setInputStream(file);
+ }
+
+ /**
+ * Constructor.
+ * @param node
+ * @throws Exception
+ */
+ public FileData(Node node) throws Exception {
+ setNode(node);
+ }
+
+ /**
+ * Node getter.
+ * @return Node
+ */
+ public Node getNode() {
+ return node_;
+ }
+
+ /**
+ * Node setter.
+ * @param node
+ * @throws Exception
+ */
+ public void setNode(Node node) throws Exception {
+ node_ = node;
+ setInputStream(node);
+ }
+
+ /**
+ * inputstream getter.
+ * @return InputStream
+ */
+ public InputStream getInputStream() {
+ return inputStream_;
+ }
+
+ /**
+ * Inputstream setter.
+ * @param file
+ * @throws Exception
+ */
+ public void setInputStream(File file) throws Exception {
+ inputStream_ = new FileInputStream(file);
+ mimeType_ = URLConnection.guessContentTypeFromName(file.getAbsolutePath());
+
+ lastModified_ = Calendar.getInstance();
+ lastModified_.setTimeInMillis(file.lastModified());
+
+ if(mimeType_.startsWith("text/") == true) {
+ encoding_ = "UTF-8";
+ }
+ }
+
+ /**
+ * Inputstream setter.
+ * @param file
+ * @throws Exception
+ */
+ public void setInputStream(Node node) throws Exception {
+ Node nodeResource = node.getNode(Property.JCR_CONTENT);
+
+ inputStream_ = nodeResource.getProperty(Property.JCR_DATA).getBinary().getStream();
+ mimeType_ = nodeResource.getProperty(Property.JCR_MIMETYPE).getString();
+ lastModified_ = nodeResource.getProperty(Property.JCR_LAST_MODIFIED).getDate();
+
+ if(mimeType_.startsWith("text/") == true) {
+ encoding_ = nodeResource.getProperty(Property.JCR_ENCODING).getString();
+ }
+ }
+
+ /**
+ * Mimetype getter.
+ * @return String
+ */
+ public String getMimeType() {
+ return mimeType_;
+ }
+
+ /**
+ * Last modified getter.
+ * @return Calendar
+ */
+ public Calendar getLastModified() {
+ return lastModified_;
+ }
+ };
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya;
+
+import java.util.LinkedHashMap;
+
+import com.wiki.standalone.moxkiriya.dialog.AlertDialog;
+
+import javafx.scene.image.Image;
+
+public class ResourceManager {
+ public static final LinkedHashMap<AlertDialog.DialogType, Image> IconTable
+ = new LinkedHashMap<AlertDialog.DialogType, Image>() {
+ private static final long serialVersionUID = 1L;
+ { put(AlertDialog.DialogType.Error, new Image(getClass().getResource("resources/image/icon_error.png").toString())); }
+ { put(AlertDialog.DialogType.Alert, new Image(getClass().getResource("resources/image/icon_alert.png").toString())); }
+ { put(AlertDialog.DialogType.Info, new Image(getClass().getResource("resources/image/icon_info.jpg").toString())); }
+ { put(AlertDialog.DialogType.Confirm, new Image(getClass().getResource("resources/image/icon_confirm.png").toString())); }
+};
+
+
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Setting manager.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Set;
+
+import com.wiki.standalone.moxkiriya.util.FileIO;
+
+/**
+ * セッティングマネージャ
+ */
+public class SettingManager {
+ /** SETTINGSMAPKEY USER_HOME */
+ public static final String SETTINGSKEY_USER_HOME = "USER_HOME";
+
+ /** SETTINGSMAPKEY MOXKIRIYA_USER_DIR*/
+ public static final String SETTINGSKEY_MOXKIRIYA_USER_DIR = "MOXKIRIYA_USER_DIR";
+
+ /** SETTINGSMAPKEY MOXKIRIYAROOT */
+ public static final String SETINGKEY_MOXKIRIYAROOT = "moxkiriyaroot";
+
+ /** SETTINGSMAPKEY WIKIROOT */
+ public static final String SETTINGSKEY_WIKIROOT = "wikiroot";
+
+ /** SETTINGSMAPKEY_CLUSTER */
+ public static final String SETINGKEY_CLUSTER = "clustersetting";
+
+ /** SETTINGSMAPKEY_DBSERVERURL*/
+ public static final String SETINGKEY_DBSERVER_URL = "dbserverurl";
+
+ /** SETTINGSMAPKEY_DBSERVERPORT*/
+ public static final String SETINGKEY_DBSERVER_PORT = "dbserverport";
+
+ /** SETTINGSMAPKEY_DBSERVERPORT*/
+ public static final String SETINGKEY_JDBC_DRIVER = "jdbcdriver";
+
+ /**/
+ private static final String MOXKIRIYA_USER_DIR = "_moxkiriya";
+
+ /** 設定ファイル名 */
+ public static final String CONFIG_FILENAME = "_moxkiriya.config";
+
+ /** Party設定ファイル名 */
+ private static final String PARTY_FILENAME = "_party.config";
+
+ private static SettingManager singleton_ = null;
+
+ /** party map */
+ private Hashtable<String, Boolean> partyTable_ = new Hashtable<String, Boolean>();
+
+ /** setting map */
+ private Hashtable<String, String> settingsTable_ = new Hashtable<String, String>();
+
+ /** fullpath map */
+ private Hashtable<String, String> fullpathTable_ = new Hashtable<String, String>();
+
+ /** selected party */
+ private String selectedParty_ = null;
+
+ /**
+ * コンストラクタ
+ */
+ private SettingManager() {
+ }
+
+ /**
+ * インスタンスを取得する。
+ */
+ public static SettingManager getInstance() {
+ try {
+ if (singleton_ == null) {
+ singleton_ = new SettingManager();
+ singleton_.initializeSettingsMap();
+ }
+ } catch (Exception e) {
+ singleton_ = null;
+ e.printStackTrace();
+ }
+
+ return singleton_;
+ }
+
+ /**
+ * 設定Mapを初期化する
+ * @throws Exception
+ */
+ private void initializeSettingsMap() throws Exception {
+ String userHome = System.getProperty("user.home");
+ File moxkiriyaUserDir = new File(userHome + "/" + MOXKIRIYA_USER_DIR);
+
+ put(SETTINGSKEY_USER_HOME, userHome);
+ put(SETTINGSKEY_MOXKIRIYA_USER_DIR, moxkiriyaUserDir.getAbsolutePath());
+ if(moxkiriyaUserDir.exists() != true) {
+ moxkiriyaUserDir.mkdirs();
+ }
+
+ loadPartyFile(moxkiriyaUserDir.getAbsolutePath());
+ if( (selectedParty_ != null)
+ && (selectedParty_.isEmpty() != true)) {
+ loadSettingFiles(moxkiriyaUserDir.getAbsolutePath());
+ }
+ }
+
+ /**
+ * Party fileを読み込む。
+ * @param path
+ * @throws Exception
+ */
+ private void loadPartyFile(String path) throws Exception {
+ File partyFile = new File(path + "/" + PARTY_FILENAME);
+
+ if(partyFile.exists() != true) {
+ partyFile.createNewFile();
+ }
+ BufferedReader buffreader = FileIO.bufferedReader(partyFile);
+
+ String line = null;
+ while ((line = buffreader.readLine()) != null) {
+ String[] list = line.split("=", 2);
+ String key = list[0].trim();
+ String value = list[1].trim();
+ putParty(key, Boolean.valueOf(value));
+ }
+
+ Hashtable<String, Boolean> partyTable = getPartyTable();
+
+ if(partyTable.isEmpty() != true) {
+ selectedParty_ = "";
+
+ Set<String> keySet = partyTable.keySet();
+ for(String key: keySet) {
+ boolean value = partyTable.get(key);
+ if(value == true) {
+ selectedParty_ = key;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Configファイルを読み込む。
+ * @throws Exception
+ * @parma path Configファイルのパス名
+ */
+ public void loadSettingFiles(String path) throws Exception {
+ String selectedParty = getSelectedParty();
+
+ if( (selectedParty != null)
+ && (selectedParty.isEmpty() != true)) {
+ settingsTable_ = loadConfigSettings(path, selectedParty);
+ }
+
+ String wikiroot = get(SETTINGSKEY_WIKIROOT);
+ if(wikiroot != null) {
+ String moxkiriya_userDir = get(SETTINGSKEY_MOXKIRIYA_USER_DIR);
+
+ fullpathTable_.put(WikiEngine.TEMPLATE_HTMLHEADER_FILE, moxkiriya_userDir + "/" + selectedParty);
+ fullpathTable_.put(WikiEngine.USER_STYLESHEET_FILENAME, moxkiriya_userDir + "/" + selectedParty);
+ fullpathTable_.put(WikiEngine.FIXED_STYLESHEET_FILENAME, wikiroot);
+ fullpathTable_.put(WikiEngine.DEFAULT_STYLESHEET_FILENAME, wikiroot);
+ fullpathTable_.put(WikiRepository.REPOSITORY_CUSTER_FILENAME, moxkiriya_userDir + "/" + selectedParty);
+ fullpathTable_.put(WikiRepository.REPOSITORY_LOCAL_FILENAME, moxkiriya_userDir + "/" + selectedParty);
+
+ if(Boolean.valueOf(get(SETINGKEY_CLUSTER)) == true) {
+ fullpathTable_.put(WikiRepository.REOPSITORY_DIRNAME, moxkiriya_userDir + "/" + selectedParty);
+ }
+ else {
+ fullpathTable_.put(WikiRepository.REOPSITORY_DIRNAME, wikiroot);
+ }
+ }
+ }
+
+ /**
+ * Load config settings of specified party name.
+ * @param partyName
+ * @throws Exception
+ */
+ public Hashtable<String, String> loadConfigSettings(String path, String partyName) throws Exception {
+ Hashtable<String, String> settingsTable = new Hashtable<String, String>();
+
+ File partyDir = new File(path + "/" + partyName);
+ if( (partyDir.exists() != true)
+ && (partyDir.isDirectory() != true)) {
+ partyDir.mkdirs();
+ }
+
+ File inifile = new File(partyDir.getAbsolutePath()
+ + "/" + SettingManager.CONFIG_FILENAME);
+ if (inifile.exists() != true) {
+ /*
+ * ファイルが存在しなかった場合、ファイルを新規作成
+ */
+ inifile.createNewFile();
+ }
+
+ BufferedReader buffreader = FileIO.bufferedReader(inifile);
+
+ String userHome = System.getProperty("user.home");
+ File moxkiriyaUserDir = new File(userHome + "/" + MOXKIRIYA_USER_DIR);
+
+ settingsTable.put(SETTINGSKEY_USER_HOME, userHome);
+ settingsTable.put(SETTINGSKEY_MOXKIRIYA_USER_DIR, moxkiriyaUserDir.getAbsolutePath());
+
+ String line = null;
+ while ((line = buffreader.readLine()) != null) {
+ String[] list = line.split("=", 2);
+
+ if (list.length >= 2) {
+ String key = list[0].trim();
+
+ if (key.length() > 0) {
+ settingsTable.put(key, list[1].trim());
+ }
+ }
+ }
+ buffreader.close();
+
+ return settingsTable;
+ }
+
+ /**
+ * Party table getter.
+ * @return Hashtable<String, Boolean>
+ */
+ public Hashtable<String, Boolean> getPartyTable() {
+ return partyTable_;
+ }
+
+ /**
+ * Selected party getter.
+ * @return String
+ */
+ public String getSelectedParty() {
+ return selectedParty_;
+ }
+
+ /**
+ * Selected party setter.
+ * @return String
+ * @throws Exception
+ */
+ public void setSelectedParty(String partyName) throws Exception {
+ selectedParty_ = partyName;
+
+ File moxkiriyaUserDir = new File(get(SETTINGSKEY_MOXKIRIYA_USER_DIR));
+ loadSettingFiles(moxkiriyaUserDir.getAbsolutePath());
+ }
+
+ /**
+ * Party list getter.
+ * @return ArrayList<String>
+ */
+ public ArrayList<String> getPartyList() {
+ ArrayList<String> PartyList = new ArrayList<String>();
+ Set<String> keySet = partyTable_.keySet();
+
+ for(String key: keySet) {
+ PartyList.add(key);
+ }
+
+ return PartyList;
+ }
+
+ /**
+ * Put party.
+ * @param partyName
+ * @param isDefault
+ */
+ public void putParty(String partyName, boolean isDefault) {
+ if(partyName.isEmpty() != true) {
+ if(isDefault == true) {
+ Set<String> keySet = partyTable_.keySet();
+
+ for(String key: keySet) {
+ partyTable_.put(key, false);
+ }
+ }
+ partyTable_.put(partyName, isDefault);
+ }
+ }
+
+ /**
+ * 設定情報を追加する。
+ * @param key 設定キー
+ * @parm val 設定値
+ */
+ public void put(String key, String val) {
+ settingsTable_.put(key, val);
+ }
+
+ /**
+ * keyに該当する設定値を取得する。
+ * @param key
+ * @return
+ */
+ public String get(String key) {
+ return settingsTable_.get(key);
+ }
+
+ /**
+ * 設定を保存する。
+ * @throws Exception
+ */
+ public void save() throws Exception {
+ String path = get(SETTINGSKEY_MOXKIRIYA_USER_DIR);
+ File moxkiriyaHomeDir = new File(path);
+
+ if( (moxkiriyaHomeDir.exists() != true)
+ || (moxkiriyaHomeDir.isDirectory() != true)) {
+ moxkiriyaHomeDir.mkdirs();
+ }
+
+ /*
+ * save _party.config
+ */
+ savePartyConfig(path);
+
+ /*
+ * save _moxkiriya.config.
+ */
+ saveSettingConfig(path);
+
+ /*
+ * (Re)load _moxkiriya.config.
+ */
+ loadSettingFiles(path);
+ }
+
+ /**
+ * Translate the setting filename to the absolutepath.
+ * @param filename
+ * @return String
+ */
+ public String getAbsolutePath(String filename) {
+ String path = fullpathTable_.get(filename);
+
+ return path + "/" + filename;
+ }
+
+ /**
+ * Save party configuration to file.
+ * @param path
+ * @throws Exception
+ */
+ public void savePartyConfig(String path) throws Exception {
+ StringBuffer stringBuf = new StringBuffer("");
+ Enumeration<String> keys = partyTable_.keys();
+
+ while (keys.hasMoreElements() == true) {
+ String key = keys.nextElement();
+ boolean value = partyTable_.get(key);
+ stringBuf.append(key + "=" + value + "\n");
+ }
+
+ File inifile = new File(path + "/" + PARTY_FILENAME);
+ BufferedWriter writer = FileIO.bufferedWriter(inifile);
+
+ writer.write(stringBuf.toString());
+ writer.close();
+ }
+
+ /**
+ * Save setting configuration to file.
+ * @param path
+ * @throws Exception
+ */
+ public void saveSettingConfig(String path) throws Exception {
+ saveSettingConfig(path, selectedParty_, settingsTable_);
+ }
+
+ /**
+ * Save setting configuration to file.
+ * @param path
+ * @param partyName
+ * @param settingTable
+ * @throws Exception
+ */
+ public void saveSettingConfig(String path, String partyName, Hashtable<String, String> settingTable) throws Exception {
+ StringBuffer stringBuf = new StringBuffer("");
+ Enumeration<String> keys = settingTable.keys();
+
+ while (keys.hasMoreElements() == true) {
+ String key = keys.nextElement();
+ String value = settingTable.get(key);
+ stringBuf.append(key + "=" + value + "\n");
+ }
+ File partyDir = new File(path + "/" + partyName);
+
+ if(partyDir.exists() != true) {
+ partyDir.mkdirs();
+ }
+
+ File inifile = new File(partyDir.getAbsolutePath() + "/" + CONFIG_FILENAME);
+ BufferedWriter writer = FileIO.bufferedWriter(inifile);
+
+ writer.write(stringBuf.toString());
+ writer.close();
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki engine.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Value;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionIterator;
+
+import com.wiki.standalone.moxkiriya.parser.blockparser.WikiBodyBlockParser;
+import com.wiki.standalone.moxkiriya.util.FileIO;
+
+/**
+ * Wiki engine.
+ *
+ */
+public class WikiEngine {
+ /** Wiki Root directory */
+ public static final String WIKIROOT_DIRECTORY = "wikiroot";
+
+ /** Main page directory */
+ public static final String MAINPAGE_TITLE = "MainPage";
+
+ /** template file HTML<head>section. */
+ public static final String TEMPLATE_HTMLHEADER_FILE = "templateHtmlHead.txt";
+
+ /** fixedstylesheetファイル名 */
+ public static final String FIXED_STYLESHEET_FILENAME = "fixedstylesheet.css";
+
+ /** user stylesheetファイル名 */
+ public static final String USER_STYLESHEET_FILENAME = "user.css";
+
+ /** defaultstylesheetファイル名 */
+ public static final String DEFAULT_STYLESHEET_FILENAME = "defaultstylesheet.css";
+
+
+ /** jcr_uuid 独自属性 */
+ public static final String ATTRIBUTE_JCR_UUID = "data-jcr_uuid";
+
+ /** namespace "Cagegory" */
+ public static final String NAMESPACE_CATEGORY = WikiRepository.PROPERTY_CATEGORY;
+
+ /** namespace "File" */
+ public static final String NAMESPACE_FILE = WikiRepository.PROPERTY_FILE;
+
+ /** Wiki Repository. */
+ protected WikiRepository wikiRepository_;
+
+ /** Page data map. */
+ private HashMap<String, PageData> pageDataMap_ = null;
+
+ /** Wiki history manager. */
+ private WikiHistory wikiHistory_ = null;
+
+ /**
+ * Constructor.
+ */
+ public WikiEngine() {
+ wikiHistory_ = new WikiHistory();
+ }
+
+ /**
+ * Wiki repository getter.
+ * return wikiRepository
+ */
+ public WikiRepository getWikiRepository() {
+ return wikiRepository_;
+ }
+
+ /**
+ * Wiki repository setter.
+ * @param wikiRepository
+ */
+ public void setWikiRepository(WikiRepository wikiRepository) {
+ wikiRepository_ = wikiRepository;
+ }
+
+ /**
+ *
+ * @param wikirootPath
+ * @param mainPageData
+ * @throws Exception
+ */
+ public void buildWikiRepository(File wikirootPath) throws Exception {
+ wikiRepository_ = new WikiRepository(wikirootPath);
+
+ PageData mainPageData = new PageData();
+ mainPageData.setNamespace(WikiRepository.PROPERTY_MAIN);
+ mainPageData.setTitle(MAINPAGE_TITLE);
+
+ wikiRepository_.buildWikiRepository(mainPageData);
+ }
+
+ /**
+ * PageData map setter.
+ * @param map
+ */
+ public void setPageDataMap(HashMap<String, PageData> map) {
+ pageDataMap_ = map;
+ }
+
+ /**
+ * PageData map setter.
+ * @param pageData
+ * @throws Exception
+ */
+ public void setPageDataMap(PageData pageData) throws Exception {
+ String uuid = pageData.getNode().getProperty(Property.JCR_UUID).getString();
+ pageDataMap_ = queryPageUUID(uuid);
+ }
+
+ /**
+ * PageData map setter.
+ * @param pageData
+ * @throws Exception
+ */
+ public void setPageDataMap(String title) throws Exception {
+ pageDataMap_ = queryPageTitle(title);
+ }
+
+ /**
+ * PageData map getter.
+ * return HashMap<String, PageData>
+ */
+ public HashMap<String, PageData> getPageDataMap() {
+ return pageDataMap_;
+ }
+
+ /**
+ * NamespaceList getter.
+ * @return ArrayList<String>
+ * @throws Exception
+ */
+ public ArrayList<String> getNamespaceList() throws Exception {
+ ArrayList<String> namespaceList = new ArrayList<String>();
+ Value[] namespaces = wikiRepository_.getNamespaceList();
+
+ for(Value value: namespaces) {
+ namespaceList.add(value.getString());
+ }
+
+ return namespaceList;
+ }
+
+ /**
+ * Checkout.
+ * @throws Exception
+ */
+ public void checkout() throws Exception {
+ PageData currentPageData = null;
+
+ if(pageDataMap_.size() == 1) {
+ currentPageData = pageDataMap_.values().iterator().next();
+ }
+
+ if(currentPageData != null) {
+ wikiRepository_.checkout(currentPageData);
+ }
+ }
+
+ /**
+ * Checkin.
+ * @throws Exception
+ */
+ public PageData checkin(PageData pageData) throws Exception {
+ return wikiRepository_.checkin(pageData);
+ }
+
+ /**
+ * Cancel checkout.
+ * @throws Exception
+ */
+ public void cancelCheckout() throws Exception {
+ PageData currentPageData = null;
+
+ if(pageDataMap_.size() == 1) {
+ currentPageData = pageDataMap_.values().iterator().next();
+ }
+
+ if(currentPageData != null) {
+ wikiRepository_.cancelCheckout(currentPageData);
+ }
+ }
+
+ /**
+ * Wikiシンタックスの文字列をHTML形式に変換する。
+ * @return HTMLコンテンツ
+ * @throws Exception
+ */
+ public String parse() throws Exception {
+ PageData pageData = null;
+ String bodyHtml = "";
+
+ if(pageDataMap_.size() == 1) {
+ pageData = pageDataMap_.values().iterator().next();
+ wikiHistory_.add(pageData);
+ bodyHtml = markupContents(pageData);
+ }
+ else {
+ bodyHtml = markupContentsList();
+ }
+
+ /*
+ * Header部の構築
+ */
+ String headerHtml = buildHtmlHeader();
+ StringBuffer buf = new StringBuffer();
+
+ buf.append(headerHtml);
+ buf.append(bodyHtml);
+ buf.append("</html>");
+
+ return buf.toString();
+ }
+
+ /**
+ * Wikiシンタックスの文字列をHTML形式に変換する。
+ * @param pageData
+ * @return HTMLコンテンツ
+ * @throws Exception
+ */
+ public String parse(PageData pageData) throws Exception {
+ String bodyHtml = markupContents(pageData);
+
+ /*
+ * Header部の構築
+ */
+ String headerHtml = buildHtmlHeader();
+ StringBuffer buf = new StringBuffer();
+
+ buf.append(headerHtml);
+ buf.append(bodyHtml);
+ buf.append("</html>");
+
+ return buf.toString();
+ }
+
+ /**
+ * Wikiシンタックスの文字列をHTML形式に変換する。
+ * @return HTMLコンテンツ
+ * @throws Exception
+ */
+ public String markupContents(PageData pageData) throws Exception {
+ WikiBodyBlockParser bodyBlockParser = new WikiBodyBlockParser(this);
+ String bodyHtml = "";
+
+ /*
+ * Contentsのparse & Body部の構築.
+ */
+ bodyBlockParser.parsePageTitle(pageData.getTitle());
+ BufferedReader buffreader = FileIO.bufferedReader(new StringReader(pageData.getContent()));
+
+ bodyHtml = bodyBlockParser.parse(buffreader)
+ + buildCategoryList(pageData);
+
+ buffreader.close();
+
+ return bodyHtml;
+ }
+
+ /**
+ * PageリストをHTML形式で生成する。
+ * @return HTMLコンテンツ
+ * @throws Exception
+ */
+ public String markupContentsList() throws Exception {
+ StringBuffer bodybuf = new StringBuffer();
+ ResourceBundle resources_ = ResourceBundle.getBundle("com.wiki.standalone.moxkiriya.resources.moxkiriya");
+
+ bodybuf.append("<h1>" + resources_.getString("key.Search.Result") + "</h1>\n");
+ if(pageDataMap_.size() > 1) {
+ bodybuf.append("<div>\n");
+ bodybuf.append(resources_.getString("key.Message.found.pages") + "\n");
+ bodybuf.append("</div>\n");
+
+ for(String uuid: pageDataMap_.keySet()) {
+ PageData pageData = pageDataMap_.get(uuid);
+
+ bodybuf.append("<h3>\n");
+ bodybuf.append("<a href="
+ + "\"" + pageData.getTitle() + "\" "
+ + ATTRIBUTE_JCR_UUID + "="
+ + pageData.getNode().getProperty(Property.JCR_UUID).getString()
+ + ">");
+ bodybuf.append(pageData.getTitle());
+ bodybuf.append("</a>\n");
+ bodybuf.append("</h3>\n");
+ bodybuf.append("<div>\n");
+ bodybuf.append(pageData.getIntroduction());
+ bodybuf.append("</div>\n");
+ }
+ }
+ else {
+ /*
+ * No page was found.
+ */
+ bodybuf.append("<div>\n");
+ bodybuf.append(resources_.getString("key.search.result.message.nopage") + "\n");
+ bodybuf.append("</div>\n");
+ }
+
+ return bodybuf.toString();
+ }
+
+ /**
+ * HTMLヘッダ部を構築する。
+ * @return HTMLヘッダ部
+ * @throws IOException
+ */
+ public static String buildHtmlHeader() throws IOException {
+ StringBuffer stringBuf = new StringBuffer();
+ SettingManager settingMgr = SettingManager.getInstance();
+ File headerTemplate = new File(settingMgr.getAbsolutePath(TEMPLATE_HTMLHEADER_FILE));
+ InputStream in = new FileInputStream(headerTemplate);
+ byte byteBuf[] = new byte[255];
+ int size;
+
+ while((size = in.read(byteBuf)) != -1) {
+ stringBuf.append(new String(byteBuf, 0, size));
+ }
+ in.close();
+ File stylesheetFile;
+
+ stylesheetFile = new File(settingMgr.getAbsolutePath(DEFAULT_STYLESHEET_FILENAME));
+ stringBuf.append("\t<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ + stylesheetFile.toURI().toString()
+ + "\">\n");
+
+ stylesheetFile = new File(settingMgr.getAbsolutePath(USER_STYLESHEET_FILENAME));
+ stringBuf.append("\t<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ + stylesheetFile.toURI().toString()
+ + "\">\n");
+
+ stylesheetFile = new File(settingMgr.getAbsolutePath(FIXED_STYLESHEET_FILENAME));
+ stringBuf.append("\t<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ + stylesheetFile.toURI().toString()
+ + "\">\n");
+
+ stringBuf.append("<script>\n"
+ + "function scrollTo(elementId) {\n"
+ + "\tdocument.getElementById(elementId).scrollIntoView()\n"
+ + "}\n"
+ + "</script>");
+
+ stringBuf.append("</head>\n");
+
+ return stringBuf.toString();
+ }
+
+ private String buildCategoryList(PageData pageData) throws Exception {
+ StringBuffer buf = new StringBuffer("");
+ ArrayList<String> categoryies = pageData.getCategories();
+
+ for(String category: categoryies) {
+ if(category.isEmpty() != true) {
+ HashMap<String, PageData> categoryPageMap = queryPageTitle(category, NAMESPACE_CATEGORY);
+
+ if(categoryPageMap.size() == 1) {
+ PageData categoryPage = categoryPageMap.values().iterator().next();
+ Node node = categoryPage.getNode();
+
+ buf.append("<a href=" + "\"" + category + "\" ");
+ buf.append(ATTRIBUTE_JCR_UUID + "=\"");
+ buf.append(node.getProperty(Property.JCR_UUID).getString());
+ buf.append("\">");
+ buf.append(category);
+ buf.append("</a> ");
+ }
+ }
+ }
+
+ String startElem = "";
+ String endElem = "";
+
+ if(buf.length() > 0) {
+ startElem = "<div class=\"categorylist\"> Categories: \n";
+ endElem = "</div>";
+ }
+
+ return startElem + buf.toString() + endElem;
+ }
+
+
+ /**
+ * Execute query node by namespace.
+ * @param namespace
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageNamespace(String namespace) throws Exception {
+ return wikiRepository_.queryPageNamespace(namespace);
+ }
+
+ /**
+ * Execute query node by UUID.
+ * @param uuid
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageUUID(String uuid) throws Exception {
+ return wikiRepository_.queryPageUUID(uuid);
+ }
+
+ /**
+ * Execute query node by pageTitle.
+ * @param pageTitle
+ * @param namespace
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageTitle(String pageTitle, String namespace) throws Exception {
+ return wikiRepository_.queryPageTitle(pageTitle, namespace);
+ }
+
+ /**
+ * Execute query node by pageTitle.
+ * @param pageTitle
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageTitle(String pageTitle) throws Exception {
+ return wikiRepository_.queryPageTitle(pageTitle);
+ }
+
+ /**
+ * Execute query full text search.
+ * @param searchKey
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageFullTextSearch(String searchKey) throws Exception {
+ return wikiRepository_.queryPageFullTextSearch(searchKey);
+ }
+
+ /**
+ * Test namespace is contains namespaceList.
+ * @param namespace
+ * @return boolean
+ * @throws Exception
+ */
+ public boolean isContainsNamespaceList(String namespace) throws Exception {
+ return wikiRepository_.isContainsNamespaceList(namespace);
+ }
+
+ /**
+ * Delete page node.
+ * @param pagedata
+ * @throws Exception
+ */
+ public void deletePage(PageData pagedata) throws Exception {
+ wikiRepository_.deletePage(pagedata);
+ }
+
+ /**
+ * Refresh session.
+ * @throws Exception
+ */
+ public void refreshSession() throws Exception {
+ wikiRepository_.refreshSession();
+ if(pageDataMap_ != null) {
+ if(pageDataMap_.size() == 1) {
+ PageData pageData = pageDataMap_.values().iterator().next();
+ String uuid = pageData.getNode().getProperty(Property.JCR_UUID).getString();
+
+ pageDataMap_ = wikiRepository_.queryPageUUID(uuid);
+ }
+ }
+ }
+
+ /**
+ * Is there an older node on a history list.
+ * @return boolean
+ */
+ public boolean canBack() {
+ return wikiHistory_.canBack();
+ }
+
+ /**
+ * Is there an newer node on a history list.
+ * @return boolean
+ */
+ public boolean canForward() {
+ return wikiHistory_.canForward();
+ }
+
+ /**
+ * Execute history back.
+ * @throws Exception
+ */
+ public String back() throws Exception {
+ PageData pageData = wikiHistory_.back();
+ setPageDataMap(pageData);
+ return parse(pageData);
+ }
+
+ /**
+ * Execute history forward.
+ * @return PageData
+ * @throws Exception
+ */
+ public String forward() throws Exception {
+ PageData pageData = wikiHistory_.forward();
+ setPageDataMap(pageData);
+ return parse(pageData);
+ }
+
+ /**
+ * History clear.
+ */
+ public void clearHistory() {
+ wikiHistory_.clear();
+ }
+
+ /**
+ * VersionHistory getter.
+ * @return VersionIterator
+ * @throws Exception
+ */
+ public VersionIterator getVersionHistory() throws Exception {
+ PageData pageData = pageDataMap_.values().iterator().next();
+ String uuid = pageData.getNode().getProperty(Property.JCR_UUID).getString();
+
+ return wikiRepository_.getVersionHistory(uuid);
+ }
+
+ /**
+ * Base version getter.
+ * @return Version
+ * @throws Exception
+ */
+ public Version getBaseVersion() throws Exception {
+ PageData pageData = pageDataMap_.values().iterator().next();
+
+ return wikiRepository_.getBaseVersion(pageData.getNode());
+ }
+
+ /**
+ * Restore version.
+ * @param version
+ * @throws Exception
+ */
+ public void restoreVersion(Version version) throws Exception {
+ PageData pageData = pageDataMap_.values().iterator().next();
+ wikiRepository_.restoreVersion(version, pageData.getNode());
+ }
+
+ /**
+ * Import system vies.
+ * @param outputFile
+ * @throws Exception
+ */
+ public void importSystemView(File outputFile) throws Exception {
+ wikiRepository_.importSystemView(outputFile);
+ }
+
+ /**
+ * Export system view.
+ * @param outputFile
+ * @throws Exception
+ */
+ public void exportSystemView(File outputFile) throws Exception {
+ wikiRepository_.exportSystemView(outputFile);
+ }
+
+ /**
+ * Session closer.
+ */
+ public void closeSession() {
+ wikiRepository_.closeSession();
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * WikiHistory.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.util.ArrayList;
+
+import javax.jcr.Property;
+
+/**
+ * Manage wiki history.
+ *
+ *
+ */
+public class WikiHistory {
+ /** History list*/
+ private ArrayList<PageData> histories_ = new ArrayList<PageData>();
+
+ /** Position on history list. */
+ private int position_ = 0;
+
+ /**
+ * Constructor.
+ */
+ public WikiHistory() {
+ histories_.clear();
+ }
+
+ /**
+ * Is there an older node on a history list.
+ * @return boolean
+ */
+ public boolean canBack() {
+ boolean canBack = false;
+
+ if(histories_.size() > 1) {
+ if(position_ > 0) {
+ canBack = true;
+ }
+ }
+
+ return canBack;
+ }
+
+ /**
+ * Is there an newer node on a history list.
+ * @return boolean
+ */
+ public boolean canForward() {
+ boolean canForward = false;
+
+ if(histories_.size() > 0) {
+ if(position_ < histories_.size() - 1) {
+ canForward = true;
+ }
+ }
+
+ return canForward;
+ }
+
+ /**
+ * Execute history back.
+ * @return PageData
+ */
+ public PageData back() {
+ PageData pageData = null;
+
+ if(canBack() == true) {
+ position_--;
+ pageData = histories_.get(position_);
+ }
+
+ return pageData;
+ }
+
+ /**
+ * Execute history forward.
+ * @return PageData
+ */
+ public PageData forward() {
+ PageData pageData = null;
+
+ if(canForward() == true) {
+ position_++;
+ pageData = histories_.get(position_);
+ }
+
+ return pageData;
+ }
+
+ /**
+ * Add PageData to history list.
+ * @param pageData
+ * @throws Exception
+ */
+ public void add(PageData pageData) throws Exception {
+ if(histories_.size() > 0) {
+ PageData latestPage = histories_.get(position_);
+ String uuid = latestPage.getNode().getProperty(Property.JCR_UUID).getString();
+
+ if(pageData.getNode().getProperty(Property.JCR_UUID).getString().equals(uuid) == true) {
+ /*
+ * History中に同じページを連続登録しようとした場合、
+ */
+ histories_.remove(position_);
+ }
+ else {
+ position_++;
+ }
+ }
+
+ for(int count = position_; count < histories_.size(); count++) {
+ histories_.remove(count);
+ }
+
+ histories_.add(pageData);
+ position_ = histories_.size() - 1;
+ }
+
+ /**
+ * Clear history.
+ */
+ public void clear() {
+ histories_.clear();
+ position_ = 0;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.net.*?>
+<?import javafx.collections.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.image.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.text.*?>
+<?import javafx.scene.web.*?>
+<?scenebuilder-preview-i18n-resource resources/moxkiriya.properties?>
+
+<AnchorPane id="rootAnchorPane" fx:id="topAnchorPain" maxHeight="-1.0" maxWidth="-1.0" mouseTransparent="false" prefHeight="680.0" prefWidth="1024.0" snapToPixel="true" style="" styleClass="rootAnchorPane" visible="true" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.WikiMainWindowController">
+ <children>
+ <MenuBar fx:id="menuBar" maxHeight="-Infinity" maxWidth="-1.0" minHeight="-1.0" minWidth="-1.0" prefHeight="30.0" prefWidth="640.0" visible="true" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+ <menus>
+ <Menu mnemonicParsing="false" text="%key.Menu.File">
+ <items>
+ <MenuItem mnemonicParsing="false" onAction="#onActionMenuItemNew" text="%key.MenuItem.New" fx:id="menuItemNew" />
+ <MenuItem mnemonicParsing="false" onAction="#onActionMenuItemImport" text="%key.MenuItem.Import" fx:id="menuItemImport" />
+ <MenuItem mnemonicParsing="false" onAction="#onActionMenuItemExport" text="%key.MenuItem.Export" fx:id="menuItemExport" />
+ <MenuItem mnemonicParsing="false" onAction="#onActionMenuItemExit" text="%key.MenuItem.Exit" fx:id="menuItemExit" />
+ </items>
+ </Menu>
+ <Menu mnemonicParsing="false" text="%key.Menu.Edit">
+ <items>
+ <MenuItem disable="false" mnemonicParsing="false" onAction="#onActionMenuItemSelectParty" text="%key.MenuItem.Select.Party" fx:id="menuItemSelectParty" />
+ </items>
+ </Menu>
+ <Menu mnemonicParsing="false" text="%key.Menu.Help">
+ <items>
+ <MenuItem mnemonicParsing="false" onAction="#onActionMenuItemAboutMoxkiriya" text="%key.MenuItem.About.Moxkiriya" fx:id="menuItemAboutMoxkiriya" />
+ </items>
+ </Menu>
+ </menus>
+ </MenuBar>
+ <AnchorPane fx:id="sideMenuAnchorPane" prefHeight="736.0" prefWidth="180.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="30.0" />
+ <AnchorPane fx:id="choiceViewAnchorPane" prefHeight="45.0" prefWidth="1010.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0">
+ <children>
+ <Hyperlink fx:id="choiceViewHyperlinkReading" onMouseClicked="#onMouseClickedHyperlinkReading" prefHeight="30.0" text="%key.Hyperlink.Reading" underline="true" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="10.0" />
+ <Hyperlink fx:id="choiceViewHyperlinkPageList" onMouseClicked="#onMouseClickedHyperlinkPageList" prefHeight="30.0" text="%key.Hyperlink.Pagelist" underline="true" AnchorPane.rightAnchor="220.0" AnchorPane.topAnchor="10.0" />
+ <Hyperlink id="hyperlink_webViewEdit" fx:id="choiceViewHyperlinkEdit" alignment="CENTER" onMouseClicked="#onMouseClickedHyperlinkEdit" prefHeight="30.0" prefWidth="80.0" text="%key.Hyperlink.Edit" underline="true" AnchorPane.rightAnchor="130.0" AnchorPane.topAnchor="10.0" />
+ </children>
+ </AnchorPane>
+ <AnchorPane id="AnchorPane" fx:id="AnchorPaneWebView" prefHeight="380.0" prefWidth="590.0" visible="true" AnchorPane.bottomAnchor="65.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="80.0">
+ <children>
+ <AnchorPane fx:id="webViewMenuAnchorPane" prefHeight="45.0" prefWidth="590.0" style="" styleClass="webViewMenuAnchorPane" visible="true" AnchorPane.leftAnchor="180.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+ <children>
+ <Button id="webViewMenuAn" fx:id="webViewMenuAnchorPaneButtonBack" disable="true" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonBack" prefHeight="35.0" prefWidth="45.0" style="" text="⇦" AnchorPane.leftAnchor="5.0" AnchorPane.topAnchor="2.0">
+ <font>
+ <Font size="17.0" fx:id="x1" />
+ </font>
+ </Button>
+ <Button fx:id="webViewMenuAnchorPaneButtonForward" disable="true" font="$x1" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonForward" prefHeight="35.0" prefWidth="45.0" text="⇨" AnchorPane.leftAnchor="55.0" AnchorPane.topAnchor="2.0" />
+ <Button fx:id="webViewMenuAnchorPaneButtonReload" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonReload" prefHeight="35.0" prefWidth="70.0" text=" 🔃" AnchorPane.leftAnchor="105.0" AnchorPane.topAnchor="2.0">
+ <font>
+ <Font size="12.0" fx:id="x3" />
+ </font>
+ </Button>
+ <Button fx:id="webViewMenuAnchorPaneButtonHome" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonHome" prefHeight="30.0" prefWidth="45.0" text="⌂" AnchorPane.leftAnchor="180.0" AnchorPane.topAnchor="2.0">
+ <font>
+ <Font size="20.0" fx:id="x2" />
+ </font>
+ </Button>
+ <TextField id="TextFieldSearchWiki" fx:id="webViewMenuAnchorPaneTextFieldSearchWiki" maxHeight="-Infinity" maxWidth="-Infinity" onKeyPressed="#onKeyPressedTextFieldSearchWiki" prefHeight="35.0" prefWidth="256.0" promptText="%key.TextField.Search_Wiki" AnchorPane.rightAnchor="85.0" AnchorPane.topAnchor="2.0" />
+ <Button id="ButtonSearch" fx:id="webViewMenuAnchorPaneButtonSearch" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonSearch" prefHeight="35.0" prefWidth="80.0" text="%key.Button.Search" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
+ </children>
+ <padding>
+ <Insets right="2.0" top="2.0" />
+ </padding>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </AnchorPane>
+ <Hyperlink id="hyperlinkMain" fx:id="webViewHyperlinkMain" alignment="CENTER" onMouseClicked="#onMouseClickedWebViewHyperlinkMain" prefHeight="30.0" prefWidth="100.0" style="" text="%key.Hyperlink.Main" textAlignment="CENTER" textOverrun="ELLIPSIS" AnchorPane.leftAnchor="180.0" AnchorPane.topAnchor="55.0">
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </Hyperlink>
+ <AnchorPane id="webViewMainAnchorPane" fx:id="webViewAnchorPaneMain" prefHeight="453.0" prefWidth="792.0" style="" styleClass="webViewMainAnchorPane" visible="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="180.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="85.0">
+ <children>
+ <HBox alignment="CENTER" prefHeight="200.0" prefWidth="200.0" style="" visible="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
+ <children>
+ <ImageView fx:id="ImageViewLoading" fitHeight="80.0" fitWidth="80.0" opacity="1.0" pickOnBounds="true" preserveRatio="true" style="-fx-background-color: transparent;" visible="true">
+ <image>
+ <Image url="@resources/image/image_processing.gif" />
+ </image>
+ </ImageView>
+ </children>
+ </HBox>
+ <WebView fx:id="webView" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: white;" visible="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
+ <!--
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ -->
+ </WebView>
+ </children>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </AnchorPane>
+ <AnchorPane id="webViewHistoryAnchorPane" fx:id="webViewAnchorPaneHistory" prefHeight="528.0" prefWidth="843.0" style="" styleClass="webViewMainAnchorPane" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="180.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="85.0">
+ <children>
+ <AnchorPane fx:id="webViewHistoryBreadcrumbs" prefHeight="35.0" prefWidth="200.0" visible="true" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="5.0">
+ <children>
+ <FlowPane fx:id="webViewHistoryBreadcrumbsPane" prefHeight="40.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+ <padding>
+ <Insets left="10.0" />
+ </padding>
+ </FlowPane>
+ </children>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </AnchorPane>
+ <ListView fx:id="webViewHistoryListView" prefHeight="200.0" prefWidth="200.0" visible="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="40.0" />
+ <AnchorPane fx:id="webViewHistoryAnchorPaneContent" prefHeight="200.0" prefWidth="200.0" styleClass="webViewHistoryContentAnchorPane" visible="false" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="40.0">
+ <children>
+ <Label font="$x3" prefHeight="30.0" text="%key.History.Content.Title" AnchorPane.leftAnchor="30.0" AnchorPane.topAnchor="10.0" />
+ <TextField fx:id="webViewHistoryTextFieldTitle" alignment="CENTER_LEFT" editable="false" focusTraversable="false" prefHeight="30.0" prefWidth="200.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="40.0" />
+ <Label prefHeight="30.0" text="%key.Edit.Label.Contents" AnchorPane.leftAnchor="30.0" AnchorPane.topAnchor="90.0" />
+ <TextArea fx:id="webViewHistorytextAreaContents" editable="false" focusTraversable="false" prefWidth="200.0" wrapText="true" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="120.0" />
+ <Button fx:id="webViewHistoryButtonRestoreVersion" maxHeight="-Infinity" mnemonicParsing="false" onAction="#onActionButtonRestoreVersion" prefHeight="30.0" text="%key.Button.Restore.Version" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="30.0" />
+ </children>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </AnchorPane>
+ </children>
+ <padding>
+ <Insets />
+ </padding>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </AnchorPane>
+ <Hyperlink fx:id="webViewHyperlinkHistory" alignment="CENTER" maxWidth="-1.0" onMouseClicked="#onMouseClickedWebViewHyperlinkHistory" prefHeight="30.0" prefWidth="100.0" style="" text="%key.Hyperlink.History" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="55.0">
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </Hyperlink>
+ <Label prefHeight="29.999900000002526" prefWidth="594.0" styleClass="webViewGapspace" text="" AnchorPane.leftAnchor="280.0" AnchorPane.rightAnchor="100.0" AnchorPane.topAnchor="55.0">
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+ </Label>
+ </children>
+ </AnchorPane>
+ <AnchorPane fx:id="AnchorPaneContentList" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="535.0" prefWidth="590.0" visible="false" AnchorPane.bottomAnchor="70.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="73.0">
+ <children>
+ <Label maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="30.0" prefWidth="100.0" text="%key.PageList.Label.Namespace" AnchorPane.leftAnchor="150.0" AnchorPane.topAnchor="80.0" />
+ <ComboBox fx:id="comboBoxNamespace" prefHeight="25.0" prefWidth="150.0" AnchorPane.leftAnchor="250.0" AnchorPane.topAnchor="82.0">
+ <items>
+ <FXCollections fx:factory="observableArrayList">
+ <String fx:value="アイテム1" />
+ <String fx:value="アイテム2" />
+ <String fx:value="アイテム3" />
+ </FXCollections>
+ </items>
+ </ComboBox>
+ <Hyperlink fx:id="hyperlinkRedraw" onMouseClicked="#onMouseClickedHyperlinkRedraw" prefHeight="30.0" prefWidth="-1.0" text="%key.PageList.Label.Redraw" AnchorPane.leftAnchor="410.0" AnchorPane.topAnchor="80.0" />
+ <TableView id="TableViewContentList" fx:id="tableViewContentList" editable="true" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="400.0" prefWidth="825.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="150.0" AnchorPane.topAnchor="110.0">
+ <columns>
+ <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="45.0" text="" fx:id="tableColumnCheck" />
+ <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="190.0" text="%key.Table.Row.Title" fx:id="tableColumnTitle" />
+ <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="340.0" text="%key.Table.Row.Content" fx:id="tableColumnContent" />
+ <TableColumn prefWidth="200.0" text="%key.Table.Row.Date" fx:id="tableColumnDate" />
+ <TableColumn prefWidth="50.0" text="%key.Table.Row.Refs" fx:id="tableColumnRefs" />
+ </columns>
+ </TableView>
+ <Button fx:id="buttonDeletePages" mnemonicParsing="false" onAction="#onActionButtonDeletePages" prefHeight="30.0" text="%key.Button.Delete.Pages" AnchorPane.bottomAnchor="15.0" AnchorPane.leftAnchor="150.0" />
+ </children>
+ </AnchorPane>
+ <AnchorPane id="EditAnchorPane" fx:id="AnchorPaneEdit" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="450.0" prefWidth="590.0" visible="false" AnchorPane.bottomAnchor="60.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="75.0">
+ <children>
+ <Label prefHeight="30.0" text="%key.Edit.Label.Title" AnchorPane.leftAnchor="150.0" AnchorPane.topAnchor="15.0" />
+ <TextField fx:id="textFieldTitle" prefHeight="30.0" prefWidth="380.0" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="9.0" AnchorPane.topAnchor="45.0" />
+ <Label maxWidth="-Infinity" prefHeight="30.0" text="%key.Edit.Label.Contents" AnchorPane.leftAnchor="150.0" AnchorPane.topAnchor="80.0" />
+ <TextArea fx:id="textAreaContents" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="330.0" prefWidth="815.0" visible="true" wrapText="true" AnchorPane.bottomAnchor="98.0" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="9.0" AnchorPane.topAnchor="110.0" />
+ <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#onActionButtonSave" prefHeight="30.0" prefWidth="100.0" text="%key.Button.Save" AnchorPane.bottomAnchor="5.0" AnchorPane.rightAnchor="120.0" />
+ <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#onActionButtonCancel" prefHeight="30.0" prefWidth="100.0" text="%key.Button.Cancel" AnchorPane.bottomAnchor="5.0" AnchorPane.rightAnchor="10.0" />
+ <Label id="textLabelAttacheFile" fx:id="labelAttacheFile" disable="true" prefHeight="30.0" prefWidth="166.0" text="%key.Edit.Label.AttachFile" AnchorPane.bottomAnchor="70.0" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="60.0" />
+ <TextField fx:id="textFieldAttachFile" disable="true" prefHeight="30.0" prefWidth="716.0" promptText="%key.Edit.TextField.InputPathname" AnchorPane.bottomAnchor="42.0" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="60.0" />
+ <Button fx:id="buttonChoiceFile" disable="true" mnemonicParsing="false" onAction="#onActionButtonChoiceFile" prefHeight="30.0" prefWidth="45.0" text="..." AnchorPane.bottomAnchor="42.0" AnchorPane.rightAnchor="10.0" />
+ <Button fx:id="buttonPreview" mnemonicParsing="false" onAction="#onActionButtonPreview" prefHeight="30.0" prefWidth="100.0" text="%key.Button.Preview" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="150.0" />
+ </children>
+ </AnchorPane>
+ </children>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+</AnchorPane>
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki main window.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+
+package com.wiki.standalone.moxkiriya;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ResourceBundle;
+
+import com.wiki.standalone.moxkiriya.util.FileIO;
+
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+
+/**
+ * Application Main.
+ *
+ *
+ */
+public class WikiMainWindow {
+ /** primary stage. */
+ private Stage primaryStage_ = null;
+
+ /** Resource Bundle */
+ private ResourceBundle resources_ = null;
+
+ /** Setting Manager */
+ private SettingManager settingManager_ = null;
+
+ /** WikiEngine */
+ private WikiEngine wikiEngine_;
+
+ /** Window Controller */
+ private WikiMainWindowController controller_;
+
+ public enum CloseType {
+ EXIT,
+ RESTART
+ };
+
+ /**
+ * Constructor.
+ */
+ public WikiMainWindow(Stage primaryStage, ResourceBundle resources) {
+ primaryStage_ = primaryStage;
+ resources_ = resources;
+ settingManager_ = SettingManager.getInstance();
+ }
+
+ /**
+ * Show WikiMainWindow
+ * @throws Exception
+ */
+ public CloseType show() throws Exception {
+ try {
+ FXMLLoader loader = new FXMLLoader(getClass().getResource("WikiMainWindow.fxml"), resources_);
+ loader.load();
+
+ controller_ = loader.getController();
+ controller_.setWikiEngine(wikiEngine_);
+
+ Scene scene = new Scene((Parent)loader.getRoot());
+ scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
+
+ wikiEngine_.setPageDataMap(WikiEngine.MAINPAGE_TITLE);
+ controller_.loadWikiContent();
+
+ Stage stage = new Stage(StageStyle.DECORATED);
+ stage.initOwner(primaryStage_);
+ controller_.setStage(stage);
+
+ stage.setScene(scene);
+ stage.setTitle(resources_.getString("key.Application.Title"));
+ stage.showAndWait();
+
+ controller_.hidePreviewWindow();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return controller_.getCloseType();
+ }
+ /**
+ * Wikiのメインページのディレクトリツリーを構築する。
+ * @param wikirootPath
+ * @throws Exception
+ */
+ public void buildWikiMainTree(File wikirootPath) throws Exception {
+ createCssFiles();
+
+ uploadResourcefile(settingManager_.getAbsolutePath(WikiEngine.FIXED_STYLESHEET_FILENAME),
+ WikiEngine.FIXED_STYLESHEET_FILENAME);
+
+ uploadResourcefile(settingManager_.getAbsolutePath(WikiEngine.DEFAULT_STYLESHEET_FILENAME),
+ WikiEngine.DEFAULT_STYLESHEET_FILENAME);
+
+ createRepositoryConfig();
+ wikiEngine_ = new WikiEngine();
+ wikiEngine_.buildWikiRepository(wikirootPath);
+ }
+
+ /**
+ * styleシートをコピーする
+ * @param absolutePath
+ * @param filename
+ * @throws IOException
+ */
+ public void uploadResourcefile(String absolutePath, String filename) throws IOException {
+ File destFile = new File(absolutePath);
+
+ if (destFile.exists() != true) {
+ InputStream in = getClass().getResourceAsStream("resources/" + filename);
+ Path destPath = Paths.get(absolutePath);
+ Files.createDirectories(destPath.getParent());
+ Files.copy(in, destPath);
+ }
+ }
+
+ /**
+ * Create Repository.xml
+ * @throws Exception
+ */
+ private void createRepositoryConfig() throws Exception {
+ SettingManager settingMgr = SettingManager.getInstance();
+ String path = settingMgr.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+ String configXML = settingMgr.get(SettingManager.SETINGKEY_CLUSTER).equals("true")
+ ? WikiRepository.REPOSITORY_CUSTER_FILENAME
+ : WikiRepository.REPOSITORY_LOCAL_FILENAME;
+ File file = new File(path + "/" + settingMgr.getSelectedParty() + "/" + configXML);
+
+ if(file.exists() != true) {
+ InputStream inputStream = getClass().getResourceAsStream("resources/" + configXML);
+ InputStreamReader streamReader = new InputStreamReader(inputStream, "UTF-8");
+ BufferedReader reader = new BufferedReader(streamReader);
+ StringBuffer buf = new StringBuffer();
+ String line;
+
+ while((line = reader.readLine()) != null) {
+ buf.append(line + "\n");
+ }
+ reader.close();
+ file.createNewFile();
+
+ BufferedWriter writer = FileIO.bufferedWriter(file);
+
+ writer.write(buf.toString());
+ writer.flush();
+ writer.close();
+ }
+ }
+
+ /**
+ * Create CSS Files.
+ * @throws Exception
+ */
+ private void createCssFiles() throws Exception {
+ SettingManager settingMgr = SettingManager.getInstance();
+ String stylesheetDestPath = settingMgr.getAbsolutePath(WikiEngine.USER_STYLESHEET_FILENAME);
+
+ if (new File(stylesheetDestPath).exists() != true) {
+ InputStream in = getClass().getResourceAsStream("resources/" + WikiEngine.DEFAULT_STYLESHEET_FILENAME);
+ Path destPath = Paths.get(stylesheetDestPath);
+ Files.copy(in, destPath);
+ }
+
+ String templateHtmlHeaderPath = settingMgr.getAbsolutePath(WikiEngine.TEMPLATE_HTMLHEADER_FILE);
+
+ if (new File(templateHtmlHeaderPath).exists() != true) {
+ InputStream in = getClass().getResourceAsStream("resources/" + WikiEngine.TEMPLATE_HTMLHEADER_FILE);
+ Path destPath = Paths.get(templateHtmlHeaderPath);
+ Files.copy(in, destPath);
+ }
+ }
+
+ /**
+ * Session closer.
+ */
+ public void closeSession() {
+ wikiEngine_.closeSession();
+ }
+}
--- /dev/null
+/**
+ * WikiMainWindowController
+ * @author Ryuhei Terada
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.awt.Desktop;
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionIterator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MouseEvent;
+import org.w3c.dom.html.HTMLAnchorElement;
+
+import com.wiki.standalone.moxkiriya.dialog.AboutMoxkiriyaDialog;
+import com.wiki.standalone.moxkiriya.dialog.AlertDialog;
+import com.wiki.standalone.moxkiriya.dialog.DialogBase;
+import com.wiki.standalone.moxkiriya.dialog.DialogBase.CloseType;
+import com.wiki.standalone.moxkiriya.dialog.SelectPartyDialog;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.concurrent.Worker.State;
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TableView.TableViewSelectionModel;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.control.cell.CheckBoxTableCell;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebView;
+import javafx.stage.FileChooser;
+import javafx.stage.FileChooser.ExtensionFilter;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+import javafx.util.Callback;
+
+/**
+ * MainWindowコントローラ
+ */
+public class WikiMainWindowController implements Initializable {
+ /** Primary Stage */
+ private Stage stage_;
+
+ /** resourceBundle */
+ private ResourceBundle resourceBundle_;
+
+ /** WikiEngine */
+ private WikiEngine wikiEngine_;
+
+ /** Preview window */
+ private WikiPreviewWindow previewWindow_ = null;
+
+ /*
+ * MenuBar controls.
+ */
+ @FXML private MenuItem menuItemNew;
+ @FXML private MenuItem menuItemImport;
+ @FXML private MenuItem menuItemExport;
+ @FXML private MenuItem menuItemExit;
+ @FXML private MenuItem menuItemSelectParty;
+ @FXML private MenuItem menuItemAboutMoxkiriya;
+
+ /*
+ * ChoiceView controls.
+ */
+ @FXML private Hyperlink choiceViewHyperlinkReading;
+ @FXML private Hyperlink choiceViewHyperlinkPageList;
+ @FXML private Hyperlink choiceViewHyperlinkEdit;
+
+ /*
+ * Loading animation.
+ */
+ @FXML private ImageView ImageViewLoading;
+
+ /*
+ * WebView controls.
+ */
+ @FXML private AnchorPane AnchorPaneWebView;
+ @FXML private Button webViewMenuAnchorPaneButtonBack;
+ @FXML private Button webViewMenuAnchorPaneButtonForward;
+ @FXML private Button webViewMenuAnchorPaneButtonReload;
+ @FXML private Button webViewMenuAnchorPaneButtonHome;
+ @FXML private TextField webViewMenuAnchorPaneTextFieldSearchWiki;
+ @FXML private Button webViewMenuAnchorPaneButtonSearch;
+
+ @FXML private Hyperlink webViewHyperlinkMain;
+ @FXML private Hyperlink webViewHyperlinkHistory;
+ @FXML private AnchorPane webViewAnchorPaneMain;
+ @FXML private WebView webView;
+ @FXML private AnchorPane webViewAnchorPaneHistory;
+ @FXML private FlowPane webViewHistoryBreadcrumbsPane;
+ @FXML private ListView<VersionHistoryListItem> webViewHistoryListView;
+ @FXML private AnchorPane webViewHistoryAnchorPaneContent;
+ @FXML private TextField webViewHistoryTextFieldTitle;
+ @FXML private TextArea webViewHistorytextAreaContents;
+ @FXML private Button webViewHistoryButtonRestoreVersion;
+
+ /*
+ * editAnchorPane controls.
+ */
+ @FXML private AnchorPane AnchorPaneEdit;
+ @FXML private TextField textFieldTitle;
+ @FXML private TextArea textAreaContents;
+ @FXML private Label labelAttacheFile;
+ @FXML private TextField textFieldAttachFile;
+ @FXML private Button buttonChoiceFile;
+ @FXML private Hyperlink hyperlinkEditAttachFiles;
+ @FXML private Button buttonPreview;
+ @FXML private Button buttonSave;
+ @FXML private Button buttonCancel;
+
+ /*
+ * AnchorPaneContentList controls.
+ */
+ @FXML private AnchorPane AnchorPaneContentList;
+ @FXML private ComboBox<String> comboBoxNamespace;
+ @FXML private Hyperlink hyperlinkRedraw;
+ @FXML private TableView<PageData> tableViewContentList;
+ @FXML private TableColumn<PageData, Boolean> tableColumnCheck;
+ @FXML private TableColumn<PageData, String> tableColumnTitle;
+ @FXML private TableColumn<PageData, String> tableColumnContent;
+ @FXML private TableColumn<PageData, String> tableColumnDate;
+ @FXML private TableColumn<PageData, String> tableColumnRefs;
+ @FXML private Button buttonDeletePages;
+ private CheckBox checkBoxAll_;
+
+ /**
+ * Edit mode NEW or MODIFY
+ */
+ private enum EditMode {
+ NONE,
+ NEW,
+ MODIFY
+ };
+
+ /** edit mode.*/
+ private EditMode editMode_ = EditMode.NONE;
+
+ /** Close type */
+ private WikiMainWindow.CloseType closeType_ = WikiMainWindow.CloseType.EXIT;
+
+ /**
+ * Version history list item
+ */
+ public class VersionHistoryListItem {
+ /** version */
+ private Version version_;
+
+ /** Created data. */
+ private Date created_;
+
+ /** version node */
+ private Node node_;
+
+ /**
+ * Constructor.
+ * @param created
+ * @param node
+ */
+ public VersionHistoryListItem(Version version, Date created, Node node) {
+ version_ = version;
+ created_ = created;
+ node_ = node;
+ }
+
+ /**
+ * Version getter.
+ * @return Version
+ */
+ public Version getVersion() {
+ return version_;
+ }
+
+ /**
+ * Created getter.
+ * @return Date
+ */
+ public Date getCreated() {
+ return created_;
+ }
+
+ /**
+ * Node getter.
+ * @return Node
+ */
+ public Node getNode() {
+ return node_;
+ }
+ }
+
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ resourceBundle_ = resourceBundle;
+
+ setLinkClickListner(webView.getEngine());
+ webView.setContextMenuEnabled(false);
+
+ previewWindow_ = new WikiPreviewWindow(stage_, resourceBundle_);
+ previewWindow_.setMainWindowController(this);
+
+ checkBoxAll_ = new CheckBox();
+ checkBoxAll_.selectedProperty().addListener(new ChangeListener<Boolean>() {
+ @Override
+ public void changed(ObservableValue<? extends Boolean> value, Boolean oldValue, Boolean newValue) {
+ ObservableList<PageData> pageDataList = tableViewContentList.getItems();
+
+ for(PageData pageData: pageDataList) {
+ pageData.checkProperty().setValue(newValue);;
+ }
+ }
+ });
+
+ tableColumnCheck.setCellFactory(new Callback<TableColumn<PageData, Boolean>, TableCell<PageData, Boolean>>() {
+ @Override
+ public TableCell<PageData, Boolean> call(TableColumn<PageData, Boolean> param) {
+ CheckBoxTableCell<PageData, Boolean> checkBoxTableCell = new CheckBoxTableCell<PageData, Boolean>();
+ checkBoxTableCell.setAlignment(Pos.CENTER);
+
+ return checkBoxTableCell;
+ }
+ });
+
+ tableColumnTitle.setCellFactory(new Callback<TableColumn<PageData, String>, TableCell<PageData, String>>() {
+ @Override
+ public TableCell<PageData, String> call(TableColumn<PageData, String> param) {
+ TableCell<PageData, String>
+ tableCell = new TableCell<PageData, String>() {
+ @Override
+ public void updateItem(String uuid, boolean empty) {
+ super.updateItem(uuid, empty);
+ if(empty != true) {
+ try {
+ HashMap<String, PageData> pageMap = wikiEngine_.queryPageUUID(uuid);
+ PageData pageData = pageMap.get(uuid);
+ Hyperlink hyperlink = new Hyperlink(pageData.getTitle());
+
+ hyperlink.setUserData(pageData);
+ hyperlink.setOnMouseClicked(new EventHandler<Event>() {
+ @Override
+ public void handle(Event event) {
+ try {
+ Hyperlink source = (Hyperlink)event.getSource();
+ PageData pageData = (PageData)source.getUserData();
+
+ wikiEngine_.setPageDataMap(pageData);
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ setGraphic(hyperlink);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ else {
+ setGraphic(null);
+ }
+ }
+ };
+
+ return tableCell;
+ }
+ });
+
+ webViewHistoryListView.setCellFactory(new Callback<ListView<VersionHistoryListItem>, ListCell<VersionHistoryListItem>>() {
+ @Override
+ public ListCell<VersionHistoryListItem> call(ListView<VersionHistoryListItem> arg0) {
+ return new ListCell<VersionHistoryListItem>() {
+ @Override
+ protected void updateItem(VersionHistoryListItem item, boolean empty) {
+ try {
+ super.updateItem(item, empty);
+ if(empty != true) {
+ Hyperlink hyperlinkCreated = new Hyperlink(item.getCreated().toString());
+ Version version = item.getVersion();
+ Version baseVersion = wikiEngine_.getBaseVersion();
+
+ if(version.getIdentifier().equals(baseVersion.getIdentifier()) == true) {
+ hyperlinkCreated.setId("webViewHistoryBaseVersion");
+ }
+
+ hyperlinkCreated.setUserData(item);
+ hyperlinkCreated.setOnAction(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent event) {
+ try {
+ ObservableList<javafx.scene.Node> breadcrumbsList = webViewHistoryBreadcrumbsPane.getChildren();
+
+ breadcrumbsList.clear();
+ breadcrumbsList.add(createBreadcrumbsHyperlink("key.History.Breadcrumbs.List",
+ new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent event) {
+ ObservableList<javafx.scene.Node> breadcrumbsList = webViewHistoryBreadcrumbsPane.getChildren();
+
+ breadcrumbsList.clear();
+ breadcrumbsList.add(createBreadcrumbsLabel("key.History.Breadcrumbs.List"));
+ webViewHistoryListView.setVisible(true);
+ webViewHistoryAnchorPaneContent.setVisible(false);
+ }
+ }));
+ breadcrumbsList.add(createBreadcrumbsLabel("key.History.Breadcrumbs.Separator"));
+ breadcrumbsList.add(createBreadcrumbsLabel("key.History.Breadcrumbs.Content"));
+
+ Hyperlink target = (Hyperlink)event.getTarget();
+ VersionHistoryListItem item = (VersionHistoryListItem)target.getUserData();
+ Node node = item.getNode();
+
+ webViewHistoryTextFieldTitle.setText(node.getProperty(WikiRepository.PROPERTY_TITLE).getString());
+ webViewHistorytextAreaContents.setText((node.getProperty(WikiRepository.PROPERTY_CONTENT).getString()));
+ webViewHistoryAnchorPaneContent.setUserData(item);
+
+ webViewHistoryListView.setVisible(false);
+ webViewHistoryAnchorPaneContent.setVisible(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ setGraphic(hyperlinkCreated);
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+ };
+ }
+ });
+ tableColumnCheck.setGraphic(checkBoxAll_);
+ tableColumnCheck.setCellValueFactory(new PropertyValueFactory<PageData, Boolean>("check"));
+ tableColumnTitle.setCellValueFactory(new PropertyValueFactory<PageData, String>("uuid"));
+ tableColumnContent.setCellValueFactory(new PropertyValueFactory<PageData, String>("introduction"));
+ tableColumnDate.setCellValueFactory(new PropertyValueFactory<PageData, String>("date"));
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ }
+
+ /**
+ * Close type getter.
+ * @return WikiMainWindow.CloseType
+ */
+ public WikiMainWindow.CloseType getCloseType() {
+ return closeType_;
+ }
+
+ /**
+ * Stageを設定する。
+ * @param stage
+ */
+ public void setStage(Stage stage) {
+ stage_ = stage;
+ }
+
+ /**
+ * WikiEngineを設定する。
+ * @param wikiEngine
+ */
+ public void setWikiEngine(WikiEngine wikiEngine) {
+ wikiEngine_ = wikiEngine;
+ }
+
+ /**
+ * WikiEngineを取得する。
+ * @return WikiEngine
+ */
+ public WikiEngine getWikiEngine() {
+ return wikiEngine_;
+ }
+
+ /**
+ * Hide preview window.
+ */
+ public void hidePreviewWindow() {
+ previewWindow_.hide();
+ }
+
+ @FXML
+ public void onActionMenuItemNew(ActionEvent event) {
+ /*
+ * 各コントロールの初期値を入力する。
+ */
+ textFieldTitle.clear();
+ textAreaContents.clear();
+ buildEditView("");
+ }
+
+ @FXML
+ public void onActionMenuItemImport(ActionEvent event) {
+ FileChooser fileChooser = new FileChooser();
+
+ fileChooser.setTitle(resourceBundle_.getString("key.ImportDialog.Title"));
+ fileChooser.getExtensionFilters().addAll(new ExtensionFilter("XML Files", "*.xml"));
+
+ File selectedFile = fileChooser.showOpenDialog(stage_);
+
+ if(selectedFile != null) {
+ try {
+ wikiEngine_.importSystemView(selectedFile);
+
+ AlertDialog dialog = new AlertDialog(AlertDialog.MessageType.SuccessImport);
+ dialog.showDialog(stage_, resourceBundle_);
+ stage_.hide();
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ AlertDialog dialog = new AlertDialog(AlertDialog.MessageType.FailureImport);
+ dialog.showDialog(stage_, resourceBundle_);
+ stage_.hide();
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @FXML
+ public void onActionMenuItemExport(ActionEvent event) {
+ FileChooser fileChooser = new FileChooser();
+
+ fileChooser.setTitle(resourceBundle_.getString("key.ExportDialog.Title"));
+ fileChooser.getExtensionFilters().addAll(new ExtensionFilter("XML Files", "*.xml"));
+
+ File selectedFile = fileChooser.showSaveDialog(stage_);
+
+ if(selectedFile != null) {
+ try {
+ wikiEngine_.exportSystemView(selectedFile);
+ AlertDialog dialog = new AlertDialog(AlertDialog.MessageType.SuccessExport);
+ dialog.showDialog(stage_, resourceBundle_);
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ AlertDialog dialog = new AlertDialog(AlertDialog.MessageType.FailureExport);
+ dialog.showDialog(stage_, resourceBundle_);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @FXML
+ public void onActionMenuItemExit(ActionEvent event) {
+ try {
+ if (AnchorPaneEdit.isVisible() == true) {
+ /*
+ * editAnchorPane表示中の場合、
+ * 編集キャンセル確認ダイアログを表示する。
+ */
+ if(showConfirmEditCancelDialog() == AlertDialog.CloseType.OK) {
+ editMode_ = EditMode.NONE;
+ wikiEngine_.cancelCheckout();
+ previewWindow_.hide();
+ stage_.hide();
+ }
+ }
+ else {
+ stage_.hide();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionMenuItemSelectParty(ActionEvent event) {
+ try {
+ if (AnchorPaneEdit.isVisible() == true) {
+ /*
+ * editAnchorPane表示中の場合、
+ * 編集キャンセル確認ダイアログを表示する。
+ */
+ if(showConfirmEditCancelDialog() == AlertDialog.CloseType.OK) {
+ editMode_ = EditMode.NONE;
+ wikiEngine_.cancelCheckout();
+ }
+ }
+
+ SelectPartyDialog selectPartyDialog = new SelectPartyDialog();
+
+ if(selectPartyDialog.showDialog(stage_, resourceBundle_) == CloseType.OK) {
+ closeType_ = WikiMainWindow.CloseType.RESTART;
+ stage_.hide();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionMenuItemAboutMoxkiriya(ActionEvent event) {
+ try {
+ DialogBase dialog = new AboutMoxkiriyaDialog();
+ dialog.showDialog(stage_, resourceBundle_);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onKeyPressedTextFieldSearchWiki(KeyEvent event) {
+ try {
+ if(event.getCode().equals(KeyCode.ENTER) == true) {
+ doSearchWiki();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonSearch(ActionEvent event) {
+ try {
+ doSearchWiki();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onMouseClickedHyperlinkReading() {
+ try {
+ AlertDialog.CloseType closeType = AlertDialog.CloseType.OK;
+
+ if(AnchorPaneEdit.isVisible() == true) {
+ /*
+ * editAnchorPane表示中の場合、
+ * 編集キャンセル確認ダイアログを表示する。
+ */
+ closeType = showConfirmEditCancelDialog();
+ }
+
+ if(closeType == AlertDialog.CloseType.OK) {
+ editMode_ = EditMode.NONE;
+ wikiEngine_.cancelCheckout();
+
+ PageData pageData = getSelectingPageData();
+
+ if(pageData != null) {
+ wikiEngine_.setPageDataMap(pageData);
+ }
+
+ menuItemNew.setDisable(false);
+
+ loadWikiContent();
+
+ AnchorPaneEdit.setVisible(false);
+ AnchorPaneContentList.setVisible(false);
+ AnchorPaneWebView.setVisible(true);
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onMouseClickedHyperlinkEdit() {
+ try {
+ wikiEngine_.refreshSession();
+ buildEditView(EditMode.MODIFY, "");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onMouseClickedHyperlinkPageList() {
+ try {
+ AlertDialog.CloseType closeType = AlertDialog.CloseType.OK;
+
+ if(AnchorPaneEdit.isVisible() == true) {
+ /*
+ * editAnchorPane表示中の場合、
+ * 編集キャンセル確認ダイアログを表示する。
+ */
+ closeType = showConfirmEditCancelDialog();
+ }
+
+ if(closeType == AlertDialog.CloseType.OK) {
+ editMode_ = EditMode.NONE;
+ wikiEngine_.cancelCheckout();
+
+ buildComboBoxNamespace();
+
+ buildTableViewPageList();
+ AnchorPaneWebView.setVisible(false);
+ AnchorPaneEdit.setVisible(false);
+ AnchorPaneContentList.setVisible(true);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonBack(ActionEvent event) {
+ try {
+ String content = wikiEngine_.back();
+ WebEngine webEngine = webView.getEngine();
+ webEngine.loadContent(content);
+
+ HashMap<String, PageData> map = wikiEngine_.getPageDataMap();
+ boolean canEdit = (map.size() != 1) ? true : false;
+
+ choiceViewHyperlinkEdit.setDisable(canEdit);
+ menuItemNew.setDisable(false);
+
+ AnchorPaneEdit.setVisible(false);
+ AnchorPaneContentList.setVisible(false);
+ AnchorPaneWebView.setVisible(true);
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+
+ webViewMenuAnchorPaneButtonBack.setDisable(!wikiEngine_.canBack());
+ webViewMenuAnchorPaneButtonForward.setDisable(!wikiEngine_.canForward());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @FXML
+ public void onActionButtonForward(ActionEvent event) {
+ try {
+ String content = wikiEngine_.forward();
+ WebEngine webEngine = webView.getEngine();
+ webEngine.loadContent(content);
+
+ HashMap<String, PageData> map = wikiEngine_.getPageDataMap();
+ boolean canEdit = (map.size() != 1) ? true : false;
+
+ choiceViewHyperlinkEdit.setDisable(canEdit);
+ menuItemNew.setDisable(false);
+
+ AnchorPaneEdit.setVisible(false);
+ AnchorPaneContentList.setVisible(false);
+ AnchorPaneWebView.setVisible(true);
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+
+ webViewMenuAnchorPaneButtonBack.setDisable(!wikiEngine_.canBack());
+ webViewMenuAnchorPaneButtonForward.setDisable(!wikiEngine_.canForward());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonReload(ActionEvent event) {
+ try {
+ wikiEngine_.refreshSession();
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonHome(ActionEvent event) {
+ try {
+ wikiEngine_.setPageDataMap(WikiEngine.MAINPAGE_TITLE);
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onMouseClickedHyperlinkRedraw() {
+ try {
+ buildTableViewPageList();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onMouseClickedWebViewHyperlinkMain() {
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ }
+
+ @FXML
+ public void onMouseClickedWebViewHyperlinkHistory() {
+ try {
+ ObservableList<javafx.scene.Node> breadcrumbsList = webViewHistoryBreadcrumbsPane.getChildren();
+
+ breadcrumbsList.clear();
+ breadcrumbsList.add(createBreadcrumbsLabel("key.History.Breadcrumbs.List"));
+
+ ObservableList<VersionHistoryListItem> list = webViewHistoryListView.getItems();
+
+ list.clear();
+
+ VersionIterator versionIter = wikiEngine_.getVersionHistory();
+ versionIter.skip(1);
+ while(versionIter.hasNext() == true) {
+ Version version = versionIter.nextVersion();
+ NodeIterator nodeIter = version.getNodes();
+
+ while(nodeIter.hasNext() == true) {
+ Node node = nodeIter.nextNode();
+
+ list.add(new VersionHistoryListItem(version, version.getCreated().getTime(), node));
+ }
+ }
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkInactive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkActive");
+ webViewAnchorPaneMain.setVisible(false);
+ webViewAnchorPaneHistory.setVisible(true);
+
+ webViewHistoryListView.setVisible(true);
+ webViewHistoryAnchorPaneContent.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonRestoreVersion(ActionEvent event) {
+ try {
+ VersionHistoryListItem item = (VersionHistoryListItem)webViewHistoryAnchorPaneContent.getUserData();
+ wikiEngine_.restoreVersion(item.getVersion());
+
+ wikiEngine_.refreshSession();
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonDeletePages(ActionEvent event) {
+ try {
+ ObservableList<PageData> pageDataList = tableViewContentList.getItems();
+
+ for(PageData pageData: pageDataList) {
+ if(pageData.checkProperty().getValue() == true) {
+ wikiEngine_.deletePage(pageData);
+ }
+ }
+
+ HashMap<String, PageData> map = wikiEngine_.queryPageTitle(WikiEngine.MAINPAGE_TITLE);
+ if(map.size() < 1) {
+ /*
+ * MainPageがなくなった場合
+ */
+ PageData pageData = new PageData();
+
+ pageData.setNamespace(WikiRepository.PROPERTY_MAIN);
+ pageData.setTitle(WikiEngine.MAINPAGE_TITLE);
+ pageData = wikiEngine_.checkin(pageData);
+ }
+
+ wikiEngine_.clearHistory();
+ wikiEngine_.setPageDataMap(WikiEngine.MAINPAGE_TITLE);
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonChoiceFile(ActionEvent event) {
+ try {
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle("Select " + textFieldTitle.getText());
+ File file = fileChooser.showOpenDialog(stage_);
+
+ if(file != null) {
+ textFieldAttachFile.setText(file.getPath());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonPreview(ActionEvent event) {
+ try {
+ previewWindow_.setWikiRepository(wikiEngine_.getWikiRepository());
+ previewWindow_.show();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonSave(ActionEvent event) {
+ try {
+ String title = textFieldTitle.getText();
+
+ if(title.isEmpty() == true) {
+ Stage stage = new Stage(StageStyle.UTILITY);
+ stage.initOwner(stage_);
+ stage.initModality(Modality.WINDOW_MODAL);
+
+ AlertDialog alertDialog = new AlertDialog(AlertDialog.MessageType.AlertTitleEmpty);
+ alertDialog.showDialog(stage, resourceBundle_);
+ }
+ else {
+ PageData pageData = (PageData)AnchorPaneEdit.getUserData();
+
+ if(editMode_ == EditMode.NEW) {
+ if(pageData == null) {
+ pageData = new PageData();
+ pageData.setNamespace(WikiRepository.PROPERTY_MAIN);
+ }
+ }
+
+ pageData.setTitle(title);
+ pageData.setContent(textAreaContents.getText());
+
+ String filename = textFieldAttachFile.getText();
+ if(filename.isEmpty() != true) {
+ pageData.setFileData(new File(filename));
+ }
+ pageData = wikiEngine_.checkin(pageData);
+ editMode_ = EditMode.NONE;
+ previewWindow_.hide();
+
+ /*
+ * 更新後のページを再parse
+ */
+ wikiEngine_.setPageDataMap(pageData);
+ loadWikiContent();
+
+ menuItemNew.setDisable(false);
+
+ /*
+ * PaneをWebViewAnchorPaneに切り替える。
+ */
+ AnchorPaneWebView.setVisible(true);
+ AnchorPaneEdit.setVisible(false);
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonCancel(ActionEvent event) {
+ try {
+ if(showConfirmEditCancelDialog() == AlertDialog.CloseType.OK) {
+ editMode_ = EditMode.NONE;
+ wikiEngine_.cancelCheckout();
+ previewWindow_.hide();
+ menuItemNew.setDisable(false);
+
+ /*
+ * 確認ダイアログでOKが押下された場合
+ * EditAnchorPaneからWebViewペインに表示を切り替え
+ */
+ AnchorPaneWebView.setVisible(true);
+ AnchorPaneEdit.setVisible(false);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 編集キャンセル確認ダイアログを表示する。
+ * @return 終了種別
+ * @throws Exception
+ */
+ private AlertDialog.CloseType showConfirmEditCancelDialog() throws Exception {
+ AlertDialog alertDialog = new AlertDialog(AlertDialog.MessageType.ConfirmEditCancel);
+
+ return alertDialog.showDialog(stage_, resourceBundle_);
+ }
+
+ /**
+ * 編集Viewを構築する。
+ */
+ public void buildEditView(String title) {
+ buildEditView(EditMode.NEW, title);
+ }
+
+ /**
+ * 編集Viewを構築する。
+ */
+ public void buildEditView(EditMode editMode, String title) {
+ try {
+ String content = "";
+ String namespace = "";
+
+ editMode_ = editMode;
+
+ if(editMode == EditMode.MODIFY) {
+ HashMap<String, PageData> map = wikiEngine_.getPageDataMap();
+ PageData pageData = map.values().iterator().next();
+
+ AnchorPaneEdit.setUserData(pageData);
+ wikiEngine_.checkout();
+ title = pageData.getTitle();
+ content = pageData.getContent();
+ namespace = pageData.getNamespace();
+ }
+ else {
+ AnchorPaneEdit.setUserData(null);
+
+ if(editMode_ == EditMode.NEW) {
+ if(title.isEmpty() != true) {
+ PageData pageData = new PageData();
+ String pageTitle = title;
+
+ pageData.setNamespace(WikiRepository.PROPERTY_MAIN);
+
+ if(title.contains(":")) {
+ namespace = title.substring(0, title.indexOf(":"));
+ }
+
+ if(namespace.isEmpty() != true) {
+ if(wikiEngine_.isContainsNamespaceList(namespace) == true) {
+ pageData.setNamespace(namespace);
+ pageTitle = title.substring(namespace.length() + ":".length(), title.length());
+ }
+ else {
+ pageTitle = title;
+ }
+ }
+
+ pageData.setTitle(pageTitle);
+ AnchorPaneEdit.setUserData(pageData);
+
+ title = pageData.getTitle();
+ namespace = pageData.getNamespace();
+ }
+ }
+ }
+
+ boolean cannotAttacheFile = namespace.equals(WikiEngine.NAMESPACE_FILE) == true
+ ? false
+ : true;
+ textFieldAttachFile.setDisable(cannotAttacheFile);
+ labelAttacheFile.setDisable(cannotAttacheFile);
+ buttonChoiceFile.setDisable(cannotAttacheFile);
+
+ /*
+ * 各コントロールの初期値を入力する。
+ */
+ textFieldTitle.setText(title);
+ textAreaContents.setText(content);
+ textFieldAttachFile.setText("");
+
+ menuItemNew.setDisable(true);
+
+ /*
+ * WebViewペインからEditAnchorPaneに表示を切り替え
+ */
+ AnchorPaneWebView.setVisible(false);
+ AnchorPaneContentList.setVisible(false);
+ AnchorPaneEdit.setVisible(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Latest contents getter.
+ * @return PageData
+ * @throws Exception
+ */
+ public PageData getLatestContents() throws Exception {
+ PageData pageData = new PageData();
+ PageData editData = (PageData)AnchorPaneEdit.getUserData();
+
+ pageData.setTitle(textFieldTitle.getText());
+ pageData.setContent(textAreaContents.getText());
+
+ String namespace = editData != null
+ ? editData.getNamespace()
+ : WikiRepository.PROPERTY_MAIN;
+ pageData.setNamespace(namespace);
+ String pathname = textFieldAttachFile.getText();
+ if( (pathname != null)
+ && (pathname.isEmpty() != true)) {
+ pageData.setFileData(new File(pathname));
+ }
+
+ return pageData;
+ }
+
+ /**
+ * WikiContentをロードする。
+ * @param contentDir
+ */
+ public void loadWikiContent() {
+ try {
+ WebEngine webEngine = webView.getEngine();
+ webEngine.loadContent(wikiEngine_.parse());
+
+ HashMap<String, PageData> map = wikiEngine_.getPageDataMap();
+ boolean canEdit = (map.size() != 1) ? true : false;
+
+ choiceViewHyperlinkEdit.setDisable(canEdit);
+
+ menuItemNew.setDisable(false);
+ AnchorPaneEdit.setVisible(false);
+ AnchorPaneContentList.setVisible(false);
+ AnchorPaneWebView.setVisible(true);
+
+ webViewMenuAnchorPaneButtonBack.setDisable(!wikiEngine_.canBack());
+ webViewMenuAnchorPaneButtonForward.setDisable(!wikiEngine_.canForward());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * ページ内の指定セクションリンクへジャンプする。
+ * @param target
+ * @throws Exception
+ */
+ private void jumpToSectionLink(EventTarget target) throws Exception {
+ HTMLAnchorElement anchor = (HTMLAnchorElement)target;
+ String href = anchor.getAttribute("href");
+ String pageTitle = URLDecoder.decode(href, "UTF-8");
+ String sectionName = pageTitle.substring(pageTitle.indexOf("#") + "#".length());
+ webView.getEngine().executeScript("scrollTo('" + sectionName + "')");
+ }
+
+ /**
+ * webViewを取得する。
+ * @return webView
+ */
+ public WebView getWebView() {
+ return webView;
+ }
+
+ /**
+ * ImageViewLoadingを取得する。
+ * @return ImageViewLoading
+ */
+ public ImageView getImageViewLoading() {
+ return ImageViewLoading;
+ }
+
+ /**
+ * Execute search wiki.
+ * @throws Exception
+ */
+ private void doSearchWiki() throws Exception {
+ String key = webViewMenuAnchorPaneTextFieldSearchWiki.getText();
+
+ if(key.isEmpty() != true) {
+ HashMap<String, PageData> map = wikiEngine_.queryPageFullTextSearch(key);
+
+ wikiEngine_.setPageDataMap(map);
+ loadWikiContent();
+
+ webViewHyperlinkMain.setId("webViewMainHyperlinkActive");
+ webViewHyperlinkHistory.setId("webViewMainHyperlinkInactive");
+ webViewAnchorPaneMain.setVisible(true);
+ webViewAnchorPaneHistory.setVisible(false);
+ }
+ }
+
+ /**
+ * 選択中または現在表示中のコンテンツのディレクトリを取得する。
+ * @return 選択中または表示中のコンテンツのディレクトリ
+ * @throws Exception
+ */
+ private PageData getSelectingPageData() throws Exception {
+ PageData pageData = null;
+
+ if(AnchorPaneContentList.isVisible() == true) {
+ TableViewSelectionModel<PageData> selectedData = tableViewContentList.selectionModelProperty().getValue();
+ pageData = selectedData.getSelectedItem();
+ }
+ else if(AnchorPaneEdit.isVisible() == true) {
+ pageData = (PageData)AnchorPaneEdit.getUserData();
+ }
+
+ return pageData;
+ }
+
+ /**
+ * Build a namespace comboBox.
+ * @throws Exception
+ */
+ private void buildComboBoxNamespace() throws Exception {
+ ArrayList<String> namespaceList = wikiEngine_.getNamespaceList();
+ ObservableList<String> items = comboBoxNamespace.getItems();
+
+ items.clear();
+ for(int index = 0; index < namespaceList.size(); index++) {
+ String item = namespaceList.get(index);
+ items.add(item);
+
+ if(item.equals(WikiRepository.PROPERTY_MAIN) == true) {
+ comboBoxNamespace.getSelectionModel().select(index);
+ }
+ }
+ }
+
+ /**
+ * Build page list view
+ * @throws Exception
+ */
+ private void buildTableViewPageList() throws Exception {
+ String namespace = comboBoxNamespace.getSelectionModel().getSelectedItem();
+ HashMap<String, PageData> pageMap = wikiEngine_.queryPageNamespace(namespace);
+ ObservableList<PageData> observableList = FXCollections.observableArrayList();
+
+ tableViewContentList.getItems().clear();
+
+ for(String key: pageMap.keySet()) {
+ observableList.add(pageMap.get(key));
+ }
+ tableViewContentList.setItems(observableList);
+ }
+
+ /**
+ * A要素のクリックリスナーを登録する。
+ * @param webEngine
+ */
+ private void setLinkClickListner(WebEngine webEngine) {
+ webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
+ @Override
+ public void changed(ObservableValue<? extends State> arg0, State oldState, State newState) {
+ WebView webView = getWebView();
+ EventListener listener = new EventListener() {
+ @Override
+ public void handleEvent(org.w3c.dom.events.Event event) {
+ try {
+ MouseEvent mouseEvent = (MouseEvent)event;
+ EventTarget target = mouseEvent.getCurrentTarget();
+
+ if(isExternalLink(target) == true) {
+ /*
+ * WebEngineのデフォルトの動作(リンク先ページをロード)をキャンセル
+ */
+ event.preventDefault();
+ externalLinkHandle(target);
+ }
+ else {
+ internalLinkHandle(target);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * targetが外部リンクか判定する。
+ * @param target
+ * @return
+ */
+ private boolean isExternalLink(EventTarget target) {
+ final ArrayList<String> schemeList = new ArrayList<String>() {
+ private static final long serialVersionUID = 1L;
+ { add("http://"); }
+ { add("https://"); }
+ { add("file://"); }
+ };
+
+ HTMLAnchorElement aElem = (HTMLAnchorElement)target;
+ String href = aElem.getAttribute("href");
+ boolean isExternal = false;
+
+ for(String scheme: schemeList) {
+ if(href.startsWith(scheme) == true) {
+ isExternal = true;
+ break;
+ }
+ }
+
+ return isExternal;
+ }
+
+ /**
+ * ExternalLinkを処理する。
+ * @param target
+ * @throws Exception
+ */
+ private void externalLinkHandle(EventTarget target) throws Exception {
+ String targetpath = target.toString();
+ if(targetpath.startsWith("file:///") == true) {
+ targetpath = URLDecoder.decode(targetpath, "UTF-8");
+ }
+ /*
+ * 既定のブラウザを起動してリンク先ページを開く
+ */
+ Desktop.getDesktop().browse(new URI(targetpath));
+ }
+
+ /**
+ * InternalLinkを処理する。
+ * @param target
+ * @throws Exception
+ */
+ private void internalLinkHandle(EventTarget target) throws Exception {
+ HashMap<String, PageData> pageDataMap;
+ HTMLAnchorElement anchor = (HTMLAnchorElement)target;
+ String href = anchor.getAttribute("href");
+ String pageTitle = URLDecoder.decode(href, "UTF-8");
+ String uuid = anchor.getAttribute(WikiEngine.ATTRIBUTE_JCR_UUID);
+
+ if(uuid != null) {
+ pageDataMap = wikiEngine_.queryPageUUID(uuid);
+ }
+ else {
+ pageDataMap = wikiEngine_.queryPageTitle(pageTitle);
+ }
+ if(pageDataMap.size() == 1) {
+ wikiEngine_.setPageDataMap(pageDataMap);
+ loadWikiContent();
+ }
+ else {
+ if(href.contains("#")) {
+ /*
+ * ページ内セクションリンク
+ */
+ jumpToSectionLink(target);
+ }
+ else {
+ buildEditView(href);
+ }
+ }
+
+ }
+ };
+
+ if(newState == State.SUCCEEDED) {
+ Document doc = webView.getEngine().getDocument();
+ NodeList listA = doc.getElementsByTagName("a");
+
+ for(int index = 0; index < listA.getLength(); index++) {
+ ((EventTarget)listA.item(index)).addEventListener("click", listener, false);
+ }
+ getImageViewLoading().setVisible(false);
+ webView.setVisible(true);
+ }
+ }
+ });
+ }
+
+ /**
+ * Bread crumbs label creator.
+ * @param key
+ * @return Label
+ */
+ private Label createBreadcrumbsLabel(String key) {
+ Label labelCrumbsList = new Label(resourceBundle_.getString(key));
+
+ labelCrumbsList.setId("webViewBreadcrumbs");
+ labelCrumbsList.setPrefHeight(40);
+
+ return labelCrumbsList;
+ }
+
+ /**
+ * Bread crumbs hyperlink creator.
+ * @param key
+ * @param eventHandler
+ * @param layoutX
+ * @return Label
+ */
+ private Hyperlink createBreadcrumbsHyperlink(String key, EventHandler<ActionEvent> eventHandler) {
+ Hyperlink linkCrumbsList = new Hyperlink(resourceBundle_.getString(key));
+
+ linkCrumbsList.setId("webViewBreadcrumbs");
+ linkCrumbsList.setPrefHeight(40);
+ linkCrumbsList.setOnAction(eventHandler);
+
+ return linkCrumbsList;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.net.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?import javafx.scene.web.*?>
+<?scenebuilder-preview-i18n-resource resources/moxkiriya.properties?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="513.0" prefWidth="842.0" styleClass="webViewMainAnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.WikiPreviewWindowController">
+ <children>
+ <Button fx:id="buttonReload" mnemonicParsing="false" onAction="#onActionButtonReload" prefHeight="35.0" prefWidth="70.0" text=" 🔃" textAlignment="CENTER" AnchorPane.leftAnchor="5.0" AnchorPane.topAnchor="10.0" />
+ <WebView fx:id="webView" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: white;" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="50.0" />
+ <Button fx:id="buttonClose" mnemonicParsing="false" onAction="#onActionButtonClose" prefHeight="35.0" prefWidth="100.0" text="%key.Button.Close" AnchorPane.bottomAnchor="5.0" AnchorPane.rightAnchor="5.0" />
+ </children>
+ <stylesheets>
+ <URL value="@application.css" />
+ </stylesheets>
+</AnchorPane>
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki preview window.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.util.ResourceBundle;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+
+/**
+ * Show preview editing content.
+ *
+ */
+public class WikiPreviewWindow {
+ /** mother stage. */
+ private Stage motherStage_ = null;
+
+ /** Resource Bundle */
+ private ResourceBundle resources_ = null;
+
+ /** Stage */
+ private Stage stage_;
+
+ /** Preview window controller */
+ private WikiPreviewWindowController controller_;
+
+ /** Main window controller */
+ private WikiMainWindowController mainController_;
+
+ /**
+ * Status of preview window.
+ *
+ */
+ private enum PreviewWindowStatus {
+ SHOW,
+ HIDE
+ };
+
+ /** Preview window status */
+ private PreviewWindowStatus previewWindowStatus_ = PreviewWindowStatus.HIDE;
+
+ /**
+ * Constructor.
+ */
+ public WikiPreviewWindow(Stage motherStage, ResourceBundle resources) {
+ motherStage_ = motherStage;
+ resources_ = resources;
+
+ try {
+ FXMLLoader loader = new FXMLLoader(getClass().getResource("WikiPreviewWindow.fxml"), resources_);
+ loader.load();
+
+ Scene scene = new Scene((Parent)loader.getRoot());
+ scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
+
+ controller_ = loader.getController();
+ controller_.setWikiPreviewWindow(this);
+
+ stage_ = new Stage(StageStyle.DECORATED);
+ stage_.initOwner(motherStage_);
+ stage_.setScene(scene);
+ stage_.setTitle(resources_.getString("key.PreviewWindow.Title"));
+ stage_.setResizable(true);
+ stage_.showingProperty().addListener(new ChangeListener<Boolean>() {
+ @Override
+ public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
+ previewWindowStatus_ = newValue == false
+ ? PreviewWindowStatus.HIDE
+ : PreviewWindowStatus.SHOW;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Main windowController setter.
+ * @param mainController
+ */
+ public void setMainWindowController(WikiMainWindowController mainController) {
+ mainController_ = mainController;
+ }
+
+ /**
+ * Wiki repository setter.
+ * @param wikiRepository
+ */
+ public void setWikiRepository(WikiRepository wikiRepository) {
+ controller_.setWikiRepository(wikiRepository);
+ }
+
+ /**
+ * Latest contents getter.
+ * @return PageData
+ * @throws Exception
+ */
+ public PageData getLatestContents() throws Exception {
+ return mainController_.getLatestContents();
+ }
+
+ /**
+ * Show Wiki preview window
+ * @throws Exception
+ */
+ public void show() throws Exception {
+ controller_.loadWikiContent(mainController_.getLatestContents());
+
+ if(previewWindowStatus_ == PreviewWindowStatus.HIDE) {
+ stage_.show();
+ } else {
+ controller_.loadWikiContent(mainController_.getLatestContents());
+ }
+ }
+
+ /**
+ * Hide Wiki preview window
+ */
+ public void hide() {
+ stage_.hide();
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki preview window controller.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.web.WebView;
+
+/**
+ * Controll preview window.
+ *
+ */
+public class WikiPreviewWindowController implements Initializable {
+ /** Wiki engine */
+ private WikiEngine wikiEngine_;
+
+ /** Wiki preview window */
+ private WikiPreviewWindow wikiPreviewWindow_;
+
+ @FXML private Button buttonReload;
+ @FXML private Button buttonClose;
+ @FXML private WebView webView;
+
+ @Override
+ public void initialize(URL url, ResourceBundle resource) {
+ wikiEngine_ = new WikiEngine();
+ }
+
+ /**
+ * WikiPreviewWindow setter.
+ */
+ public void setWikiPreviewWindow(WikiPreviewWindow previewWindow) {
+ wikiPreviewWindow_ = previewWindow;
+ }
+
+ /**
+ * Wiki repository setter.
+ * @param wikiRepository
+ */
+ public void setWikiRepository(WikiRepository wikiRepository) {
+ wikiEngine_.setWikiRepository(wikiRepository);
+ }
+
+ /**
+ * Wiki content loader.
+ * @param pageData
+ */
+ public void loadWikiContent(PageData pageData) {
+ try {
+ HashMap<String, PageData> map = new HashMap<String, PageData>();
+ map.put("preview", pageData);
+ wikiEngine_.setPageDataMap(map);
+
+ String content = wikiEngine_.parse(pageData);
+ webView.getEngine().loadContent(content);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonReload(ActionEvent event) {
+ try {
+ PageData pageData = wikiPreviewWindow_.getLatestContents();
+ loadWikiContent(pageData);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void onActionButtonClose(ActionEvent event) {
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki Repository.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+
+package com.wiki.standalone.moxkiriya;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import javax.jcr.Credentials;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.NamespaceException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.VersionManager;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.apache.jackrabbit.core.jndi.RegistryHelper;
+import org.apache.jackrabbit.value.StringValue;
+
+import com.wiki.standalone.moxkiriya.PageData.FileData;
+
+/**
+ * WikiRepository class.
+ *
+ */
+public class WikiRepository {
+ /** repository_cluster_derby.xml */
+ public static final String REPOSITORY_CUSTER_FILENAME = "repository_cluster_derby.xml";
+
+ /** repository_local.xml */
+ public static final String REPOSITORY_LOCAL_FILENAME = "repository_local.xml";
+
+ public static final String REOPSITORY_DIRNAME = "Repository";
+
+ /** Moxkiriya repository generic namespace */
+ public static final String NAMESPACE_MOXKI = "moxki";
+
+ public static final String NAMESPACE_MOXKI_URI = "https://osdn.net/users/ryuhei__terada/pf/Moxkiriya7/moxki/1.0";
+
+ /** Node name "wikiroot" */
+ public static final String NODE_WIKIROOT = NAMESPACE_MOXKI + ":wikiroot";
+
+ /** Node name "namespace" */
+ public static final String NODE_NAMESPACE = NAMESPACE_MOXKI + ":namespacelist";
+
+ /** Property name "namespace" */
+ public static final String PROPERTY_NAMESPACE = NAMESPACE_MOXKI + ":namespace";
+
+ /** Property value "Main" in namespace */
+ public static final String PROPERTY_MAIN = "Main";
+
+ /** Property value "Category" in namespace */
+ public static final String PROPERTY_CATEGORY = "Category";
+
+ /** Property value "File" in namespace */
+ public static final String PROPERTY_FILE = "File";
+
+ /** Node name "pages" */
+ public static final String NODE_PAGES = NAMESPACE_MOXKI + ":pages";
+
+ /** Node name "page" */
+ public static final String NODE_PAGE = NAMESPACE_MOXKI + ":page";
+
+ /** Property name "title" */
+ public static final String PROPERTY_TITLE = NAMESPACE_MOXKI + ":title";
+
+ /** Property name "content" */
+ public static final String PROPERTY_CONTENT = NAMESPACE_MOXKI + ":content";
+
+ /** Property name "category" */
+ public static final String PROPERTY_category = NAMESPACE_MOXKI + ":category";
+
+ /** Node name "file" */
+ public static final String NODE_FILE = NAMESPACE_MOXKI + ":file";
+
+ /** Repository Home directory */
+ private String repositoryHomeDir_;
+
+ /** repository.xml */
+ private String repositoryFile_;
+
+ /** Initial context settings table */
+ private static Hashtable<String, String> envHashTable = new Hashtable<String, String>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(Context.INITIAL_CONTEXT_FACTORY,
+ "org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory");
+ }
+ {
+ put(Context.PROVIDER_URL, "localhost");
+ }
+ };
+
+ /** Repository */
+ private Repository repository_;
+
+ /** Session */
+ private Session session_;
+
+ /**
+ * Constructor.
+ * @param wikirootPath
+ * @throws Exception
+ */
+ public WikiRepository(File wikirootPath) throws Exception {
+ SettingManager settingMgr = SettingManager.getInstance();
+
+ setSystemProperties();
+
+ String configXML = settingMgr.get(SettingManager.SETINGKEY_CLUSTER).equals("true")
+ ? REPOSITORY_CUSTER_FILENAME
+ : REPOSITORY_LOCAL_FILENAME;
+
+ repositoryHomeDir_ = settingMgr.getAbsolutePath(REOPSITORY_DIRNAME);
+ repositoryFile_ = settingMgr.getAbsolutePath(configXML);
+
+ InitialContext initialContext = new InitialContext(envHashTable);
+ RegistryHelper.registerRepository(initialContext,
+ "repo",
+ repositoryFile_,
+ repositoryHomeDir_,
+ true);
+ repository_ = (Repository)initialContext.lookup("repo");
+ session_ = repository_.login((Credentials)null);
+ }
+
+ /**
+ * Session closer.
+ */
+ public void closeSession() {
+ session_.logout();
+ }
+
+ /**
+ * Build Apache Jackrabbit Repository.
+ * @param pageData
+ * @throws Exception
+ */
+ public void buildWikiRepository(PageData pageData) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+
+ try {
+ NamespaceRegistry nsRegistry = workspace.getNamespaceRegistry();
+
+ nsRegistry.getPrefix(NAMESPACE_MOXKI_URI);
+ } catch(NamespaceException e) {
+ /*
+ * Build Apache Jackrabbit Repository if namespace"moxki" hasnot registered.
+ */
+ workspace.getNamespaceRegistry().registerNamespace(NAMESPACE_MOXKI, NAMESPACE_MOXKI_URI);
+
+ Node root = session_.getRootNode();
+ Node wikiroot = root.addNode(NODE_WIKIROOT);
+ Node namespace = wikiroot.addNode(NODE_NAMESPACE);
+ namespace.setProperty(PROPERTY_NAMESPACE,
+ new Value[] {
+ new StringValue(PROPERTY_MAIN),
+ new StringValue(PROPERTY_CATEGORY),
+ new StringValue(PROPERTY_FILE)
+ });
+ wikiroot.addNode(NODE_PAGES);
+
+ /*
+ * "page"ノードを作成
+ */
+ checkin(pageData);
+ }
+ }
+
+ /**
+ * Add pageNode.
+ * @param pageData
+ * @throws Exception
+ */
+ public Node addPageNode(PageData pageData) throws Exception {
+ Node root = session_.getRootNode();
+ Node wikiroot = root.getNode(NODE_WIKIROOT);
+ Node pagesNode = wikiroot.getNode(NODE_PAGES);
+ Node pageNode = pagesNode.addNode(NODE_PAGE);
+
+ pageNode.addMixin(NodeType.MIX_VERSIONABLE);
+ pageNode.addMixin(NodeType.MIX_REFERENCEABLE);
+
+ return transformPageDataToNode(pageData, pageNode);
+ }
+
+ /**
+ * Transform PageData to node.
+ * @param pageData
+ * @param node
+ * @return Node
+ * @throws Exception
+ */
+ public Node transformPageDataToNode(PageData pageData, Node node) throws Exception {
+ node.setProperty(PROPERTY_NAMESPACE, new StringValue(pageData.getNamespace()));
+ node.setProperty(PROPERTY_TITLE, new StringValue(pageData.getTitle()));
+ node.setProperty(PROPERTY_CONTENT, new StringValue(pageData.getContent()));
+
+ ArrayList<String> categories = pageData.getCategories();
+ Value[] values = new Value[] { new StringValue("") };
+ if(categories.size() > 0) {
+ values = new Value[categories.size()];
+ for(int count = 0; count < categories.size(); count++) {
+ values[count] = new StringValue(categories.get(count));
+ }
+ }
+ node.setProperty(PROPERTY_category, values);
+
+ FileData fileData = pageData.getFileData();
+
+ if(fileData != null) {
+ Node fileNode;
+ if(node.hasNode(WikiRepository.NODE_FILE) == true) {
+ fileNode = node.getNode(WikiRepository.NODE_FILE);
+ }
+ else {
+ fileNode = node.addNode(WikiRepository.NODE_FILE, NodeType.NT_FILE);
+ fileNode.addNode(Property.JCR_CONTENT, NodeType.NT_RESOURCE);
+ }
+
+ Node nodeResource = fileNode.getNode(Property.JCR_CONTENT);
+ ValueFactory valueFactory = session_.getValueFactory();
+
+ nodeResource.setProperty(Property.JCR_DATA, valueFactory.createBinary(fileData.getInputStream()));
+ nodeResource.setProperty(Property.JCR_MIMETYPE, new StringValue(fileData.getMimeType()));
+ nodeResource.setProperty(Property.JCR_LAST_MODIFIED, valueFactory.createValue(fileData.getLastModified()));
+ if(fileData.getMimeType().startsWith("text/") == true) {
+ nodeResource.setProperty(Property.JCR_ENCODING, new StringValue("UTF-8"));
+ }
+ }
+
+ return node;
+ }
+
+ /**
+ * Execute query.
+ * @param sql
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ private HashMap<String, PageData> executeQuery(String sql) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+ QueryManager queryMgr = workspace.getQueryManager();
+ Query query = queryMgr.createQuery(sql, Query.JCR_SQL2);
+ NodeIterator iter = query.execute().getNodes();
+
+ return convertNodeIteratorToPageDataMap(iter);
+ }
+
+ /**
+ * Get node matched namespace.
+ * @param pageTitle
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageNamespace(String namespace) throws Exception {
+ return executeQuery(
+ "SELECT * "
+ + " FROM [nt:unstructured]"
+ + " WHERE"
+ + " ISDESCENDANTNODE(["
+ + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
+ + " AND"
+ + " [" + PROPERTY_NAMESPACE + "] = '" + namespace + "'"
+ );
+ }
+
+ /**
+ * Get node matched uuid.
+ * @param uuid
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageUUID(String uuid) throws Exception {
+ return executeQuery(
+ "SELECT * "
+ + " FROM [nt:unstructured]"
+ + " WHERE"
+ + " ISDESCENDANTNODE(["
+ + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
+ + " AND"
+ + " [" + Property.JCR_UUID + "] = '" + uuid + "'"
+ );
+ }
+
+ /**
+ * Get node matched page title.
+ * @param pageTitle
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageTitle(String pageTitle) throws Exception {
+ String namespace = PROPERTY_MAIN;
+ String title = pageTitle;
+
+ if(pageTitle.contains(":") == true) {
+ namespace = pageTitle.substring(0, pageTitle.indexOf(":"));
+ title = pageTitle.substring(pageTitle.indexOf(":") + ":".length());
+ }
+
+ return queryPageTitle(title, namespace);
+ }
+
+ /**
+ * Get node matched page title.
+ * @param pageTitle
+ * @param namespace
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageTitle(String pageTitle, String namespace) throws Exception {
+ return executeQuery(
+ "SELECT * "
+ + " FROM [nt:unstructured]"
+ + " WHERE"
+ + " ISDESCENDANTNODE(["
+ + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
+ + " AND"
+ + " [" + PROPERTY_NAMESPACE + "] = '" + namespace + "'"
+ + " AND"
+ + " [" + PROPERTY_TITLE + "] = '" + pageTitle + "'"
+ );
+ }
+
+ /**
+ * Execute full text search.
+ * @param searchKey
+ * @return String
+ * @throws Exception
+ */
+ public HashMap<String, PageData> queryPageFullTextSearch(String searchKey) throws Exception {
+ return executeQuery(
+ "SELECT * "
+ + " FROM [nt:unstructured]"
+ + " WHERE"
+ + " ISDESCENDANTNODE(["
+ + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
+ + " AND "
+ + " CONTAINS([" + PROPERTY_TITLE + "], '" + searchKey + "')"
+ + " OR "
+ + " CONTAINS([" + PROPERTY_CONTENT + "], '" + searchKey + "')"
+ );
+ }
+
+ /**
+ * Converter NodeIterator to PageDatMap.
+ * @param nodeIter
+ * @return HashMap<String, PageData>
+ * @throws Exception
+ */
+ public HashMap<String, PageData> convertNodeIteratorToPageDataMap(NodeIterator nodeIter) throws Exception {
+ HashMap<String, PageData> pageDataMap = new HashMap<String, PageData>();
+ while(nodeIter.hasNext() == true) {
+ Node node = nodeIter.nextNode();
+ Version baseVersion = getBaseVersion(node);
+ PageData pageData = new PageData(node);
+
+ pageData.setBaseVersion(baseVersion);
+ pageDataMap.put(node.getProperty(Property.JCR_UUID).getString(), pageData);
+ }
+
+ return pageDataMap;
+ }
+
+ /**
+ * NamespaceList getter
+ * @return Value[]
+ * @throws Exception
+ */
+ public Value[] getNamespaceList() throws Exception {
+ Node namespace = session_.getNode("/" + NODE_WIKIROOT + "/" + NODE_NAMESPACE);
+
+ return namespace.getProperty(PROPERTY_NAMESPACE).getValues();
+ }
+
+ /**
+ * Checkout
+ * @param pageData
+ * @throws Exception
+ */
+ public void checkout(PageData pageData) throws Exception {
+ Node node = pageData.getNode();
+ if(node != null) {
+ session_.refresh(false);
+
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+ versionMgr.checkout(node.getPath());
+ }
+ }
+
+ /**
+ * Checkin.
+ * @param pageData
+ * @throws Exception
+ */
+ public PageData checkin(PageData pageData) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+ Node node = pageData.getNode();
+
+ if(node == null) {
+ node = addPageNode(pageData);
+ session_.save();
+ versionMgr.checkout(node.getPath());
+ }
+ else {
+ String uuid = node.getProperty(Property.JCR_UUID).getString();
+
+ node = transformPageDataToNode(pageData, session_.getNodeByIdentifier(uuid));
+ session_.save();
+ }
+
+ versionMgr.checkin(node.getPath());
+ createCategoryPages(node);
+
+ String uuid = node.getProperty(Property.JCR_UUID).getString();
+
+ return new PageData(session_.getNodeByIdentifier(uuid));
+ }
+
+ /**
+ * Cancel checkout
+ * @param pageData
+ * @throws Exception
+ */
+ public void cancelCheckout(PageData pageData) throws Exception {
+ Node node = pageData.getNode();
+ if(node != null) {
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+ String path = node.getPath();
+ if(versionMgr.isCheckedOut(path) == true) {
+ versionMgr.restore(versionMgr.getBaseVersion(path), true);
+ }
+ }
+ }
+
+ /**
+ * Delete page node.
+ * @param pageData
+ * @throws Exception
+ */
+ public void deletePage(PageData pageData) throws Exception {
+ pageData.getNode().remove();
+ session_.save();
+ }
+
+ /**
+ * Refresh session.
+ * @throws RepositoryException
+ */
+ public void refreshSession() throws RepositoryException {
+ session_.refresh(false);
+ }
+
+ /**
+ * Set SystemProperties.
+ * @throws Exception
+ */
+ private void setSystemProperties() throws Exception {
+ SettingManager settingMgr = SettingManager.getInstance();
+
+ String macAddress = getMacAddress();
+ String username = System.getProperty("user.name");
+ String approot = settingMgr.get(SettingManager.SETTINGSKEY_WIKIROOT);
+ String partyName = settingMgr.getSelectedParty();
+
+ System.setProperty("cluster.id", String.valueOf(macAddress.hashCode()
+ + "-" + partyName
+ + "-" + username));
+ System.setProperty("wiki.root", approot);
+
+ if(settingMgr.get(SettingManager.SETINGKEY_CLUSTER).equals("true")) {
+ System.setProperty("party.name", partyName);
+ System.setProperty("cluster.setting", "TRUE");
+ System.setProperty("dbserver.url", settingMgr.get(SettingManager.SETINGKEY_DBSERVER_URL));
+ System.setProperty("dbserver.port", settingMgr.get(SettingManager.SETINGKEY_DBSERVER_PORT));
+ System.setProperty("jdbc.driver", settingMgr.get(SettingManager.SETINGKEY_JDBC_DRIVER));
+ }
+ else {
+ System.setProperty("cluster.setting", "FALSE");
+ System.setProperty("dbserver.url", "");
+ System.setProperty("dbserver.port", "");
+ System.setProperty("jdbc.driver", "");
+ }
+ }
+
+ /**
+ * Mac Address getter.
+ * @return
+ * @throws Exception
+ */
+ private String getMacAddress() throws Exception {
+ StringBuffer buf = new StringBuffer();
+ Enumeration<NetworkInterface> nicList = NetworkInterface.getNetworkInterfaces();
+
+ while(nicList.hasMoreElements() == true) {
+ NetworkInterface nic = nicList.nextElement();
+ if(nic.getName().equals("lo") != true) {
+ byte[] macAddress = nic.getHardwareAddress();
+ if(macAddress != null) {
+ for(byte b: macAddress) {
+ buf.append(String.format("%02X-", b));
+ }
+ break;
+ }
+ }
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ *
+ * @param node
+ * @throws Exception
+ */
+ private void createCategoryPages(Node node) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+ Value[] categories = node.getProperty(PROPERTY_category).getValues();
+
+ for(Value category: categories) {
+ String title = category.getString();
+
+ if(title.isEmpty() != true) {
+ HashMap<String, PageData> map = queryPageTitle(title, PROPERTY_CATEGORY);
+
+ if(map.size() == 0) {
+ /*
+ * category pageが未作成の場合、
+ */
+ PageData pageData = new PageData();
+ pageData.setNamespace(PROPERTY_CATEGORY);
+ pageData.setTitle(title);
+
+ Node categoryNode = addPageNode(pageData);
+ session_.save();
+ versionMgr.checkout(categoryNode.getPath());
+ versionMgr.checkin(categoryNode.getPath());
+ }
+ }
+ }
+ }
+
+ /**
+ * Test namespace is contains namespaceList.
+ * @param namespace
+ * @return boolean
+ * @throws Exception
+ */
+ public boolean isContainsNamespaceList(String namespace) throws Exception {
+ Node root = session_.getRootNode();
+ Node wikiroot = root.getNode(NODE_WIKIROOT);
+ Node namespaceNode = wikiroot.getNode(NODE_NAMESPACE);
+
+ Value[] list = namespaceNode.getProperty(PROPERTY_NAMESPACE).getValues();
+ boolean isContains = false;
+
+ for(Value entry: list) {
+ if(entry.getString().equals(namespace) == true) {
+ isContains = true;
+ break;
+ }
+ }
+
+ return isContains;
+ }
+
+ /**
+ * Version history getter.
+ * @param uuid
+ * @return VersionIterator
+ * @throws Exception
+ */
+ public VersionIterator getVersionHistory(String uuid) throws Exception {
+ HashMap<String, PageData> nodeMap = queryPageUUID(uuid);
+ PageData pageData = nodeMap.values().iterator().next();
+ Node node = pageData.getNode();
+
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+ VersionHistory versionHistory = versionMgr.getVersionHistory(node.getPath());
+
+ return versionHistory.getAllVersions();
+ }
+
+ /**
+ * Base version getter.
+ * @param node
+ * @return Version
+ * @throws Exception
+ */
+ public Version getBaseVersion(Node node) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+
+ return versionMgr.getBaseVersion(node.getPath());
+ }
+
+ /**
+ * Restore version.
+ * @param version
+ * @param node
+ * @throws Exception
+ */
+ public void restoreVersion(Version version, Node node) throws Exception {
+ Workspace workspace = session_.getWorkspace();
+ VersionManager versionMgr = workspace.getVersionManager();
+
+ versionMgr.restore(version, true);
+ }
+
+ /**
+ * Import system view.
+ * @param outputFile
+ * @throws Exception
+ */
+ public void importSystemView(File outputFile) throws Exception {
+ FileInputStream inStream = new FileInputStream(outputFile);
+
+ try {
+ Node root = session_.getRootNode();
+ Node wikiroot = root.getNode(NODE_WIKIROOT);
+ Node pagesNode = wikiroot.getNode(NODE_PAGES);
+
+ session_.importXML(pagesNode.getPath(), inStream, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+ session_.save();
+
+ Node namespaceNode = wikiroot.getNode(NODE_NAMESPACE);
+ Value[] namespaces = namespaceNode.getProperty(PROPERTY_NAMESPACE).getValues();
+
+ for(Value namespace: namespaces) {
+ HashMap<String,PageData> map = queryPageNamespace(namespace.getString());
+ Iterator<PageData> iter = map.values().iterator();
+ while(iter.hasNext() == true) {
+ PageData pageData = iter.next();
+ checkout(pageData);
+ checkin(pageData);
+ }
+ }
+ } finally {
+ inStream.close();
+ }
+ }
+
+ /**
+ * Export system view.
+ * @param outputFile
+ * @throws Exception
+ */
+ public void exportSystemView(File outputFile) throws Exception {
+ FileOutputStream outStream = new FileOutputStream(outputFile);
+
+ try {
+ Node root = session_.getRootNode();
+ Node wikiroot = root.getNode(NODE_WIKIROOT);
+ Node pagesNode = wikiroot.getNode(NODE_PAGES);
+
+ session_.exportSystemView(pagesNode.getPath(), outStream, false, false);
+ } finally {
+ outStream.close();
+ }
+ }
+}
--- /dev/null
+/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
+.rootAnchorPane {
+ -fx-background-color: white;
+}
+
+.webViewMenuAnchorPane {
+ -fx-border-color: #c0c0c0;
+ -fx-border-style:solid;
+ -fx-border-width:1px;
+ -fx-background-color: #f5f5f5;
+}
+
+.webViewMainAnchorPane {
+ -fx-border-color:#c0c0c0;
+ -fx-border-style:solid;
+ -fx-border-width:0px 1px 1px 1px;
+ -fx-background-color: #f5f5f5;
+}
+
+.webViewGapspace {
+ -fx-border-color:#c0c0c0;
+ -fx-border-style:solid;
+ -fx-border-width:0px 0px 1px 0px;
+ -fx-background-color: transparent;
+}
+.webViewHistoryContentAnchorPane {
+ -fx-border-color:#c0c0c0;
+ -fx-border-style:solid;
+ -fx-border-width:1px;
+ -fx-background-color: #f8f8ff;
+}
+
+.selectPartyRadioButtonTableCell {
+ -fx-pref-width: 80;
+ -fx-alignment:center;
+}
+
+#webViewMainHyperlinkActive {
+ -fx-background-color: #f5f5f5;
+ -fx-border-color: #c0c0c0;
+ -fx-border-width:1px 1px 0px 1px;
+ -fx-border-style: solid;
+}
+
+#webViewMainHyperlinkInactive {
+ -fx-background-color: #e0e0e0;
+ -fx-border-color: #c0c0c0;
+ -fx-border-width:1px 1px 1px 1px;
+ -fx-border-style: solid;
+}
+
+#webViewBreadcrumbs {
+ -fx-alignment: center-left;
+ -fx-padding: 0.0 2.0 0.0 2.0;
+}
+
+#webViewHistoryBaseVersion {
+ -fx-font-weight: bold;
+ -fx-text-fill: crimson;
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?scenebuilder-preview-i18n-resource ../resources/moxkiriya.properties?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.dialog.AboutMoxkiriyaDialogController">
+ <children>
+ <Button fx:id="buttonOK" layoutX="250.0" layoutY="358.0" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonOK" prefHeight="30.0" prefWidth="100.0" text="%key.Button.OK" />
+ <Label prefHeight="30.0" prefWidth="480.0" text="%key.About.Moxkiriya" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="30.0" />
+ <Label prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.Copyright" AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="55.0" />
+ <Label prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.License" AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="80.0" />
+ <Label maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="30.0" prefWidth="480.0" text="%key.About.Moxkiriya.Other.info" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="230.0" />
+ <Label maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.Powered.Apache.Lucene" AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="255.0" />
+ <Label prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.System.requirement" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="130.0" />
+ <Label prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.System.requirement.Java" AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="155.0" />
+ <Label maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="30.0" prefWidth="500.0" text="%key.About.Moxkiriya.Lucene.license" AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="285.0" />
+ </children>
+</AnchorPane>
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * About Moxkiriya Dialog.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+/**
+ * About Moxkiriyaダイアログを表示する。
+ */
+public class AboutMoxkiriyaDialog extends DialogBase {
+
+ @Override
+ protected String getFXML() {
+ return "AboutMoxkiriyaDialog.fxml";
+ }
+
+ @Override
+ protected DialogController getController() throws Exception {
+ AboutMoxkiriyaDialogController controller = loader_.getController();
+
+ return controller;
+ }
+
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * About Moxkiriya Dialog Controller.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+
+/**
+ * About Moxkiriyaダイアログのコントローラ。
+ */
+public class AboutMoxkiriyaDialogController extends DialogControllerBase {
+ @FXML private Button buttonOK;
+
+ @FXML
+ void onActionButtonOK(ActionEvent event) {
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.image.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?import javafx.scene.text.*?>
+<?scenebuilder-preview-i18n-resource ../resources/moxkiriya.properties?>
+
+<GridPane hgap="14.0" maxHeight="+Infinity" maxWidth="+Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="20.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.dialog.AlertDialogController">
+ <children>
+ <ImageView fx:id="ImageViewIcon" fitHeight="60.0" fitWidth="60.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="0" GridPane.halignment="CENTER" GridPane.rowIndex="0" GridPane.valignment="TOP" />
+ <VBox maxHeight="+Infinity" maxWidth="+Infinity" minHeight="-Infinity" prefWidth="400.0" spacing="7.0" GridPane.columnIndex="1" GridPane.rowIndex="0">
+ <children>
+ <Label id="messageLabel" fx:id="labelMessage" text="" textAlignment="LEFT" wrapText="true">
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ </Label>
+ <Label id="detailsLabel" fx:id="labelDetails" text="" textAlignment="LEFT" wrapText="true">
+ <font>
+ <Font size="12.0" />
+ </font>
+ </Label>
+ </children>
+ </VBox>
+ <HBox maxHeight="-Infinity" maxWidth="+Infinity" minHeight="-Infinity" minWidth="-Infinity" GridPane.columnIndex="1" GridPane.rowIndex="1">
+ <children>
+ <HBox id="HBox" fx:id="actionParent" alignment="CENTER">
+ <HBox.margin>
+ <Insets />
+ </HBox.margin>
+ </HBox>
+ <Pane maxWidth="+Infinity" HBox.hgrow="ALWAYS" />
+ <Button id="cancelButton" fx:id="buttonCancel" cancelButton="true" minWidth="80.0" mnemonicParsing="false" onAction="#onActionButtonCancel" text="%key.Button.Cancel" HBox.hgrow="NEVER">
+ <HBox.margin>
+ <Insets />
+ </HBox.margin>
+ </Button>
+ <HBox id="HBox" fx:id="okParent" alignment="CENTER">
+ <children>
+ <Button id="okButton" fx:id="buttonOK" minWidth="80.0" mnemonicParsing="false" onAction="#onActionButtonOK" text="%key.Button.OK" HBox.hgrow="NEVER">
+ <HBox.margin>
+ <Insets left="14.0" />
+ </HBox.margin>
+ </Button>
+ </children>
+ </HBox>
+ </children>
+ </HBox>
+ </children>
+ <columnConstraints>
+ <ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" />
+ <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="+Infinity" minWidth="-Infinity" />
+ </columnConstraints>
+ <padding>
+ <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
+ </padding>
+ <rowConstraints>
+ <RowConstraints maxHeight="+Infinity" minHeight="-Infinity" valignment="CENTER" vgrow="ALWAYS" />
+ <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" vgrow="NEVER" />
+ </rowConstraints>
+</GridPane>
--- /dev/null
+/**
+ * AlertDialog
+ * @author Ryuhei Terada
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+
+/**
+ * AlertDialog
+ *
+ */
+public class AlertDialog extends DialogBase {
+ /**
+ * Message種別列挙定数
+ */
+ public enum MessageType {
+ ConfirmEditCancel, // 編集キャンセル確認ダイアログ
+ AlertTitleEmpty, // Title未入力警告ダイアログ
+ SuccessImport, // Import成功情報ダイアログ
+ FailureImport, // Import失敗情報ダイアログ
+ SuccessExport, // Export成功情報ダイアログ
+ FailureExport, // Export失敗情報ダイアログ
+ };
+
+ /**
+ * Dialog種別列挙定数
+ */
+ public enum DialogType {
+ Error, // エラーダイアログ
+ Alert, // 警告ダイアログ
+ Info, // 情報ダイアログ
+ Confirm // 確認ダイアログ
+ };
+
+ /**
+ * Button種別列挙定数
+ */
+ public enum ButtoType {
+ OK,
+ CANCEL_OK
+ }
+
+ /**
+ * メッセージタイプ
+ */
+ private MessageType msgType_;
+
+
+ /**
+ * コンストラクタ
+ * @param msgType
+ */
+ public AlertDialog(MessageType msgType) {
+ msgType_ = msgType;
+ Stage stage = new Stage(StageStyle.UTILITY);
+ stage.initOwner(parentStage_);
+ stage.initModality(Modality.WINDOW_MODAL);
+ }
+
+ @Override
+ protected String getFXML() {
+ return "AlertDialog.fxml";
+ }
+
+ @Override
+ protected DialogController getController() throws Exception {
+ AlertDialogController controller = loader_.getController();
+ controller.setMessageType(msgType_);
+
+ return controller;
+ }
+
+ @Override
+ protected CloseType getCloseType() {
+ return ((AlertDialogController)controller_).getCloseType();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.wiki.standalone.moxkiriya.dialog;
+
+import java.net.MalformedURLException;
+import java.util.LinkedHashMap;
+
+import com.wiki.standalone.moxkiriya.ResourceManager;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+
+public class AlertDialogController extends DialogControllerBase {
+ @FXML
+ private ImageView ImageViewIcon;
+
+ @FXML
+ private Label labelMessage;
+
+ @FXML
+ private Label labelDetails;
+
+ @FXML
+ private Button buttonCancel;
+
+ /**
+ * 終了種別
+ */
+ private AlertDialog.CloseType closeType_;
+
+ /**
+ * Dialogに表示するicon, メッセージ, 詳細を設定する。
+ */
+ static class DialogProperty {
+ /**
+ * Constructor
+ * @param messageResourceKey
+ * @param detailResourceKey
+ * @param dialogType
+ */
+ DialogProperty(String messageResourceKey, String detailResourceKey, AlertDialog.DialogType dialogType) {
+ this(messageResourceKey, detailResourceKey, dialogType, AlertDialog.ButtoType.CANCEL_OK);
+ };
+
+ /**
+ * Constructor.
+ * @param messageResourceKey
+ * @param detailResourceKey
+ * @param dialogType
+ * @param buttonType
+ */
+ DialogProperty(String messageResourceKey, String detailResourceKey, AlertDialog.DialogType dialogType, AlertDialog.ButtoType buttonType) {
+ messageResourceKey_ = messageResourceKey;
+ detailResourceKey_ = detailResourceKey;
+ dialogType_ = dialogType;
+ buttonType_ = buttonType;
+ };
+
+ String messageResourceKey_;
+ String detailResourceKey_;
+ AlertDialog.DialogType dialogType_;
+ AlertDialog.ButtoType buttonType_;
+ };
+
+ /**
+ * MessageType/DialogPropertyテーブル
+ */
+ private final static LinkedHashMap<AlertDialog.MessageType, DialogProperty> dialogPropertyTable
+ = new LinkedHashMap<AlertDialog.MessageType, DialogProperty>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ put(AlertDialog.MessageType.ConfirmEditCancel,
+ new DialogProperty("key.Dialog.Message.Cancel.Editing",
+ "key.Dialog.Detail.Cancel.Editing",
+ AlertDialog.DialogType.Confirm));
+ put(AlertDialog.MessageType.AlertTitleEmpty,
+ new DialogProperty("key.Dialog.Message.Empty.Title",
+ "key.Dialog.Detail.Input.Title",
+ AlertDialog.DialogType.Alert,
+ AlertDialog.ButtoType.OK));
+ put(AlertDialog.MessageType.SuccessImport,
+ new DialogProperty("key.Dialog.Import.Result.Title",
+ "key.Dialog.Detail.Import.Success",
+ AlertDialog.DialogType.Info,
+ AlertDialog.ButtoType.OK));
+ put(AlertDialog.MessageType.FailureImport,
+ new DialogProperty("key.Dialog.Import.Result.Title",
+ "key.Dialog.Detail.Import.Failure",
+ AlertDialog.DialogType.Error,
+ AlertDialog.ButtoType.OK));
+ put(AlertDialog.MessageType.SuccessExport,
+ new DialogProperty("key.Dialog.Export.Result.Title",
+ "key.Dialog.Detail.Export.Success",
+ AlertDialog.DialogType.Info,
+ AlertDialog.ButtoType.OK));
+ put(AlertDialog.MessageType.FailureExport,
+ new DialogProperty("key.Dialog.Export.Result.Title",
+ "key.Dialog.Detail.Export.Failure",
+ AlertDialog.DialogType.Error,
+ AlertDialog.ButtoType.OK));
+ }
+ };
+
+ /**
+ * MessageTypeを設定する。
+ * @param msgType
+ * @throws MalformedURLException
+ */
+ public void setMessageType(AlertDialog.MessageType msgType) throws MalformedURLException {
+ DialogProperty dialogProperty = dialogPropertyTable.get(msgType);
+
+ if(dialogProperty != null) {
+ /*
+ * メッセージ、詳細情報を設定する。
+ */
+ labelMessage.setText(resource_.getString(dialogProperty.messageResourceKey_));
+ labelDetails.setText(resource_.getString(dialogProperty.detailResourceKey_));
+
+ /*
+ * アイコンを設定する。
+ */
+ Image image = ResourceManager.IconTable.get(dialogProperty.dialogType_);
+ ImageViewIcon.setImage(image);
+
+ /*
+ * ボタンを設定する。
+ */
+ if(dialogProperty.buttonType_ == AlertDialog.ButtoType.OK) {
+ buttonCancel.setVisible(false);
+ }
+ else {
+ buttonCancel.setVisible(true);
+ }
+ }
+ }
+
+ /**
+ * 終了種別を取得する。
+ * @param closeType
+ */
+ public AlertDialog.CloseType getCloseType() {
+ return closeType_;
+ }
+
+ @FXML
+ public void onActionButtonOK(ActionEvent event) {
+ closeType_ = AlertDialog.CloseType.OK;
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+
+ @FXML
+ public void onActionButtonCancel(ActionEvent event) {
+ closeType_ = AlertDialog.CloseType.Cancel;
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?scenebuilder-preview-i18n-resource ../resources/moxkiriya.properties?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="339.0" prefWidth="690.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.dialog.ConfigSettingsDialogController">
+ <children>
+ <Label prefHeight="30.0" prefWidth="574.0" text="%key.Config.Setting.Dialog.Message" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="15.0" />
+ <Button id="ButtonOK" fx:id="buttonOK" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#onActionButtonOK" prefHeight="30.0" prefWidth="100.0" text="%key.Button.OK" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="87.0" />
+ <GridPane prefHeight="144.0" prefWidth="505.0" AnchorPane.bottomAnchor="40.0" AnchorPane.leftAnchor="45.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="46.0">
+ <children>
+ <Label prefHeight="28.0" prefWidth="197.0" text="%key.Config.Setting.Approot" GridPane.columnIndex="0" GridPane.rowIndex="2">
+ <GridPane.margin>
+ <Insets left="20.0" fx:id="x1" />
+ </GridPane.margin>
+ </Label>
+ <TextField id="TextFieldWikiroot" fx:id="textFieldApproot" disable="false" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="30.0" prefWidth="384.0" promptText="%key.Config.Setting.Approot.textField.prompt" text="" GridPane.columnIndex="1" GridPane.rowIndex="2" />
+ <Button id="ButtonChooseDirectory" fx:id="buttonChooseDirectory" maxHeight="-Infinity" maxWidth="-1.0" minWidth="27.0" mnemonicParsing="false" onAction="#onActionButtonChooseDirectory" prefHeight="25.0" prefWidth="30.0" text="..." GridPane.columnIndex="2" GridPane.rowIndex="2" />
+ <Label prefHeight="30.0" prefWidth="197.0" text="%key.Config.Setting.Cluster.setting" GridPane.columnIndex="0" GridPane.margin="$x1" GridPane.rowIndex="3" />
+ <CheckBox fx:id="checkBoxClusterSetting" mnemonicParsing="false" prefHeight="30.0" prefWidth="384.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="3" />
+ <Label prefHeight="30.0" prefWidth="177.0" text="%key.Config.Setting.DBServer.URL" GridPane.columnIndex="0" GridPane.rowIndex="4">
+ <GridPane.margin>
+ <Insets left="40.0" fx:id="x2" />
+ </GridPane.margin>
+ </Label>
+ <TextField fx:id="textFieldDBServerURL" disable="true" prefHeight="28.0" prefWidth="325.0" promptText="%key.Config.Setting.DBServer.URL.textField.prompt" GridPane.columnIndex="1" GridPane.rowIndex="4" />
+ <Label prefHeight="30.0" prefWidth="177.0" text="%key.Config.Setting.DBServer.port" GridPane.columnIndex="0" GridPane.margin="$x2" GridPane.rowIndex="5" />
+ <TextField fx:id="textFieldPortNumber" disable="true" prefHeight="30.0" prefWidth="271.0" promptText="%key.Config.Setting.DBServer.port.textField.prompt" GridPane.columnIndex="1" GridPane.rowIndex="5" />
+ <Label prefHeight="30.0" prefWidth="177.0" text="%key.Config.Setting.DBServer.JDBC.Driver" GridPane.columnIndex="0" GridPane.margin="$x2" GridPane.rowIndex="6" />
+ <TextField fx:id="textFieldJDBCDriver" disable="true" prefHeight="30.0" prefWidth="271.0" promptText="%key.Config.Setting.DBServer.JDBC.Driver.textField.prompt" text="" GridPane.columnIndex="1" GridPane.rowIndex="6" />
+ <Label prefHeight="28.0" prefWidth="227.0" text="%key.Config.Setting.Party.name" GridPane.columnIndex="0" GridPane.rowIndex="0" />
+ <Label prefHeight="24.999900000002526" prefWidth="227.0" text="%key.Config.Setting.Party.Default.check" GridPane.columnIndex="0" GridPane.rowIndex="1">
+ <GridPane.margin>
+ <Insets left="20.0" fx:id="x1" />
+ </GridPane.margin>
+ </Label>
+ <TextField id="textFieldDivisionName" fx:id="textFieldPartyName" prefHeight="30.0" prefWidth="384.0" promptText="%key.Config.Setting.Party.textField.prompt" text="" GridPane.columnIndex="1" GridPane.rowIndex="0" />
+ <CheckBox fx:id="checkBoxDefaultParty" mnemonicParsing="false" prefHeight="30.0" prefWidth="384.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="1" />
+ </children>
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="270.0" minWidth="10.0" prefWidth="197.0" />
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="444.0" minWidth="10.0" prefWidth="271.0" />
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="444.0" minWidth="10.0" prefWidth="37.0" />
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints maxHeight="31.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="31.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="31.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="31.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
+ <RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
+ </rowConstraints>
+ </GridPane>
+ </children>
+</AnchorPane>
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * ConfigSettingsDialog.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+import java.util.Hashtable;
+
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+
+/**
+ * ConfigSettingsDialog
+ */
+public class ConfigSettingsDialog extends DialogBase {
+ /** target party name. */
+ private String partyName_;
+
+ /**
+ * Constructor.
+ */
+ public ConfigSettingsDialog() {
+ this(null);
+ }
+
+ /**
+ * Constructor.
+ * @param partyName
+ */
+ public ConfigSettingsDialog(String partyName) {
+ super();
+ partyName_ = partyName;
+ }
+
+ @Override
+ protected String getFXML() {
+ return "ConfigSettingsDialog.fxml";
+ }
+
+ @Override
+ protected DialogController getController() {
+ ConfigSettingsDialogController controller = loader_.getController();
+ controller.setWindow(scene_.getWindow());
+ controller.setPartyName(partyName_);
+ return controller;
+ }
+
+ @Override
+ protected CloseType show() {
+ Stage stage = new Stage();
+
+ stage.initOwner(parentStage_);
+ stage.initModality(Modality.APPLICATION_MODAL);
+ stage.setScene(scene_);
+ stage.setResizable(false);
+ stage.showAndWait();
+
+ return getCloseType();
+ }
+
+ /**
+ * Settings table getter.
+ * @return Hashtable<String, String>
+ */
+ public Hashtable<String, String> getSettingsTable() {
+ return ((ConfigSettingsDialogController)controller_).getSettingsTable();
+ }
+
+ /**
+ * Default party checkbox value getter.
+ * @return boolean
+ */
+ public boolean getDefaultPartyCheckValue() {
+ return ((ConfigSettingsDialogController)controller_).getDefaultPartyCheckValue();
+ }
+
+ /**
+ * Party name getter.
+ * @return String
+ */
+ public String getPartyName() {
+ return ((ConfigSettingsDialogController)controller_).getPartyName();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * ConfigSettingsDialogController.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */package com.wiki.standalone.moxkiriya.dialog;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.ResourceBundle;
+
+import com.wiki.standalone.moxkiriya.SettingManager;
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.TextField;
+import javafx.stage.DirectoryChooser;
+import javafx.stage.Window;
+
+/**
+ * ConfigSettingダイアログコントローラ
+ */
+public class ConfigSettingsDialogController extends DialogControllerBase {
+ @FXML private TextField textFieldPartyName;
+ @FXML private CheckBox checkBoxDefaultParty;
+ @FXML private TextField textFieldApproot;
+ @FXML private Button buttonChooseDirectory;
+ @FXML private CheckBox checkBoxClusterSetting;
+ @FXML private TextField textFieldDBServerURL;
+ @FXML private TextField textFieldPortNumber;
+ @FXML private TextField textFieldJDBCDriver;
+ @FXML private Button buttonOK;
+
+ /** parent window */
+ private Window parentWindow_;
+
+ /** party name specified parent window. */
+ private String partyName_;
+
+ /** setting map */
+ private Hashtable<String, String> settingsTable_;
+
+ /**
+ * 親Windowを設定する。
+ * @param window
+ */
+ public void setWindow(Window window) {
+ parentWindow_ = window;
+ }
+
+ /**
+ * Party name setter.
+ * @param partyName
+ */
+ public void setPartyName(String partyName) {
+ partyName_ = partyName;
+
+ if( (partyName_ != null)
+ && (partyName_.isEmpty() != true)) {
+ SettingManager settingMgr = SettingManager.getInstance();
+ String path = settingMgr.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+ try {
+ settingsTable_ = settingMgr.loadConfigSettings(path, partyName_);
+ textFieldPartyName.setText(partyName_);
+ if( (partyName_ != null)
+ && (partyName_.isEmpty() != true)) {
+ textFieldPartyName.setEditable(false);
+ textFieldPartyName.setDisable(true);
+ }
+ Hashtable<String, Boolean> partyTable = settingMgr.getPartyTable();
+ if(partyTable.get(partyName_) == true) {
+ checkBoxDefaultParty.setSelected(true);
+ }
+
+ String text = settingsTable_.get(SettingManager.SETINGKEY_MOXKIRIYAROOT);
+
+ textFieldApproot.setText(text == null ? "" : text);
+ String clusterSetting = settingsTable_.get(SettingManager.SETINGKEY_CLUSTER);
+ if( (clusterSetting != null)
+ && (clusterSetting.equals("true"))) {
+ checkBoxClusterSetting.setSelected(true);
+
+ text = settingsTable_.get(SettingManager.SETINGKEY_DBSERVER_URL);
+ textFieldDBServerURL.setText(text == null ? "" : text);
+
+ text = settingsTable_.get(SettingManager.SETINGKEY_DBSERVER_PORT);
+ textFieldPortNumber.setText(text == null ? "" : text);
+
+ text = settingsTable_.get(SettingManager.SETINGKEY_JDBC_DRIVER);
+ textFieldJDBCDriver.setText(text == null ? "" : text);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void initialize(URL url, ResourceBundle resource) {
+ super.initialize(url, resource);
+ buttonOK.setDisable(true);
+
+ ChangeListener<String> textFieldchangeListener = new ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String> arg0, String oldValue, String newValue) {
+ buttonOK.setDisable(canEnableOKButton());
+ }
+ };
+ textFieldPartyName.textProperty().addListener(textFieldchangeListener);
+ textFieldApproot.textProperty().addListener(textFieldchangeListener);
+ textFieldDBServerURL.textProperty().addListener(textFieldchangeListener);
+ textFieldPortNumber.textProperty().addListener(textFieldchangeListener);
+ textFieldJDBCDriver.textProperty().addListener(textFieldchangeListener);
+
+ checkBoxClusterSetting.selectedProperty().addListener(new ChangeListener<Boolean>() {
+ @Override
+ public void changed(ObservableValue<? extends Boolean> value, Boolean oldValue, Boolean newValue) {
+ if(newValue == true) {
+ textFieldDBServerURL.setDisable(false);
+ textFieldPortNumber.setDisable(false);
+ textFieldJDBCDriver.setDisable(false);
+ }
+ else {
+ textFieldDBServerURL.setDisable(true);
+ textFieldPortNumber.setDisable(true);
+ textFieldJDBCDriver.setDisable(true);
+ }
+ buttonOK.setDisable(canEnableOKButton());
+ }
+ });
+
+ }
+
+ @FXML
+ void onActionButtonChooseDirectory(ActionEvent event) {
+ DirectoryChooser directoryChooser = new DirectoryChooser();
+ String home = SettingManager.getInstance().get(SettingManager.SETTINGSKEY_USER_HOME);
+
+ directoryChooser.setInitialDirectory(new File(home));
+ File choicedDirectory = directoryChooser.showDialog(parentWindow_);
+
+ if ((choicedDirectory.exists() == true)
+ && (choicedDirectory.isDirectory() == true)) {
+ textFieldApproot.setText(choicedDirectory.getPath());
+ buttonOK.setDisable(false);
+ }
+ }
+
+ @FXML
+ void onActionButtonOK(ActionEvent event) {
+ try {
+ if(partyName_ == null) {
+ SettingManager settingMgr = SettingManager.getInstance();
+ String selectedParty = textFieldPartyName.getText();
+ String moxkiriyaRoot = textFieldApproot.getText();
+
+ settingMgr.putParty(selectedParty, checkBoxDefaultParty.isSelected());
+ settingMgr.setSelectedParty(selectedParty);
+
+ settingMgr.put(SettingManager.SETINGKEY_MOXKIRIYAROOT, moxkiriyaRoot);
+ settingMgr.put(SettingManager.SETTINGSKEY_WIKIROOT,
+ moxkiriyaRoot
+ + "/"
+ + WikiEngine.WIKIROOT_DIRECTORY);
+
+ File wikiroot = new File(settingMgr.get(SettingManager.SETTINGSKEY_WIKIROOT));
+ if(wikiroot.exists() != true) {
+ wikiroot.mkdirs();
+ }
+ if(checkBoxClusterSetting.selectedProperty().get() == true) {
+ settingMgr.put(SettingManager.SETINGKEY_CLUSTER, "true");
+ settingMgr.put(SettingManager.SETINGKEY_DBSERVER_URL, textFieldDBServerURL.getText());
+ settingMgr.put(SettingManager.SETINGKEY_DBSERVER_PORT, textFieldPortNumber.getText());
+ settingMgr.put(SettingManager.SETINGKEY_JDBC_DRIVER, textFieldJDBCDriver.getText());
+ }
+ else {
+ settingMgr.put(SettingManager.SETINGKEY_CLUSTER, "false");
+ settingMgr.put(SettingManager.SETINGKEY_DBSERVER_URL, "");
+ settingMgr.put(SettingManager.SETINGKEY_DBSERVER_PORT, "");
+ settingMgr.put(SettingManager.SETINGKEY_JDBC_DRIVER, "");
+ }
+ settingMgr.save();
+ settingMgr.putParty(selectedParty, true);
+ }
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Judge whether OK button can enable or not.
+ * @return
+ */
+ private boolean canEnableOKButton() {
+ boolean isDisable = textFieldPartyName.getText().isEmpty();
+
+ if(isDisable == false) {
+ String text = textFieldApproot.getText();
+ isDisable = (text == null) || (text.isEmpty() == true);
+ }
+
+ if(checkBoxClusterSetting.selectedProperty().getValue() == true) {
+ if(isDisable == false) {
+ String text = textFieldDBServerURL.getText();
+ isDisable = (text == null) || (text.isEmpty() == true);
+ }
+
+ if(isDisable == false) {
+ String text = textFieldPortNumber.getText();
+ isDisable = (text == null) || (text.isEmpty() == true);
+ }
+
+ if(isDisable == false) {
+ String text = textFieldJDBCDriver.getText();
+ isDisable = (text == null) || (text.isEmpty() == true);
+ }
+ }
+
+ return isDisable;
+ }
+
+ /**
+ * Settings table getter.
+ * @return Hashtable<String, String>
+ */
+ public Hashtable<String, String> getSettingsTable() {
+ Hashtable<String, String> settingsTable = new Hashtable<String, String>();
+ String moxkiriyaRoot = textFieldApproot.getText();
+
+ settingsTable.put(SettingManager.SETINGKEY_MOXKIRIYAROOT, moxkiriyaRoot);
+ settingsTable.put(SettingManager.SETTINGSKEY_WIKIROOT,
+ moxkiriyaRoot
+ + "/"
+ + WikiEngine.WIKIROOT_DIRECTORY);
+
+ if(checkBoxClusterSetting.selectedProperty().get() == true) {
+ settingsTable.put(SettingManager.SETINGKEY_CLUSTER, "true");
+ settingsTable.put(SettingManager.SETINGKEY_DBSERVER_URL, textFieldDBServerURL.getText());
+ settingsTable.put(SettingManager.SETINGKEY_DBSERVER_PORT, textFieldPortNumber.getText());
+ settingsTable.put(SettingManager.SETINGKEY_JDBC_DRIVER, textFieldJDBCDriver.getText());
+ }
+ else {
+ settingsTable.put(SettingManager.SETINGKEY_CLUSTER, "false");
+ settingsTable.put(SettingManager.SETINGKEY_DBSERVER_URL, "");
+ settingsTable.put(SettingManager.SETINGKEY_DBSERVER_PORT, "");
+ settingsTable.put(SettingManager.SETINGKEY_JDBC_DRIVER, "");
+ }
+
+ return settingsTable;
+ }
+
+ /**
+ * Default party checkbox value getter.
+ * @return boolean
+ */
+ public boolean getDefaultPartyCheckValue() {
+ return checkBoxDefaultParty.isSelected();
+ }
+
+ /**
+ * Party name getter.
+ * @return String
+ */
+ public String getPartyName() {
+ return textFieldPartyName.getText();
+ }
+}
--- /dev/null
+/**
+ * ダイアログ基本クラス
+ * @author Ryuhei Terada
+ */
+
+package com.wiki.standalone.moxkiriya.dialog;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+
+/**
+ * DialogBase
+ *
+ */
+public abstract class DialogBase {
+ /**
+ * リソースバンドル
+ */
+ protected ResourceBundle resource_;
+
+ /**
+ * FXMLローダー
+ */
+ protected FXMLLoader loader_;
+
+ /**
+ * 親Windowのstage
+ */
+ protected Stage parentStage_;
+
+ /**
+ * My stage.
+ */
+ protected Stage stage_;
+ /**
+ * シーン
+ */
+ Scene scene_;
+
+ /**
+ * Dialogコントローラ
+ */
+ DialogController controller_;
+
+ /**
+ * Dialogの終了種別列挙定数
+ */
+ public enum CloseType {
+ OK,
+ Cancel
+ };
+
+ /**
+ * ダイアログを表示する
+ * @param stage
+ * @param resouces
+ * @throws Exception
+ */
+ public CloseType showDialog(Stage stage, ResourceBundle resource) throws Exception {
+ parentStage_ = stage;
+ resource_ = resource;
+ loader_ = FXMLLoad();
+ scene_ = new Scene((Parent)loader_.getRoot());
+ controller_ = getController();
+ scene_.getStylesheets().add(getClass().getResource("dialog.css").toExternalForm());
+
+ return show();
+ }
+
+ /**
+ * FXMLをロードする。
+ * return FXMLLoader
+ * @throws IOException
+ */
+ protected FXMLLoader FXMLLoad() throws IOException {
+ FXMLLoader loader = new FXMLLoader(getClass().getResource(getFXML()), resource_);
+ loader.load();
+
+ return loader;
+ }
+
+ /**
+ * Dialogのクローズ種別を取得する。
+ * @return CloseType
+ */
+ protected CloseType getCloseType() {
+ return CloseType.OK;
+ }
+
+ /**
+ * FXMLファイル名を取得する。
+ * @return String FXMLファイル名
+ */
+ protected abstract String getFXML();
+
+ /**
+ * コントローラを取得する。
+ * @return Initializable
+ * @throws Exception
+ */
+ protected abstract DialogController getController() throws Exception;
+
+ /**
+ * ダイアログをj表示する。
+ * @return CloseTypeダイアログの終了種別
+ */
+ protected CloseType show() {
+ stage_ = new Stage();
+
+ stage_.initOwner(parentStage_);
+ stage_.initModality(Modality.APPLICATION_MODAL);
+ stage_.setScene(scene_);
+ stage_.setResizable(false);
+ stage_.showAndWait();
+
+ return getCloseType();
+ }
+}
--- /dev/null
+/**
+ * DialogController
+ * @author Ryuhei Terada
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+import javafx.fxml.Initializable;
+
+/**
+ * DialogController
+ */
+public interface DialogController extends Initializable {
+ /**
+ * 終了種別を取得する。
+ * @param closeType
+ */
+ public DialogBase.CloseType getCloseType();
+}
--- /dev/null
+/**
+ * DialogControllerベースクラス
+ * @author Ryuhei Terada
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+
+/**
+ * DialogControllerBase
+ */
+public abstract class DialogControllerBase implements DialogController {
+ /** URL */
+ URL url_;
+
+ /** Resource Bundle */
+ protected ResourceBundle resource_;
+
+ @Override
+ public void initialize(URL url, ResourceBundle resource) {
+ url_ = url;
+ resource_ = resource;
+ }
+
+ /**
+ * 終了種別を取得する。
+ * @param closeType
+ */
+ public DialogBase.CloseType getCloseType() {
+ return DialogBase.CloseType.OK;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
+ <children>
+ <Label prefHeight="30.0" prefWidth="600.0" text="Label" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+ <TreeView prefHeight="370.0" prefWidth="500.0" AnchorPane.bottomAnchor="40.0" AnchorPane.leftAnchor="100.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
+ </children>
+</AnchorPane>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?scenebuilder-preview-i18n-resource ../resources/moxkiriya.properties?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.wiki.standalone.moxkiriya.dialog.SelectPartyDialogController">
+ <children>
+ <Label maxHeight="-Infinity" prefHeight="30.0" text="%key.Config.Select.Party.Dialog.Message" AnchorPane.leftAnchor="40.0" AnchorPane.topAnchor="35.0" />
+ <TableView fx:id="tableViewPartyList" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="270.0" prefWidth="520.0" AnchorPane.bottomAnchor="65.0" AnchorPane.leftAnchor="40.0" AnchorPane.rightAnchor="40.0" AnchorPane.topAnchor="65.0">
+ <columns>
+ <TableColumn id="selectPartyRadioButtonTableCell" prefWidth="80.0" resizable="false" sortable="false" text="%key.Config.Select.Party.Select" fx:id="tableColumnSelect" />
+ <TableColumn maxWidth="520.0" minWidth="439.0" prefWidth="520.0" resizable="false" text="%key.Config.Select.Party.name" fx:id="tableColumnPartyName" />
+ </columns>
+ </TableView>
+ <Button fx:id="buttonOK" mnemonicParsing="false" onAction="#onActionButtonOK" prefHeight="30.0" prefWidth="100.0" text="%key.Button.OK" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="40.0" />
+ <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#onActionButtonCancel" prefHeight="30.0" prefWidth="100.0" text="%key.Button.Cancel" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="150.0" />
+ <Button fx:id="buttonAddNewParty" mnemonicParsing="false" onAction="#onActionButtonAddNewParty" prefHeight="30.0" prefWidth="120.0" text="%key.Button.Add.Party" AnchorPane.bottomAnchor="15.0" AnchorPane.leftAnchor="40.0" />
+ </children>
+</AnchorPane>
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Select party dialog.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.dialog;
+
+/**
+ * SelectPartyDialog
+ */
+public class SelectPartyDialog extends DialogBase {
+
+ /**
+ * Constructor.
+ */
+ public SelectPartyDialog() {
+ }
+
+ @Override
+ protected String getFXML() {
+ return "SelectPartyDialog.fxml";
+ }
+
+ @Override
+ protected DialogController getController() {
+ SelectPartyDialogController controller = loader_.getController();
+
+ controller.setStage(parentStage_);
+
+ return controller;
+ }
+
+ @Override
+ protected CloseType getCloseType() {
+ return controller_.getCloseType();
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Select party dialog controller.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */package com.wiki.standalone.moxkiriya.dialog;
+
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import com.wiki.standalone.moxkiriya.SettingManager;
+
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.control.RadioButton;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.ToggleGroup;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.stage.Stage;
+import javafx.util.Callback;
+
+/**
+ * SelectPartyダイアログコントローラ
+ */
+public class SelectPartyDialogController extends DialogControllerBase {
+ /**
+ * Party property.
+ */
+ public class PartyProperty {
+ /** Select status. */
+ private SimpleBooleanProperty select_;
+
+ /** Party name. */
+ private SimpleStringProperty partyName_;
+
+ /**
+ * Constructor.
+ * @param aSelect
+ * @param aPartyName
+ */
+ public PartyProperty(boolean aSelect, String aPartyName) {
+ select_ = new SimpleBooleanProperty(aSelect);
+ partyName_ = new SimpleStringProperty(aPartyName);
+ }
+
+ /**
+ * Select property getter.
+ * @return BooleanProperty
+ */
+ public BooleanProperty selectProperty() {
+ return select_;
+ }
+
+ /**
+ * Party name getter.
+ * @return StringProperty
+ */
+ public StringProperty partyNameProperty() {
+ return partyName_;
+ }
+ }
+
+ @FXML private TableView<PartyProperty> tableViewPartyList;
+ @FXML private TableColumn<PartyProperty, Boolean> tableColumnSelect;
+ @FXML private TableColumn<PartyProperty, String> tableColumnPartyName;
+ @FXML private Button buttonCancel;
+ @FXML private Button buttonOK;
+ @FXML private Button buttonAddNewParty;
+
+ /** Selected party name. */
+ private String selectedParty_;
+
+ /** ToggleGroup for select RadioButton. */
+ private ToggleGroup toggleGroupSelect_;
+
+ /** Close type. */
+ private DialogBase.CloseType closeType_;
+
+ /** My stage */
+ private Stage stage_;
+
+ @Override
+ public void initialize(URL url, ResourceBundle resource) {
+ super.initialize(url, resource);
+
+ buttonOK.setDisable(true);
+
+ toggleGroupSelect_ = new ToggleGroup();
+
+ setCellFactory(tableColumnSelect, toggleGroupSelect_, new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent event) {
+ RadioButton target = (RadioButton)event.getTarget();
+ PartyProperty partyProperty = (PartyProperty)target.getUserData();
+
+ if(target.isSelected() == true) {
+ buttonOK.setDisable(false);
+
+ selectedParty_ = partyProperty.partyNameProperty().getValue();
+ }
+ }
+ });
+
+ setCellFactory(tableColumnPartyName, new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent event) {
+ Hyperlink target = (Hyperlink)event.getTarget();
+ PartyProperty partyProperty = (PartyProperty)target.getUserData();
+ String partyName = partyProperty.partyName_.get();
+
+ try {
+ if(showConfigSettingsDialog(stage_, partyName) == DialogBase.CloseType.OK) {
+ SettingManager settingMgr = SettingManager.getInstance();
+ String path = settingMgr.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+ settingMgr.loadSettingFiles(path);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ buildTableViewPartyList();
+
+ SettingManager settingMgr = SettingManager.getInstance();
+ String defaultParty = settingMgr.getSelectedParty();
+
+ if(defaultParty != null) {
+ buttonCancel.setDisable(false);
+ }
+ }
+
+ /**
+ * Stage setter.
+ * @param stage
+ */
+ public void setStage(Stage stage) {
+ stage_ = stage;
+ }
+
+ /**
+ * 終了種別を取得する。
+ * @param closeType
+ */
+ public DialogBase.CloseType getCloseType() {
+ return closeType_;
+ }
+
+ @FXML
+ public void onActionButtonCancel(ActionEvent event) {
+ closeType_ = DialogBase.CloseType.Cancel;
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+
+ @FXML
+ public void onActionButtonOK(ActionEvent event) {
+ try {
+ SettingManager settingMgr = SettingManager.getInstance();
+ settingMgr.setSelectedParty(selectedParty_);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ closeType_ = DialogBase.CloseType.OK;
+ ((Node)event.getSource()).getScene().getWindow().hide();
+ }
+
+ @FXML
+ public void onActionButtonAddNewParty(ActionEvent event) {
+ try {
+ showConfigSettingsDialog(stage_, null);
+
+ SettingManager settingMgr = SettingManager.getInstance();
+ Hashtable<String, Boolean> partyTable = settingMgr.getPartyTable();
+ Set<String> keys = partyTable.keySet();
+ ObservableList<PartyProperty> observableList = FXCollections.observableArrayList();
+
+ for(String key: keys) {
+ boolean isDefault = partyTable.get(key);
+ PartyProperty partyProperty = new PartyProperty(isDefault, key);
+ observableList.add(partyProperty);
+ }
+ tableViewPartyList.getItems().clear();
+ tableViewPartyList.setItems(observableList);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Cell factory setter.
+ * @param tableColumn
+ * @param toggleGroup
+ */
+ private void setCellFactory(TableColumn<PartyProperty, Boolean> tableColumn, final ToggleGroup toggleGroup, final EventHandler<ActionEvent> eventHandler) {
+ tableColumn.setCellFactory(new Callback<TableColumn<PartyProperty, Boolean>, TableCell<PartyProperty, Boolean>>() {
+ @Override
+ public TableCell<PartyProperty, Boolean> call(TableColumn<PartyProperty, Boolean> param) {
+ TableCell<PartyProperty, Boolean> tableCell = new TableCell<PartyProperty, Boolean>() {
+ @Override
+ public void updateItem(Boolean select, boolean empty) {
+ super.updateItem(select, empty);
+ if(empty != true) {
+ RadioButton radioButton = new RadioButton();
+
+ radioButton.setOnAction(eventHandler);
+ radioButton.setToggleGroup(toggleGroup);
+ setGraphic(radioButton);
+
+ int index = getIndex();
+ ObservableList<PartyProperty> items = getTableView().getItems();
+ radioButton.setUserData(items.get(index));
+ }
+ }
+ };
+ tableCell.setId("selectPartyRadioButtonTableCell");
+
+ return tableCell;
+ }
+ });
+ }
+
+ /**
+ * Cell factory setter.
+ * @param tableColumn
+ */
+ private void setCellFactory(TableColumn<PartyProperty, String> tableColumn, final EventHandler<ActionEvent> eventHandler) {
+ tableColumn.setCellFactory(new Callback<TableColumn<PartyProperty, String>, TableCell<PartyProperty, String>>() {
+ @Override
+ public TableCell<PartyProperty, String> call(TableColumn<PartyProperty, String> param) {
+ TableCell<PartyProperty, String> tableCell = new TableCell<PartyProperty, String>() {
+ @Override
+ public void updateItem(String partyName, boolean empty) {
+ super.updateItem(partyName, empty);
+ if(empty != true) {
+ Hyperlink hyperlink = new Hyperlink(partyName);
+
+ hyperlink.setOnAction(eventHandler);
+ setGraphic(hyperlink);
+
+ int index = getIndex();
+ ObservableList<PartyProperty> items = getTableView().getItems();
+ hyperlink.setUserData(items.get(index));
+ }
+ }
+ };
+
+ return tableCell;
+ }
+ });
+ }
+
+ /**
+ * Build party list TableView
+ */
+ private void buildTableViewPartyList() {
+ tableColumnSelect.setCellValueFactory(new PropertyValueFactory<PartyProperty, Boolean>("select"));
+ tableColumnPartyName.setCellValueFactory(new PropertyValueFactory<PartyProperty, String>("partyName"));
+
+ SettingManager settingMgr = SettingManager.getInstance();
+ Hashtable<String, Boolean> partyTable = settingMgr.getPartyTable();
+ Set<String> keys = partyTable.keySet();
+ ObservableList<PartyProperty> observableList = FXCollections.observableArrayList();
+
+ for(String key: keys) {
+ boolean isDefault = partyTable.get(key);
+ PartyProperty partyProperty = new PartyProperty(isDefault, key);
+ observableList.add(partyProperty);
+ }
+ tableViewPartyList.setItems(observableList);
+ }
+
+ /**
+ * WikiConfigSettingDialogを表示する。
+ * @param primaryStage
+ * @param selectedParty
+ * @return DialogBase.CloseType
+ * @throws Exception
+ */
+ private DialogBase.CloseType showConfigSettingsDialog(Stage stage, String partyName) throws Exception {
+ SettingManager settingMgr_ = SettingManager.getInstance();
+
+ ConfigSettingsDialog dialog = new ConfigSettingsDialog(partyName);
+
+ DialogBase.CloseType closeType = dialog.showDialog(stage, resource_);
+ if(closeType == DialogBase.CloseType.OK) {
+
+ Hashtable<String, String> settingsTable = dialog.getSettingsTable();
+ String path = settingMgr_.get(SettingManager.SETTINGSKEY_MOXKIRIYA_USER_DIR);
+
+ partyName = dialog.getPartyName();
+ settingMgr_.putParty(partyName, dialog.getDefaultPartyCheckValue());
+ settingMgr_.savePartyConfig(path);
+ settingMgr_.saveSettingConfig(path, partyName, settingsTable);
+ }
+
+ return closeType;
+ }
+}
--- /dev/null
+/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
+#selectPartyRadioButtonTableCell {
+ -fx-pref-width: 80;
+ -fx-alignment: center;
+}
\ No newline at end of file
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+
+public interface WikiBlockParser {
+ /** parse状態 */
+ public enum Status {
+ INIT,
+ OPEN,
+ NESTING,
+ CLOSE
+ };
+
+ /**
+ * Block要素開始処理。
+ * @param buf バッファ
+ * @return 処理後の文字列
+ */
+ public String startElementProcess(String line, StringBuffer buf);
+
+ /**
+ * WikiのSyntaxを解析し、HTML形式の文字列に変換する。
+ * @param line readerから読み込んだ最初の行
+ * @param buf バッファ
+ * @return 処理後の文字列
+ */
+ public String parse(String line, StringBuffer buf) throws Exception;
+
+ /**
+ * Block要素終了処理。
+ * @param buf
+ * @return 処理後の文字列
+ */
+ public String endElementProcess(String line, StringBuffer buf);
+
+ /**
+ * ネスト要素のcloseをヘルプする。
+ * 先祖の要素に<code>があった場合、ネスト要素を<要素>にするため。
+ * @param tagPart
+ * @return 処理したクローズタグ文字列
+ */
+ public String daughterElementCloseHelper(String tagPart);
+
+ /**
+ * 要素Block終了判定
+ * @return 終了判定結果
+ */
+ public boolean isBlockEnd();
+
+ /**
+ * 処理中の1行のうち処理した文字数を取得する。
+ * @return 処理した文字数
+ */
+ public int getCount();
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Base class of Blocklevel element parser, processor.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+import com.wiki.standalone.moxkiriya.parser.inlineparser.WikiInlineParser;
+import com.wiki.standalone.moxkiriya.parser.inlineparser.WikiInlineParserCreator;
+
+public abstract class WikiBlockParserBase implements WikiBlockParser {
+ /** Wiki engine */
+ WikiEngine wikiEngine_;
+
+ /** ブロック終了状態 */
+ protected boolean isBlockEnd_ = false;
+
+ /** 処理終了後の残り文字列 */
+ protected String remain_ = "";
+
+ /** 処理した文字数 */
+ protected int count_ = 0;
+
+ /** parse状態 */
+ protected Status status_;
+
+ /** インスタンス生成時のparse状態 */
+ protected Status initialStatus_;
+
+ /** ネスト元要素parser */
+ protected WikiBlockParser motherParser_;
+
+ /** ネスト要素parser */
+ protected WikiBlockParser daughterParser_;
+
+ /**
+ * Constructor.
+ * @param wikiRepository
+ */
+ public WikiBlockParserBase(WikiEngine wikiEngine) {
+ isBlockEnd_ = false;
+ wikiEngine_ = wikiEngine;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ buf.append(inlineParse(line));
+ return "";
+ }
+
+ @Override
+ public String daughterElementCloseHelper(String tagPart) {
+ return tagPart;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+
+ /**
+ * インライン要素を解析する。
+ * @param line
+ * @return インライン要素の解析結果
+ */
+ public String inlineParse(String line) {
+ return inlineParse(line, new WikiInlineParserCreator(wikiEngine_));
+ }
+
+ /**
+ * インライン要素を解析する。
+ * @param line
+ * @param creatorList
+ * @return インライン要素の解析結果
+ */
+ public String inlineParse(String line, WikiInlineParserCreator creator) {
+ StringBuffer buf = new StringBuffer();
+ String inlineHtml = line;
+
+ WikiInlineParserCreator inlineParserCreator = creator;
+ WikiInlineParser inlineParser = inlineParserCreator.create(line);
+
+ inlineHtml = inlineParser.parse(line);
+ buf.append(inlineHtml);
+
+ return buf.toString();
+ }
+
+ @Override
+ public int getCount() {
+ return count_;
+ }
+
+ /**
+ * ネストparser開始処理
+ * @param creator
+ * @param line
+ */
+ protected void startDaughterParse(WikiBlockParserCreator creator, String line) {
+ if(status_ == Status.INIT) {
+ /*
+ * インスタンス生成後初parse&初matchの場合
+ */
+ isBlockEnd_ = false;
+ status_ = Status.OPEN;
+ }
+ else {
+ status_ = Status.NESTING;
+ daughterParser_ = creator.create(line);
+ }
+ }
+
+ /**
+ * ネストparser開始処理
+ * @param creator
+ */
+ protected void startDaughterParse(WikiBlockParserCreator.Creator creator) {
+ if(status_ == Status.INIT) {
+ /*
+ * インスタンス生成後初parse&初matchの場合
+ */
+ isBlockEnd_ = false;
+ status_ = Status.OPEN;
+ }
+ else {
+ status_ = Status.NESTING;
+ daughterParser_ = creator.create(wikiEngine_);
+ }
+ }
+
+ /**
+ * lineの行頭からのtokenの数をカウントする。
+ * @param line
+ * @parma token
+ * @return 行頭からのtokenの数
+ */
+ public int countToken(String line, char token) {
+ int count = 0;
+ for(count = 0; count < line.length(); count++) {
+ if(token != line.charAt(count)) {
+ break;
+ }
+ }
+
+ return count;
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Blocklevel element parser, processor creator.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * WikiBlockParserインスタンスを生成する。
+ *
+ */
+public class WikiBlockParserCreator {
+ /** TOC構築クラス */
+ private WikiTOCBuilder wikiTOCBuilder_;
+
+ /** Wiki engine */
+ private WikiEngine wikiEngine_;
+
+ interface Creator {
+ public WikiBlockParser create(WikiEngine wikiEngine);
+ };
+
+ /** WikiBlockParser Creator Table*/
+ private LinkedHashMap<String, Creator> creatorMap
+ = new LinkedHashMap<String, Creator>() {
+
+ private static final long serialVersionUID = 1L;
+
+ {
+ put(WikiHnBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiHnBlockParser(wikiEngine, wikiTOCBuilder_);
+ }
+ } );
+ put(WikiHrBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiHrBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiTableBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiTableBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiUnorderedListBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiUnorderedListBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiOrderedListBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiOrderedListBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiBlockquoteBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiBlockquoteBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiPreBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiPreBlockParser(wikiEngine);
+ }
+ } );
+ put(WikiCodeBlockParser.NOTATION_REGEX, new Creator() {
+ @Override
+ public WikiBlockParser create(WikiEngine wikiEngine) {
+ return new WikiCodeBlockParser(wikiEngine);
+ }
+ } );
+ }
+ };
+
+ /**
+ * Constructor
+ * @param wikiRepository
+ */
+ public WikiBlockParserCreator(WikiEngine wikiEngine) {
+ wikiTOCBuilder_ = new WikiTOCBuilder();
+ wikiEngine_ = wikiEngine;
+ }
+
+ /**
+ * lineのSyntaxにマッチするWikiBlockParserのインスタンスを生成する。
+ * @param line
+ * @return WikiBlockParser
+ */
+ public WikiBlockParser create(String line) {
+ WikiBlockParser parser = null;
+ Set<String> keySet = creatorMap.keySet();
+
+ for(String key: keySet) {
+ if(line.toLowerCase().matches(key) == true) {
+ parser = creatorMap.get(key).create(wikiEngine_);
+ break;
+ }
+ }
+
+ if (parser == null) {
+ parser = new WikiDefaultBlockParser(wikiEngine_);
+ }
+
+ return parser;
+ }
+
+ /**
+ * TOC(目次)ノードを取得する
+ * @param firstLine
+ * @return
+ */
+ public String getTOC(String firstLine) {
+ return wikiTOCBuilder_.buildTOC(firstLine);
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Unordered list block parser.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * 番号なしリストのマークアップを解析し、HTML形式に変換する。
+ *
+ */
+public class WikiBlockquoteBlockParser extends WikiBlockParserBase {
+ private static final String START_TAG = "<blockquote";
+
+ private static final String END_TAG = "</blockquote>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^>";
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD
+ + "..*"
+ + NOTATION_REGEX_LINETAIL;
+
+ /** ブロック終了状態 */
+ private boolean isBlockEnd_ = false;
+
+ /** 処理終了後の残り文字列 */
+ private String remain_;
+
+ /**
+ * コンストラクタ
+ */
+ public WikiBlockquoteBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, Status.INIT);
+ }
+
+ /**
+ * コンストラクタ
+ */
+ public WikiBlockquoteBlockParser(WikiEngine wikiEngine, Status status) {
+ super(wikiEngine);
+ status_ = status;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ status_ = Status.OPEN;
+ buf.append(START_TAG + " class=\"quotation\">");
+ return line;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ if(line.matches(NOTATION_REGEX) == true) {
+ String token = line.substring(line.indexOf(">"));
+ int countToken = countToken(token, '>');
+ if(countToken > 1) {
+ /*
+ * '>'を一つ減らして子parserへ渡す。
+ */
+ String daughterPart = token.substring(1);
+
+ if(status_ == Status.OPEN) {
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiBlockquoteBlockParser create(WikiEngine wikiEngine) {
+ return new WikiBlockquoteBlockParser(wikiEngine, Status.OPEN);
+ }
+ });
+
+ daughterParser_.startElementProcess(daughterPart, buf);
+ }
+ daughterParser_.parse(daughterPart, buf);
+ }
+ else {
+ if(status_ == Status.NESTING) {
+ /*
+ * トークンが1つでネスト処理中の場合、
+ * ネスト処理を終了する。
+ */
+ daughterParser_.endElementProcess(line, buf);
+ daughterParser_ = null;
+ status_ = Status.OPEN;
+ }
+ buf.append("<div>");
+ super.parse(token.substring(countToken), buf);
+ buf.append("</div>\n");
+ remain_ = "";
+ }
+ }
+ else {
+ isBlockEnd_ = true;
+ remain_ = line;
+ }
+
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.endElementProcess(line, buf);
+ }
+ buf.append(END_TAG + "\n");
+ return remain_;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import java.io.BufferedReader;
+import java.util.ArrayList;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiBodyBlockParser {
+ /** body要素開始タグ 文字列 */
+ private final String START_TAG = "<body>";
+
+ /** body要素終了タグ 文字列 */
+ private final String END_TAG = "</body>";
+
+ /** Page titleのparse結果 */
+ private String titleHtml_;
+
+ /** BlockParserクリエイター */
+ WikiBlockParserCreator blockParserCreator_;
+
+ /** Pageの先頭行 */
+ private String firstLine_ = null;
+
+ /**
+ * Wikiマークアップで許可するHTML要素のリスト
+ */
+ private static final ArrayList<String> acceptElementList_ = new ArrayList<String>() {
+ private static final long serialVersionUID = 1L;
+ { add(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD); }
+ { add(WikiCodeBlockParser.NOTATION_REGEX_LINETAIL);}
+ { add(WikiPreBlockParser.NOTATION_REGEX_LINEHEAD); }
+ { add(WikiPreBlockParser.NOTATION_REGEX_LINETAIL);}
+ };
+
+ /** プリプロセッサ状態enum */
+ enum PreprocessStatus {
+ INIT,
+ OPEN,
+ CLOSE;
+ };
+
+ /** parse状態enum */
+ enum ParseStatus {
+ INIT,
+ OPEN,
+ CLOSE;
+ };
+
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ */
+ public WikiBodyBlockParser(WikiEngine wikiEngine) {
+ blockParserCreator_ = new WikiBlockParserCreator(wikiEngine);
+ }
+
+ /**
+ * Pageタイトルparse処理
+ * @param title
+ */
+ public void parsePageTitle(String title) {
+ titleHtml_ = "<h1>" + title + "</h1>\n";
+ }
+
+ public String parse(BufferedReader reader) throws Exception {
+ StringBuffer buf = new StringBuffer();
+
+ startElementProcess(buf);
+ buf.append(titleHtml_);
+
+ String bodyBlock = parseCore(reader);
+
+ buf.append(blockParserCreator_.getTOC(firstLine_));
+ buf.append(bodyBlock);
+ endElementProcess(buf);
+
+ return buf.toString();
+ }
+
+ /**
+ * Wikiマークアップで許可するHTML要素以外を無効化する
+ * @param line
+ * @return
+ */
+ private String parsePreprocess(String line) {
+ StringBuffer buf = new StringBuffer("");
+ StringBuffer tagBuf = null;
+ char[] lineCharArray = line.toCharArray();
+
+ PreprocessStatus status = PreprocessStatus.INIT;
+ for(int count = 0; count < lineCharArray.length; count++) {
+ if(status == PreprocessStatus.INIT) {
+ if(lineCharArray[count] == '<') {
+ status = PreprocessStatus.OPEN;
+ tagBuf = new StringBuffer();
+ tagBuf.append(lineCharArray[count]);
+ }
+ else {
+ buf.append(lineCharArray[count]);
+ }
+ }
+ else if(status == PreprocessStatus.OPEN) {
+ tagBuf.append(lineCharArray[count]);
+ if(lineCharArray[count] == '>') {
+ String tag = tagBuf.toString();
+ for(String accept: acceptElementList_) {
+ if(tag.toLowerCase().matches(accept)) {
+ buf.append(tag);
+ tagBuf = null;
+ }
+ }
+
+ if(tagBuf != null) {
+ /*
+ * acceptリストにないタグパターンの場合
+ */
+ buf.append(tag.replaceAll("<", "<")
+ .replaceAll(">", ">"));
+ tagBuf = null;
+ }
+ status = PreprocessStatus.INIT;
+ }
+ }
+ else {
+ buf.append(lineCharArray[count]);
+ }
+ }
+
+ if(status == PreprocessStatus.OPEN) {
+ String tag = tagBuf.toString();
+ buf.append(tag.replaceAll("<", "<"));
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * parseコア処理
+ * @param reader
+ * @return htmlコンテンツ文字列
+ * @throws Exception
+ */
+ private String parseCore(BufferedReader reader) throws Exception {
+ StringBuffer buf = new StringBuffer("");
+ StringBuffer paragraphBuf = null;
+ String line = null;
+ ParseStatus status = ParseStatus.INIT;
+
+ WikiBlockParser parser = null;
+
+ while((line = reader.readLine()) != null) {
+ if(firstLine_ == null) {
+ firstLine_ = line;
+ if(firstLine_.equals("{{#TOC}}") == true) {
+ continue;
+ }
+ }
+
+ /*
+ * XSS殺し
+ */
+ String processingline = parsePreprocess(line);
+
+ do {
+ if(status != ParseStatus.OPEN) {
+ status = ParseStatus.OPEN;
+ paragraphBuf = new StringBuffer();
+ }
+
+ if(parser == null) {
+ parser = blockParserCreator_.create(processingline);
+ processingline = parser.startElementProcess(processingline, paragraphBuf);
+ }
+
+ processingline = parser.parse(processingline, paragraphBuf);
+
+ if(parser.isBlockEnd() == true) {
+ processingline = parser.endElementProcess(processingline, paragraphBuf);
+ parser = null;
+
+ if(line.isEmpty() == true) {
+ buf.append("<p>\n");
+ buf.append(paragraphBuf + "\n");
+ buf.append("</p>\n");
+
+ status = ParseStatus.CLOSE;
+ paragraphBuf = null;
+ }
+ }
+ } while(processingline.isEmpty() != true);
+ }
+
+ if(status == ParseStatus.OPEN) {
+ if(parser != null) {
+ parser.endElementProcess(line, paragraphBuf);
+ }
+ buf.append("<p>\n");
+ buf.append(paragraphBuf + "\n");
+ buf.append("</p>\n");
+ status = ParseStatus.CLOSE;
+ }
+
+ return buf.toString();
+ }
+
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG + "\n");
+ }
+
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG + "\n");
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ *
+ *
+ */
+public class WikiCodeBlockParser extends WikiBlockParserBase {
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ public static final String NOTATION_REGEX_LINEHEAD = "<code[ \t]*>" + (".*");
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ public static final String NOTATION_REGEX_LINETAIL = "<*/[ \t]*code>" + ".*";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = ".*" + NOTATION_REGEX_LINEHEAD
+ + ".*";
+
+ /**
+ * コンストラクタ
+ * @param file
+ */
+ public WikiCodeBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, null, Status.INIT);
+ }
+
+ /**
+ * ネスト要素処理用コンストラクタ
+ * @param motherParser ネスト元要素parser
+ * @param file
+ * @param status
+ */
+ public WikiCodeBlockParser(WikiEngine wikiEngine, WikiBlockParser motherParser, Status status) {
+ super(wikiEngine);
+ motherParser_ = motherParser;
+ status_ = status;
+ initialStatus_ = status;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ char[] charLine = line.toCharArray();
+ String previous = "";
+ String main = "";
+
+ for(count_ = 0; count_ < charLine.length; count_++) {
+ if(charLine[count_] == '<') {
+ String now = line.substring(count_);
+
+ if(now.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
+ previous = line.substring(0, line.indexOf(now));
+ main = now;
+ break;
+ }
+ }
+ }
+
+ if(previous.isEmpty() != true) {
+ buf.append(inlineParse(previous));
+ }
+
+ return main;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ char[] charLine = line.toCharArray();
+
+ for(count_ = 0; count_ < charLine.length; count_++) {
+ if(status_ == Status.NESTING) {
+ String nestpart = new String(line.substring(count_));
+ daughterParser_.parse(nestpart, buf);
+ count_ += daughterParser_.getCount();
+
+ if(daughterParser_.isBlockEnd() == true) {
+ daughterParser_.endElementProcess(null, buf);
+ status_ = Status.OPEN;
+ daughterParser_ = null;
+ }
+ continue;
+ }
+
+ if(charLine[count_] == '<') {
+ String now = line.substring(count_);
+ String nowLower = now.toLowerCase();
+ String tagpart = now.substring(0, now.indexOf(">") + ">".length());
+
+ if(nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
+ count_ += tagpart.length() - 1;
+
+ if(status_ != Status.INIT) {
+ tagpart = tagpart.replaceAll("<", "<").replaceAll(">", ">");
+ }
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiCodeBlockParser create(WikiEngine wikiEngine) {
+ return new WikiCodeBlockParser(wikiEngine, WikiCodeBlockParser.this, Status.OPEN);
+ }
+ });
+ buf.append(tagpart);
+ }
+ else if(nowLower.matches(NOTATION_REGEX_LINETAIL)) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.parse(now, buf);
+ count_ += daughterParser_.getCount() - 1;
+
+ if(daughterParser_.isBlockEnd() == true) {
+ status_ = Status.OPEN;
+ daughterParser_ = null;
+ }
+ }
+ else {
+ remain_ = now.substring(now.indexOf(">") + ">".length());
+ count_ += tagpart.length() - 1;
+
+ if(initialStatus_ == Status.OPEN) {
+ /*
+ * nest要素のparserとしてインスタンス生成された場合、
+ */
+ motherParser_.daughterElementCloseHelper(tagpart);
+ }
+ buf.append(tagpart);
+ isBlockEnd_ = true;
+ break;
+ }
+ }
+ else {
+ count_ += tagpart.length() - 1;
+ buf.append(tagpart.replaceAll("<", "<").replaceAll(">", ">"));
+ }
+ }
+ else if(status_ == Status.OPEN) {
+ buf.append(charLine[count_]);
+ }
+ }
+
+ if(initialStatus_ == Status.INIT) {
+ buf.append("\n");
+ }
+
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ return remain_;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+
+ @Override
+ public String daughterElementCloseHelper(String tagPart) {
+ return tagPart.replaceAll("<", "<").replaceAll(">", ">");
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ *
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * Default block parser.
+ *
+ */
+public class WikiDefaultBlockParser extends WikiBlockParserBase {
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ */
+ public WikiDefaultBlockParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ return line;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ buf.append("<div>");
+ buf.append(inlineParse(line));
+ buf.append("</div>\n");
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ return "";
+ }
+
+
+ @Override
+ public boolean isBlockEnd() {
+ return true;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiHnBlockParser extends WikiBlockParserBase {
+ private static final String START_TAG = "<div><h%d ";
+
+ private static final String END_TAG = "</h%d></div>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^==+";
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "==+$";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD
+ + "..*"
+ + NOTATION_REGEX_LINETAIL;
+
+ /** 最大ヘッダレベル */
+ public static final int HEADERLEVEL_MAX = 6;
+
+ /** ヘッダレベル */
+ private int headerLevel_;
+
+ /** TOC(目次)構築クラス */
+ private WikiTOCBuilder wikiTOCBuilder_;
+
+ /**
+ * コンストラクタ
+ */
+ public WikiHnBlockParser(WikiEngine wikiEngine, WikiTOCBuilder wikiTOCBuilder) {
+ super(wikiEngine);
+ wikiTOCBuilder_ = wikiTOCBuilder;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ int startCount = countToken(line, '=');
+ int lastCount = 0;
+ char[] lineCharArray = line.toCharArray();
+
+ for(lastCount = 0; lastCount < line.length(); lastCount++) {
+ if(lineCharArray[lineCharArray.length - lastCount - 1] != '=') {
+ break;
+ }
+ }
+
+ headerLevel_ = Math.min(Math.min(startCount, lastCount), HEADERLEVEL_MAX);
+
+ buf.append(String.format(START_TAG, headerLevel_));
+
+ StringBuffer replaceString = new StringBuffer();
+ for(int count = 0; count < headerLevel_; count++) {
+ replaceString.append("=");
+ }
+
+ String headline = line.replaceFirst("^" + replaceString, "")
+ .replaceFirst(replaceString + "$", "").trim();
+ buf.append("id=\"" + headline + "\">");
+ wikiTOCBuilder_.add(headline, headerLevel_);
+
+ return headline;
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ buf.append(String.format(END_TAG, headerLevel_));
+ return "";
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return true;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiHrBlockParser extends WikiBlockParserBase {
+ private static final String START_TAG = "<hr>";
+
+ private static final String END_TAG = "";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^----";
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "$";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD
+ + NOTATION_REGEX_LINETAIL;
+
+ /**
+ * コンストラクタ
+ */
+ public WikiHrBlockParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ buf.append(START_TAG);
+ return line.replaceFirst(NOTATION_REGEX_LINEHEAD, "");
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ buf.append(END_TAG);
+ return "";
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return true;
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Ordered list block parser.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * 番号付きリストのマークアップを解析し、HTML形式に変換する。
+ *
+ */
+public class WikiOrderedListBlockParser extends WikiBlockParserBase {
+ private static final String START_TAG = "<div><ol>\n";
+
+ private static final String END_TAG = "</ol></div>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^[ \t]*"
+ + "#+"
+ + " +[^#]";
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD
+ + "..*"
+ + NOTATION_REGEX_LINETAIL;
+
+ /** ブロック終了状態 */
+ private boolean isBlockEnd_ = false;
+
+ /** 処理終了後の残り文字列 */
+ private String remain_;
+
+ /**
+ * コンストラクタ
+ */
+ public WikiOrderedListBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, Status.INIT);
+ }
+
+ /**
+ * コンストラクタ
+ */
+ public WikiOrderedListBlockParser(WikiEngine wikiEngine, Status status) {
+ super(wikiEngine);
+ status_ = status;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ status_ = Status.OPEN;
+ buf.append(START_TAG);
+ return line;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ if(line.matches(NOTATION_REGEX) == true) {
+ String token = line.substring(line.indexOf("#"));
+ int countToken = countToken(token, '#');
+ if(countToken > 1) {
+ /*
+ * '#'を一つ減らして子parserへ渡す。
+ */
+ String daughterPart = token.substring(1);
+
+ if(status_ == Status.OPEN) {
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiOrderedListBlockParser create(WikiEngine wikiEngine) {
+ return new WikiOrderedListBlockParser(wikiEngine, Status.OPEN);
+ }
+ });
+
+ daughterParser_.startElementProcess(daughterPart, buf);
+ }
+ daughterParser_.parse(daughterPart, buf);
+ }
+ else {
+ if(status_ == Status.NESTING) {
+ /*
+ * トークンが1つでネスト処理中の場合、
+ * ネスト処理を終了する。
+ */
+ daughterParser_.endElementProcess(line, buf);
+ daughterParser_ = null;
+ status_ = Status.OPEN;
+ }
+ super.parse(line, buf);
+ remain_ = "";
+ }
+ }
+ else {
+ isBlockEnd_ = true;
+ remain_ = line;
+ }
+
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.endElementProcess(line, buf);
+ }
+ buf.append(END_TAG + "\n");
+ return remain_;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiPreBlockParser extends WikiBlockParserBase {
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ public static final String NOTATION_REGEX_LINEHEAD = "<pre[ \t]*>" + (".*");
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ public static final String NOTATION_REGEX_LINETAIL = "<*/[ \t]*pre>" + ".*";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = ".*" + NOTATION_REGEX_LINEHEAD
+ + ".*";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiPreBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, Status.INIT);
+ }
+
+ /**
+ * コンストラクタ
+ */
+ public WikiPreBlockParser(WikiEngine wikiEngine, Status status) {
+ super(wikiEngine);
+ status_ = status;
+ initialStatus_ = status;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ char[] charLine = line.toCharArray();
+ String previous = "";
+ String main = "";
+
+ for(count_ = 0; count_ < charLine.length; count_++) {
+ if(charLine[count_] == '<') {
+ String now = line.substring(count_);
+
+ if(now.matches(WikiPreBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
+ previous = line.substring(0, line.indexOf(now));
+ main = now;
+ break;
+ }
+ }
+ }
+
+ if(previous.isEmpty() != true) {
+ buf.append(inlineParse(previous));
+ }
+
+ return main;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ char[] charLine = line.toCharArray();
+
+ for(count_ = 0; count_ < charLine.length; count_++) {
+ if(status_ == Status.NESTING) {
+ String nestpart = new String(line.substring(count_));
+ daughterParser_.parse(nestpart, buf);
+ count_ += daughterParser_.getCount();
+
+ if(daughterParser_.isBlockEnd() == true) {
+ daughterParser_.endElementProcess(null, buf);
+ status_ = Status.OPEN;
+ daughterParser_ = null;
+ }
+ continue;
+ }
+
+ if(charLine[count_] == '<') {
+ String now = line.substring(count_);
+ String nowLower = now.toLowerCase();
+ String tagpart = now.substring(0, now.indexOf(">") + ">".length());
+
+ if(nowLower.matches(WikiPreBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
+ /*
+ * <pre>要素がネストしている場合
+ */
+ count_ += tagpart.length() - 1;
+
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiPreBlockParser create(WikiEngine wikiEngine) {
+ return new WikiPreBlockParser(wikiEngine, Status.OPEN);
+ }
+ });
+ buf.append(tagpart);
+ }
+ else if(nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
+ /*
+ * <code>要素がネストしている場合
+ */
+ count_ += tagpart.length() - 1;
+
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiCodeBlockParser create(WikiEngine wikiEngine) {
+ return new WikiCodeBlockParser(wikiEngine, WikiPreBlockParser.this, Status.OPEN);
+ }
+ });
+ buf.append(tagpart);
+ }
+ else if((nowLower.matches(WikiPreBlockParser.NOTATION_REGEX_LINETAIL) == true)
+ || (nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINETAIL) == true)) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.parse(now, buf);
+ count_ += daughterParser_.getCount() - 1;
+
+ if(daughterParser_.isBlockEnd() == true) {
+ status_ = Status.OPEN;
+ daughterParser_ = null;
+ }
+ }
+ else {
+ remain_ = now.substring(now.indexOf(">") + ">".length());
+ count_ += tagpart.length() - 1;
+ buf.append(tagpart);
+ isBlockEnd_ = true;
+ break;
+ }
+ }
+ else {
+ count_ += tagpart.length() - 1;
+ buf.append(tagpart.replaceAll("<", "<").replaceAll(">", ">"));
+ }
+ }
+ else if(status_ == Status.OPEN) {
+ buf.append(charLine[count_]);
+ }
+ }
+
+ if(initialStatus_ == Status.INIT) {
+ buf.append("\n");
+ }
+
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ return remain_;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+
+ @Override
+ public String daughterElementCloseHelper(String tagPart) {
+ return (motherParser_ != null)
+ ? motherParser_.daughterElementCloseHelper(tagPart)
+ : tagPart;
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * TOC(Table Of Contents) Builder.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+
+/**
+ * WikiTOCBuilder
+ *
+ */
+public class WikiTOCBuilder {
+ private static final String MACRO_INSERTTOC = "{{#TOC}}";
+
+ /**
+ * Headline(見出し)リストのノード
+ */
+ class HeadlineNode {
+ /** Headline(見出し)名 */
+ String id_;
+
+ /** Headlineレベル */
+ int headLineLevel_;
+
+ /**
+ * Constractor
+ * @param id
+ * @param level
+ */
+ HeadlineNode(String id, int level) {
+ id_ = id;
+ headLineLevel_ = level;
+ }
+ }
+
+ /** page内の見出しのリスト */
+ private ArrayList<HeadlineNode> headlineList_ = new ArrayList<HeadlineNode>();
+
+ /**
+ * headlineListにエントリーを追加する。
+ * @param id
+ * @param level
+ */
+ public void add(String id, int level) {
+ headlineList_.add(new HeadlineNode(id, level));
+ }
+
+ /**
+ * TOC(目次)を構築する
+ * @param line
+ * @return 構築した目次
+ */
+ public String buildTOC(String line) {
+ StringBuffer buf = new StringBuffer("");
+ ResourceBundle bundle = ResourceBundle.getBundle("com.wiki.standalone.moxkiriya.resources.moxkiriya");
+
+ if( (line != null)
+ && (line.startsWith(MACRO_INSERTTOC) == true)) {
+ if(false) {
+ /*
+ * クリックに反応しないので、[show]/[hide]一時無効
+ */
+ buf.append( "<div class=\"tocbox\">\n"
+ + "<input type=\"checkbox\" id=\"toc\">\n"
+ + "<label for=\"toc\">"
+ + bundle.getString("key.Contents")
+ + "</label>\n"
+ + "<div class=\"hidden_show\">\n");
+ buf.append(buildTOCList());
+ buf.append( "</div>\n"
+ + "</div>");
+ }
+ else {
+ buf.append("<div class=\"tocbox\">\n"
+ + "<div class=\"title\">"
+ + bundle.getString("key.Contents")
+ + "</div>\n");
+ buf.append(buildTOCList());
+ buf.append( "</div>\n");
+ }
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * TOC(目次)リストを構築する。
+ * @return 構築した目次リスト
+ */
+ private String buildTOCList() {
+ int depth = 0;
+ StringBuffer buf = new StringBuffer("<ul>\n");
+
+ for(HeadlineNode node: headlineList_) {
+ if(node.headLineLevel_ - 2 < depth) {
+ while(node.headLineLevel_ - 2 < depth) {
+ depth--;
+ buf.append("</ul>\n");
+ }
+ }
+ else if(node.headLineLevel_ - 2 > depth) {
+ while(node.headLineLevel_ - 2 > depth) {
+ depth++;
+ buf.append("<ul>\n");
+ }
+
+ }
+
+ buf.append( "<li><a href=\"#"
+ + node.id_
+ + "\")>"
+ + node.id_
+ + "</a></li>\n");
+ }
+ buf.append("</ul>\n");
+
+ return buf.toString();
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * '<table>' Blocklevel element parser, processor.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import java.util.LinkedHashMap;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiTableBlockParser extends WikiBlockParserBase {
+ /** startタグ */
+ private static final String START_TAG = "<div><table";
+
+ /** endタグ*/
+ private static final String END_TAG = "</table></div>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^[ \t]*"
+ + Pattern.quote("{|");
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "^[ \t]*"
+ + Pattern.quote("|}");
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD + ".*";
+
+ /** CSSセレクターマップ */
+ private static final LinkedHashMap<String, String> selectorMap_ = new LinkedHashMap<String, String>() {
+ private static final long serialVersionUID = 1L;
+ { put("#", "id="); }
+ { put(".", "class=");}
+ };
+
+ /** table 1行分の文字列を蓄積するバッファ */
+ private StringBuffer rowBuf_;
+
+ /** Daughterブロックパーサクリエイター */
+ private final WikiBlockParserCreator creator_ = new WikiBlockParserCreator(wikiEngine_) {
+ @Override
+ public WikiBlockParser create(String line) {
+ return new WikiTableRowBlockParser(wikiEngine_);
+ }
+ };
+
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ */
+ public WikiTableBlockParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ status_ = Status.INIT;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ buf.append(START_TAG);
+
+ String style = line.replaceFirst(NOTATION_REGEX_LINEHEAD, "").trim();
+ String selector = "";
+
+ if(style.isEmpty() != true) {
+ /*
+ * 表開始マークアップ後の文字列のスタイルシートのセレクタ形式か判定する
+ */
+ for(String key: selectorMap_.keySet()) {
+ if(style.startsWith(key) == true) {
+ selector = selectorMap_.get(key);
+ style = style.substring(style.indexOf(key) + key.length());
+ break;
+ }
+ }
+
+ if(selector.isEmpty() != true) {
+ buf.append(" ");
+ buf.append(selector);
+ buf.append("\"" + style + "\"");
+ }
+ }
+ buf.append(">\n");
+
+ return "";
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ if(line.matches(NOTATION_REGEX_LINETAIL+ ".*") == true) {
+ isBlockEnd_ = true;
+ remain_ = line.replaceFirst(NOTATION_REGEX_LINETAIL, "");
+ line = "";
+ }
+ else {
+ if(rowBuf_ == null) {
+ rowBuf_ = new StringBuffer();
+ }
+
+ if(status_ == Status.INIT) {
+ status_ = Status.OPEN;
+ }
+ else if(status_ == Status.OPEN) {
+ startDaughterParse(creator_, line);
+ line = daughterParser_.startElementProcess(line, rowBuf_);
+ }
+ else if(status_ == Status.NESTING) {
+ line = daughterParser_.parse(line, rowBuf_);
+ if(daughterParser_.isBlockEnd() == true) {
+ line = daughterParser_.endElementProcess(line, rowBuf_);
+ status_ = Status.OPEN;
+ }
+ }
+ }
+
+ if(line.startsWith("|-") == true) {
+ flushRowBuf(buf);
+ line = "";
+ }
+ return line;
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.endElementProcess(line, rowBuf_);
+ status_ = Status.OPEN;
+ }
+ flushRowBuf(buf);
+ buf.append(END_TAG + "\n");
+ return remain_;
+ }
+
+ /**
+ * 表の行終端や表終端マークアップに到達したときに1行分の文字列をbufに書き込む
+ * @param buf
+ */
+ private void flushRowBuf(StringBuffer buf) {
+ if( (rowBuf_ != null)
+ && (rowBuf_.length() > 0)) {
+ buf.append("<tr>\n");
+ buf.append(rowBuf_);
+ buf.append("</tr>\n");
+ rowBuf_ = null;
+ }
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Table row Blocklevel element parser, processor.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import java.util.LinkedHashMap;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiTableRowBlockParser extends WikiBlockParserBase {
+ /** startタグ(th) */
+ private static final String START_TH_TAG = "<th";
+
+ /** endタグ(th) */
+ private static final String END_TH_TAG = "</th>\n";
+
+ /** startタグ(td) */
+ private static final String START_TD_TAG = "<td";
+
+ /** endタグ(td) */
+ private static final String END_TD_TAG = "</td>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^[ \t]*[!|]";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD + ".*";
+
+ /**
+ * 開始タグと終了タグのペア
+ */
+ static class TagPair {
+ /** 開始タグ */
+ String startTag_;
+
+ /** 終了タグ */
+ String endTag_;
+
+ /**
+ * コンストラクタ
+ * @param startTag
+ * @param endTag
+ */
+ TagPair(String startTag, String endTag) {
+ startTag_ = startTag;
+ endTag_ = endTag;
+ }
+ }
+
+ /** 開始文字と開始/終了タグのマップ */
+ private static final LinkedHashMap<String, TagPair> tagPairHashMap_ = new LinkedHashMap<String, TagPair>() {
+ private static final long serialVersionUID = 1L;
+ { put("!", new TagPair(START_TH_TAG, END_TH_TAG)); }
+ { put("|", new TagPair(START_TD_TAG, END_TD_TAG)); }
+ };
+
+ /** 開始/終了タグのペア */
+ private TagPair tagpair_;
+
+ /** CSSセレクターマップ */
+ private static final LinkedHashMap<String, String> selectorMap_
+ = new LinkedHashMap<String, String>() {
+ private static final long serialVersionUID = 1L;
+ { put("colspan=", ""); }
+ { put("rowspan=", ""); }
+ { put("scope=", ""); }
+ { put("style=", ""); }
+ };
+
+ /** Daughterブロックパーサクリエイター */
+ private WikiBlockParserCreator creator_;
+
+ private StringBuffer rowBuf_;
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ */
+ public WikiTableRowBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, Status.INIT);
+ }
+
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ * @param status
+ */
+ public WikiTableRowBlockParser(WikiEngine wikiEngine, Status status) {
+ super(wikiEngine);
+ status_ = status;
+ creator_ = new WikiBlockParserCreator(wikiEngine);
+ rowBuf_ = new StringBuffer("");
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ status_ = Status.OPEN;
+
+ String trimedLine = line.trim();
+ String firstLetter = trimedLine.substring(0, 1);
+
+ tagpair_ = tagPairHashMap_.get(firstLetter);
+ buf.append(tagpair_.startTag_ + " ");
+ trimedLine = trimedLine.substring(1);
+
+ StringBuffer cellBuf = new StringBuffer("");
+ boolean selectorFound = false;
+ int count;
+ for(count = 0; count < trimedLine.length(); count++) {
+ char letter = trimedLine.charAt(count);
+
+ if(letter == '|') {
+ break;
+ }
+
+ cellBuf.append(letter);
+
+ if(selectorFound != true) {
+ for(String key: selectorMap_.keySet()) {
+ if(cellBuf.toString().equals(key) == true) {
+ selectorFound = true;
+ buf.append(key);
+ break;
+ }
+ }
+ }
+ else {
+ buf.append(letter);
+ }
+ }
+
+ buf.append(">\n");
+
+ if(selectorFound == true) {
+ trimedLine = trimedLine.substring(count + 1);
+ }
+
+ return trimedLine;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ if( (line.startsWith("|") == true)
+ || (line.startsWith("!") == true)) {
+ isBlockEnd_ = true;
+ remain_ = line;
+ line = "";
+ }
+ else {
+ if(status_ != Status.NESTING) {
+ startDaughterParse(creator_, line);
+ line = daughterParser_.startElementProcess(line, rowBuf_);
+ }
+
+ line = daughterParser_.parse(line, rowBuf_);
+ if(daughterParser_.isBlockEnd() == true) {
+ line = daughterParser_.endElementProcess(line, rowBuf_);
+ status_ = Status.OPEN;
+ }
+ }
+
+ return line;
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.endElementProcess(line, rowBuf_);
+ status_ = Status.OPEN;
+ }
+ flushRowBuf(buf);
+ buf.append(tagpair_.endTag_);
+ return remain_;
+ }
+
+ /**
+ * 表の行終端や表終端マークアップに到達したときに1行分の文字列をbufに書き込む
+ * @param buf
+ */
+ private void flushRowBuf(StringBuffer buf) {
+ if( (rowBuf_ != null)
+ && (rowBuf_.length() > 0)) {
+ buf.append(rowBuf_);
+ rowBuf_ = null;
+ }
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Unordered list block parser.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.parser.blockparser;
+
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * 番号なしリストのマークアップを解析し、HTML形式に変換する。
+ *
+ */
+public class WikiUnorderedListBlockParser extends WikiBlockParserBase {
+ private static final String START_TAG = "<div><ul>\n";
+
+ private static final String END_TAG = "</ul></div>\n";
+
+ /** WIKI記法の正規表現文字列 行頭パターン */
+ private static final String NOTATION_REGEX_LINEHEAD = "^[ \t]*"
+ + Pattern.quote("*")
+ + "+ +[^*]";
+
+ /** WIKI記法の正規表現文字列 行末パターン */
+ private static final String NOTATION_REGEX_LINETAIL = "";
+
+ /** WIKI記法の正規表現文字列 */
+ public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD
+ + "..*"
+ + NOTATION_REGEX_LINETAIL;
+
+ /** ブロック終了状態 */
+ private boolean isBlockEnd_ = false;
+
+ /** 処理終了後の残り文字列 */
+ private String remain_;
+
+ /**
+ * コンストラクタ
+ */
+ public WikiUnorderedListBlockParser(WikiEngine wikiEngine) {
+ this(wikiEngine, Status.INIT);
+ }
+
+ /**
+ * コンストラクタ
+ */
+ public WikiUnorderedListBlockParser(WikiEngine wikiEngine, Status status) {
+ super(wikiEngine);
+ status_ = status;
+ }
+
+ @Override
+ public String startElementProcess(String line, StringBuffer buf) {
+ status_ = Status.OPEN;
+ buf.append(START_TAG);
+ return line;
+ }
+
+ @Override
+ public String parse(String line, StringBuffer buf) throws Exception {
+ if(line.matches(NOTATION_REGEX) == true) {
+ String token = line.substring(line.indexOf("*"));
+ int countToken = countToken(token, '*');
+ if(countToken > 1) {
+ /*
+ * '#'を一つ減らして子parserへ渡す。
+ */
+ String daughterPart = token.substring(1);
+
+ if(status_ == Status.OPEN) {
+ startDaughterParse(new WikiBlockParserCreator.Creator() {
+ @Override
+ public WikiUnorderedListBlockParser create(WikiEngine wikiEngine) {
+ return new WikiUnorderedListBlockParser(wikiEngine, Status.OPEN);
+ }
+ });
+
+ daughterParser_.startElementProcess(daughterPart, buf);
+ }
+ daughterParser_.parse(daughterPart, buf);
+ }
+ else {
+ if(status_ == Status.NESTING) {
+ /*
+ * トークンが1つでネスト処理中の場合、
+ * ネスト処理を終了する。
+ */
+ daughterParser_.endElementProcess(line, buf);
+ daughterParser_ = null;
+ status_ = Status.OPEN;
+ }
+ super.parse(line, buf);
+ remain_ = "";
+ }
+ }
+ else {
+ isBlockEnd_ = true;
+ remain_ = line;
+ }
+
+ return "";
+ }
+
+ @Override
+ public String endElementProcess(String line, StringBuffer buf) {
+ if(status_ == Status.NESTING) {
+ daughterParser_.endElementProcess(line, buf);
+ }
+ buf.append(END_TAG + "\n");
+ return remain_;
+ }
+
+ @Override
+ public boolean isBlockEnd() {
+ return isBlockEnd_;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiBoldInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = "'''";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "'''[^']";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^']'''";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_ITALIC_END = WikiItalicInlineParser.PATTERN_END;
+
+ /** 開始タグ */
+ private static final String START_TAG = "<span id=\"bold\">\n";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</span>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiBoldInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiBoldInlineParser.PATTERN_START)
+ .matcher(line);
+
+ if(startMatcher.find() == true) {
+ isMatch = true;
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(WIKI_TOKEN, "");
+ if(deleteTop.contains(WIKI_TOKEN) == true) {
+ deleteTop = deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN));
+ }
+ return deleteTop;
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiDefaultInlineParser extends WikiInlineParserBase {
+ /**
+ * コンストラクタ
+ */
+ public WikiDefaultInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ @Override
+ public String parse(String line) {
+ StringBuffer buf = new StringBuffer();
+ String rest = line;
+
+ buf.append(rest);
+
+ return buf.toString();
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ }
+
+ @Override
+ public String getStartPattern() {
+ return "";
+ }
+
+ @Override
+ public String getEndPattern() {
+ return "";
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ return line;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.SettingManager;
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiExternalLinkInlineParser extends WikiInlineParserBase {
+ /** WIKI開始トークン */
+ public static final String WIKI_TOKEN_START = "[";
+
+ /** WIKI開始トークン */
+ public static final String WIKI_TOKEN_END = "]";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = Pattern.quote(WIKI_TOKEN_START)
+ + "[^"
+ + Pattern.quote("[")
+ + "]";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^]]"
+ + Pattern.quote(WIKI_TOKEN_END);
+
+ /** startタグ */
+ private static final String START_TAG = "<a href=";
+
+ /** endタグ */
+ private static final String END_TAG = "</a>\n";
+
+ /** icon startタグ*/
+ private static final String START_ICON_TAG = "<img src=";
+
+ /** icon endタグ */
+ private static final String END_ICON_TAG = "</img>";
+
+ /** external link icon画像名 */
+ private static final String EXTERNAL_LINK_ICON = "icon\\Icon_External_Link.png";
+
+ /** Link先のURL */
+ private String url_;
+
+ /** Link先のtextNode */
+ private String textNode_;
+
+ /**
+ * スキーマリスト
+ */
+ private static final ArrayList<String> schemeList = new ArrayList<String>() {
+ private static final long serialVersionUID = 1L;
+ { add("http://"); }
+ { add("https://"); }
+ { add("file://"); }
+ };
+
+ /**
+ * コンストラクタ
+ */
+ public WikiExternalLinkInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiExternalLinkInlineParser.PATTERN_START).matcher(line);
+
+ if(startMatcher.find() == true) {
+ /*
+ * PATTERN_STARTの開始位置を取得
+ */
+ int startIndex = startMatcher.start();
+
+ /*
+ * PATTERN_ENDの開始位置を取得
+ */
+ String startString = line.substring(startIndex + 1);
+ Matcher endMatcher = Pattern.compile(WikiExternalLinkInlineParser.PATTERN_END).matcher(startString);
+
+ if(endMatcher.find() == true) {
+ isMatch = isSchemeString(startString);
+ }
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public String[] devideLine(String line) {
+ int depth = 0;
+ char[] charArrayLine = line.toCharArray();
+ int startIndex = -1;
+ int endIndex = -1;
+ int lastIndex = -1;
+ boolean withinElem = false;
+
+ for(int count = 0; count < charArrayLine.length; count++) {
+ if(charArrayLine[count] == '>') {
+ withinElem = false;
+ continue;
+ } else if(charArrayLine[count] == '<') {
+ withinElem = true;
+ }
+
+ if(withinElem == true) {
+ /*
+ * HTML要素内をスキップ
+ */
+ continue;
+ }
+
+ if(charArrayLine[count] == '[') {
+ String startString = line.substring(count + 1);
+ if(isSchemeString(startString) == true) {
+ if(startIndex != -1) {
+ /*
+ * 次の外部リンクの開始の場合、
+ */
+ endIndex = lastIndex;
+ break;
+ }
+ else if(depth == 0) {
+ startIndex = count;
+ }
+ }
+ else if(startString.startsWith("[")) {
+ /*
+ * 内部リンクの開始に到達した場合、
+ */
+ endIndex = lastIndex;
+ break;
+ }
+ depth++;
+ }
+ else if(charArrayLine[count] == ']') {
+ lastIndex = count;
+ if(depth > 0) {
+ depth--;
+
+ if(depth == 0) {
+ endIndex = count;
+ break;
+ }
+ }
+ }
+ }
+
+ if(endIndex == -1) {
+ endIndex = (lastIndex == -1) ? line.length() - 1 : lastIndex;
+ }
+
+ String split0 = line.substring(0, startIndex);
+ String split1 = line.substring(startIndex, endIndex + 1);
+ String split2 = line.substring(endIndex + 1);
+
+ return new String[] {split0, split1, split2};
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(Pattern.quote(WIKI_TOKEN_START), "");
+ String text = deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN_END));
+
+ if(text.contains("|") == true) {
+ url_ = text.substring(0, text.indexOf("|"));
+ textNode_ = text.substring(text.indexOf("|") + "|".length());
+ }
+ else {
+ url_ = text;
+ textNode_ = text;
+ }
+ return textNode_.replaceAll(Pattern.quote("["), "[")
+ .replaceAll(Pattern.quote("]"), "]");
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ buf.append("\"");
+ buf.append(url_);
+ buf.append("\">");
+ }
+
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ buf.append(textNode);
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ try {
+ buf.append(START_ICON_TAG);
+
+ SettingManager settingMgr = SettingManager.getInstance();
+ String Approot = settingMgr.get(SettingManager.SETINGKEY_MOXKIRIYAROOT);
+ String iconPath = Approot + "\\" + EXTERNAL_LINK_ICON;
+ URL url = new File(iconPath).toURI().toURL();
+ buf.append("\"" + url.toString() + "\">");
+
+ buf.append(END_ICON_TAG);
+ buf.append(END_TAG);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+
+ /**
+ * lineがscheme文字列で始まるか判定する。
+ * @param line
+ * @return 判定結果
+ */
+ private static boolean isSchemeString(String line) {
+ boolean result = false;
+
+ for(String scheme: schemeList) {
+ if(line.startsWith(scheme) == true) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+public interface WikiInlineParser {
+ /**
+ * WikiのSyntaxを解析し、HTML形式の文字列に変換する。
+ * @param line
+ * @return 変換結果
+ */
+ public String parse(String line);
+
+ /**
+ * lineをkey前、key、key後に分割する。
+ * @param line
+ * @return 分割した文字列配列
+ */
+ public String[] devideLine(String line);
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public abstract class WikiInlineParserBase implements WikiInlineParser {
+ /** Wiki Engine */
+ protected WikiEngine wikiEngine_;
+
+ /**
+ * Constructor.
+ * @param wikiRepository
+ */
+ public WikiInlineParserBase(WikiEngine wikiEngine) {
+ wikiEngine_ = wikiEngine;
+ }
+
+ @Override
+ public String parse(String line) {
+ String htmlString = line;
+
+ if (line.isEmpty() != true
+ && line.equals("{{#TOC}}") != true) {
+ WikiInlineParserCreator creator = new WikiInlineParserCreator(wikiEngine_);
+ WikiInlineParser parser;
+
+ /*
+ * 外側のWikiトークンをHTMLに変換する。
+ */
+ StringBuffer buf = new StringBuffer("");
+ String[] split = devideLine(line);
+ buf.append(split[0]);
+
+ /*
+ * 処理したトークンより内側のトークンをHTMLに変換する(もしあれば)。
+ */
+ String textNode = deleteWikiToken(split[1]);
+ parser = creator.create(textNode);
+ textNode = parser.parse(textNode);
+
+ StringBuffer mainBuf = new StringBuffer();
+ startElementProcess(mainBuf);
+ textNodeProcess(mainBuf, textNode);
+ endElementProcess(mainBuf);
+
+ buf.append(mainBuf.toString());
+ htmlString = buf.append(split[2]).toString();
+
+ /*
+ * 処理したWikiトークンより外側のトークンを処理する。
+ */
+ parser = creator.create(htmlString);
+
+ StringBuffer buf2 = new StringBuffer("");
+
+ buf2.append(parser.parse(htmlString));
+ htmlString = buf2.toString();
+ }
+
+ return htmlString;
+ }
+
+ /**
+ * Wikiトークンを削除する。
+ * @param line
+ * @return 削除後の文字列
+ */
+ abstract public String deleteWikiToken(String line);
+
+ /**
+ * 要素開始を処理する。
+ * @param buf
+ */
+ abstract public void startElementProcess(StringBuffer buf);
+
+ /**
+ * テキストノードを処理する。
+ * @param buf
+ * @param textNode
+ */
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ buf.append(textNode);
+ }
+
+ /**
+ * 要素終了を処理する。
+ * @param buf
+ */
+ abstract public void endElementProcess(StringBuffer buf);
+
+ /**
+ * Wiki記法の開始パターンを取得する
+ * @return Wiki記法の開始パターン
+ */
+ abstract public String getStartPattern();
+
+ /**
+ * Wiki記法の終了パターンを取得する
+ * @return Wiki記法の終了パターン
+ */
+ abstract public String getEndPattern();
+
+ @Override
+ public String[] devideLine(String line) {
+ String matchString = null;
+ String[] result = null;
+
+ Matcher startMatcher = Pattern.compile(getStartPattern()).matcher(line);
+
+ if(startMatcher.find() == true) {
+ String startSub = line.substring(startMatcher.start());
+ Matcher endMatcher = Pattern.compile(getEndPattern()).matcher(startSub);
+
+ if(endMatcher.find() == true) {
+ matchString = startSub.substring(0, endMatcher.end());
+ }
+ else {
+ matchString = startSub;
+ }
+ }
+
+ if(matchString != null) {
+ String[] split = line.split(Pattern.quote(matchString), 2);
+ result = new String[] {split[0], matchString, split[1]};
+ }
+
+ return result;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.ArrayList;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+/**
+ * WikiInlineParserインスタンスを生成する。
+ * @author Ryuhei Terada
+ *
+ */
+public class WikiInlineParserCreator {
+ /** WikiInlineParser Creator Table */
+ private ArrayList<Creator> creatorList_;
+
+ /** Wiki Eepository */
+ private WikiEngine wikiEngine_;
+
+ /**
+ * CreatorテーブルのノードInterface
+ */
+ public interface Creator {
+ /**
+ * Wiki記法とパターンマッチングする。
+ * @param line
+ * @return マッチング結果
+ */
+ public boolean matches(String line);
+
+ /**
+ * InlineParser生成処理
+ * @param wikiRepository
+ * @return InlineParser
+ */
+ public WikiInlineParser create(WikiEngine wikiEngine);
+ };
+
+ /** default WikiInlineParser Creator Table */
+ private final static ArrayList<Creator> defaultCreatorList_ = new ArrayList<Creator>() {
+ private static final long serialVersionUID = 1L;
+ {
+ /* WikiInternalLinkInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiInternalLinkInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiInternalLinkInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiExternalLinkInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiExternalLinkInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiExternalLinkInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiBoldInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiBoldInlineParser.matches(line.toLowerCase());
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiBoldInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiItalicInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiItalicInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiItalicInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiUnderlineInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiUnderlineInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiUnderlineInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiLineThroughInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiLineThroughInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiLineThroughInlineParser(wikiEngine);
+ }
+ } );
+
+ /* WikiUnorderedListItemInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiUnorderedListItemInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiUnorderedListItemInlineParser(wikiEngine);
+ }
+ } );
+ /* WikiOrderedListItemInlineParser creator. */
+ add(new Creator() {
+ @Override
+ public boolean matches(String line) {
+ return WikiOrderedListItemInlineParser.matches(line);
+ }
+
+ @Override
+ public WikiInlineParser create(WikiEngine wikiEngine) {
+ return new WikiOrderedListItemInlineParser(wikiEngine);
+ }
+ } );
+ }
+ };
+
+ /**
+ * コンストラクタ
+ */
+ public WikiInlineParserCreator(WikiEngine wikiEngine) {
+ this(defaultCreatorList_, wikiEngine);
+ }
+
+ /**
+ * コンストラクタ
+ * @param creatorList
+ */
+ public WikiInlineParserCreator(ArrayList<Creator> creatorList, WikiEngine wikiEngine) {
+ creatorList_ = creatorList;
+ wikiEngine_ = wikiEngine;
+ }
+
+ /**
+ * lineのSyntaxにマッチするWikiInlineParserのインスタンスを生成する。
+ * @param line
+ * @param file
+ * @return WikiInlineParser
+ */
+ public WikiInlineParser create(String line) {
+ WikiInlineParser parser = null;
+ StringBuffer withoutElem = new StringBuffer("");
+
+ if( (line.isEmpty() != true)
+ && (line.contains("<") == true)
+ && (line.contains(">") == true)) {
+ withoutElem.append(line.substring(0, line.indexOf("<")));
+ withoutElem.append(line.substring(line.lastIndexOf(">") + ">".length()));
+ }
+ else {
+ withoutElem.append(line);
+ }
+
+ if(withoutElem.toString().isEmpty() != true) {
+ for(Creator creator: creatorList_) {
+ if(creator.matches(withoutElem.toString()) == true) {
+ parser = creator.create(wikiEngine_);
+ break;
+ }
+ }
+ }
+
+ if(parser == null) {
+ parser = new WikiDefaultInlineParser(wikiEngine_);
+ }
+
+ return parser;
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * Wiki Internallink inline parser
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+
+import org.apache.jackrabbit.util.Base64;
+
+import com.wiki.standalone.moxkiriya.PageData;
+import com.wiki.standalone.moxkiriya.WikiEngine;
+import com.wiki.standalone.moxkiriya.WikiRepository;
+import com.wiki.standalone.moxkiriya.util.FileTypeDeterminator;
+
+/**
+ * Wiki internal inline parser.
+ * Transform [[linkTarget|Title]] to <a href="linkTarget">Title</a>
+ */
+public class WikiInternalLinkInlineParser extends WikiInlineParserBase {
+ /** WIKI開始トークン */
+ public static final String WIKI_TOKEN_START = "[[";
+
+ /** WIKI開始トークン */
+ public static final String WIKI_TOKEN_END = "]]";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = Pattern.quote(WIKI_TOKEN_START)
+ + "[^"
+ + Pattern.quote("[")
+ + "]";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^]]"
+ + Pattern.quote(WIKI_TOKEN_END);
+
+ /** アンカー開始タグ */
+ private static final String START_TAG = "<a href=";
+
+ /** アンカー終了タグ */
+ private static final String END_TAG = "</a>\n";
+
+ /** jcr_uuid 独自属性 */
+ public static final String ATTRIBUTE_JCR_UUID = WikiEngine.ATTRIBUTE_JCR_UUID;
+
+ /** img開始タグ */
+ private static final String IMAGE_START_TAG = "<img src=";
+
+ /** img終了タグ */
+ private static final String IMAGE_END_TAG = "</img>";
+
+ /** ページ名接頭辞 "File:" */
+ private static final String PAGENAME_PREFIX_FILE = WikiEngine.NAMESPACE_FILE + ":";
+
+ /** ページ名接頭辞 ":File:" */
+ private static final String PAGENAME_PREFIX_COLONFILE = ":" + WikiEngine.NAMESPACE_FILE + ":";
+
+ /** ページ名接頭辞 "Category:" */
+ private static final String PAGENAME_PREFIX_CATEGORY = WikiEngine.NAMESPACE_CATEGORY + ":";
+
+ /** ページ名接頭辞 ":Category:" */
+ private static final String PAGENAME_PREFIX_COLONCATEGORY = ":" + WikiEngine.NAMESPACE_CATEGORY + ":";
+
+ /** ページタイトルマクロ "#title" */
+ private static final String PAGENAME_HASH_TITLE = "#title";
+
+ /** 存在しないファイルのスタイルクラス */
+ private static final String STYLE_CLASS_NOEXIST = "class=\"noexist\"";
+
+ /** リンク先のページ名 */
+ private String pagename_;
+
+ /** リンク先ファイルのフルパス */
+ private String linkpath_;
+
+ /** リンクモード */
+ private enum LinkMode {
+ NONE,
+ INNERLINK,
+ IMAGERENDER,
+ ATTACHEDFILELINK
+ };
+
+ /** リンクモード */
+ private LinkMode linkMode;
+
+ /**
+ * テキストノード処理クラス
+ */
+ private interface TextNodeProcessor {
+ /**
+ * テキストノードを処理する
+ * @param buf
+ * @param textNode
+ */
+ void textNodeProcess(StringBuffer buf, String textNode);
+ };
+
+ private final LinkedHashMap<LinkMode, TextNodeProcessor> textNodeProcessorMap = new LinkedHashMap<LinkMode, TextNodeProcessor>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(LinkMode.NONE, new TextNodeProcessor() {
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+
+ }
+ });
+ }
+ {
+ put(LinkMode.INNERLINK, new TextNodeProcessor() {
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ if(linkpath_.isEmpty() != true) {
+ if( (textNode.startsWith(PAGENAME_PREFIX_COLONFILE) == true)
+ || (textNode.startsWith(PAGENAME_PREFIX_COLONCATEGORY) == true)) {
+ textNode = textNode.replaceFirst(Pattern.quote(":"), "");
+ }
+
+ buf.append(textNode);
+ }
+ }
+ });
+ }
+ {
+ put(LinkMode.IMAGERENDER, new TextNodeProcessor() {
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ try {
+ String mediaType = null;
+ StringBuffer databuf = new StringBuffer("");
+
+ HashMap<String, PageData> pageDataMap = wikiEngine_.queryPageTitle(linkpath_);
+ PageData.FileData fileData = null;
+ PageData pageData = null;
+
+ if(pageDataMap.isEmpty() != true) {
+ /*
+ * File名前空間のpageは重複しないため、最初に見つかったnodeを対象にする
+ */
+ pageData = pageDataMap.values().iterator().next();
+ fileData = pageData.getFileData();
+ }
+
+ if(fileData == null) {
+ /*
+ * 表示/編集中のページデータを取得する
+ */
+ HashMap<String, PageData> nowPageDataMap = wikiEngine_.getPageDataMap();
+ PageData nowPageData = nowPageDataMap.values().iterator().next();
+ if(nowPageData.getNamespace().equals(WikiRepository.PROPERTY_FILE) == true) {
+ String title = nowPageData.getTitle();
+ if(linkpath_.equals(WikiRepository.PROPERTY_FILE + ":" + title) == true) {
+ /*
+ * parse中のページのtitleとリンク対象のページが同一の場合、
+ * PageData内のFileを設定する。
+ * File:タイトルを新規編集中でAttach file textboxにパス名が入力されているとき用の処理
+ */
+ fileData = nowPageData.getFileData();
+ }
+ }
+ }
+
+ if(fileData != null) {
+ mediaType = fileData.getMimeType();
+
+ InputStream inputStream = fileData.getInputStream();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ if(mediaType.startsWith("image/") == true) {
+ Base64.encode(inputStream, outputStream);
+ databuf.append(outputStream.toString());
+ }
+
+ buf.append(IMAGE_START_TAG);
+ if(databuf.length() > 0) {
+ buf.append("\"data:");
+ buf.append(mediaType + ";base64,");
+ buf.append(databuf);
+ buf.append("\"");
+ }
+ buf.append(" alt=\"");
+ buf.append(textNode);
+ buf.append("\"");
+ buf.append(" title=\"");
+ buf.append(textNode);
+ buf.append("\" >");
+ buf.append(IMAGE_END_TAG);
+ }
+ else {
+ buf.append(textNode);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ {
+ put(LinkMode.ATTACHEDFILELINK, new TextNodeProcessor() {
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ String basename = linkpath_.substring(linkpath_.lastIndexOf("\\") + "\\".length());
+ buf.append(basename);
+ }
+ });
+ }
+ };
+
+ /**
+ * コンストラクタ
+ * @param wikiRepository
+ */
+ public WikiInternalLinkInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiInternalLinkInlineParser.PATTERN_START)
+ .matcher(line);
+
+ if(startMatcher.find() == true) {
+ /*
+ * PATTERN_STARTの開始位置を取得
+ */
+ int startIndex = startMatcher.start();
+
+ /*
+ * PATTERN_ENDの開始位置を取得
+ */
+ String subline = line.substring(startIndex);
+ Matcher endMatcher = Pattern.compile(WikiInternalLinkInlineParser.PATTERN_END)
+ .matcher(subline);
+
+ if(endMatcher.find() == true) {
+ isMatch = true;
+ }
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public String[] devideLine(String line) {
+ char[] charArrayLine = line.toCharArray();
+ int startIndex = -1;
+ int endIndex = -1;
+ boolean withinElem = false;
+
+ for(int count = 0; count < charArrayLine.length; count++) {
+ if(charArrayLine[count] == '>') {
+ withinElem = false;
+ continue;
+ } else if(charArrayLine[count] == '<') {
+ withinElem = true;
+ }
+
+ if(withinElem == true) {
+ /*
+ * HTML要素内をスキップ
+ */
+ continue;
+ }
+
+ if(charArrayLine[count] == '[') {
+ String startString = line.substring(count);
+ if(startString.startsWith(WIKI_TOKEN_START) == true) {
+ startIndex = count;
+ }
+ }
+ else if(charArrayLine[count] == ']') {
+ if(startIndex != -1) {
+ String endString = line.substring(count);
+ if(endString.startsWith(WIKI_TOKEN_END) == true) {
+ endIndex = count;
+ break;
+ }
+ }
+ }
+ }
+
+ String split0 = line.substring(0, startIndex);
+ String split1 = line.substring(startIndex, endIndex + 2);
+ String split2 = line.substring(endIndex + 2);
+
+ return new String[] {split0.replaceAll(Pattern.quote("["), "[")
+ .replaceAll(Pattern.quote("]"), "]"),
+ split1,
+ split2};
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(Pattern.quote(WIKI_TOKEN_START), "");
+ String deleteToken = deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN_END));
+ String textNode = deleteToken;
+
+ if(deleteToken.contains("|") == true) {
+ pagename_ = deleteToken.substring(0, deleteToken.indexOf("|"));
+ textNode = deleteToken.substring(deleteToken.indexOf("|") + "|".length());
+
+ if(textNode.equals(PAGENAME_HASH_TITLE) == true) {
+ textNode = pagename_.substring(pagename_.lastIndexOf(":") + ":".length());
+ }
+ }
+ else {
+ pagename_ = deleteToken;
+ }
+
+ return textNode;
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ try {
+ linkpath_ = buildLinkpathFromPagename(pagename_);
+
+ if(linkpath_.isEmpty() != true) {
+ buf.append(START_TAG);
+ buf.append("\"");
+ buf.append(linkpath_ + "\" ");
+
+ HashMap<String, PageData> pageDataMap = wikiEngine_.queryPageTitle(linkpath_);
+ if(pageDataMap.size() == 0) {
+ buf.append(STYLE_CLASS_NOEXIST);
+ }
+ else if(pageDataMap.size() == 1) {
+ Set<String> key = pageDataMap.keySet();
+ PageData pageData = pageDataMap.get(key.iterator().next());
+ Node node = pageData.getNode();
+ buf.append(" " + ATTRIBUTE_JCR_UUID + "=\"");
+ buf.append(node.getProperty(Property.JCR_UUID).getString());
+ buf.append("\"");
+ }
+ buf.append(">");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void textNodeProcess(StringBuffer buf, String textNode) {
+ textNodeProcessorMap.get(linkMode).textNodeProcess(buf, textNode);
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ if(linkpath_.isEmpty() != true) {
+ buf.append(END_TAG);
+ }
+ linkMode = LinkMode.NONE;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+
+ /**
+ * pagenameからLinkパスを構築する
+ * @param pagename
+ * @return Linkパス
+ * @throws Exception
+ */
+ private String buildLinkpathFromPagename(String pagename) throws Exception {
+ String linkpath = null;
+
+ if(pagename.startsWith(PAGENAME_PREFIX_FILE) == true) {
+ if(FileTypeDeterminator.isImageFile(pagename) == true) {
+ linkMode = LinkMode.IMAGERENDER;
+ linkpath = buildImageLinkpath(pagename);
+ }
+ else {
+ linkMode = LinkMode.ATTACHEDFILELINK;
+ linkpath = buildAttachLinkpath(pagename);
+ }
+ }
+ else if(pagename.startsWith(PAGENAME_PREFIX_CATEGORY) == true) {
+ linkMode = LinkMode.INNERLINK;
+ linkpath = "";
+ }
+ else {
+ linkMode = LinkMode.INNERLINK;
+ linkpath = buildInternalLinkpath(pagename);
+ }
+
+ return linkpath;
+ }
+
+ /**
+ * イメージリンクパスを構築する。
+ * @param pagename
+ * @return イメージリンクパス
+ */
+ private String buildAttachLinkpath(String pagename) {
+ /*
+ * 先頭の":"を削除
+ */
+ return pagename.substring(1);
+ }
+
+ /**
+ * イメージリンクパスを構築する。
+ * @param pagename
+ * @return イメージリンクパス
+ */
+ private String buildImageLinkpath(String pagename) {
+ return pagename;
+ }
+
+ /**
+ * 内部リンクパスを構築する
+ * @param pagename
+ * @return 内部リンクパス
+ * @throws Exception
+ */
+ private String buildInternalLinkpath(String pagename) throws Exception {
+ if( (pagename.startsWith(PAGENAME_PREFIX_COLONFILE) == true)
+ || (pagename.startsWith(PAGENAME_PREFIX_COLONCATEGORY) == true)) {
+ pagename = pagename.replaceFirst(Pattern.quote(":"), "");
+ }
+
+ return pagename;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiItalicInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = "''";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "''[^']";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^']''";
+
+ /** 開始タグ */
+ private static final String START_TAG = "<span id=\"italic\">\n";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</span>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiItalicInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする。
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiItalicInlineParser.PATTERN_START)
+ .matcher(line);
+
+ if(startMatcher.find() == true) {
+ isMatch = true;
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(WIKI_TOKEN, "");
+ if(deleteTop.contains(WIKI_TOKEN) == true) {
+ deleteTop = deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN));
+ }
+ return deleteTop;
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiLineThroughInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = "--";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "--[^-]";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^-]--";
+
+ /** 開始タグ */
+ private static final String START_TAG = "<span id=\"linethrough\">\n";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</span>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiLineThroughInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiLineThroughInlineParser.PATTERN_START)
+ .matcher(line);
+
+ if(startMatcher.find() == true) {
+ /*
+ * PATTERN_STARTの開始位置を取得
+ */
+ int startIndex = startMatcher.start();
+
+ /*
+ * PATTERN_ENDの開始位置を取得
+ */
+ String subline = line.substring(startIndex);
+ Matcher underlineEndMatcher = Pattern.compile(WikiLineThroughInlineParser.PATTERN_END)
+ .matcher(subline);
+
+ if(underlineEndMatcher.find() == true) {
+ isMatch = true;
+ }
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(WIKI_TOKEN, "");
+ return deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN));
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiOrderedListItemInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = "# ";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "^[ \t]*# ";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "$";
+
+ /** 開始タグ */
+ private static final String START_TAG = "<li>";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</li>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiOrderedListItemInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ Matcher startMatcher
+ = Pattern.compile(WikiOrderedListItemInlineParser.PATTERN_START).matcher(line);
+
+ return startMatcher.find();
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ return line.replaceFirst(WIKI_TOKEN, "");
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiUnderlineInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = "__";
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "__[^_]";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "[^_]__";
+
+ /** 開始タグ */
+ private static final String START_TAG = "<span id=\"underline\">\n";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</span>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiUnderlineInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ boolean isMatch = false;
+
+ Matcher startMatcher
+ = Pattern.compile(WikiUnderlineInlineParser.PATTERN_START)
+ .matcher(line);
+
+ if(startMatcher.find() == true) {
+ /*
+ * PATTERN_STARTの開始位置を取得
+ */
+ int startIndex = startMatcher.start();
+
+ /*
+ * PATTERN_ENDの開始位置を取得
+ */
+ String subline = line.substring(startIndex);
+ Matcher underlineEndMatcher = Pattern.compile(WikiUnderlineInlineParser.PATTERN_END)
+ .matcher(subline);
+
+ if(underlineEndMatcher.find() == true) {
+ isMatch = true;
+ }
+ }
+
+ return isMatch;
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ String deleteTop = line.replaceFirst(WIKI_TOKEN, "");
+ return deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN));
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.parser.inlineparser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.wiki.standalone.moxkiriya.WikiEngine;
+
+public class WikiUnorderedListItemInlineParser extends WikiInlineParserBase {
+ /** WIKIトークン */
+ public static final String WIKI_TOKEN = Pattern.quote("* ");
+
+ /** WIKI記法の正規表現文字列 先頭頭パターン */
+ public static final String PATTERN_START = "^[ \t]*"
+ + Pattern.quote("*")
+ + " ";
+
+ /** WIKI記法の正規表現文字列 末尾パターン */
+ public static final String PATTERN_END = "$";
+
+ /** 開始タグ */
+ private static final String START_TAG = "<li>";
+
+ /** 終了タグ */
+ private static final String END_TAG = "</li>\n";
+
+ /**
+ * コンストラクタ
+ */
+ public WikiUnorderedListItemInlineParser(WikiEngine wikiEngine) {
+ super(wikiEngine);
+ }
+
+ /**
+ * lineとWiki記法をマッチングする
+ * @param line
+ * @return マッチング結果
+ */
+ public static boolean matches(String line) {
+ Matcher startMatcher
+ = Pattern.compile(WikiUnorderedListItemInlineParser.PATTERN_START).matcher(line);
+
+ return startMatcher.find();
+ }
+
+ @Override
+ public void startElementProcess(StringBuffer buf) {
+ buf.append(START_TAG);
+ }
+
+ @Override
+ public void endElementProcess(StringBuffer buf) {
+ buf.append(END_TAG);
+ }
+
+ @Override
+ public String deleteWikiToken(String line) {
+ return line.replaceFirst(WIKI_TOKEN, "");
+ }
+
+ @Override
+ public String getStartPattern() {
+ return PATTERN_START;
+ }
+
+ @Override
+ public String getEndPattern() {
+ return PATTERN_END;
+ }
+}
--- /dev/null
+body {
+ font-family: 'メイリオ','Meiryo','sans-serif';
+}
+
+h1 {
+ padding: 0.25em;
+ color: #494949;
+ border-bottom: solid 3px #d7d7d7;
+}
+
+h2 {
+ padding: 0.25em;
+ color: #494949;
+ border-bottom: solid 3px #d7d7d7;
+}
+
+h3 {
+ padding: 0.25em;
+ color: #494949;
+ border-bottom: solid 1px #d7d7d7;
+}
+
+pre {
+ font-style: monospace;
+ font-size: 16px;
+ padding: 0.5em;
+ margin: 1em;
+ border: solid 1px #c0c0c0;
+ background: #f0f0f0;
+}
+
+code {
+ font-size: 16;
+ padding: 0.5em;
+ margin: 1em;
+}
+
+table {
+ border-collapse: collapse;
+ border: solid 1px #c0c0c0;
+}
+
+table th {
+ background: #f0f0f0;
+ border: solid 1px #c0c0c0;
+ padding-left: 1em;
+ padding-right: 1em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
+
+table td {
+ border: solid 1px #c0c0c0;
+ padding-left: 1em;
+ padding-right: 1em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
+
+a.noexist {
+ color: #ff8c00;
+}
+
+blockquote.quotation {
+ margin: 0.2em 0.5em;
+ border-style: solid;
+ border-width: 0 0 0 2px;
+ padding-left: 0.5em;
+ border-color: red;
+}
+
+.quotation blockquote.quotation {
+ border-color: blue;
+}
+
+.quotation .quotation blockquote.quotation {
+ border-color: green;
+}
+
+.quotation .quotation .quotation blockquote.quotation {
+ border-color: red;
+}
+
+.quotation .quotation .quotation .quotation blockquote.quotation {
+ border-color: blue;
+}
+
+.quotation .quotation .quotation .quotation .quotation blockquote.quotation {
+ border-color: green;
+}
+
+.tocbox {
+ margin: 0em 0;
+ padding-top: 0px;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ border-style: solid;
+ border-color: #c0c0c0;
+ border-width: 1px 1px 1px 1px;
+ border-radius: 10px 10px 10px 10px;
+ background: #efefef;
+ max-width: 600px;
+}
+
+.tocbox .title {
+ padding-top: 10px;
+ padding-left: 10px;
+ font-weight: bold;
+ font-size: 120%;
+}
+
+.tocbox label {
+ padding: 0px;
+ font-weight: bold;
+ background: #efefef;
+ cursor :pointer;
+ transition: .5s;
+}
+
+.tocbox label:after {
+ display: inline-block;
+ content: '[show]';
+ padding-right: 5px;
+ transition: 0.2s;
+}
+
+.tocbox label:hover {
+}
+
+.tocbox input:checked ~ label:after {
+ content: '[hide]';
+ -ms-transform: rotate(360deg);
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ color: #668ad8;
+}
+
+.tocbox input {
+ display: none;
+ height: auto;
+ opacity: 1;
+ background: #efefef;
+}
+
+.tocbox .hidden_show {
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+ opacity: 0;
+ transition: 0.8s;
+}
+
+.tocbox input:checked ~ .hidden_show {
+ padding: 3px 0;
+ height: auto;
+ opacity: 1;
+ background: #efefef;
+}
+
+div.categorylist {
+ background: #f0f0f0;
+ border: solid 1px #c0c0c0;
+ padding-left: 1em;
+ padding-right: 1em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
--- /dev/null
+#bold {
+ font-weight: bold;
+}
+
+#italic {
+ font-style: italic;
+}
+
+#underline {
+ text-decoration: underline;
+}
+
+#linethrough {
+ text-decoration: line-through;
+}
+
+table.transparent {
+ border-collapse: collapse;
+ border: solid 0px;
+}
+
+table.transparent th, table.transparent td {
+ background: #ffffff;
+ border: solid 0px #000000;
+ padding-left: 1em;
+ padding-right: 1em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
+
--- /dev/null
+@charset "UTF-8"
+key.Application.Title: MoxkiWiki - Moxkiriya Stand-Alone Wiki
+key.PreviewWindow.Title: Preview editing content.
+
+key.MainPage: MainPage
+key.Search.Result: Search result
+
+key.Message.found.pages: The following page was found.
+
+key.Contents: Contents
+
+key.Checkbox.Select.all: Select all
+
+key.Button.OK: OK
+key.Button.Cancel: Cancel
+key.Button.Save: Save
+key.Button.Search: Search
+key.Button.Close: Close
+key.Button.Upload: Upload
+key.Button.DeleteCheckedFiles: Delete checked files
+key.Button.Add.Category: Add new category
+key.Button.Delete.Pages: Delete selected pages
+key.Button.Add.Party: Add new party
+key.Button.Preview: Preview
+key.Button.Restore.Version: Restore this version
+
+key.Menu.File: File
+key.Menu.Edit: Edit
+key.Menu.Help: Help
+
+key.MenuItem.New: New
+key.MenuItem.Import: Import
+key.MenuItem.Export: Export
+key.MenuItem.Exit: Exit
+key.MenuItem.Select.Party: Select a party
+key.MenuItem.About.Moxkiriya: About Moxkiriya.
+
+key.TextField.Search_Wiki: Search Wiki
+key.Hyperlink.Reading: Reading
+key.Hyperlink.Pagelist: Page list
+key.Hyperlink.Edit: Edit
+key.Hyperlink.Main: Main
+key.Hyperlink.History: History
+key.Hyperlink.EditAttachFiles: Edit Attach Files
+
+key.Config.Setting.Dialog.Message: Moxkiriya Configuration settings.
+key.Config.Setting.Party.name: Party name:
+key.Config.Setting.Party.textField.prompt: Input a party name
+key.Config.Setting.Party.Default.check: Default party:
+key.Config.Setting.Approot: Approot:
+key.Config.Setting.Approot.textField.prompt: Choose Approot path.
+key.Config.Setting.Cluster.setting: Cluster setting:
+key.Config.Setting.DBServer.URL: Database server URL:
+key.Config.Setting.DBServer.URL.textField.prompt: Input Database server URL.
+key.Config.Setting.DBServer.port: Database server port number:
+key.Config.Setting.DBServer.port.textField.prompt: Input Database server port number.
+key.Config.Setting.DBServer.JDBC.Driver: JDBC Driver:
+key.Config.Setting.DBServer.JDBC.Driver.textField.prompt: Input JDBC Driver.
+
+key.Config.Select.Party.Dialog.Message: Select a party.
+key.Config.Select.Party.Select: Select
+key.Config.Select.Party.name: Party name
+key.Config.Select.Party.Default: Default
+
+key.History.Breadcrumbs.List: List
+key.History.Breadcrumbs.Separator: >
+key.History.Breadcrumbs.Content: Content
+key.History.Content.Title: Title
+
+key.Edit.Label.Category: Category:
+key.Edit.Label.Title: Title(MANDATORY):
+key.Edit.Label.Summary: Summary:
+key.Edit.Label.Contents: Contents:
+key.Edit.Label.AttachFile: Attach file:
+key.Edit.TextField.InputPathname: - Input pathname -
+key.Edit.ComboBox.Category.PromptText: - Select a category. -
+key.Edit.ComboBox.Category.Item.None: None
+
+key.PageList.Label.Namespace: Namespace:
+key.PageList.Label.Redraw: Redraw
+key.Table.Row.Select: Sel
+key.Table.Row.Title: Title
+key.Table.Row.Content: Content
+key.Table.Row.Date: Date
+key.Table.Row.Refs: Refs
+
+
+key.webView.Hyperlink.Reload: Reload
+
+key.Dialog.Message.Cancel.Editing: Cancel editing?
+key.Dialog.Detail.Cancel.Editing: Discard the editing content when you cancel editing.
+
+key.Dialog.Message.Empty.Title: Title is empty.
+key.Dialog.Detail.Input.Title: Please input title.
+
+key.Dialog.Import.Result.Title: Import result.
+key.Dialog.Detail.Import.Success: Succeeded to import.\nExit application to refresh a repository.
+key.Dialog.Detail.Import.Failure: Failed to import.
+
+key.Dialog.Export.Result.Title: Export result.
+key.Dialog.Detail.Export.Success: Succeeded to Export.
+key.Dialog.Detail.Export.Failure: Failed to Export.
+
+key.ImportDialog.Title: Select an import file
+key.ExportDialog.Title: Select an export file
+
+key.EditAttachedFileDialog.Title: Edit attach files.
+key.EditAttachedFileDialog.Button.DeleteCheckedFiles: Delete checked files
+key.EditAttachedFileDialog.Addfiles.DialogTitle: Select attach files.
+key.EditAttachedFileDialog.Current.contents: Current contents:
+
+key.AddCategoryDialog.Label.Select.parent: Select a parent category.
+key.AddCategoryDialog.TextField.Prompt.input.new.category.name: - Input new category name. -
+key.AddCategoryDialg.Button.OK:OK
+key.AddCategoryDialg.Button.Cancel:Cancel
+
+key.search.result.PageTitle: Search results
+key.search.result.SearchKey: Search key:
+key.search.result.message.nopage: There was no pages that hit the search.
+
+key.About.Moxkiriya: About Moxkiriya.
+key.About.Moxkiriya.Copyright: Copyright 2018 Ryuhei Terada All rights reserved.
+key.About.Moxkiriya.License: This software is licensed by GPL version 3.0.
+key.About.Moxkiriya.System.requirement: System requirement.
+key.About.Moxkiriya.System.requirement.Java: Java version 1.7.0 or later.
+key.About.Moxkiriya.Other.info: Other infomation.
+key.About.Moxkiriya.Powered.Apache.Lucene: This software uses Apache Jackrabbit.
+key.About.Moxkiriya.Lucene.license: Apache Jackrabbit is licensed by Apache license version 2.0.
+
--- /dev/null
+<?xml version="1.0"?>\r
+<!--\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+-->\r
+\r
+<!DOCTYPE Repository\r
+ PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 2.0//EN"\r
+ "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">\r
+\r
+<!-- Example Repository Configuration File\r
+ Used by\r
+ - org.apache.jackrabbit.core.config.RepositoryConfigTest.java\r
+ -\r
+-->\r
+<Repository>\r
+ <!--\r
+ virtual file system where the repository stores global state\r
+ (e.g. registered namespaces, custom node types, etc.)\r
+ -->\r
+ <!--\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${rep.home}/repository"/>\r
+ </FileSystem>\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.db.DerbyFileSystem">\r
+ <param name="url" value="jdbc:derby:${rep.home}/db;create=true"/>\r
+ <param name="schemaObjectPrefix" value="rep_"/>\r
+ </FileSystem> \r
+ <!--\r
+ data store configuration\r
+ -->\r
+ <DataStore class="org.apache.jackrabbit.core.data.FileDataStore">\r
+ <param name="path" value="${wiki.root}/${party.name}/datastore"/>\r
+ <param name="minRecordLength" value="1024"/>\r
+ </DataStore>\r
+\r
+ <!--\r
+ security configuration\r
+ -->\r
+ <Security appName="Jackrabbit">\r
+ <!--\r
+ security manager:\r
+ class: FQN of class implementing the JackrabbitSecurityManager interface\r
+ -->\r
+ <SecurityManager class="org.apache.jackrabbit.core.DefaultSecurityManager" workspaceName="security">\r
+ <!--\r
+ workspace access:\r
+ class: FQN of class implementing the WorkspaceAccessManager interface\r
+ -->\r
+ <!-- <WorkspaceAccessManager class="..."/> -->\r
+ <WorkspaceAccessManager class="org.apache.jackrabbit.core.security.simple.SimpleWorkspaceAccessManager" />\r
+ <!-- <param name="config" value="${rep.home}/security.xml"/> -->\r
+ </SecurityManager>\r
+\r
+ <!--\r
+ access manager:\r
+ class: FQN of class implementing the AccessManager interface\r
+ -->\r
+ <!--\r
+ <AccessManager class="org.apache.jackrabbit.core.security.DefaultAccessManager">\r
+ -->\r
+ <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">\r
+ <!-- <param name="config" value="${rep.home}/access.xml"/> -->\r
+ </AccessManager>\r
+\r
+ <!--\r
+ <LoginModule class="org.apache.jackrabbit.core.security.authentication.DefaultLoginModule">\r
+ -->\r
+ <LoginModule class="com.sun.security.auth.module.NTLoginModule">\r
+ <!-- \r
+ anonymous user name ('anonymous' is the default value)\r
+ -->\r
+ </LoginModule>\r
+ </Security>\r
+\r
+ <!--\r
+ location of workspaces root directory and name of default workspace\r
+ -->\r
+ <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>\r
+ <!--\r
+ workspace configuration template:\r
+ used to create the initial workspace if there's no workspace yet\r
+ -->\r
+ <Workspace name="${wsp.name}">\r
+ <!--\r
+ virtual file system of the workspace:\r
+ class: FQN of class implementing the FileSystem interface\r
+ -->\r
+ <!-- \r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${wsp.home}"/>\r
+ </FileSystem>\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.db.DerbyFileSystem">\r
+ <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>\r
+ <param name="schemaObjectPrefix" value="wsp_"/>\r
+ </FileSystem>\r
+ <!--\r
+ persistence manager of the workspace:\r
+ class: FQN of class implementing the PersistenceManager interface\r
+ -->\r
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager">\r
+ <!--\r
+ <param name="url" value="jdbc:derby://192.168.123.25:1527/moxkiriyadb/workspace/db;create=true"/>\r
+ <param name="driver" value="org.apache.derby.jdbc.ClientDriver"/>\r
+ -->\r
+ <param name="url" value="${dbserver.url}:${dbserver.port}/moxkiriyadb/${party.name}/workspace/db;create=true"/>\r
+ <param name="driver" value="${jdbc.driver}"/>\r
+ <param name="schemaObjectPrefix" value="${wsp.name}_"/>\r
+ <param name="externalBLOBs" value="true"/>\r
+ </PersistenceManager>\r
+ <!--\r
+ Search index and the file system it uses.\r
+ class: FQN of class implementing the QueryHandler interface\r
+ -->\r
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">\r
+ <param name="path" value="${wsp.home}/index"/>\r
+ <param name="supportHighlighting" value="true"/>\r
+ </SearchIndex>\r
+ </Workspace>\r
+\r
+ <!--\r
+ Configures the versioning\r
+ -->\r
+ <Versioning rootPath="${rep.home}/version">\r
+ <!--\r
+ Configures the filesystem to use for versioning for the respective\r
+ persistence manager\r
+ -->\r
+ <!--\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${rep.home}/version" />\r
+ </FileSystem>\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.db.DerbyFileSystem">\r
+ <param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>\r
+ <param name="schemaObjectPrefix" value="version_"/>\r
+ </FileSystem>\r
+ <!--\r
+ Configures the persistence manager to be used for persisting version state.\r
+ Please note that the current versioning implementation is based on\r
+ a 'normal' persistence manager, but this could change in future\r
+ implementations.\r
+ -->\r
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager">\r
+ <param name="url" value="${dbserver.url}:${dbserver.port}/moxkiriyadb/${party.name}/version/db;create=true"/>\r
+ <param name="driver" value="${jdbc.driver}"/>\r
+ <param name="schemaObjectPrefix" value="version_"/>\r
+ <param name="externalBLOBs" value="true"/>\r
+ </PersistenceManager>\r
+ </Versioning>\r
+\r
+ <!--\r
+ Search index for content that is shared repository wide\r
+ (/jcr:system tree, contains mainly versions)\r
+ -->\r
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">\r
+ <param name="path" value="${rep.home}/repository/index"/>\r
+ <param name="supportHighlighting" value="true"/>\r
+ </SearchIndex>\r
+\r
+ <!--\r
+ Run with a cluster journal\r
+ -->\r
+ <Cluster id="${cluster.id}">\r
+ <!-- \r
+ <Journal class="org.apache.jackrabbit.core.journal.FileJournal">\r
+ <param name="revision" value="${rep.home}/revision.log" />\r
+ <param name="directory" value="${wiki.root}/${party.name}/journal" />\r
+ </Journal>\r
+ -->\r
+ <Journal class="org.apache.jackrabbit.core.journal.DatabaseJournal">\r
+ <param name="revision" value="${rep.home}/revision.log" />\r
+ <param name="driver" value="${jdbc.driver}" />\r
+ <param name="url" value="${dbserver.url}:${dbserver.port}/moxkiriyadb/${party.name}/journal/db;create=true"/>\r
+ <param name="databaseType" value="derby"/>\r
+ </Journal>\r
+ </Cluster>\r
+</Repository>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>\r
+<!--\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+-->\r
+\r
+<!DOCTYPE Repository\r
+ PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 2.0//EN"\r
+ "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">\r
+\r
+<!-- Example Repository Configuration File\r
+ Used by\r
+ - org.apache.jackrabbit.core.config.RepositoryConfigTest.java\r
+ -\r
+-->\r
+<Repository>\r
+ <!--\r
+ virtual file system where the repository stores global state\r
+ (e.g. registered namespaces, custom node types, etc.)\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${rep.home}/repository"/>\r
+ </FileSystem>\r
+\r
+ <!--\r
+ data store configuration\r
+ -->\r
+ <DataStore class="org.apache.jackrabbit.core.data.FileDataStore"/>\r
+\r
+ <!--\r
+ security configuration\r
+ -->\r
+ <Security appName="Jackrabbit">\r
+ <!--\r
+ security manager:\r
+ class: FQN of class implementing the JackrabbitSecurityManager interface\r
+ -->\r
+ <SecurityManager class="org.apache.jackrabbit.core.DefaultSecurityManager" workspaceName="security">\r
+ <!--\r
+ workspace access:\r
+ class: FQN of class implementing the WorkspaceAccessManager interface\r
+ -->\r
+ <!-- <WorkspaceAccessManager class="..."/> -->\r
+ <WorkspaceAccessManager class="org.apache.jackrabbit.core.security.simple.SimpleWorkspaceAccessManager" />\r
+ <!-- <param name="config" value="${rep.home}/security.xml"/> -->\r
+ </SecurityManager>\r
+\r
+ <!--\r
+ access manager:\r
+ class: FQN of class implementing the AccessManager interface\r
+ -->\r
+ <!--\r
+ <AccessManager class="org.apache.jackrabbit.core.security.DefaultAccessManager">\r
+ -->\r
+ <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">\r
+ <!-- <param name="config" value="${rep.home}/access.xml"/> -->\r
+ </AccessManager>\r
+\r
+ <LoginModule class="org.apache.jackrabbit.core.security.authentication.DefaultLoginModule">\r
+ <!-- \r
+ anonymous user name ('anonymous' is the default value)\r
+ -->\r
+ <param name="anonymousId" value="anonymous"/>\r
+ <!--\r
+ administrator user id (default value if param is missing is 'admin')\r
+ -->\r
+ <param name="adminId" value="admin"/>\r
+ </LoginModule>\r
+ </Security>\r
+\r
+ <!--\r
+ location of workspaces root directory and name of default workspace\r
+ -->\r
+ <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>\r
+ <!--\r
+ workspace configuration template:\r
+ used to create the initial workspace if there's no workspace yet\r
+ -->\r
+ <Workspace name="${wsp.name}">\r
+ <!--\r
+ virtual file system of the workspace:\r
+ class: FQN of class implementing the FileSystem interface\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${wsp.home}"/>\r
+ </FileSystem>\r
+ <!--\r
+ persistence manager of the workspace:\r
+ class: FQN of class implementing the PersistenceManager interface\r
+ -->\r
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager">\r
+ <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>\r
+ <param name="schemaObjectPrefix" value="${wsp.name}_"/>\r
+ </PersistenceManager>\r
+ <!--\r
+ Search index and the file system it uses.\r
+ class: FQN of class implementing the QueryHandler interface\r
+ -->\r
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">\r
+ <param name="path" value="${wsp.home}/index"/>\r
+ <param name="supportHighlighting" value="true"/>\r
+ </SearchIndex>\r
+ </Workspace>\r
+\r
+ <!--\r
+ Configures the versioning\r
+ -->\r
+ <Versioning rootPath="${rep.home}/version">\r
+ <!--\r
+ Configures the filesystem to use for versioning for the respective\r
+ persistence manager\r
+ -->\r
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">\r
+ <param name="path" value="${rep.home}/version" />\r
+ </FileSystem>\r
+\r
+ <!--\r
+ Configures the persistence manager to be used for persisting version state.\r
+ Please note that the current versioning implementation is based on\r
+ a 'normal' persistence manager, but this could change in future\r
+ implementations.\r
+ -->\r
+ <!--\r
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager">\r
+ <param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>\r
+ <param name="schemaObjectPrefix" value="version_"/>\r
+ </PersistenceManager>\r
+ -->\r
+ <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />\r
+ </Versioning>\r
+\r
+ <!--\r
+ Search index for content that is shared repository wide\r
+ (/jcr:system tree, contains mainly versions)\r
+ -->\r
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">\r
+ <param name="path" value="${rep.home}/repository/index"/>\r
+ <param name="supportHighlighting" value="true"/>\r
+ </SearchIndex>\r
+\r
+ <!--\r
+ Run with a cluster journal\r
+ -->\r
+ <Cluster id="node1">\r
+ <Journal class="org.apache.jackrabbit.core.journal.MemoryJournal"/>\r
+ </Cluster>\r
+</Repository>\r
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
--- /dev/null
+package com.wiki.standalone.moxkiriya.util;
+
+import java.awt.Desktop;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+public class DefaultProgramExecutor {
+ public static void execute(String path) {
+ Desktop desktop = Desktop.getDesktop();
+
+ try {
+ desktop.open(new File(path));
+ } catch(Exception e) {
+ try {
+ desktop.browse(new java.net.URI("file://" + path));
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+}
--- /dev/null
+/**
+ * Moxkiriya standalone Wiki.
+ * File IO utility.
+ *
+ * @author Ryuhei Terada
+ * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
+ */
+package com.wiki.standalone.moxkiriya.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+
+/**
+ * ファイル IO utilityクラス
+ *
+ */
+public class FileIO {
+ /**
+ * バッファreaderを生成する。文字セットは"UTF-8"を指定する。
+ * @param stringReader
+ * @return 生成したバッファreader
+ * @throws Exception
+ */
+ public static BufferedReader bufferedReader(StringReader stringReader)
+ throws Exception {
+ return new BufferedReader(stringReader);
+ }
+
+ /**
+ * バッファreaderを生成する。文字セットは"UTF-8"を指定する。
+ * @param pathname
+ * @return 生成したバッファreader
+ * @throws Exception
+ */
+ public static BufferedReader bufferedReader(String pathname)
+ throws Exception {
+ return bufferedReader(pathname, "UTF-8");
+ }
+
+ /**
+ * charsetNameで指定された文字セットのバッファreaderを生成する
+ * @param pathname
+ * @param charsetName
+ * @return 生成したバッファreader
+ * @throws Exception
+ */
+ public static BufferedReader bufferedReader(String pathname, String charsetName)
+ throws Exception {
+ return bufferedReader(new File(pathname), charsetName);
+ }
+
+ /**
+ * バッファreaderを生成する。文字セットは"UTF-8"を指定する。
+ * @param file
+ * @return 生成したバッファreader
+ * @throws Exception
+ */
+ public static BufferedReader bufferedReader(File file)
+ throws Exception {
+ return bufferedReader(file, "UTF-8");
+ }
+
+ /**
+ * charsetNameで指定された文字セットのバッファreaderを生成する。
+ * @param file
+ * @param charsetName
+ * @return 生成したバッファreader
+ * @throws Exception
+ */
+ public static BufferedReader bufferedReader(File file, String charsetName)
+ throws Exception {
+ BufferedReader reader = null;
+ if(file.exists() == true) {
+ FileInputStream inputStream = new FileInputStream(file);
+ InputStreamReader streamReader = new InputStreamReader(inputStream, charsetName);
+ reader = new BufferedReader(streamReader);
+ }
+
+ return reader;
+ }
+
+ /**
+ * バッファwriterを生成する。文字セットは"UTF-8"を指定する。
+ * @param pathname
+ * @return 生成したバッファwriter
+ * @throws Exception
+ */
+ public static BufferedWriter bufferedWriter(String pathname)
+ throws Exception {
+ return bufferedWriter(pathname, "UTF-8");
+ }
+
+ /**
+ * charsetNameで指定された文字セットのバッファwriterを生成する
+ * @param pathname
+ * @param charsetName
+ * @return 生成したバッファwriter
+ * @throws Exception
+ */
+ public static BufferedWriter bufferedWriter(String pathname, String charsetName)
+ throws Exception {
+ return bufferedWriter(new File(pathname), charsetName);
+ }
+
+ /**
+ * バッファwriterを生成する。文字セットは"UTF-8"を指定する。
+ * @param file
+ * @return 生成したバッファwriter
+ * @throws Exception
+ */
+ public static BufferedWriter bufferedWriter(File file)
+ throws Exception {
+ return bufferedWriter(file, "UTF-8");
+ }
+
+ /**
+ * charsetNameで指定された文字セットのバッファwriterを生成する。
+ * @param file
+ * @param charsetName
+ * @return 生成したバッファwriter
+ * @throws Exception
+ */
+ public static BufferedWriter bufferedWriter(File file, String charsetName)
+ throws Exception {
+ BufferedWriter writer = null;
+ if(file.exists() != true) {
+ file.createNewFile();
+ }
+
+ FileOutputStream outputStream = new FileOutputStream(file);
+ OutputStreamWriter streamReader = new OutputStreamWriter(outputStream, charsetName);
+ writer = new BufferedWriter(streamReader);
+
+ return writer;
+ }
+
+}
--- /dev/null
+package com.wiki.standalone.moxkiriya.util;
+
+import java.util.ArrayList;
+
+/**
+ * File種別を判定する。
+ */
+public class FileTypeDeterminator {
+ /**
+ * 画像ファイルと判定する拡張子のリスト
+ */
+ private final static ArrayList<String> imageExtensionList = new ArrayList<String>() {
+ private static final long serialVersionUID = 1L;
+ { add(".jpg"); }
+ { add(".png"); }
+ { add(".gif"); }
+ };
+
+ /**
+ * ファイルが画像ファイルか判定する。
+ * @param filename
+ * @return 画像ファイルかどうか
+ */
+ public static boolean isImageFile(String filename) {
+ boolean isImage = false;
+
+ if(filename.contains(".") == true) {
+ String extension = filename.substring(filename.lastIndexOf("."));
+
+ for(String key: imageExtensionList) {
+ if(extension.equalsIgnoreCase(key) == true) {
+ isImage = true;
+ break;
+ }
+ }
+ }
+
+ return isImage;
+ }
+}