mirror of https://github.com/apache/openjpa.git
[OPENJPA-2751] trailing white-spaces were removed
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1842614 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4709f38ba2
commit
f2fc98031e
2
LICENSE
2
LICENSE
|
@ -250,7 +250,7 @@ openjpa-persistence -
|
|||
persistence-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from:
|
||||
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd)
|
||||
persistence_2_0-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from:
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd).
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd).
|
||||
===========================
|
||||
|
||||
COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!--
|
||||
Please keep the project tag on one line to avoid confusing
|
||||
<!--
|
||||
Please keep the project tag on one line to avoid confusing
|
||||
the release plugin.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
@ -85,7 +85,7 @@
|
|||
<createSourcesJar>${createSources}</createSourcesJar>
|
||||
<keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
|
||||
<promoteTransitiveDependencies>true</promoteTransitiveDependencies>
|
||||
<!--
|
||||
<!--
|
||||
Have to do this again here, as these settings
|
||||
from shaded openjpa.jar get lost in the shading
|
||||
-->
|
||||
|
|
|
@ -239,27 +239,27 @@ serp-1.13.1.jar - BSD License
|
|||
Copyright (c) 2002, A. Abram White
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of 'serp' nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
===========================
|
||||
|
@ -271,7 +271,7 @@ openjpa-persistence -
|
|||
persistence-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from:
|
||||
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd)
|
||||
persistence_2_0-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from:
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd).
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd).
|
||||
===========================
|
||||
|
||||
COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
|
||||
|
|
|
@ -24,7 +24,7 @@ openjpa-all includes software developed by the:
|
|||
Apache Commons Lang project
|
||||
Apache Commons Logging project
|
||||
Apache Commons Pool project
|
||||
Apache Geronimo project
|
||||
Apache Geronimo project
|
||||
Java EE Specs - JMS 1.1, JTA 1.1, Bean Validation 1.0 and JPA 2.0
|
||||
SERP project
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class TestJPAValidation extends junit.framework.TestCase {
|
|||
* and pre-persist lifecycle events.
|
||||
*/
|
||||
public void testValidation() {
|
||||
EntityManagerFactory emf =
|
||||
EntityManagerFactory emf =
|
||||
Persistence.createEntityManagerFactory("BeanValidation");
|
||||
EntityManager em = emf.createEntityManager();
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class TestJPAValidation extends junit.framework.TestCase {
|
|||
img.setFileName("Winter_01.gif");
|
||||
loadImage(img);
|
||||
img.setLocation(loc);
|
||||
|
||||
|
||||
// *** PERSIST ***
|
||||
try {
|
||||
em.getTransaction().begin();
|
||||
|
@ -77,7 +77,7 @@ public class TestJPAValidation extends junit.framework.TestCase {
|
|||
// *** UPDATE ***
|
||||
try {
|
||||
em.getTransaction().begin();
|
||||
// Modify the file name to a non-matching file name
|
||||
// Modify the file name to a non-matching file name
|
||||
// and commit to trigger an update
|
||||
System.out.println("Modifying file name to use an extension that does not");
|
||||
System.out.println("match the file type. This will cause a CVE.");
|
||||
|
@ -90,7 +90,7 @@ public class TestJPAValidation extends junit.framework.TestCase {
|
|||
System.out.println("Update failed as expected");
|
||||
handleConstraintViolation(cve);
|
||||
}
|
||||
// The update failure caused img to be detached. It must be merged back
|
||||
// The update failure caused img to be detached. It must be merged back
|
||||
// into the persistence context.
|
||||
img = em.merge(img);
|
||||
|
||||
|
@ -131,10 +131,10 @@ public class TestJPAValidation extends junit.framework.TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
// Mock image loading utility... simply loads the GIF89a header to satisfy the
|
||||
// Mock image loading utility... simply loads the GIF89a header to satisfy the
|
||||
// constraint validator.
|
||||
private static void loadImage(Image img) {
|
||||
img.setData(new byte[] { 'G', 'I', 'F', '8', '9', 'a' });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
@ -32,7 +32,7 @@ import static org.apache.openjpa.example.gallery.ImageType.GIF;
|
|||
import static org.apache.openjpa.example.gallery.ImageType.JPEG;
|
||||
|
||||
/**
|
||||
* Type-level annotation used to specify an image constraint. Uses
|
||||
* Type-level annotation used to specify an image constraint. Uses
|
||||
* ImageValidator to perform the validation.
|
||||
*/
|
||||
@Documented
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
@ -33,7 +33,7 @@ import static org.apache.openjpa.example.gallery.ImageType.GIF;
|
|||
import static org.apache.openjpa.example.gallery.ImageType.JPEG;
|
||||
|
||||
/**
|
||||
* Attribute-level annotation used to specify an image content constraint. Uses
|
||||
* Attribute-level annotation used to specify an image content constraint. Uses
|
||||
* ImageContentValidator to perform the validation.
|
||||
*/
|
||||
@Documented
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
@ -51,13 +51,13 @@ public class ImageValidator implements ConstraintValidator<ImageConstraint, Imag
|
|||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// All these values will be pre-validated with @NotNull constraints
|
||||
// so they are safe to use
|
||||
byte[] data = value.getData();
|
||||
String fileName = value.getFileName();
|
||||
ImageType type = value.getType();
|
||||
|
||||
|
||||
// Verify the GIF type is correct, has the correct extension and
|
||||
// the data header is either GIF87 or GIF89
|
||||
if (allowedTypes.contains(ImageType.GIF) &&
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.constraint;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import javax.validation.groups.Default;
|
|||
|
||||
/**
|
||||
* Sequenced validation group definition. When this validation group is
|
||||
* used constraints within the Default group will validate first. If
|
||||
* used constraints within the Default group will validate first. If
|
||||
* successful, constraints within the ImageGroup will validate next.
|
||||
*/
|
||||
@GroupSequence({Default.class, ImageGroup.class})
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.model;
|
||||
|
||||
|
@ -37,13 +37,13 @@ public class Album {
|
|||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
|
||||
@OneToMany
|
||||
private List<Image> images;
|
||||
|
||||
|
||||
@ManyToMany
|
||||
private List<Creator> creator;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.model;
|
||||
|
||||
|
@ -38,20 +38,20 @@ public class Creator {
|
|||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
|
||||
@NotNull(message="Photographer's first name must be specified.")
|
||||
private String firstName;
|
||||
|
||||
|
||||
@NotNull(message="Photographer's last name must be specified.")
|
||||
private String lastName;
|
||||
|
||||
@OneToMany
|
||||
@OrderBy("fileName")
|
||||
private List<Image> images;
|
||||
|
||||
|
||||
@ManyToMany
|
||||
private List<Album> albums;
|
||||
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.example.gallery.model;
|
||||
|
||||
|
@ -38,14 +38,14 @@ import org.apache.openjpa.example.gallery.constraint.ImageGroup;
|
|||
@Entity
|
||||
@ImageConstraint(groups=ImageGroup.class)
|
||||
public class Image {
|
||||
|
||||
|
||||
private long id;
|
||||
private ImageType type;
|
||||
private String fileName;
|
||||
private byte[] data;
|
||||
private byte[] data;
|
||||
private Location location;
|
||||
private Creator creator;
|
||||
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
public long getId() {
|
||||
|
@ -61,11 +61,11 @@ public class Image {
|
|||
public ImageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public void setType(ImageType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@NotNull(message="Image file name must not be null.")
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
|
|
|
@ -33,16 +33,16 @@ public class Location {
|
|||
|
||||
@NotNull(message="City must be specified.")
|
||||
private String city;
|
||||
|
||||
|
||||
private String street;
|
||||
|
||||
|
||||
private String state;
|
||||
|
||||
@NotNull(message="Country must be specified.")
|
||||
@Size(message="Country must be 50 characters or less.", max=50)
|
||||
@Column(length=50)
|
||||
private String country;
|
||||
|
||||
|
||||
@Size(message="Zip code must be 10 characters or less.", max=10)
|
||||
@Pattern(message="Zip code must be 5 digits or use the 5+4 format.",
|
||||
regexp="^\\d{5}(([\\-]|[\\+])\\d{4})?$")
|
||||
|
|
|
@ -7,22 +7,22 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
|
||||
version="2.0" >
|
||||
|
||||
|
||||
<persistence-unit name="BeanValidation">
|
||||
<description>Example persistence unit for Bean Validation</description>
|
||||
<class>org.apache.openjpa.example.gallery.model.Album</class>
|
||||
|
@ -32,13 +32,13 @@
|
|||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<validation-mode>CALLBACK</validation-mode>
|
||||
<properties>
|
||||
<property name="openjpa.ConnectionDriverName"
|
||||
<property name="openjpa.ConnectionDriverName"
|
||||
value="org.apache.derby.jdbc.EmbeddedDriver" />
|
||||
<property name="openjpa.ConnectionURL"
|
||||
value="jdbc:derby:target/database/ImageDB;create=true" />
|
||||
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
|
||||
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
|
||||
|
||||
|
||||
<property name="javax.persistence.validation.group.pre-persist"
|
||||
value="org.apache.openjpa.example.gallery.constraint.SequencedImageGroup"/>
|
||||
<property name="javax.persistence.validation.group.pre-update"
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
|
@ -41,20 +41,20 @@ tt {
|
|||
<body>
|
||||
<h3>Instructions to build, deploy and run JEST demo</h3>
|
||||
<hr>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt><b>Step 1: Download OpenJPA binary</b></dt>
|
||||
<dd> OpenJPA binaries are available from OpenJPA
|
||||
<dt><b>Step 1: Download OpenJPA binary</b></dt>
|
||||
<dd> OpenJPA binaries are available from OpenJPA
|
||||
<a href="http://openjpa.apache.org/downloads.html" target="_blank">download site</a>.
|
||||
The nightly snapshots of version <tt>2.2.0</tt> that includes JEST are ready for
|
||||
<a href="https://repository.apache.org/snapshots/org/apache/openjpa/apache-openjpa/2.2.0-SNAPSHOT/"
|
||||
target="_blank">download</a> at lower half of the page.
|
||||
</dd>
|
||||
The nightly snapshots of version <tt>2.2.0</tt> that includes JEST are ready for
|
||||
<a href="https://repository.apache.org/snapshots/org/apache/openjpa/apache-openjpa/2.2.0-SNAPSHOT/"
|
||||
target="_blank">download</a> at lower half of the page.
|
||||
</dd>
|
||||
<br>
|
||||
<dt><b>Step 2: Get the JEST demo application</b></dt>
|
||||
<dd> A simple servlet based application is used to demonstrate JEST usage. This simple
|
||||
application merely defines a persistent unit with two persistent classes: <tt>Actor</tt>
|
||||
and <tt>Movie</tt>. The source code, persistence unit descriptor
|
||||
and <tt>Movie</tt>. The source code, persistence unit descriptor
|
||||
<tt>META-INF/persistence.xml</tt>, deployment descriptor <tt>WEB-INF/web.xml</tt>
|
||||
and Ant-based build script are available from OpenJPA svn repository.<br>
|
||||
Checkout these source files from the repository to a local directory.
|
||||
|
@ -66,11 +66,11 @@ tt {
|
|||
<dt><b>Step 3: Configure for your environment</b></dt>
|
||||
<dd>
|
||||
The persistence unit descriptor <tt>META-INF/persistence.xml</tt> for the example application
|
||||
needs to be configured with database details. By default, it is configured for a MySQL database.
|
||||
needs to be configured with database details. By default, it is configured for a MySQL database.
|
||||
<br>
|
||||
The build script requires the location of openjpa library and servlet API library jar.
|
||||
The build script requires the location of openjpa library and servlet API library jar.
|
||||
Edit <tt>build.properties</tt> file to set the variables to locations appropriate for
|
||||
your environment.
|
||||
your environment.
|
||||
</dd>
|
||||
<br>
|
||||
<dt><b>Step 4: Build the application</b></dt>
|
||||
|
@ -92,7 +92,7 @@ tt {
|
|||
<dt><b>Step 5: Deploy the web archive</b></dt>
|
||||
<dd>
|
||||
Once the web archive is ready, deploy it in an application server or servlet container by
|
||||
following standard practice. Needless to say, the database driver specified in
|
||||
following standard practice. Needless to say, the database driver specified in
|
||||
<tt>META-INF/persistence.xml</tt> should also be available in the deployment environment.
|
||||
</dd>
|
||||
<br>
|
||||
|
@ -101,12 +101,12 @@ tt {
|
|||
Once the web archive has been deployed, you can verify by visiting the home page (and the only page)
|
||||
of the sample application in your browser<br>
|
||||
<code>http://localhost:8080/demo/</code> <br>
|
||||
The context path of the deployed servlet is <tt>demo</tt> as you may have noticed in <tt>WEB-INF/web.xml</tt>.
|
||||
The context path of the deployed servlet is <tt>demo</tt> as you may have noticed in <tt>WEB-INF/web.xml</tt>.
|
||||
The JEST servlet is just next door at<br>
|
||||
<code>http://localhost:8080/demo/jest/</code> <br>
|
||||
<span class="warn">notice the trailing forward slash in the URL above</span><br>
|
||||
Now you should see JEST home page with colorful icons. Enjoy browsing!
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</body>
|
||||
|
|
|
@ -26,7 +26,7 @@ maven.repos=${user.home}/.m2/repository
|
|||
# OpenJPA version
|
||||
openjpa.version=2.2.0-SNAPSHOT
|
||||
|
||||
# The variable of interest are openjpa.dir and openjpa.jar.
|
||||
# The variable of interest are openjpa.dir and openjpa.jar.
|
||||
# Though the varaible value is expressed in terms of other variables here, you can specify the value directly.
|
||||
openjpa.dir=${maven.repos}/org/apache/openjpa/openjpa-all/${openjpa.version}
|
||||
openjpa.jar=openjpa-all-${openjpa.version}.jar
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
|
@ -50,7 +50,7 @@
|
|||
<property name="webapp.war" value="demo.war" />
|
||||
<!-- ================================================================== -->
|
||||
|
||||
<path id="compile.classpath" description="Compilation classpath requires OpenJPA specific library
|
||||
<path id="compile.classpath" description="Compilation classpath requires OpenJPA specific library
|
||||
because of bytecode enhancement">
|
||||
<pathelement location="${src.dir}" />
|
||||
<pathelement location="${classes.dir}" />
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package demo;
|
||||
|
@ -34,7 +34,7 @@ import org.apache.openjpa.persistence.FetchGroups;
|
|||
|
||||
/**
|
||||
* A persistent entity with singular and plural association.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -46,7 +46,7 @@ import org.apache.openjpa.persistence.FetchGroups;
|
|||
})
|
||||
})
|
||||
public class Actor {
|
||||
public static enum Gender {Male, Female};
|
||||
public static enum Gender {Male, Female};
|
||||
@Id
|
||||
private String id;
|
||||
private String firstName;
|
||||
|
@ -57,11 +57,11 @@ public class Actor {
|
|||
private Actor partner;
|
||||
@OneToMany
|
||||
private Set<Movie> movies;
|
||||
|
||||
|
||||
protected Actor() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Actor(String id, String firstName, String lastName, Gender gender, Date dob) {
|
||||
super();
|
||||
this.id = id;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package demo;
|
||||
|
@ -25,7 +25,7 @@ import javax.persistence.EntityManager;
|
|||
|
||||
/**
|
||||
* Loads some example Actor-Movie data.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -38,14 +38,14 @@ public class DataLoader {
|
|||
new Object[] {"m3", "Al", "Pacino", Actor.Gender.Male, new Date(50, 1, 12)},
|
||||
new Object[] {"m4", "Jack", "Nichelson",Actor.Gender.Male, new Date(40, 4, 14)},
|
||||
new Object[] {"m5", "Clint", "Eastwood", Actor.Gender.Male, new Date(50, 1, 12)},
|
||||
|
||||
|
||||
new Object[] {"f1", "Meryl", "Streep", Actor.Gender.Female, new Date(40, 4, 14)},
|
||||
new Object[] {"f2", "Fay", "Dunaway", Actor.Gender.Female, new Date(50, 1, 12)},
|
||||
new Object[] {"f3", "Jodie", "Foster", Actor.Gender.Female, new Date(40, 4, 14)},
|
||||
new Object[] {"f4", "Diane", "Keaton", Actor.Gender.Female, new Date(50, 1, 12)},
|
||||
new Object[] {"f5", "Catherine", "Hepburn", Actor.Gender.Female, new Date(40, 4, 14)},
|
||||
};
|
||||
|
||||
|
||||
public static Object[][] MOVIE_DATA = {
|
||||
new Object[] {"1", "China Town", 1980},
|
||||
new Object[] {"2", "Taxi Driver", 1980},
|
||||
|
@ -53,7 +53,7 @@ public class DataLoader {
|
|||
new Object[] {"4", "Godfather", 1980},
|
||||
new Object[] {"5", "Horse Whisperer", 1980},
|
||||
};
|
||||
|
||||
|
||||
public static int[][] MOVIE_ACTORS = {
|
||||
new int[] {3,6},
|
||||
new int[] {1,7},
|
||||
|
@ -61,7 +61,7 @@ public class DataLoader {
|
|||
new int[] {2,3,8},
|
||||
new int[] {0}
|
||||
};
|
||||
|
||||
|
||||
public static int[][] PARTNERS = {
|
||||
new int[] {3,6},
|
||||
new int[] {1,7},
|
||||
|
@ -74,8 +74,8 @@ public class DataLoader {
|
|||
System.err.println("Found " + count + " Movie records in the database");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Actor[] actors = createActors();
|
||||
Movie[] movies = createMovies();
|
||||
linkActorAndMovie(movies, actors);
|
||||
|
@ -89,7 +89,7 @@ public class DataLoader {
|
|||
}
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
|
||||
Actor[] createActors() {
|
||||
Actor[] actors = new Actor[ACTOR_DATA.length];
|
||||
for (int i = 0; i < ACTOR_DATA.length; i++) {
|
||||
|
@ -98,7 +98,7 @@ public class DataLoader {
|
|||
}
|
||||
return actors;
|
||||
}
|
||||
|
||||
|
||||
Movie[] createMovies() {
|
||||
Movie[] movies = new Movie[MOVIE_DATA.length];
|
||||
for (int i = 0; i < MOVIE_DATA.length; i++) {
|
||||
|
@ -107,7 +107,7 @@ public class DataLoader {
|
|||
}
|
||||
return movies;
|
||||
}
|
||||
|
||||
|
||||
void linkActorAndMovie(Movie[] movies, Actor[] actors) {
|
||||
for (int i = 0; i < MOVIE_ACTORS.length; i++) {
|
||||
int[] roles = MOVIE_ACTORS[i];
|
||||
|
@ -119,7 +119,7 @@ public class DataLoader {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void makePartner(Actor[] actors) {
|
||||
for (int i = 0; i < PARTNERS.length; i++) {
|
||||
int[] partners = PARTNERS[i];
|
||||
|
@ -129,5 +129,5 @@ public class DataLoader {
|
|||
a2.setPartner(a1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package demo;
|
||||
|
@ -49,38 +49,38 @@ public class Movie {
|
|||
private int year;
|
||||
@OneToMany(fetch=FetchType.EAGER)
|
||||
private Set<Actor> actors;
|
||||
|
||||
|
||||
protected Movie() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Movie(String id, String title, int year) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
|
||||
public void addActor(Actor a) {
|
||||
if (actors == null)
|
||||
actors = new HashSet<Actor>();
|
||||
actors.add(a);
|
||||
}
|
||||
|
||||
|
||||
public Set<Actor> getActors() {
|
||||
return actors;
|
||||
}
|
||||
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package demo;
|
||||
|
@ -42,7 +42,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
/**
|
||||
* A very simple servlet that is initialized with some example Actor-Movie records.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -50,8 +50,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
public class SimpleApp extends HttpServlet {
|
||||
EntityManagerFactory _emf;
|
||||
private static String UNIT_NAME = "jestdemo";
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
config.getServletContext().log("Initializing persistence unit [" + UNIT_NAME + "]");
|
||||
|
@ -65,7 +65,7 @@ public class SimpleApp extends HttpServlet {
|
|||
}
|
||||
config.getServletContext().log("Initialized with persistence unit [" + UNIT_NAME + "]");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The only response by this application is an <code>index.html</code> file.
|
||||
*/
|
||||
|
@ -78,7 +78,7 @@ public class SimpleApp extends HttpServlet {
|
|||
out.write((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (_emf != null) {
|
||||
|
|
|
@ -7,26 +7,26 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
version="1.0">
|
||||
|
||||
|
||||
<persistence-unit name="jestdemo">
|
||||
|
||||
|
||||
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
|
||||
|
||||
|
||||
<class>demo.Movie</class>
|
||||
<class>demo.Actor</class>
|
||||
|
||||
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/jest"/>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
|
||||
|
||||
|
||||
</persistence>
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
under the License.
|
||||
-->
|
||||
|
||||
<web-app version="2.4"
|
||||
xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<web-app version="2.4"
|
||||
xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
|
||||
<display-name>Demo Application with JEST Servlet</display-name>
|
||||
<display-name>Demo Application with JEST Servlet</display-name>
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
@ -30,19 +30,19 @@
|
|||
An example of deploying a simple web application with JEST servlet.
|
||||
This descriptor specifies the Demo Application servlet as well as JEST servlet.
|
||||
</description>
|
||||
|
||||
|
||||
<servlet>
|
||||
<description>
|
||||
<description>
|
||||
This is the Demo Application Servlet.
|
||||
The servlet is mapped to URL pattern /app/* so this servlet can be accessed as
|
||||
http://host:port/demo/app/
|
||||
http://host:port/demo/app/
|
||||
where "demo" is the name of the deployed web application.
|
||||
|
||||
Assume that the Demo Application Servlet is using a persistence unit named
|
||||
|
||||
Assume that the Demo Application Servlet is using a persistence unit named
|
||||
'jestdemo'. The JEST Servlet will require the persistence unit name to
|
||||
browse the Demo Application.
|
||||
browse the Demo Application.
|
||||
</description>
|
||||
|
||||
|
||||
<servlet-name>demo</servlet-name>
|
||||
<servlet-class>demo.SimpleApp</servlet-class>
|
||||
</servlet>
|
||||
|
@ -50,18 +50,18 @@
|
|||
<servlet-name>demo</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<!-- Deployment descriptor for JESTServlet. -->
|
||||
<servlet>
|
||||
<description>
|
||||
This is the JEST servlet.
|
||||
This is the JEST servlet.
|
||||
JEST Servlet needs to know the name of the persistence unit used by the Demo Application.
|
||||
The unit name is specified by mandatory "persistence.unit" parameter during initialization.
|
||||
|
||||
|
||||
The JEST servlet is mapped to URL pattern /jest/* in servlet mapping section. So to access
|
||||
JEST servlet, use the following URI
|
||||
http://host:port/demo/jest/
|
||||
Notice the trailing forward slash character is significant.
|
||||
Notice the trailing forward slash character is significant.
|
||||
</description>
|
||||
<servlet-name>jest</servlet-name>
|
||||
<servlet-class>org.apache.openjpa.persistence.jest.JESTServlet</servlet-class>
|
||||
|
@ -78,5 +78,5 @@
|
|||
<servlet-name>jest</servlet-name>
|
||||
<url-pattern>/jest/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-app>
|
||||
|
|
|
@ -28,36 +28,36 @@ body {background-image:url("images/back40.gif");
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>DNA: Do-Nothing Application</h1>
|
||||
<h1>DNA: Do-Nothing Application</h1>
|
||||
<hr>
|
||||
<span style="font-size:1.2em;color:green;font-weight:bold">DNA application is used to demonstrate </span>
|
||||
<span style="font-size:1.2em;color:green;font-weight:bold">DNA application is used to demonstrate </span>
|
||||
<A HREF="./jest/">JEST</A>.
|
||||
<br>
|
||||
DNA application is deployed as a HTTP Servlet.<br>
|
||||
|
||||
|
||||
The servlet creates an OpenJPA persistence unit at initialization.<br>
|
||||
|
||||
|
||||
It does nothing else, other than serving this single web page you are reading now.
|
||||
The fact that you are reading this page means the persistence unit has been initialized.
|
||||
The fact that you are reading this page means the persistence unit has been initialized.
|
||||
<p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Requirement for enabling JEST</h2>
|
||||
|
||||
|
||||
The requirements for an application to enable JEST are
|
||||
|
||||
|
||||
<p>
|
||||
► JEST Servlet must be <A href="#web.xml">deployed</A> within the same module scope of the application. <br>
|
||||
► The unit name of the persistence unit used by the application must be known to JEST Servlet <br>
|
||||
► The persistence unit must be configured with <br>
|
||||
<span style="color:green;font-weight:bold;text-align:center;background-color: #EEEEEE"><tt>openjpa.EntityManagerFactoryPool=true</tt></span>
|
||||
<span style="color:green;font-weight:bold;text-align:center;background-color: #EEEEEE"><tt>openjpa.EntityManagerFactoryPool=true</tt></span>
|
||||
<p>
|
||||
Once JEST servlet knows the name of the persistence unit, it can <br>
|
||||
|
||||
|
||||
► browse the domain model<br>
|
||||
► execute query <br>
|
||||
from any web browser in a <em>meta-data driven</em>, <em>generic</em> fashion
|
||||
i.e. without knowing anything further about he application.
|
||||
from any web browser in a <em>meta-data driven</em>, <em>generic</em> fashion
|
||||
i.e. without knowing anything further about he application.
|
||||
<p>
|
||||
<p>
|
||||
<hr>
|
||||
|
@ -73,7 +73,7 @@ body {background-image:url("images/back40.gif");
|
|||
<servlet-name></span><span style="color:blue;">demo</span><span style="color:gray;font-weight:bold;"></servlet-name>
|
||||
<url-pattern></span><span style="color:blue;">/*</span><span style="color:gray;font-weight:bold;"></url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<span style="color:green;font-weight:bold;"><!-- Deployment descriptor for JESTServlet. --></span>
|
||||
<servlet>
|
||||
<servlet-name></span><span style="color:red;">jest</span><span style="color:gray;font-weight:bold;"></servlet-name>
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<assembly>
|
||||
<id>binary</id>
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
|
@ -25,16 +25,16 @@
|
|||
<!-- ====================================================================== -->
|
||||
|
||||
<project name="OpenBooks.JEE.Liberty">
|
||||
|
||||
|
||||
<!-- Location of WebSphere Application Server Liberty Profile home/install dir -->
|
||||
<property name="liberty.home" value="/was8.5/gm1216.05/WebSphere/AppServer/wlp"/>
|
||||
|
||||
|
||||
<!-- WebSphere Liberty Server name (IP name or address) -->
|
||||
<property name="liberty.server" value=""/>
|
||||
|
||||
|
||||
<!-- Location of WebSphere Application Server Liberty Profile bin dir -->
|
||||
<property name="liberty.bin" value="${liberty.home}/bin"/>
|
||||
|
||||
|
||||
<!-- WebSphere Liberty Server dropins directory -->
|
||||
<property name="liberty.dropins" value="${liberty.home}/usr/servers/${liberty.server}/dropins"/>
|
||||
|
||||
|
@ -42,12 +42,12 @@
|
|||
<echo message="In Liberty pre-package"/>
|
||||
<copy file="${rsrc.dir}/META-INF/persistence.jee.liberty.xml" tofile="${classes.dir}/META-INF/persistence.xml"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="uninstall"
|
||||
description="Uninstall OpenBooks from the WebSphere Application Server, Liberty Profile">
|
||||
<echo message="Uninstall is a no-op in Liberty, just copy in a new war during the install process..."/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="install"
|
||||
description="Deploy OpenBooks as a WAR application in WebSphere Application Server, Liberty Profile">
|
||||
<condition property="default.deploy">
|
||||
|
@ -64,7 +64,7 @@
|
|||
Creating Derby JDBC provider and data source
|
||||
WAS Liberty Home: ${liberty.home}
|
||||
WAS Liberty Server: ${liberty.server}
|
||||
|
||||
|
||||
Nothing to do since "liberty.server" is not set...
|
||||
</echo>
|
||||
</target>
|
||||
|
@ -73,20 +73,20 @@
|
|||
<!-- Liberty server IP name is provided. This type of deployment -->
|
||||
<!-- requires server IP name liberty.home, liberty.server, liberty.dropins, -->
|
||||
<!-- to be provided. -->
|
||||
|
||||
|
||||
<target name="liberty.deploy.server" unless="default.deploy">
|
||||
<echo>
|
||||
-------------------------------------------
|
||||
Creating Derby JDBC Provider and DataSource
|
||||
WAS Home: ${liberty.home}
|
||||
WAS Server: ${liberty.server}
|
||||
|
||||
|
||||
Have to figure out how to configure datasources in server.xml...
|
||||
</echo>
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Deploying OpenBooks demo application
|
||||
|
||||
|
||||
Copying openbooks.war to dropins directory...
|
||||
Liberty server ${liberty.server} should automatically restart application...
|
||||
</echo>
|
||||
|
@ -97,7 +97,7 @@
|
|||
<exec osfamily="unix" dir="${liberty.bin}" executable="server">
|
||||
<arg line="start ${liberty.server}"/>
|
||||
</exec>
|
||||
|
||||
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Start OpenBooks via http://localhost:9080/openbooks
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
|
@ -29,37 +29,37 @@
|
|||
<!-- ====================================================================== -->
|
||||
|
||||
<project name="OpenBooks.JEE.WAS">
|
||||
|
||||
|
||||
<!-- WebSphere Application Server task definitions -->
|
||||
<taskdef name="wsUninstallApp" classname="com.ibm.websphere.ant.tasks.UninstallApplication"/>
|
||||
<taskdef name="wsInstallApp" classname="com.ibm.websphere.ant.tasks.InstallApplication"/>
|
||||
<taskdef name="wsInstallApp" classname="com.ibm.websphere.ant.tasks.InstallApplication"/>
|
||||
<taskdef name="wsUninstallApp" classname="com.ibm.websphere.ant.tasks.UninstallApplication"/>
|
||||
<taskdef name="wsStartApplication" classname="com.ibm.websphere.ant.tasks.StartApplication"/>
|
||||
<taskdef name="wsadmin" classname="com.ibm.websphere.ant.tasks.WsAdmin"/>
|
||||
|
||||
<!-- Location of WebSphere Application Server home/install dir -->
|
||||
<property name="was.home" value="/opt/IBM/WebSphere/AppServer"/>
|
||||
|
||||
|
||||
<!-- WebSphere Server name (IP name or address) -->
|
||||
<property name="was.server" value=""/>
|
||||
|
||||
|
||||
<!-- WebSphere Admin port -->
|
||||
<property name="was.port" value=""/>
|
||||
|
||||
<!-- WebSphere admin connection type. SOAP, RMI, JMS, or NONE. -->
|
||||
<property name="was.conntype" value=""/>
|
||||
|
||||
|
||||
<!-- WebSphere User name (required if security is enabled) -->
|
||||
<property name="was.user" value=""/>
|
||||
|
||||
|
||||
<!-- WebSphere Password (required if security enabled) -->
|
||||
<property name="was.password" value=""/>
|
||||
|
||||
|
||||
<target name="pre-package">
|
||||
<echo message="In WAS pre-package"/>
|
||||
<copy file="${rsrc.dir}/META-INF/persistence.jee.was.xml" tofile="${classes.dir}/META-INF/persistence.xml"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="install"
|
||||
description="Deploy OpenBooks as a WAR application in WebSphere Application Server">
|
||||
<condition property="default.deploy">
|
||||
|
@ -85,26 +85,26 @@
|
|||
Uninstalling OpenBooks demo application
|
||||
WAS Home: ${was.home}
|
||||
</echo>
|
||||
<wsUninstallApp wasHome="${was.home}"
|
||||
application="OpenBooks"/>
|
||||
<wsUninstallApp wasHome="${was.home}"
|
||||
application="OpenBooks"/>
|
||||
</target>
|
||||
|
||||
<!-- App uninstall when security is enabled -->
|
||||
<target name="was.secure.uninstall" unless="default.uninstall">
|
||||
<target name="was.secure.uninstall" unless="default.uninstall">
|
||||
<echo>
|
||||
---------------------------------------
|
||||
Uninstalling OpenBooks demo application
|
||||
</echo>
|
||||
<wsUninstallApp wasHome="${was.home}"
|
||||
<wsUninstallApp wasHome="${was.home}"
|
||||
application="OpenBooks"
|
||||
conntype="${was.conntype}"
|
||||
host="${was.server}"
|
||||
port="${was.port}"
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Default simple deployment if WAS security is disabled -->
|
||||
<target name="was.deploy" if="default.deploy">
|
||||
<echo>
|
||||
|
@ -112,32 +112,32 @@
|
|||
Creating Derby JDBC provider and data source
|
||||
WAS Home: ${was.home}
|
||||
</echo>
|
||||
<wsadmin wasHome="${was.home}"
|
||||
<wsadmin wasHome="${was.home}"
|
||||
script="scripts/was/ds_config.py"
|
||||
lang="jython"/>
|
||||
|
||||
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Deploying OpenBooks demo application
|
||||
</echo>
|
||||
<wsInstallApp wasHome="${was.home}"
|
||||
ear="${target.dir}/openbooks.war"
|
||||
<wsInstallApp wasHome="${was.home}"
|
||||
ear="${target.dir}/openbooks.war"
|
||||
options="-usedefaultbindings -contextroot OpenBooks -appname OpenBooks"/>
|
||||
|
||||
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Starting OpenBooks demo application
|
||||
</echo>
|
||||
<wsStartApplication wasHome="${was.home}"
|
||||
application="OpenBooks"/>
|
||||
|
||||
<wsStartApplication wasHome="${was.home}"
|
||||
application="OpenBooks"/>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- Target for installation and deployment of the application when a -->
|
||||
<!-- server IP name or address is provided. This type of deployment -->
|
||||
<!-- requires server IP name was.home, was.server, was.conntype, -->
|
||||
<!-- was.port, was.user, and was.password to be provided. -->
|
||||
|
||||
|
||||
<target name="was.deploy.secure" unless="default.deploy">
|
||||
<echo>
|
||||
-------------------------------------------
|
||||
|
@ -149,39 +149,39 @@
|
|||
User: ${was.user}
|
||||
Password: Not shown
|
||||
</echo>
|
||||
<wsadmin wasHome="${was.home}"
|
||||
<wsadmin wasHome="${was.home}"
|
||||
script="scripts/was/ds_config.py"
|
||||
lang="jython"
|
||||
conntype="${was.conntype}"
|
||||
host="${was.server}"
|
||||
port="${was.port}"
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Deploying OpenBooks demo application
|
||||
</echo>
|
||||
|
||||
<wsInstallApp wasHome="${was.home}"
|
||||
ear="${target.dir}/openbooks.war"
|
||||
|
||||
<wsInstallApp wasHome="${was.home}"
|
||||
ear="${target.dir}/openbooks.war"
|
||||
conntype="${was.conntype}"
|
||||
host="${was.server}"
|
||||
port="${was.port}"
|
||||
user="${was.user}"
|
||||
user="${was.user}"
|
||||
password="${was.password}"
|
||||
options="-usedefaultbindings -contextroot OpenBooks -appname OpenBooks"/>
|
||||
options="-usedefaultbindings -contextroot OpenBooks -appname OpenBooks"/>
|
||||
<echo>
|
||||
-------------------------------------
|
||||
Starting OpenBooks demo application
|
||||
Start OpenBooks via http://server:port/OpenBooks
|
||||
</echo>
|
||||
<wsStartApplication wasHome="${was.home}"
|
||||
application="OpenBooks"
|
||||
<wsStartApplication wasHome="${was.home}"
|
||||
application="OpenBooks"
|
||||
conntype="${was.conntype}"
|
||||
host="${was.server}"
|
||||
port="${was.port}"
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
user="${was.user}"
|
||||
password="${was.password}"/>
|
||||
</target>
|
||||
</project>
|
||||
|
|
|
@ -7,29 +7,29 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
<!-- Ant build script for JEE version of OpenBooks -->
|
||||
<!-- -->
|
||||
<!-- ====================================================================== -->
|
||||
|
||||
|
||||
<project name="OpenBooks.JEE" default="package">
|
||||
|
||||
|
||||
<target name="package"
|
||||
description="Build, package and deploy OpenBooks as a WAR application in an Application Server">
|
||||
|
||||
<condition property="app.server" value="" else=".${appserver}">
|
||||
<equals arg1="${appserver}" arg2="" casesensitive="true" trim="true"/>
|
||||
<condition property="app.server" value="" else=".${appserver}">
|
||||
<equals arg1="${appserver}" arg2="" casesensitive="true" trim="true"/>
|
||||
</condition>
|
||||
<antcall target="jee.uninstall"/>
|
||||
<mkdir dir="${classes.dir}/META-INF"/>
|
||||
|
@ -59,9 +59,9 @@
|
|||
|
||||
<target name="jee.uninstall"
|
||||
description="AppServer specific installation">
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="uninstall"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="uninstall"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
</target>
|
||||
|
@ -73,27 +73,27 @@
|
|||
|
||||
<target name="jee.pre-package"
|
||||
description="AppServer specific pre-packaging. Occurs before war packaging.">
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="pre-package"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="pre-package"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
</target>
|
||||
|
||||
<target name="pre-package"
|
||||
description="Default application pre-packaging">
|
||||
<copy file="${rsrc.dir}/META-INF/persistence.xml" todir="${classes.dir}/META-INF"/>
|
||||
<copy file="${rsrc.dir}/META-INF/persistence.xml" todir="${classes.dir}/META-INF"/>
|
||||
</target>
|
||||
|
||||
<target name="jee.install"
|
||||
description="AppServer selective installation.">
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="install"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}${app.server}.xml"
|
||||
target="install"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="install"
|
||||
description="Default application installation">
|
||||
<move file="${target.dir}/openbooks.war" todir="${deploy.dir}" overwrite="true"/>
|
||||
|
@ -108,11 +108,11 @@
|
|||
<exclude name="openbook/client/**/*.java"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="generate-source-with-options">
|
||||
<java2html
|
||||
sourcepath="${src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
<java2html
|
||||
sourcepath="${src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
extension=".html"
|
||||
addLineBreak="false"
|
||||
addExplicitSpace="false"
|
||||
|
@ -121,9 +121,9 @@
|
|||
<exclude name="jpa/**/*.java"/>
|
||||
<exclude name="openbook/util/*.java"/>
|
||||
</java2html>
|
||||
<java2html
|
||||
sourcepath="${generated.src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
<java2html
|
||||
sourcepath="${generated.src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
extension=".html"
|
||||
addLineBreak="false"
|
||||
addExplicitSpace="false"
|
||||
|
@ -131,5 +131,5 @@
|
|||
</java2html>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
@ -7,29 +7,29 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
<!-- Ant build script to build/package JSE version of OpenBooks -->
|
||||
<!-- -->
|
||||
<!-- ====================================================================== -->
|
||||
|
||||
|
||||
<project name="OpenBooks.JSE" default="package">
|
||||
|
||||
|
||||
<target name="package"
|
||||
description="Build, package and deploy OpenBooks as a Swing-based JSE application">
|
||||
<delete file="${target.dir}/openbooks.jar" failonerror="false"/>
|
||||
<delete file="${target.dir}/openbooks.zip" failonerror="false"/>
|
||||
|
||||
|
||||
<jar destfile="${target.dir}/openbooks.jar" basedir="${classes.dir}">
|
||||
<exclude name="junit/**" />
|
||||
</jar>
|
||||
|
@ -75,19 +75,19 @@
|
|||
</copy>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="compile"
|
||||
|
||||
<target name="compile"
|
||||
description="Compile classes.">
|
||||
<javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true">
|
||||
<classpath refid="compile.classpath" />
|
||||
<exclude name="openbook/tools/**/*.java"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="generate-source-with-options">
|
||||
<java2html
|
||||
sourcepath="${src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
<java2html
|
||||
sourcepath="${src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
extension=".html"
|
||||
addLineBreak="true"
|
||||
addExplicitSpace="true"
|
||||
|
@ -96,9 +96,9 @@
|
|||
<exclude name="jpa/**/*.java"/>
|
||||
<exclude name="openbook/util/*.java"/>
|
||||
</java2html>
|
||||
<java2html
|
||||
sourcepath="${generated.src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
<java2html
|
||||
sourcepath="${generated.src.dir}"
|
||||
destDir="${generated.html.dir}"
|
||||
extension=".html"
|
||||
addLineBreak="true"
|
||||
addExplicitSpace="true"
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Environment variables to build OpenBooks
|
||||
#
|
||||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Directory location of maven repository
|
||||
maven.repos=${user.home}/.m2/repository
|
||||
# OpenJPA runtime artifact
|
||||
openjpa.version=2.3.0-SNAPSHOT
|
||||
|
||||
# This is the variable of interest.
|
||||
# This is the variable of interest.
|
||||
# Notice that the variable points to a directory, not a *.jar file.
|
||||
# All *.jar files under the directory will be included in compilation.
|
||||
# Though the varaible value is expressed in terms of other variables here,
|
||||
|
|
|
@ -7,24 +7,24 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
<!-- Ant build script for OpenBooks -->
|
||||
<!-- -->
|
||||
<!-- ====================================================================== -->
|
||||
|
||||
|
||||
<project name="OpenBooks" default="package">
|
||||
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<property file="build.properties" />
|
||||
<!-- ================================================================== -->
|
||||
|
@ -43,11 +43,11 @@
|
|||
<!-- ================================================================== -->
|
||||
<!-- JPA configuration file anchored by the persistence unit name -->
|
||||
<property name="jpa.properties" value="META-INF/persistence.xml#OpenBooks"/>
|
||||
<!-- ================================================================== -->
|
||||
<!-- ================================================================== -->
|
||||
<!-- Application/Web Server type: -->
|
||||
<!-- geronimo, was, tomcat, glassfish, or empty string for default -->
|
||||
<property name="appserver" value=""/>
|
||||
<!-- ================================================================== -->
|
||||
<!-- ================================================================== -->
|
||||
<!-- Root directory of all derived artifacts -->
|
||||
<property name="target.dir" value="${basedir}/target"/>
|
||||
<!-- ================================================================== -->
|
||||
|
@ -61,10 +61,10 @@
|
|||
<property name="generated.html.dir" value="${target.dir}/generated-html"/>
|
||||
<!-- ================================================================== -->
|
||||
<!-- directory for deployable artifacts -->
|
||||
<property name="deploy.dir" value="${target.dir}/openbooks"/>
|
||||
<property name="deploy.dir" value="${target.dir}/openbooks"/>
|
||||
<!-- ================================================================== -->
|
||||
|
||||
<path id="compile.classpath"
|
||||
<path id="compile.classpath"
|
||||
description="Compilation classpath requires OpenJPA specific library because of bytecode enhancement">
|
||||
<pathelement location="${src.dir}" />
|
||||
<pathelement location="${classes.dir}" />
|
||||
|
@ -73,8 +73,8 @@
|
|||
<include name="*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="code.generation.classpath"
|
||||
|
||||
<path id="code.generation.classpath"
|
||||
description="">
|
||||
<pathelement location="${classes.dir}" />
|
||||
<fileset dir="${antlr.lib}">
|
||||
|
@ -84,13 +84,13 @@
|
|||
<include name="*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
|
||||
<fileset id="canonical.metamodel" dir="${src.dir}"
|
||||
|
||||
|
||||
<fileset id="canonical.metamodel" dir="${src.dir}"
|
||||
description="Set of *.java files generated for static, cannonical domain model">
|
||||
<include name="**/*_.java"/>
|
||||
</fileset>
|
||||
|
||||
|
||||
<target name="clean" description="Removes all *.class and generated metamodel source files">
|
||||
<delete dir="${target.dir}" failonerror="false"/>
|
||||
<mkdir dir="${deploy.dir}"/>
|
||||
|
@ -108,15 +108,15 @@
|
|||
Deploy Location: ${deploy.dir}
|
||||
</echo>
|
||||
</target>
|
||||
|
||||
<target name="check-env"
|
||||
|
||||
<target name="check-env"
|
||||
description="Checks if required libraries exist"
|
||||
depends="info">
|
||||
<available file="${openjpa.lib}" property="openjpa.exists"/>
|
||||
|
||||
|
||||
<fail unless="openjpa.exists">*** Error:
|
||||
The directory for OpenJPA libraries can not be located at ${openjpa.lib}.
|
||||
Make sure openjpa.lib property value is correct in build.properties file.
|
||||
The directory for OpenJPA libraries can not be located at ${openjpa.lib}.
|
||||
Make sure openjpa.lib property value is correct in build.properties file.
|
||||
</fail>
|
||||
<condition property="build.mode.is.valid">
|
||||
<or>
|
||||
|
@ -131,7 +131,7 @@
|
|||
<condition property="build.mode.is.jee">
|
||||
<equals arg1="${build.mode}" arg2="jee" casesensitive="true" trim="true"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<available file="${antlr.lib}" property="antlr.exists"/>
|
||||
<!--
|
||||
<condition property="antlr.exists">
|
||||
|
@ -143,7 +143,7 @@
|
|||
<fail unless="antlr.exists" message="ANTLR is missing from classpath"/>
|
||||
-->
|
||||
</target>
|
||||
|
||||
|
||||
<target name="generate-canonical-model" depends="check-env"
|
||||
description="Generate canonical meta-model source">
|
||||
<mkdir dir="${generated.src.dir}" />
|
||||
|
@ -161,16 +161,16 @@
|
|||
<compilerarg value="${generated.src.dir}" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="compile" depends="generate-canonical-model"
|
||||
description="Compile classes.">
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="compile"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="compile"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="enhance" depends="check-env"
|
||||
description="Enhance persistent domain classes.">
|
||||
<java classname="org.apache.openjpa.enhance.PCEnhancer" fork="true">
|
||||
|
@ -179,7 +179,7 @@
|
|||
<classpath refid="compile.classpath" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="package" description="Build and Package based on JSE or JEE mode"
|
||||
depends="check-env,
|
||||
clean,
|
||||
|
@ -187,13 +187,13 @@
|
|||
compile,
|
||||
enhance,
|
||||
generate-source">
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="package"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="package"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="build-parser" depends="check-env" if="antlr.exists">
|
||||
<java classname="org.antlr.Tool">
|
||||
<classpath refid="code.generation.classpath"/>
|
||||
|
@ -222,12 +222,12 @@
|
|||
<delete dir="${generated.html.dir}"></delete>
|
||||
<mkdir dir="${generated.html.dir}"/>
|
||||
<copy file="${rsrc.dir}/java.css" todir="${generated.html.dir}"/>
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="generate-source-with-options"
|
||||
inheritrefs="true"
|
||||
<subant antfile="build.${build.mode}.xml"
|
||||
target="generate-source-with-options"
|
||||
inheritrefs="true"
|
||||
inheritall="true"
|
||||
buildpath="${basedir}"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
@ -50,7 +50,7 @@ font-size:16px;
|
|||
<body>
|
||||
<h1>OpenBooks: A sample JPA 2.0 Application</h1>
|
||||
<hr>
|
||||
OpenBooks is a sample (and perhaps simple) application to demonstrate some of the new features of
|
||||
OpenBooks is a sample (and perhaps simple) application to demonstrate some of the new features of
|
||||
version 2.0 of <A HREF="http://jcp.org/en/jsr/detail?id=317">Java Persistence API</A> (JPA) specification, such as
|
||||
<br>
|
||||
<OL>
|
||||
|
@ -60,20 +60,20 @@ font-size:16px;
|
|||
</LI>
|
||||
</OL>
|
||||
<br>
|
||||
|
||||
|
||||
OpenBooks runs with <A HREF="http://openjpa.apache.org">OpenJPA</A> as its JPA provider.
|
||||
<hr>
|
||||
<h2>Instructions to download and run OpenBooks Demo</h2>
|
||||
OpenBooks comes with
|
||||
OpenBooks comes with
|
||||
<OL>
|
||||
<LI>complete source code
|
||||
<LI>build scripts to demonstrate how to build a typical OpenJPA application and package it for JSE or JEE
|
||||
<LI>build scripts to demonstrate how to build a typical OpenJPA application and package it for JSE or JEE
|
||||
environment
|
||||
<LI>scripts to run OpenBooks in on your local database installation.
|
||||
<LI>scripts to run OpenBooks in on your local database installation.
|
||||
</OL>
|
||||
<br>
|
||||
Follow the simple instructions below to build and run OpenBooks:
|
||||
|
||||
|
||||
<OL>
|
||||
<LI><A href="#Download">Download OpenBooks distribution</A>.
|
||||
<LI><A href="#Configure">Configure build and run environment</A>.
|
||||
|
@ -82,7 +82,7 @@ font-size:16px;
|
|||
</OL>
|
||||
<hr>
|
||||
<h2><A name="Download">Download Instructions</A></h2>
|
||||
OpenBooks is distributed under <A HREF="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</A>
|
||||
OpenBooks is distributed under <A HREF="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</A>
|
||||
<br>
|
||||
OpenBooks can be checked out from OpenJPA repository.
|
||||
<br>
|
||||
|
@ -95,70 +95,70 @@ font-size:16px;
|
|||
<LI> Java Runtime version 6.0 or higher
|
||||
<LI> OpenJPA Libraries version 2.0 or higher
|
||||
<LI> Ant version 1.6 or higher
|
||||
<LI> Any JDBC complaint database supported by OpenJPA.
|
||||
<LI> Any JDBC complaint database supported by OpenJPA.
|
||||
See <A href="http://openjpa.apache.org/builds/latest/docs/manual/manual.html#ref_guide_dbsetup_dbsupport">OpenJPA documentation</A> for a list of supported databases.
|
||||
</OL>
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<h2><A name="Configure">Configure build and run environment</A></h2>
|
||||
OpenBooks builds with Ant. The Ant build script is somewhat involved because OpenBooks can be built and packaged
|
||||
either as a JSE (Swing based) application or a JEE Web Application. By default, OpenBooks is built as a
|
||||
either as a JSE (Swing based) application or a JEE Web Application. By default, OpenBooks is built as a
|
||||
JSE application.
|
||||
<br>
|
||||
Before you run a build, configure the build environment by editing
|
||||
<A HREF="build.properties"><code>build.properties</code></A>.
|
||||
Essentially, you need to
|
||||
<A HREF="build.properties"><code>build.properties</code></A>.
|
||||
Essentially, you need to
|
||||
<OL>
|
||||
<LI>point <code>openjpa.lib</code> variable to the local directory where OpenJPA class library(ies) reside.
|
||||
Notice that the variable points to a directory and not a <code>*.jar</code> file. All <code>*.jar</code> files
|
||||
found under the directory are included in compilation classpath.
|
||||
</OL>
|
||||
</OL>
|
||||
<br>
|
||||
The next step is to configure runtime environment.
|
||||
The next step is to configure runtime environment.
|
||||
<OL>
|
||||
<LI>Edit <A HREF="resources/META-INF/persistence.xml"><code>persistence.xml</code></A> located in
|
||||
<code>resources/META-INF</code> directory.
|
||||
<LI>Edit <A HREF="resources/META-INF/persistence.xml"><code>persistence.xml</code></A> located in
|
||||
<code>resources/META-INF</code> directory.
|
||||
Modify the <code>javax.persistence.jdbc.driver</code>
|
||||
and <code>javax.persistence.jdbc.url</code> property to suit your local database and its driver.
|
||||
<br>
|
||||
The example <code>persistence.xml</code> provided is primarily for a JSE environment.
|
||||
In JEE environment, you may already have a JTA data source configured and registered in JNDI.
|
||||
Of course, then the <code>persistence.xml</code> is to be edited accordingly in
|
||||
<code><jta-data-source></code> clause.
|
||||
<LI>In JSE mode, edit <A HREF="run.properties"><code>run.properties</code></A> to specify location of OpenJPA
|
||||
Of course, then the <code>persistence.xml</code> is to be edited accordingly in
|
||||
<code><jta-data-source></code> clause.
|
||||
<LI>In JSE mode, edit <A HREF="run.properties"><code>run.properties</code></A> to specify location of OpenJPA
|
||||
class libraries and JDBC Driver used in runtime classpath.
|
||||
<br>
|
||||
In JEE mode, OpenJPA library and JDBC drivers are configured in JEE server and hence variables in
|
||||
this file are irrelevant.
|
||||
</OL>
|
||||
|
||||
|
||||
Both <code>build.properties</code> and <code>run.properties</code> files are commented in-place on what is to be
|
||||
edited.
|
||||
this file are irrelevant.
|
||||
</OL>
|
||||
|
||||
|
||||
Both <code>build.properties</code> and <code>run.properties</code> files are commented in-place on what is to be
|
||||
edited.
|
||||
<hr>
|
||||
|
||||
|
||||
<h2><A name="Build">Build OpenBooks from source</A></h2>
|
||||
Once you have configured the environment, simply issue
|
||||
Once you have configured the environment, simply issue
|
||||
<br>
|
||||
<code>$ ant</code>
|
||||
<br>or<br>
|
||||
<code>$ ant -Dbuild.mode=jee</code>
|
||||
<br>
|
||||
The default target of the ant script will
|
||||
The default target of the ant script will
|
||||
<LI>generate metamodel classes (required for Criteria API)
|
||||
<LI>compile the source code
|
||||
<LI>enhance the persistence domain model
|
||||
<LI>package the application based on the build.mode as a Swing-based application or a Web Application Archive.
|
||||
and <LI>copy the deployable artifacts to <code>target/openbooks</code> directory relative to the current directory.
|
||||
and <LI>copy the deployable artifacts to <code>target/openbooks</code> directory relative to the current directory.
|
||||
<hr>
|
||||
|
||||
<h2><A name="Run">Run OpenBooks</A></h2>
|
||||
If you have built OpenBooks for JSE, then go to the <code>target/openbooks</code> directory.
|
||||
|
||||
<h2><A name="Run">Run OpenBooks</A></h2>
|
||||
If you have built OpenBooks for JSE, then go to the <code>target/openbooks</code> directory.
|
||||
<br>
|
||||
Invoke the Ant script to run OpenBooks<br>
|
||||
<code>$ ant -f run.xml</code>
|
||||
|
||||
|
||||
<hr>
|
||||
If you have build OpenBooks for JEE, a Web Application Archive <code>openbooks.war</code> will be
|
||||
created in <code>target/openbooks</code> directory. You need to deploy <code>openbooks.war</code>
|
||||
|
@ -168,16 +168,16 @@ font-size:16px;
|
|||
<br>
|
||||
to access OpenBooks as an web application.
|
||||
<hr>
|
||||
|
||||
<h2><A name="Seed">Populate OpenBooks Database</A></h2>
|
||||
|
||||
<h2><A name="Seed">Populate OpenBooks Database</A></h2>
|
||||
OpenBooks checks for existing data at first connection to the database.
|
||||
If the database is empty, the schema is defined and populated with initial data.
|
||||
However, you can explicitly populate the database in JSE build.
|
||||
Edit <A HREF="load.properties"><code>load.properties</code></A>
|
||||
to specify load parameters such as number of Books etc. OpenBooks uses this data to populate a database
|
||||
with some sample data. This example file has some typical values. If you are satisfied with it,
|
||||
However, you can explicitly populate the database in JSE build.
|
||||
Edit <A HREF="load.properties"><code>load.properties</code></A>
|
||||
to specify load parameters such as number of Books etc. OpenBooks uses this data to populate a database
|
||||
with some sample data. This example file has some typical values. If you are satisfied with it,
|
||||
you can leave them as it is. Then invoke the Ant script<br>
|
||||
<code>$ ant -f run.xml load</code>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,19 +7,19 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<!--
|
||||
Please keep the project tag on one line to avoid confusing
|
||||
<!--
|
||||
Please keep the project tag on one line to avoid confusing
|
||||
the release plugin.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Environment variables for provider specific library to run OpenBooks
|
||||
#
|
||||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Directory location of maven repository
|
||||
maven.repos=${user.home}/.m2/repository
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
under the License.
|
||||
-->
|
||||
<!-- ====================================================================== -->
|
||||
<!-- -->
|
||||
|
@ -27,7 +27,7 @@
|
|||
<property name="jpa.provider" value="openjpa" />
|
||||
<property name="load.properties" value="load.properties" />
|
||||
<property name="demo.properties" value="demo.properties" />
|
||||
|
||||
|
||||
<path id="run.classpath"
|
||||
description="Runs on OpenBooks packaged library and database driver">
|
||||
<pathelement location="${basedir}" />
|
||||
|
@ -39,14 +39,14 @@
|
|||
</fileset>
|
||||
<pathelement location="${jdbc.driver}" />
|
||||
</path>
|
||||
|
||||
|
||||
<target name="check-env" description="Checks if OpenJPA and JDBC driver exists">
|
||||
<available file="${openjpa.lib}" property="openjpa.exists"/>
|
||||
<available file="${jdbc.driver}" property="jdbc.driver.exists"/>
|
||||
<fail unless="openjpa.exists" message="The directory for OpenJPA libraries can not be located at ${openjpa.lib}. Make sure openjpa.lib property value is correectly specified in run.properties file"/>
|
||||
<fail unless="jdbc.driver.exists" message="The JDBC Driver can not be located at ${jdbc.driver}. Make sure jdbc.driver property value is correctly specified in run.properties file"/>
|
||||
<fail unless="openjpa.exists" message="The directory for OpenJPA libraries can not be located at ${openjpa.lib}. Make sure openjpa.lib property value is correectly specified in run.properties file"/>
|
||||
<fail unless="jdbc.driver.exists" message="The JDBC Driver can not be located at ${jdbc.driver}. Make sure jdbc.driver property value is correctly specified in run.properties file"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="load" depends="check-env"
|
||||
description="Popluates a OpenBooks database with initial data">
|
||||
<echo message="Popluating a OpenBooks database with ${jpa.provider} as configured in ${load.properties}" />
|
||||
|
@ -56,12 +56,12 @@
|
|||
<classpath refid="run.classpath" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="run" depends="check-env"
|
||||
description="Runs OpenBooks Demo">
|
||||
<java classname="openbook.client.Demo" fork="true">
|
||||
<classpath refid="run.classpath" />
|
||||
</java>
|
||||
</target>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
host="localhost"
|
||||
httpPort="9080"
|
||||
httpsPort="9443" />
|
||||
|
||||
<jdbcDriver id="DerbyEmbedded" libraryRef="DerbyLib" />
|
||||
<library id="DerbyLib" filesetRef="DerbyFileset" />
|
||||
|
||||
<jdbcDriver id="DerbyEmbedded" libraryRef="DerbyLib" />
|
||||
<library id="DerbyLib" filesetRef="DerbyFileset" />
|
||||
<fileset id="DerbyFileset" dir="${derbyInstallDir}/lib" includes="derby.jar"/>
|
||||
<dataSource id="OpenBooks" jndiName="jdbc/OpenBooks" jdbcDriverRef="DerbyEmbedded">
|
||||
<properties databaseName="OpenBooks" createDatabase="create" />
|
||||
<properties databaseName="OpenBooks" createDatabase="create" />
|
||||
</dataSource>
|
||||
<dataSource id="OpenBooksNoTx" jndiName="jdbc/NonTxOpenBooks" jdbcDriverRef="DerbyEmbedded">
|
||||
<properties databaseName="OpenBooks" createDatabase="create" />
|
||||
<properties databaseName="OpenBooks" createDatabase="create" />
|
||||
</dataSource>
|
||||
</server>
|
|
@ -44,7 +44,7 @@ def getNodeId ():
|
|||
if (len(nodeList) == 1):
|
||||
node = nodeList[0]
|
||||
#endIf
|
||||
|
||||
|
||||
return node
|
||||
#endDef
|
||||
|
||||
|
@ -55,7 +55,7 @@ def getNodeId ():
|
|||
#-----------------------------------------------------------------
|
||||
def getServerId ():
|
||||
serverList = AdminConfig.list("Server").split("\n")
|
||||
|
||||
|
||||
server = serverList[0]
|
||||
return server
|
||||
#endDef
|
||||
|
@ -63,7 +63,7 @@ def getServerId ():
|
|||
def addDatasourceProperty (datasourceId, name, value):
|
||||
parms = ["-propertyName", name, "-propertyValue", value]
|
||||
AdminTask.setResourceProperty(datasourceId, parms)
|
||||
#endDef
|
||||
#endDef
|
||||
|
||||
# Set the default database provider to Derby
|
||||
DefaultProviderType="Derby"
|
||||
|
|
|
@ -26,13 +26,13 @@ import javax.swing.JPanel;
|
|||
|
||||
/**
|
||||
* Displays color codes of each attribute type.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AttributeLegendView extends JPanel {
|
||||
|
||||
|
||||
public AttributeLegendView() {
|
||||
super(true);
|
||||
setBorder(BorderFactory.createTitledBorder("Attribute Legends"));
|
||||
|
@ -41,13 +41,13 @@ public class AttributeLegendView extends JPanel {
|
|||
add(createColoredLabel("VERSION", Color.DARK_GRAY));
|
||||
for (Attribute.PersistentAttributeType type : Attribute.PersistentAttributeType.values()) {
|
||||
add(createColoredLabel(type.toString().replace('_', ' '), MetamodelHelper.getColor(type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JComponent createColoredLabel(String text, Color c) {
|
||||
int width = 40;
|
||||
int height = 20;
|
||||
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
for (int i = 0; i < width; i++)
|
||||
for (int j = 0; j < height; j++)
|
||||
bimage.setRGB(i, j, c.getRGB());
|
||||
|
|
|
@ -20,21 +20,21 @@ import javax.swing.JLabel;
|
|||
|
||||
/**
|
||||
* View of a persistent attribute as a JLabel.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AttributeView extends JLabel {
|
||||
private final Attribute<?,?> _attr;
|
||||
|
||||
|
||||
public AttributeView(Attribute<?,?> attr) {
|
||||
_attr = attr;
|
||||
Color color = MetamodelHelper.getColor(attr);
|
||||
setForeground(color);
|
||||
setText(MetamodelHelper.getDisplayName(attr));
|
||||
}
|
||||
|
||||
|
||||
public Attribute<?,?> getAttribute() {
|
||||
return _attr;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import javax.swing.JTextPane;
|
|||
|
||||
/**
|
||||
* Displays Properties.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ConfigurationViewer extends JTextPane {
|
||||
|
@ -46,7 +46,7 @@ public class ConfigurationViewer extends JTextPane {
|
|||
replaceSelection(toString(config.get(key)) + "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String toString(Object value) {
|
||||
if (value == null)
|
||||
return "null";
|
||||
|
|
|
@ -31,11 +31,11 @@ import javax.swing.table.TableModel;
|
|||
/**
|
||||
* A data model for a tabular view of a list of persistent entities.
|
||||
* The data supplied by this model can be filtered to display field values of
|
||||
* basic type or single-valued or multi-valued relationships.
|
||||
* basic type or single-valued or multi-valued relationships.
|
||||
* <br>
|
||||
* The meta-information about the attributes of the entity are supplied by
|
||||
* The meta-information about the attributes of the entity are supplied by
|
||||
* newly defined {@link Metamodel meta-model API} of JPA 2.0 specification.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -66,15 +66,15 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
private List<Class<?>> columnClasses;
|
||||
private List<Method> methods;
|
||||
private List<T> data;
|
||||
private List<Attribute<? super T,?>> attributes;
|
||||
private List<Attribute<? super T,?>> attributes;
|
||||
private static Object[] EMPTY_ARGS = null;
|
||||
private static Class<?>[] EMPTY_CLASSES = null;
|
||||
|
||||
|
||||
private boolean showsRowCount;
|
||||
private boolean showsBasicAttr;
|
||||
private boolean showsSingularAttr;
|
||||
private boolean showsPluralAttr;
|
||||
|
||||
|
||||
/**
|
||||
* Attributes of the entity are reordered with basic attributes, followed by singular
|
||||
* association followed by the many-valued attributes.
|
||||
|
@ -83,17 +83,17 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
super();
|
||||
this.data = data;
|
||||
EntityType<T> entityType = meta.entity(cls);
|
||||
|
||||
|
||||
columnNames = new ArrayList<String>();
|
||||
columnClasses = new ArrayList<Class<?>>();
|
||||
attributes = new ArrayList<Attribute<? super T,?>>();
|
||||
methods = new ArrayList<Method>();
|
||||
|
||||
|
||||
showsRowCount = (styleBits & ROW_COUNT) != 0;
|
||||
showsBasicAttr = (styleBits & BASIC_ATTR) != 0;
|
||||
showsSingularAttr = (styleBits & ASSOCIATION_ATTR) != 0;
|
||||
showsPluralAttr = (styleBits & PLURAL_ATTR) != 0;
|
||||
|
||||
|
||||
Set<SingularAttribute<? super T, ?>> sAttrs = entityType.getSingularAttributes();
|
||||
if (showsBasicAttr) {
|
||||
for (SingularAttribute<? super T, ?> attr : sAttrs) {
|
||||
|
@ -126,7 +126,7 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
methods.add(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void populate(Class<T> cls, Attribute<?,?> attr) {
|
||||
columnNames.add(attr.getName());
|
||||
columnClasses.add(wrap(attr.getJavaType()));
|
||||
|
@ -135,19 +135,19 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
|
||||
/**
|
||||
* Gets the attribute at a given column index.
|
||||
* Can be null for 0-th index if row count is being shown.
|
||||
* Can be null for 0-th index if row count is being shown.
|
||||
*/
|
||||
public Attribute<?,?> getAttribute(int columnIndex) {
|
||||
public Attribute<?,?> getAttribute(int columnIndex) {
|
||||
return attributes.get(columnIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the entity represented in the given row.
|
||||
*/
|
||||
public T getRow(int row) {
|
||||
return data.get(row);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return columnClasses.get(columnIndex);
|
||||
|
@ -176,7 +176,7 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
}
|
||||
Object row = data.get(rowIndex);
|
||||
Object val = getValueByReflection(rowIndex, row, columnIndex, method);
|
||||
return val;
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -209,7 +209,7 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Class<?> wrap(Class<?> c) {
|
||||
if (c == null || c.isInterface() || c.isArray())
|
||||
return Object.class;
|
||||
|
@ -225,7 +225,7 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
private Method getMethod(Class<T> type, String p) {
|
||||
try {
|
||||
String getter = "get" + Character.toUpperCase(p.charAt(0))+p.substring(1);
|
||||
|
@ -234,9 +234,9 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void updateData(List<T> newData) {
|
||||
data = newData;
|
||||
fireTableDataChanged();
|
||||
|
@ -246,5 +246,5 @@ public class EntityDataModel<T> extends AbstractTableModel implements TableModel
|
|||
public Iterator<T> iterator() {
|
||||
return data.iterator();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ import org.apache.openjpa.enhance.StateManager;
|
|||
* that is supplied at construction.
|
||||
* <br>
|
||||
* The table view uses specialized cell renderer to display single-valued and multi-valued
|
||||
* association.
|
||||
*
|
||||
*
|
||||
* association.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -52,27 +52,27 @@ import org.apache.openjpa.enhance.StateManager;
|
|||
public class EntityTable<T> extends JTable {
|
||||
private InstanceCellRenderer instanceCellRenderer;
|
||||
private CollectionCellRenderer collectionCellRenderer;
|
||||
|
||||
|
||||
public EntityTable(Class<T> cls, List<T> data, int styleBits, EntityManagerFactory unit) {
|
||||
super();
|
||||
instanceCellRenderer = new InstanceCellRenderer(unit.getPersistenceUnitUtil());
|
||||
collectionCellRenderer = new CollectionCellRenderer();
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
|
||||
setModel(new EntityDataModel<T>(cls, data, unit.getMetamodel(), styleBits));
|
||||
getModel().addTableModelListener(this);
|
||||
initColumnSizes();
|
||||
setFillsViewportHeight(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public InstanceCellRenderer getInstanceRenderer() {
|
||||
return instanceCellRenderer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the special renderer for single- and multi-valued association.
|
||||
* Otherwise uses the super classes' renderer defined by the field type.
|
||||
* Otherwise uses the super classes' renderer defined by the field type.
|
||||
*/
|
||||
public TableCellRenderer getCellRenderer(int row, int column) {
|
||||
Attribute<?,?> attr = ((EntityDataModel)getModel()).getAttribute(column);
|
||||
|
@ -89,10 +89,10 @@ public class EntityTable<T> extends JTable {
|
|||
if (renderer instanceof DefaultTableCellRenderer) {
|
||||
((DefaultTableCellRenderer)renderer).setHorizontalAlignment(JLabel.CENTER);
|
||||
}
|
||||
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
public TableCellEditor getCellEditor(int row, int column) {
|
||||
Attribute<?,?> attr = ((EntityDataModel)getModel()).getAttribute(column);
|
||||
if (attr == null)
|
||||
|
@ -101,7 +101,7 @@ public class EntityTable<T> extends JTable {
|
|||
return new DefaultCellEditor((JComboBox)getCellRenderer(row, column));
|
||||
return super.getCellEditor(row, column);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Picks good column sizes.
|
||||
* If all column heads are wider than the column's cells'
|
||||
|
@ -112,7 +112,7 @@ public class EntityTable<T> extends JTable {
|
|||
TableColumn column = null;
|
||||
Component comp = null;
|
||||
int headerWidth = 0;
|
||||
|
||||
|
||||
TableCellRenderer headerRenderer = getTableHeader().getDefaultRenderer();
|
||||
|
||||
for (int columnIndex = 0; columnIndex < model.getColumnCount(); columnIndex++) {
|
||||
|
@ -126,7 +126,7 @@ public class EntityTable<T> extends JTable {
|
|||
TableCellRenderer renderer = getCellRenderer(0, columnIndex);
|
||||
int rowCount = Math.min(model.getRowCount(), 10);
|
||||
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
||||
Object value = model.getValueAt(rowIndex, columnIndex);
|
||||
Object value = model.getValueAt(rowIndex, columnIndex);
|
||||
comp = renderer.getTableCellRendererComponent(
|
||||
this, value,
|
||||
false, false, rowIndex, columnIndex);
|
||||
|
@ -135,26 +135,26 @@ public class EntityTable<T> extends JTable {
|
|||
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders the value of a persistent entity in a table column as the persistent identifier.
|
||||
* The persistent identifier is extracted by the new {@link PersistenceUnitUtil utility} feature
|
||||
* of JPA 2.0 API.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class InstanceCellRenderer extends DefaultTableCellRenderer {
|
||||
private final PersistenceUnitUtil util;
|
||||
|
||||
|
||||
public InstanceCellRenderer(PersistenceUnitUtil util) {
|
||||
super();
|
||||
this.util = util;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the stringified persistence identifier of the given instance.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public String renderAsString(Object instance) {
|
||||
if (instance == null) {
|
||||
|
@ -178,10 +178,10 @@ public class EntityTable<T> extends JTable {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Renders a many-valued attribute as simply three dots.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -190,9 +190,9 @@ public class EntityTable<T> extends JTable {
|
|||
setPreferredSize(new Dimension(10,20));
|
||||
}
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, value == null ? null : "...",
|
||||
return super.getTableCellRendererComponent(table, value == null ? null : "...",
|
||||
isSelected, hasFocus, row, column);
|
||||
}
|
||||
|
||||
|
@ -200,5 +200,5 @@ public class EntityTable<T> extends JTable {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import jpa.tools.swing.EntityTable.InstanceCellRenderer;
|
|||
|
||||
/**
|
||||
* An entity table view consists of a JTable and optionally another table for many-valued associations.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -46,16 +46,16 @@ import jpa.tools.swing.EntityTable.InstanceCellRenderer;
|
|||
public class EntityTableView<T> extends JPanel implements ListSelectionListener {
|
||||
private EntityTable<T> _table;
|
||||
private JTextArea _details;
|
||||
|
||||
|
||||
public EntityTableView(Class<T> cls, int styleBits, EntityManagerFactory unit) {
|
||||
this(cls, (List<T>)Collections.EMPTY_LIST, styleBits, unit);
|
||||
}
|
||||
|
||||
|
||||
public EntityTableView(Class<T> cls, List<T> data, int styleBits, EntityManagerFactory unit) {
|
||||
super(true);
|
||||
_table = new EntityTable<T>(cls, data, styleBits, unit);
|
||||
_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
|
||||
if ((styleBits & EntityDataModel.PLURAL_ATTR) != 0) {
|
||||
_table.getSelectionModel().addListSelectionListener(this);
|
||||
_details = new JTextArea("Click many-valued columns for display");
|
||||
|
@ -65,23 +65,23 @@ public class EntityTableView<T> extends JPanel implements ListSelectionListener
|
|||
}
|
||||
setBorder(BorderFactory.createTitledBorder(_table.getModel().getRowCount() + " " +
|
||||
unit.getMetamodel().entity(cls).getName()));
|
||||
|
||||
|
||||
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
|
||||
add(new JScrollPane(_table,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
add(new JScrollPane(_table,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
|
||||
if (_details != null)
|
||||
add(_details);
|
||||
}
|
||||
|
||||
|
||||
public EntityTable<T> getTable() {
|
||||
return _table;
|
||||
}
|
||||
|
||||
|
||||
public EntityDataModel<T> getDataModel() {
|
||||
return (EntityDataModel<T>)_table.getModel();
|
||||
}
|
||||
|
||||
|
||||
public void updateTitle(String txt) {
|
||||
Border border = getBorder();
|
||||
if (border instanceof TitledBorder) {
|
||||
|
@ -108,15 +108,15 @@ public class EntityTableView<T> extends JPanel implements ListSelectionListener
|
|||
showDetails(attr, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void showDetails(Attribute<?,?> attr, Object val) {
|
||||
_details.setText(null);
|
||||
ManagedType<?> owner = attr.getDeclaringType();
|
||||
String title = (owner instanceof EntityType)
|
||||
String title = (owner instanceof EntityType)
|
||||
? ((EntityType<?>)owner).getName() + "." + attr.getName()
|
||||
: owner.getJavaType().getSimpleName() + "." + attr.getName();
|
||||
: owner.getJavaType().getSimpleName() + "." + attr.getName();
|
||||
TitledBorder border = (TitledBorder)_details.getBorder();
|
||||
|
||||
|
||||
if (val == null) {
|
||||
border.setTitle(title + " (null)");
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@ import javax.swing.JPanel;
|
|||
|
||||
/**
|
||||
* View of a persistent entity type as a JPanel.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -36,14 +36,14 @@ public class EntityTypeView<T> extends JPanel {
|
|||
final EntityType<T> type;
|
||||
final int hgap = 4;
|
||||
final int vgap = 4;
|
||||
|
||||
|
||||
public EntityTypeView(EntityType<T> type) {
|
||||
this.type = type;
|
||||
GridLayout layout = new GridLayout(0,1);
|
||||
setLayout(layout);
|
||||
layout.setVgap(vgap);
|
||||
layout.setHgap(hgap);
|
||||
|
||||
|
||||
setBackground(Color.WHITE);
|
||||
setBorder(BorderFactory.createTitledBorder(MetamodelHelper.getDisplayName(type)));
|
||||
|
||||
|
@ -58,12 +58,12 @@ public class EntityTypeView<T> extends JPanel {
|
|||
}
|
||||
// setPreferredSize(new Dimension(w,h));
|
||||
}
|
||||
|
||||
|
||||
public EntityType<T> getEntityType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the top left position of the attribute label relative to this entity view.
|
||||
*/
|
||||
|
|
|
@ -35,25 +35,25 @@ import javax.swing.JTextPane;
|
|||
|
||||
/**
|
||||
* A dialog to display runtime error.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ErrorDialog extends JDialog {
|
||||
private static List<String> filters = Arrays.asList(
|
||||
"java.awt.",
|
||||
"javax.swing.",
|
||||
"java.awt.",
|
||||
"javax.swing.",
|
||||
"sun.reflect.",
|
||||
"java.util.concurrent.");
|
||||
private static Dimension MESSAGE_SIZE = new Dimension(600,200);
|
||||
private static Dimension STACKTRACE_SIZE = new Dimension(600,300);
|
||||
private static Dimension TOTAL_SIZE = new Dimension(600,500);
|
||||
|
||||
|
||||
|
||||
|
||||
static String NEWLINE = "\r\n";
|
||||
static String INDENT = " ";
|
||||
|
||||
|
||||
private boolean _showingDetails;
|
||||
private boolean _isFiltering = true;
|
||||
private JComponent _message;
|
||||
|
@ -61,10 +61,10 @@ public class ErrorDialog extends JDialog {
|
|||
private JScrollPane _details;
|
||||
private JTextPane _stacktrace;
|
||||
private final Throwable _error;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a modal dialog to display the given exception message.
|
||||
*
|
||||
*
|
||||
* @param t the exception to display
|
||||
*/
|
||||
public ErrorDialog(Throwable t) {
|
||||
|
@ -74,10 +74,10 @@ public class ErrorDialog extends JDialog {
|
|||
public ErrorDialog(JComponent owner, Throwable t) {
|
||||
this(owner, null, t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a modal dialog to display the given exception message.
|
||||
*
|
||||
*
|
||||
* @param owner if non-null, then the dialog is positioned (centered) w.r.t. this component
|
||||
* @param t the exception to display
|
||||
*/
|
||||
|
@ -85,7 +85,7 @@ public class ErrorDialog extends JDialog {
|
|||
super();
|
||||
setTitle(t.getClass().getName());
|
||||
setModal(true);
|
||||
if (icon != null && icon instanceof ImageIcon)
|
||||
if (icon != null && icon instanceof ImageIcon)
|
||||
setIconImage(((ImageIcon)icon).getImage());
|
||||
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
_error = t;
|
||||
|
@ -96,11 +96,11 @@ public class ErrorDialog extends JDialog {
|
|||
pack();
|
||||
SwingHelper.position(this, owner);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the display with the top-level exception message
|
||||
* Creates the display with the top-level exception message
|
||||
* followed by a pane (that toggles) for detailed stack traces.
|
||||
*
|
||||
*
|
||||
* @param t a non-null exception
|
||||
*/
|
||||
JComponent createContent() {
|
||||
|
@ -129,7 +129,7 @@ public class ErrorDialog extends JDialog {
|
|||
}
|
||||
});
|
||||
JPanel messagePanel = new JPanel();
|
||||
|
||||
|
||||
final JCheckBox filter = new JCheckBox("Filter stack traces");
|
||||
filter.setSelected(_isFiltering);
|
||||
filter.addActionListener(new ActionListener(){
|
||||
|
@ -151,16 +151,16 @@ public class ErrorDialog extends JDialog {
|
|||
messagePanel.add(_message, BorderLayout.CENTER);
|
||||
messagePanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
messagePanel.setPreferredSize(MESSAGE_SIZE);
|
||||
|
||||
|
||||
JPanel main = new JPanel();
|
||||
main.setLayout(new BorderLayout());
|
||||
main.add(messagePanel, BorderLayout.NORTH);
|
||||
return main;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a non-editable widget to display the error message.
|
||||
*
|
||||
*
|
||||
*/
|
||||
JComponent createErrorMessage(Throwable t) {
|
||||
String txt = t.getLocalizedMessage();
|
||||
|
@ -170,23 +170,23 @@ public class ErrorDialog extends JDialog {
|
|||
message.setText(txt);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a non-editable widget to display the detailed stack trace.
|
||||
*/
|
||||
JScrollPane createDetailedMessage(Throwable t) {
|
||||
_stacktrace = new JTextPane();
|
||||
_stacktrace.setEditable(false);
|
||||
JScrollPane pane = new JScrollPane(_stacktrace,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
JScrollPane pane = new JScrollPane(_stacktrace,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively print the stack trace on the given buffer.
|
||||
*/
|
||||
*/
|
||||
StringBuilder generateStackTrace(Throwable t, StringBuilder buffer) {
|
||||
buffer.append(t.getClass().getName() + ": " + t.getMessage() + NEWLINE);
|
||||
buffer.append(toString(t.getStackTrace()));
|
||||
|
@ -196,7 +196,7 @@ public class ErrorDialog extends JDialog {
|
|||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
StringBuilder toString(StackTraceElement[] traces) {
|
||||
StringBuilder error = new StringBuilder();
|
||||
for (StackTraceElement e : traces) {
|
||||
|
@ -207,7 +207,7 @@ public class ErrorDialog extends JDialog {
|
|||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the error messages from the given class name is to be suppressed.
|
||||
*/
|
||||
|
@ -218,12 +218,12 @@ public class ErrorDialog extends JDialog {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
String m1 = "This is test error with very very very very very long line of error message that "
|
||||
String m1 = "This is test error with very very very very very long line of error message that "
|
||||
+ " should not be in a single line. Another message string that shoul dbe split across word." +
|
||||
"The quick brown fox jumpled over the lazy dog";
|
||||
String m2 = "This is another test error with very long line of error message that "
|
||||
String m2 = "This is another test error with very long line of error message that "
|
||||
+ " should not be in a single line";
|
||||
Throwable nested = new NumberFormatException(m2);
|
||||
Throwable top = new IllegalArgumentException(m1, nested);
|
||||
|
|
|
@ -26,21 +26,21 @@ import java.util.List;
|
|||
public class FileScanner {
|
||||
private String ext;
|
||||
boolean recursive;
|
||||
|
||||
|
||||
public FileScanner(String ext, boolean recurse) {
|
||||
this.ext = ext;
|
||||
this.recursive = recurse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scans the given
|
||||
* Scans the given
|
||||
*/
|
||||
public List<File> scan(File dir) {
|
||||
List<File> bag = new ArrayList<File>();
|
||||
scan(dir, bag);
|
||||
return bag;
|
||||
}
|
||||
|
||||
|
||||
private void scan(File dir, List<File> bag) {
|
||||
if (dir == null || !dir.exists() || !dir.isDirectory())
|
||||
return;
|
||||
|
@ -54,5 +54,5 @@ public class FileScanner {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -29,19 +29,19 @@ import java.util.jar.JarFile;
|
|||
/**
|
||||
* Searches for a given class in the set of directories recursively.
|
||||
* If a given directory contains jar file then searches inside the jar.
|
||||
*
|
||||
*
|
||||
* Usage
|
||||
* $ java find.Finder class dir1 dir2...
|
||||
* where
|
||||
* class is fully qualified class name
|
||||
* dir name of a file system directory
|
||||
*
|
||||
*
|
||||
* Example
|
||||
* $ java find.Finder org.eclipse.ui.plugin.AbstractUIPlugin c:\eclipse\plugins
|
||||
* will print
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin found in
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin found in
|
||||
* c:\eclipse\plugins\org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jar
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@ public class Finder {
|
|||
private static final String JAR_SUFFIX = ".jar";
|
||||
private static final char DOT = '.';
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
|
||||
private static void usage() {
|
||||
System.err.println("Searches a given class in the given directories."
|
||||
+ "\r\nIf a given directory contains jar then searches within the jar."
|
||||
|
@ -64,7 +64,7 @@ public class Finder {
|
|||
System.err.println("\r\n Example:");
|
||||
System.err.println(" $ java find.Finder java.lang.Object c:\\java");
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 2) {
|
||||
usage();
|
||||
|
@ -76,7 +76,7 @@ public class Finder {
|
|||
finder.scan(root, args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void scan(File dir, String cls) throws IOException {
|
||||
File[] classes = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File path) {
|
||||
|
@ -95,21 +95,21 @@ public class Finder {
|
|||
return path.getName().endsWith(JAR_SUFFIX);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (File jar : jars) {
|
||||
JarFile jarFile = new JarFile(jar);
|
||||
scan(jarFile, cls);
|
||||
}
|
||||
|
||||
|
||||
File[] dirs = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File path) {
|
||||
return path.isDirectory();
|
||||
}
|
||||
});
|
||||
for (File cdir : dirs)
|
||||
for (File cdir : dirs)
|
||||
scan(cdir, cls);
|
||||
}
|
||||
|
||||
|
||||
private void scan(JarFile jar, String cls) {
|
||||
String clsName = cls.replace('.', '/') + CLASS_SUFFIX;
|
||||
debug("Scanning " + jar.getName() + " for [" + clsName + "]");
|
||||
|
@ -123,7 +123,7 @@ public class Finder {
|
|||
System.err.println(cls + " found in " + jar.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void debug(String s) {
|
||||
if (DEBUG)
|
||||
System.err.println(s);
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.swing.text.StyleContext;
|
|||
/**
|
||||
* An output stream that uses a {@link ScrollingTextPane} as its sink.
|
||||
* Flushes the buffer at line end.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -35,15 +35,15 @@ public class GraphicOutputStream extends OutputStream {
|
|||
private Map<String, AttributeSet> _styles = new HashMap<String, AttributeSet>();
|
||||
private static AttributeSet _defaultStyle = StyleContext.getDefaultStyleContext()
|
||||
.getStyle(StyleContext.DEFAULT_STYLE);
|
||||
|
||||
|
||||
public GraphicOutputStream(ScrollingTextPane delegate) {
|
||||
_sink = delegate;
|
||||
}
|
||||
|
||||
|
||||
public void registerStyle(String pattern, AttributeSet style) {
|
||||
_styles.put(pattern, style);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer[count++] = (char)b;
|
||||
|
@ -51,7 +51,7 @@ public class GraphicOutputStream extends OutputStream {
|
|||
flushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void flushBuffer() {
|
||||
String txt = new String(buffer, 0, count);
|
||||
count = 0;
|
||||
|
@ -59,7 +59,7 @@ public class GraphicOutputStream extends OutputStream {
|
|||
_sink.setCharacterAttributes(style, true);
|
||||
_sink.appendText(txt);
|
||||
}
|
||||
|
||||
|
||||
AttributeSet getStyle(String txt) {
|
||||
if (txt == null || txt.isEmpty())
|
||||
return _defaultStyle;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package jpa.tools.swing;
|
||||
|
||||
|
@ -31,8 +31,8 @@ import java.util.Set;
|
|||
* The index of a given key is stable. It never changes unless the map is cleared.
|
||||
* On <code>remove(k)</code>, the key is not removed, but its value is nullified.
|
||||
* Then <code>indexOf(k)</code> will return <code>-1</code>.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
* @param <K>
|
||||
|
@ -42,45 +42,45 @@ public class IndexedMap<K,V> implements Map<K, V> {
|
|||
private final List<K> _keys = new ArrayList<K>();
|
||||
private final List<V> _values = new ArrayList<V>();
|
||||
private final Set<K> _nulls = new HashSet<K>();
|
||||
|
||||
|
||||
public void clear() {
|
||||
_keys.clear();
|
||||
_values.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return _keys.contains(key) && !_nulls.contains(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return _values.contains(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
*/
|
||||
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public V get(Object key) {
|
||||
int i = indexOf(key);
|
||||
return i == -1 ? null : _values.get(i);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEmpty() {
|
||||
return (_keys.size() - _nulls.size()) == 0;
|
||||
}
|
||||
|
||||
|
||||
public Set<K> keySet() {
|
||||
Set<K> result = new HashSet<K>(_keys);
|
||||
result.removeAll(_nulls);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public V put(K key, V value) {
|
||||
int i = _keys.indexOf(key);
|
||||
if (i == -1) {
|
||||
|
@ -92,24 +92,24 @@ public class IndexedMap<K,V> implements Map<K, V> {
|
|||
return _values.set(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
for (K k : m.keySet()) {
|
||||
this.put(k, m.get(k));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public V remove(Object key) {
|
||||
V v = get(key);
|
||||
_nulls.add((K)key);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return _keys.size() - _nulls.size();
|
||||
}
|
||||
|
||||
|
||||
public Collection<V> values() {
|
||||
Collection<V> result = new ArrayList<V>();
|
||||
for (int i = 0; i < _values.size(); i++) {
|
||||
|
@ -118,7 +118,7 @@ public class IndexedMap<K,V> implements Map<K, V> {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public int indexOf(Object key) {
|
||||
return _keys.indexOf(key);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import javax.persistence.metamodel.Type;
|
|||
|
||||
/**
|
||||
* Static utility for analyzing persistent metadata model using JPA 2.0.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -44,25 +44,25 @@ public class MetamodelHelper {
|
|||
public static final int ATTR_BASIC = 2;
|
||||
public static final int ATTR_SINGULAR_RELATION = 3;
|
||||
public static final int ATTR_PLURAL_RELATION = 4;
|
||||
|
||||
|
||||
public static final Color MIDNIGHT_BLUE = new Color(25,25,112);
|
||||
public static final Color DARK_GREEN = new Color(0,100,0);
|
||||
public static final Color KHAKI = new Color(240, 230, 140);
|
||||
|
||||
|
||||
public static String getDisplayName(Type<?> type) {
|
||||
if (type instanceof EntityType) {
|
||||
return getDisplayName((EntityType<?>)type);
|
||||
}
|
||||
return getDisplayName(type.getJavaType());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the displayed name of a given entity type.
|
||||
*/
|
||||
public static String getDisplayName(EntityType<?> type) {
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
|
||||
public static String getDisplayName(Class<?> cls) {
|
||||
String fullName = cls.getName();
|
||||
if (fullName.startsWith("java.") || fullName.startsWith("openbook.domain.")) {
|
||||
|
@ -71,8 +71,8 @@ public class MetamodelHelper {
|
|||
}
|
||||
return fullName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static String getDisplayName(Attribute<?,?> attr) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(getDisplayName(attr.getJavaType()));
|
||||
|
@ -81,18 +81,18 @@ public class MetamodelHelper {
|
|||
.append(getDisplayName(((MapAttribute)attr).getElementType())).append(">");
|
||||
} else if (attr instanceof PluralAttribute) {
|
||||
buffer.append("<").append(getDisplayName(((PluralAttribute)attr).getElementType())).append(">");
|
||||
}
|
||||
}
|
||||
buffer.append(" ").append(attr.getName());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static <T> List<Attribute<? super T,?>> getAttributes(EntityType<T> type) {
|
||||
List<Attribute<? super T,?>> list = new ArrayList<Attribute<? super T,?>>(type.getAttributes());
|
||||
Collections.sort(list, new AttributeComparator());
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public static int getAttributeType(Attribute<?, ?> a) {
|
||||
if (a instanceof SingularAttribute) {
|
||||
SingularAttribute<?, ?> sa = (SingularAttribute<?, ?>)a;
|
||||
|
@ -105,9 +105,9 @@ public class MetamodelHelper {
|
|||
if (a.isCollection()) return ATTR_PLURAL_RELATION;
|
||||
}
|
||||
return ATTR_BASIC;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static <T> Set<SingularAttribute<? super T, ?>> getIdAttributes(EntityType<T> type) {
|
||||
Set<SingularAttribute<? super T,?>> attrs = type.getSingularAttributes();
|
||||
Set<SingularAttribute<? super T,?>> idAttrs = new HashSet<SingularAttribute<? super T,?>>();
|
||||
|
@ -118,7 +118,7 @@ public class MetamodelHelper {
|
|||
}
|
||||
return idAttrs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the derived target of the given type, if any. Otherwise null.
|
||||
*/
|
||||
|
@ -132,7 +132,7 @@ public class MetamodelHelper {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static EntityType<?> getParentType(SingularAttribute<?,?> id) {
|
||||
if (id.getType() instanceof EntityType) {
|
||||
return (EntityType<?>)id.getType();
|
||||
|
@ -140,7 +140,7 @@ public class MetamodelHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static boolean isId(Attribute<?,?> a) {
|
||||
if (a instanceof SingularAttribute)
|
||||
return ((SingularAttribute<?,?>)a).isId();
|
||||
|
@ -151,7 +151,7 @@ public class MetamodelHelper {
|
|||
return ((SingularAttribute<?,?>)a).isVersion();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static Color getColor(Attribute<?,?> attr) {
|
||||
if (isId(attr))
|
||||
return Color.RED;
|
||||
|
@ -159,7 +159,7 @@ public class MetamodelHelper {
|
|||
return Color.DARK_GRAY;
|
||||
return getColor(attr.getPersistentAttributeType());
|
||||
}
|
||||
|
||||
|
||||
public static Color getColor(Attribute.PersistentAttributeType type) {
|
||||
switch (type) {
|
||||
case BASIC : return Color.BLACK;
|
||||
|
@ -172,18 +172,18 @@ public class MetamodelHelper {
|
|||
default: return Color.BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Integer getAttributeTypeCode(Attribute<?,?> attr) {
|
||||
if (isId(attr))
|
||||
return 0;
|
||||
if (isVersion(attr))
|
||||
return 1;
|
||||
|
||||
|
||||
switch (attr.getPersistentAttributeType()) {
|
||||
case BASIC :
|
||||
case BASIC :
|
||||
case EMBEDDED:
|
||||
return 2;
|
||||
case ONE_TO_ONE:
|
||||
case ONE_TO_ONE:
|
||||
case MANY_TO_ONE:
|
||||
return 3;
|
||||
case ONE_TO_MANY:
|
||||
|
@ -217,7 +217,7 @@ public class MetamodelHelper {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Method getMethod(Class<?> type, String p) {
|
||||
try {
|
||||
String getter = "get" + Character.toUpperCase(p.charAt(0))+p.substring(1);
|
||||
|
@ -226,13 +226,13 @@ public class MetamodelHelper {
|
|||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compares EntityType by their dependency of derived targets.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -245,18 +245,18 @@ public class MetamodelHelper {
|
|||
return -1;
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compares attribute by their qualification.
|
||||
* Identity
|
||||
* Identity
|
||||
* Version
|
||||
* Basic
|
||||
* Singular association
|
||||
* Plural association
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -37,22 +37,22 @@ import javax.swing.JPanel;
|
|||
* Hence the view is organized in terms of corresponding views of {@link EntityTypeView entity}
|
||||
* and their {@link AttributeView attributes}.
|
||||
* <br>
|
||||
* This view also draws linkage with A*-algorithm between the derived primary key attributes that
|
||||
* reference other entity types.
|
||||
*
|
||||
* This view also draws linkage with A*-algorithm between the derived primary key attributes that
|
||||
* reference other entity types.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MetamodelView extends JPanel implements Maze {
|
||||
|
||||
|
||||
private static final int GRID = 8;
|
||||
int hgap = 40;
|
||||
int vgap = 40;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a panel where each {@link EntityTypeView} is placed in a FlowLayout.
|
||||
* Only the entities of the model are ordered based on their primary key
|
||||
* Only the entities of the model are ordered based on their primary key
|
||||
* dependencies, if any.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -70,7 +70,7 @@ public class MetamodelView extends JPanel implements Maze {
|
|||
add(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EntityTypeView<?> findViewByType(EntityType<?> type) {
|
||||
if (type == null)
|
||||
return null;
|
||||
|
@ -84,7 +84,7 @@ public class MetamodelView extends JPanel implements Maze {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
|
@ -97,11 +97,11 @@ public class MetamodelView extends JPanel implements Maze {
|
|||
EntityTypeView<?> target = findViewByType(MetamodelHelper.getParentType(id));
|
||||
if (target == null)
|
||||
continue;
|
||||
|
||||
|
||||
PathFinder runner = new PathFinder(this);
|
||||
Point start = getConnectLocation(view, id);
|
||||
Point finish = target.getLocation();
|
||||
List<Point> path = runner.findPath(start.x/GRID, start.y/GRID,
|
||||
List<Point> path = runner.findPath(start.x/GRID, start.y/GRID,
|
||||
finish.x/GRID, finish.y/GRID);
|
||||
if (path.isEmpty())
|
||||
continue;
|
||||
|
@ -115,20 +115,20 @@ public class MetamodelView extends JPanel implements Maze {
|
|||
g.setColor(Color.BLACK);
|
||||
int r = 4;
|
||||
g.fillOval(p1.x*GRID -r, p1.y*GRID - r, 2*r, 2*r);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the position of the attribute in the entity view relative to this panel.
|
||||
* Gets the position of the attribute in the entity view relative to this panel.
|
||||
*/
|
||||
Point getConnectLocation(EntityTypeView<?> a, Attribute<?,?> attr) {
|
||||
Point p1 = a.getLocation();
|
||||
Point p2 = a.getPosition(attr);
|
||||
return new Point(p1.x + p2.x, p1.y + p2.y);
|
||||
}
|
||||
|
||||
|
||||
// contract for the maze
|
||||
@Override
|
||||
public boolean isReachable(int x, int y) {
|
||||
|
@ -136,7 +136,7 @@ public class MetamodelView extends JPanel implements Maze {
|
|||
Rectangle r = view.getBounds();
|
||||
int px = x*GRID;
|
||||
int py = y*GRID;
|
||||
if (r.contains(px, py))
|
||||
if (r.contains(px, py))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -21,17 +21,17 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* A* Algorithm to find rectilinear path through a {@link Maze}.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class PathFinder {
|
||||
private final Maze _maze;
|
||||
|
||||
|
||||
public PathFinder(Maze maze) {
|
||||
_maze = maze;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A* algorithm to find a path through a maze.
|
||||
* The algorithm follows these steps
|
||||
|
@ -40,13 +40,13 @@ public class PathFinder {
|
|||
* <LI> Current node is the lowest cost square on the open list
|
||||
* <LI> Move current node to the closed list.
|
||||
* <LI> For each of adjacent neighbor n to this current square
|
||||
* <LI> If n is not {@link Maze#isReachable(int, int) reachable} or if n is on the closed list, ignore.
|
||||
* <LI> If n is not {@link Maze#isReachable(int, int) reachable} or if n is on the closed list, ignore.
|
||||
* Otherwise do the following.
|
||||
* <LI> If n is not on the open list, add it to the open list. Make the current square
|
||||
* the parent of n. Record the cost of n.
|
||||
* <LI> If n is on the open list already, replace if this path to n is lower cost.
|
||||
* <LI> If n is not on the open list, add it to the open list. Make the current square
|
||||
* the parent of n. Record the cost of n.
|
||||
* <LI> If n is on the open list already, replace if this path to n is lower cost.
|
||||
* until the target node is added to the closed list, or fail to find the target square
|
||||
* i.e. the open list is empty.
|
||||
* i.e. the open list is empty.
|
||||
*
|
||||
* @param x1 the x-coordinate of the starting point
|
||||
* @param y1 the y-coordinate of the starting point
|
||||
|
@ -69,11 +69,11 @@ public class PathFinder {
|
|||
}
|
||||
} while (!openList.isEmpty() && findMatchingNode(x2, y2, closedList) == null);
|
||||
target = findMatchingNode(x2, y2, closedList);
|
||||
if (target == null)
|
||||
if (target == null)
|
||||
return traceBackPath(closedList.get(closedList.size()-1));
|
||||
return traceBackPath(target);
|
||||
}
|
||||
|
||||
|
||||
private void exploreNeighbours(Node current, Node target, List<Node> openList, List<Node> closedList) {
|
||||
insertNeighbour(current, current.x+1, current.y, target, openList, closedList);
|
||||
insertNeighbour(current, current.x-1, current.y, target, openList, closedList);
|
||||
|
@ -81,7 +81,7 @@ public class PathFinder {
|
|||
insertNeighbour(current, current.x, current.y-1, target, openList, closedList);
|
||||
Collections.sort(openList);
|
||||
}
|
||||
|
||||
|
||||
private Node insertNeighbour(Node n, int x, int y, Node target, List<Node> openList, List<Node> closedList) {
|
||||
if (distance(x,y,target) != 0) {
|
||||
if (!_maze.isReachable(x, y) || findMatchingNode(x, y, closedList) != null) {
|
||||
|
@ -102,7 +102,7 @@ public class PathFinder {
|
|||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
private Node findMatchingNode(int x, int y, List<Node> list) {
|
||||
for (Node n : list) {
|
||||
if (n.x == x && n.y == y)
|
||||
|
@ -110,17 +110,17 @@ public class PathFinder {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
int distance(Node n, Node m) {
|
||||
return Math.abs(n.x - m.x) + Math.abs(n.y - m.y);
|
||||
}
|
||||
int distance(int x, int y, Node m) {
|
||||
return Math.abs(x - m.x) + Math.abs(y - m.y);
|
||||
}
|
||||
|
||||
|
||||
List<Point> traceBackPath(Node target) {
|
||||
LinkedList<Point> path = new LinkedList<Point>();
|
||||
path.add(new Point(target.x, target.y));
|
||||
path.add(new Point(target.x, target.y));
|
||||
Node next = target.parent;
|
||||
while (next != null) {
|
||||
path.add(0,new Point(next.x, next.y));
|
||||
|
@ -128,7 +128,7 @@ public class PathFinder {
|
|||
}
|
||||
return straighten(path);
|
||||
}
|
||||
|
||||
|
||||
List<Point> straighten(List<Point> path) {
|
||||
if (path.size() < 3)
|
||||
return path;
|
||||
|
@ -146,18 +146,18 @@ public class PathFinder {
|
|||
path.removeAll(mids);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
private static class Node implements Comparable<Node> {
|
||||
int f,g,h;
|
||||
int x; int y;
|
||||
Node parent;
|
||||
|
||||
|
||||
public Node(Node p, int x, int y) {
|
||||
parent = p;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof Node) {
|
||||
|
@ -172,7 +172,7 @@ public class PathFinder {
|
|||
if (f == o.f) return 0;
|
||||
return f > o.f ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return "(" + x + "," + y + ":" + g + ")";
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import openbook.client.Images;
|
|||
|
||||
/**
|
||||
* Displays and navigates PowerPoint slides.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -50,16 +50,16 @@ public class PowerPointViewer extends JPanel {
|
|||
private JSpinner _goto;
|
||||
private JButton[] _navButtons;
|
||||
private int MAX_BUTTONS = 10; // Total number of navigation buttons excluding the PREVIOUS and NEXT button.
|
||||
|
||||
|
||||
// The slide
|
||||
private JLabel _view;
|
||||
|
||||
// The key for client property in the navigation buttons denoting the 0-based index of the slides.
|
||||
|
||||
// The key for client property in the navigation buttons denoting the 0-based index of the slides.
|
||||
private static final String SLIDE_INDEX = "slide.index";
|
||||
|
||||
|
||||
/**
|
||||
* Create a viewer with slides in the specified directory.
|
||||
*
|
||||
*
|
||||
* @param dir path to a directory containing PowerPoint slides.
|
||||
* @param slides name of the slides
|
||||
*/
|
||||
|
@ -71,21 +71,21 @@ public class PowerPointViewer extends JPanel {
|
|||
for (int i = 0; i < _total; i++) {
|
||||
_slides.add(null);
|
||||
}
|
||||
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
_view = new JLabel(getSlideAt(0));
|
||||
add(new JScrollPane(_view), BorderLayout.CENTER);
|
||||
add(createNavigationButtons(), BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create buttons to navigate the slides.
|
||||
*
|
||||
*
|
||||
* @return a panel containing the navigation buttons.
|
||||
*/
|
||||
private JPanel createNavigationButtons() {
|
||||
JPanel buttons = new JPanel();
|
||||
_navButtons = new JButton[Math.min(MAX_BUTTONS, _total)];
|
||||
_navButtons = new JButton[Math.min(MAX_BUTTONS, _total)];
|
||||
_prev = new RoundButton(Images.BACK);
|
||||
buttons.add(_prev);
|
||||
_prev.addActionListener(new ActionListener() {
|
||||
|
@ -128,9 +128,9 @@ public class PowerPointViewer extends JPanel {
|
|||
}
|
||||
});
|
||||
return buttons;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the next page.
|
||||
*/
|
||||
|
@ -141,7 +141,7 @@ public class PowerPointViewer extends JPanel {
|
|||
current += 1;
|
||||
showPage(current);
|
||||
}
|
||||
|
||||
|
||||
private void prevPage() {
|
||||
int current = getCurrentPageIndex();
|
||||
if (current <= 0)
|
||||
|
@ -149,44 +149,44 @@ public class PowerPointViewer extends JPanel {
|
|||
current -= 1;
|
||||
showPage(current);
|
||||
}
|
||||
|
||||
|
||||
int getCurrentPageIndex() {
|
||||
return (Integer)_goto.getValue()-1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows the slide at the given index.
|
||||
*
|
||||
*
|
||||
* @param index 0-based index of the slides.
|
||||
*/
|
||||
private void showPage(int index) {
|
||||
_view.setIcon(getSlideAt(index));
|
||||
updateButtons(index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the buttons.
|
||||
*
|
||||
*
|
||||
* @param current 0-based index of the currently displayed slide.
|
||||
*/
|
||||
private void updateButtons(int index) {
|
||||
_goto.setValue(index+1);
|
||||
|
||||
|
||||
int last = index + _navButtons.length;
|
||||
if (last >= _total)
|
||||
return;
|
||||
|
||||
|
||||
for (int i = 0; i < _navButtons.length; i++) {
|
||||
int slideIndex = index+i+2;
|
||||
_navButtons[i].setText(String.format("%02d", slideIndex));
|
||||
_navButtons[i].putClientProperty(SLIDE_INDEX, (index+i+1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getSlideCount() {
|
||||
return _total;
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getSlideAt(int index) {
|
||||
WeakReference<ImageIcon> weak = _slides.get(index);
|
||||
if (weak == null) {
|
||||
|
@ -194,14 +194,14 @@ public class PowerPointViewer extends JPanel {
|
|||
}
|
||||
return (weak.get() == null) ? loadSlide(index) : weak.get();
|
||||
}
|
||||
|
||||
|
||||
ImageIcon loadSlide(int index) {
|
||||
URL imgURL = _slideURLs.get(index);
|
||||
ImageIcon icon = new ImageIcon(imgURL);
|
||||
_slides.add(index, new WeakReference<ImageIcon>(icon));
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
List<URL> validateSlides(String dir, List<String> slides) {
|
||||
List<URL> valid = new ArrayList<URL>();
|
||||
for (String slide : slides) {
|
||||
|
@ -212,7 +212,7 @@ public class PowerPointViewer extends JPanel {
|
|||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
private URL findResource(String path) {
|
||||
if (path == null)
|
||||
return null;
|
||||
|
@ -226,5 +226,5 @@ public class PowerPointViewer extends JPanel {
|
|||
}
|
||||
return imgURL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
|||
|
||||
/**
|
||||
* A specialized table to display statistics of queries.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PreparedQueryViewer extends JTable {
|
||||
|
||||
|
||||
public PreparedQueryViewer(OpenJPAEntityManagerFactory emf) {
|
||||
super(new QueryStatisticsModel(((OpenJPAEntityManagerFactorySPI)emf).getConfiguration()
|
||||
.getQuerySQLCacheInstance().getStatistics()));
|
||||
|
|
|
@ -18,7 +18,7 @@ import javax.persistence.Query;
|
|||
/**
|
||||
* Decorates an executable query.
|
||||
* Concrete decorative action can be binding parameters, limiting the result range etc.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -25,12 +25,12 @@ import org.apache.openjpa.kernel.QueryStatistics;
|
|||
class QueryStatisticsModel extends AbstractTableModel {
|
||||
QueryStatistics<String> _stats;
|
||||
private List<String> _keys = new ArrayList<String>();
|
||||
|
||||
|
||||
QueryStatisticsModel(QueryStatistics<String> stats) {
|
||||
_stats = stats;
|
||||
sortKeys(stats);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 3;
|
||||
|
@ -41,7 +41,7 @@ class QueryStatisticsModel extends AbstractTableModel {
|
|||
sortKeys(_stats);
|
||||
return _keys.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
|
@ -62,7 +62,7 @@ class QueryStatisticsModel extends AbstractTableModel {
|
|||
default : return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sortKeys(QueryStatistics<String> stats) {
|
||||
if (_stats.keys().size() != _keys.size()) {
|
||||
_keys = new ArrayList<String>(_stats.keys());
|
||||
|
|
|
@ -30,31 +30,31 @@ import javax.swing.JButton;
|
|||
|
||||
/**
|
||||
* A Circular Swing Button.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class RoundButton extends JButton {
|
||||
protected Shape shape, base;
|
||||
|
||||
|
||||
public RoundButton() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
|
||||
public RoundButton(Icon icon) {
|
||||
this(null, icon);
|
||||
}
|
||||
|
||||
|
||||
public RoundButton(String text) {
|
||||
this(text, null);
|
||||
}
|
||||
|
||||
|
||||
public RoundButton(Action a) {
|
||||
this();
|
||||
setAction(a);
|
||||
}
|
||||
|
||||
|
||||
public RoundButton(String text, Icon icon) {
|
||||
setModel(new DefaultButtonModel());
|
||||
init(text, icon);
|
||||
|
@ -74,7 +74,7 @@ public class RoundButton extends JButton {
|
|||
setAlignmentY(Component.TOP_ALIGNMENT);
|
||||
initShape();
|
||||
}
|
||||
|
||||
|
||||
protected void initShape() {
|
||||
if(!getBounds().equals(base)) {
|
||||
Dimension s = getPreferredSize();
|
||||
|
@ -82,7 +82,7 @@ public class RoundButton extends JButton {
|
|||
shape = new Ellipse2D.Float(0, 0, s.width-1, s.height-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void paintBorder(Graphics g) {
|
||||
initShape();
|
||||
|
@ -92,7 +92,7 @@ public class RoundButton extends JButton {
|
|||
g2.draw(shape);
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean contains(int x, int y) {
|
||||
initShape();
|
||||
|
|
|
@ -28,13 +28,13 @@ import javax.swing.text.Document;
|
|||
|
||||
/**
|
||||
* A TextPane where text that scrolls as new text is appended.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ScrollingTextPane extends JTextPane {
|
||||
|
||||
|
||||
public void appendText(String text) {
|
||||
if (text == null)
|
||||
return;
|
||||
|
@ -47,21 +47,21 @@ public class ScrollingTextPane extends JTextPane {
|
|||
scrollRectToVisible(r);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
JFrame f = new JFrame();
|
||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
|
||||
final ScrollingTextPane test = new ScrollingTextPane();
|
||||
f.getContentPane().add(new JScrollPane(test));
|
||||
f.pack();
|
||||
f.setSize(600,450);
|
||||
f.setVisible(true);
|
||||
|
||||
|
||||
Timer timer = new Timer(1000, new ActionListener() {
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss");
|
||||
@Override
|
||||
|
|
|
@ -34,8 +34,8 @@ import javax.swing.JScrollPane;
|
|||
* An internal viewer for HTML formatted source code.
|
||||
* The input to this viewer is a root URL.
|
||||
* The viewer shows the anchors in a combo-box and displays the
|
||||
* corresponding HTML in the main editor.
|
||||
*
|
||||
* corresponding HTML in the main editor.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -45,45 +45,45 @@ public class SourceCodeViewer extends JPanel {
|
|||
private final JComboBox _bookmarks;
|
||||
private IndexedMap<String, URI> _anchors = new IndexedMap<String, URI>();
|
||||
private LinkedList<String> _visited = new LinkedList<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a Source Code Browser.
|
||||
*/
|
||||
public SourceCodeViewer() {
|
||||
super(true);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
|
||||
_editor = new JEditorPane();
|
||||
_editor.setContentType("text/html");
|
||||
_editor.setEditable(false);
|
||||
|
||||
|
||||
DefaultComboBoxModel model = new DefaultComboBoxModel();
|
||||
_bookmarks = new JComboBox(model);
|
||||
_bookmarks.setEditable(false);
|
||||
|
||||
|
||||
_bookmarks.addActionListener(new ActionListener(){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showAnchor((String)_bookmarks.getSelectedItem());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
JPanel topPanel = new JPanel();
|
||||
((FlowLayout)topPanel.getLayout()).setAlignment(FlowLayout.LEADING);
|
||||
topPanel.add(new JLabel("Go to "));
|
||||
topPanel.add(_bookmarks);
|
||||
topPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
|
||||
|
||||
|
||||
add(new JScrollPane(_editor,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS),
|
||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS),
|
||||
BorderLayout.CENTER);
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a page to this browser.
|
||||
*
|
||||
*
|
||||
* @param anchor a user visible description to identify the page
|
||||
* @param uri the unique resource location
|
||||
*/
|
||||
|
@ -91,10 +91,10 @@ public class SourceCodeViewer extends JPanel {
|
|||
_anchors.put(anchor, url);
|
||||
((DefaultComboBoxModel)_bookmarks.getModel()).addElement(anchor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows the page identified by the given anchor.
|
||||
*
|
||||
*
|
||||
* @param anchor an anchor added a priori.
|
||||
*/
|
||||
public void showAnchor(String anchor) {
|
||||
|
@ -103,14 +103,14 @@ public class SourceCodeViewer extends JPanel {
|
|||
return;
|
||||
showPage(anchor, _anchors.get(anchor));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows the given URI.
|
||||
* @param anchor an anchor added a priori or a new one.
|
||||
* @param uri the URI of the anchor
|
||||
*/
|
||||
public void showPage(String anchor, URI uri) {
|
||||
if (anchor == null || uri == null)
|
||||
if (anchor == null || uri == null)
|
||||
return;
|
||||
try {
|
||||
URL url = uri.toURL();
|
||||
|
|
|
@ -34,13 +34,13 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
private JProgressBar memoryBar;
|
||||
private JLabel messageText;
|
||||
private TaskProgress task;
|
||||
|
||||
|
||||
public StatusBar() {
|
||||
progressBar = new JProgressBar();
|
||||
memoryBar = new JProgressBar();
|
||||
|
||||
|
||||
messageText = new JLabel();
|
||||
|
||||
|
||||
setLayout(new GridLayout(1,0));
|
||||
add(messageText);
|
||||
add(Box.createHorizontalGlue());
|
||||
|
@ -50,11 +50,11 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
MemoryDisplay memory = new MemoryDisplay(memoryBar);
|
||||
new Timer(100, memory).start();
|
||||
}
|
||||
|
||||
|
||||
public void showMessage(String text) {
|
||||
messageText.setText(text);
|
||||
}
|
||||
|
||||
|
||||
public void startTimer(long duration, int interval, TimeUnit unit) {
|
||||
progressBar.setEnabled(true);
|
||||
if (duration > 0) {
|
||||
|
@ -72,17 +72,17 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
task.execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoked when task's progress property changes.
|
||||
*/
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if ("progress".equals(evt.getPropertyName())) {
|
||||
progressBar.setValue((Integer)evt.getNewValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void stopTimer() {
|
||||
if (task != null) {
|
||||
task.cancel(true);
|
||||
|
@ -92,7 +92,7 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
progressBar.setString("");
|
||||
progressBar.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emits progress property from a background thread.
|
||||
*/
|
||||
|
@ -100,7 +100,7 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
private long startTimeInMillis;
|
||||
private long _total = 100;
|
||||
private int _interval = 100;
|
||||
|
||||
|
||||
public TaskProgress(long total, int interval) {
|
||||
_total = Math.max(total, 1);
|
||||
_interval = Math.max(interval, 1);
|
||||
|
@ -122,7 +122,7 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class MemoryDisplay implements ActionListener {
|
||||
JProgressBar bar;
|
||||
public MemoryDisplay(JProgressBar bar) {
|
||||
|
@ -141,16 +141,16 @@ public class StatusBar extends JPanel implements PropertyChangeListener {
|
|||
bar.setValue((int)usedPct);
|
||||
bar.setString(usedPct + "% (" + mb(usedMemory) + "/" + mb(totalMemory) + "MB) ");
|
||||
}
|
||||
|
||||
|
||||
private long mb(long m) {
|
||||
return m/1000000;
|
||||
}
|
||||
|
||||
|
||||
Color getColor(int pct) {
|
||||
int red = 255*pct/100;
|
||||
int green = 255*(100-pct)/100;
|
||||
return new Color(red, green, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -36,18 +36,18 @@ import javax.swing.plaf.FontUIResource;
|
|||
|
||||
/**
|
||||
* Assorted utility methods.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class SwingHelper {
|
||||
/**
|
||||
* Position the given component at the center of the given parent component or physical screen.
|
||||
*
|
||||
*
|
||||
* @param c the component to be positioned
|
||||
* @param parent the component whose center will match the center of the given component.
|
||||
* If null, the given component will match the screen center.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static void position(Component c, Component parent) {
|
||||
Dimension d = c.getPreferredSize();
|
||||
|
@ -61,9 +61,9 @@ public class SwingHelper {
|
|||
c.setLocation(p.x + pw/2 - d.width/2, p.y + ph/2 - d.height/2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int[] factors = {1000, 1000, 1000, 1000, 60, 60, 24};
|
||||
|
||||
|
||||
public static String getTimeString(long value, TimeUnit unit) {
|
||||
if (value <= 0)
|
||||
return "";
|
||||
|
@ -75,13 +75,13 @@ public class SwingHelper {
|
|||
next = units[i+1];
|
||||
factor = factors[i+1];
|
||||
long nextValue = value/factor;
|
||||
if (nextValue > 0)
|
||||
return getTimeString(value/factor, next) + " " + getTimeString(value%factor, unit);
|
||||
}
|
||||
|
||||
if (nextValue > 0)
|
||||
return getTimeString(value/factor, next) + " " + getTimeString(value%factor, unit);
|
||||
}
|
||||
|
||||
return value + toString(unit);
|
||||
}
|
||||
|
||||
|
||||
public static String toString(TimeUnit unit) {
|
||||
switch (unit) {
|
||||
case HOURS:
|
||||
|
@ -98,7 +98,7 @@ public class SwingHelper {
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static void print(Component c, String format, File output) {
|
||||
try {
|
||||
Robot robot = new Robot();
|
||||
|
@ -113,7 +113,7 @@ public class SwingHelper {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static AbstractButton getSelectedButton(ButtonGroup group) {
|
||||
Enumeration<AbstractButton> buttons = group.getElements();
|
||||
while (buttons.hasMoreElements()) {
|
||||
|
@ -124,7 +124,7 @@ public class SwingHelper {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static void setLookAndFeel(int fontSize) throws Exception {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
UIDefaults defaults = UIManager.getDefaults();
|
||||
|
@ -138,7 +138,7 @@ public class SwingHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class TextStyles {
|
|||
KEYS = ctx.addAttribute(KEYS, StyleConstants.Bold, true);
|
||||
KEYS = ctx.addAttribute(KEYS, StyleConstants.FontSize, 14);
|
||||
KEYS = ctx.addAttribute(KEYS, StyleConstants.FontFamily, "Courier");
|
||||
|
||||
|
||||
Color indianRed = new Color(205, 92, 92);
|
||||
VALUES = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, indianRed);
|
||||
VALUES = ctx.addAttribute(VALUES, StyleConstants.Bold, true);
|
||||
|
|
|
@ -18,6 +18,6 @@ under the License.
|
|||
-->
|
||||
<html>
|
||||
<body>
|
||||
Swing widgets to browse persistent entities using JPA 2.0 MetaModel API.
|
||||
Swing widgets to browse persistent entities using JPA 2.0 MetaModel API.
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -53,22 +53,22 @@ import openbook.server.QueryDecorator;
|
|||
import org.apache.openjpa.lib.jdbc.SQLFormatter;
|
||||
|
||||
/**
|
||||
* A visual page coordinates the following functions of {@link OpenBookService} :
|
||||
* A visual page coordinates the following functions of {@link OpenBookService} :
|
||||
* <li>query for books
|
||||
* <li>choose one or more of the selected books
|
||||
* <li>add them to Shopping Cart
|
||||
* <li>place a purchase order of the books in the shopping cart.
|
||||
* <p>
|
||||
* Each interaction with the underlying service occurs in a background i.e.
|
||||
* Each interaction with the underlying service occurs in a background i.e.
|
||||
* a <em>non</em>-AWT event dispatching thread. The background threads are
|
||||
* used via {@link SwingWorker} and hence each persistence operation is
|
||||
* can be potentially handled by a different JPA persistence context.
|
||||
* This threading model not only adheres to the good practice of responsive graphical
|
||||
* user interface design, it exercises the <em>remote</em> nature of JPA service
|
||||
* This threading model not only adheres to the good practice of responsive graphical
|
||||
* user interface design, it exercises the <em>remote</em> nature of JPA service
|
||||
* (even within this single process Swing application) where every operation
|
||||
* on a persistence context results into a set of <em>detached</em> instances
|
||||
* to the remote client.
|
||||
*
|
||||
* to the remote client.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
@ -79,10 +79,10 @@ public final class BuyBookPage extends JPanel {
|
|||
private final BuyPanel _buyPanel;
|
||||
private final SelectBookPanel _selectPanel;
|
||||
private final ShoppingCartPanel _cartPanel;
|
||||
|
||||
|
||||
/**
|
||||
* A Page with 2x2 Grid of panels each for one of the specific action.
|
||||
*
|
||||
*
|
||||
* @param service the OpenBooks service handle.
|
||||
*/
|
||||
public BuyBookPage(OpenBookService service, Customer customer) {
|
||||
|
@ -102,7 +102,7 @@ public final class BuyBookPage extends JPanel {
|
|||
add(_cartPanel);
|
||||
add(_selectPanel);
|
||||
add(_buyPanel);
|
||||
|
||||
|
||||
_selectPanel._selectedBooks.getTable()
|
||||
.getSelectionModel()
|
||||
.addListSelectionListener(_buyPanel);
|
||||
|
@ -112,16 +112,16 @@ public final class BuyBookPage extends JPanel {
|
|||
* A form like panel displays the different fields to search for books.
|
||||
* Zero or more form fields can be filled in. Though the service level
|
||||
* contract does not mandate how to form the exact query from the form
|
||||
* field values, the actual implementation demonstrates how dynamic
|
||||
* field values, the actual implementation demonstrates how dynamic
|
||||
* query construction introduced via Criteria Query API in JPA 2.0
|
||||
* can aid in such common user scenarios.
|
||||
* <br>
|
||||
* The object level query is displayed to demonstrate the ability of
|
||||
* OpenJPA to express a dynamic Criteria Query is a human-readable,
|
||||
* JPQL-like query string.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
class SearchPanel extends JPanel implements ActionListener {
|
||||
private final JTextField _title = new JTextField("", 20);
|
||||
|
@ -130,7 +130,7 @@ public final class BuyBookPage extends JPanel {
|
|||
private final JTextField _minPrice = new JTextField("", 6);
|
||||
private final JTextArea _queryView = new JTextArea();
|
||||
private final SQLFormatter _formatter = new SQLFormatter();
|
||||
|
||||
|
||||
SearchPanel(String title) {
|
||||
super(true);
|
||||
setBorder(BorderFactory.createTitledBorder(title));
|
||||
|
@ -159,7 +159,7 @@ public final class BuyBookPage extends JPanel {
|
|||
.addComponent(_minPrice)
|
||||
.addComponent(toLabel)
|
||||
.addComponent(_maxPrice)));
|
||||
|
||||
|
||||
GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
|
||||
vGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(titleLabel)
|
||||
|
@ -173,7 +173,7 @@ public final class BuyBookPage extends JPanel {
|
|||
.addComponent(_minPrice)
|
||||
.addComponent(toLabel)
|
||||
.addComponent(_maxPrice));
|
||||
|
||||
|
||||
layout.setHorizontalGroup(hGroup);
|
||||
layout.setVerticalGroup(vGroup);
|
||||
|
||||
|
@ -182,19 +182,19 @@ public final class BuyBookPage extends JPanel {
|
|||
ShowCodeAction showCode = Demo.getInstance().new ShowCodeAction();
|
||||
showCode.setPage("Dynamic Query", "server/OpenBookServiceImpl.java.html#buildQuery");
|
||||
JButton viewCodeButton = new JButton(showCode);
|
||||
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(searchButton);
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(viewCodeButton);
|
||||
|
||||
|
||||
BoxLayout box = new BoxLayout(this, BoxLayout.Y_AXIS);
|
||||
setLayout(box);
|
||||
add(panel);
|
||||
add(Box.createVerticalGlue());
|
||||
add(buttonPanel);
|
||||
|
||||
|
||||
_queryView.setBorder(BorderFactory.createTitledBorder("Criteria Query as CQL"));
|
||||
_queryView.setWrapStyleWord(true);
|
||||
_queryView.setEditable(false);
|
||||
|
@ -202,10 +202,10 @@ public final class BuyBookPage extends JPanel {
|
|||
add(_queryView);
|
||||
searchButton.addActionListener(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a query and displays the result onto {@linkplain SelectBookPanel}.
|
||||
*
|
||||
*
|
||||
* The query is executed in a background, non-AWT thread.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
@ -213,12 +213,12 @@ public final class BuyBookPage extends JPanel {
|
|||
private String queryString;
|
||||
@Override
|
||||
protected List<Book> doInBackground() throws Exception {
|
||||
queryString = _service.getQuery(_title.getText(),
|
||||
asDouble(_minPrice), asDouble(_maxPrice),
|
||||
queryString = _service.getQuery(_title.getText(),
|
||||
asDouble(_minPrice), asDouble(_maxPrice),
|
||||
_author.getText());
|
||||
return _service.select(_title.getText(),
|
||||
asDouble(_minPrice), asDouble(_maxPrice),
|
||||
_author.getText(),
|
||||
return _service.select(_title.getText(),
|
||||
asDouble(_minPrice), asDouble(_maxPrice),
|
||||
_author.getText(),
|
||||
(QueryDecorator[])null);
|
||||
}
|
||||
|
||||
|
@ -255,27 +255,27 @@ public final class BuyBookPage extends JPanel {
|
|||
|
||||
/**
|
||||
* A panel to display the selected books in a tabular format.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
class SelectBookPanel extends JPanel {
|
||||
private final JLabel _bookCount;
|
||||
private final EntityTableView<Book> _selectedBooks;
|
||||
|
||||
|
||||
SelectBookPanel(String title) {
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(BorderFactory.createTitledBorder(title));
|
||||
|
||||
_selectedBooks = new EntityTableView<Book>(Book.class,
|
||||
EntityDataModel.BASIC_ATTR | EntityDataModel.ROW_COUNT,
|
||||
EntityDataModel.BASIC_ATTR | EntityDataModel.ROW_COUNT,
|
||||
_service.getUnit());
|
||||
_bookCount = new JLabel();
|
||||
|
||||
|
||||
add(_bookCount, BorderLayout.NORTH);
|
||||
add(_selectedBooks, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
|
||||
void updateDataModel(List<Book> books) {
|
||||
_bookCount.setText(books.size() + " Book selected");
|
||||
_selectedBooks.getDataModel().updateData(books);
|
||||
|
@ -285,9 +285,9 @@ public final class BuyBookPage extends JPanel {
|
|||
/**
|
||||
* A panel to display the details of a single book and a button to add the
|
||||
* book to cart. Listens to the selection in the selected books.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
class BuyPanel extends JPanel implements ListSelectionListener {
|
||||
JLabel _bookTitle;
|
||||
|
@ -297,13 +297,13 @@ public final class BuyBookPage extends JPanel {
|
|||
JButton _addToCart;
|
||||
JSpinner _quantity;
|
||||
JPanel _quantityPanel;
|
||||
|
||||
|
||||
public BuyPanel(String title) {
|
||||
super(true);
|
||||
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createTitledBorder(title));
|
||||
|
||||
|
||||
JPanel descPanel = new JPanel();
|
||||
descPanel.setLayout(new BoxLayout(descPanel, BoxLayout.Y_AXIS));
|
||||
_bookTitle = new JLabel();
|
||||
|
@ -324,9 +324,9 @@ public final class BuyBookPage extends JPanel {
|
|||
_quantityPanel.add(_quantity);
|
||||
_quantityPanel.setVisible(false);
|
||||
add(_quantityPanel);
|
||||
|
||||
|
||||
add(Box.createVerticalGlue());
|
||||
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
_addToCart = new JButton("Add to Cart", Images.CART);
|
||||
|
@ -338,7 +338,7 @@ public final class BuyBookPage extends JPanel {
|
|||
_addToCart.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
_cartPanel.addBook((Book)_addToCart.getClientProperty("Book"),
|
||||
_cartPanel.addBook((Book)_addToCart.getClientProperty("Book"),
|
||||
(Integer)_quantity.getValue());
|
||||
}
|
||||
});
|
||||
|
@ -380,23 +380,23 @@ public final class BuyBookPage extends JPanel {
|
|||
|
||||
/**
|
||||
* A panel to display the shopping cart.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ShoppingCartPanel extends JPanel implements ActionListener {
|
||||
private static final int MAX_ITEMS = 10;
|
||||
private final ShoppingCart _cart;
|
||||
private final JButton _placeOrder;
|
||||
private final JLabel[] _items = new JLabel[MAX_ITEMS];
|
||||
|
||||
|
||||
public ShoppingCartPanel(String title) {
|
||||
_cart = _customer.newCart();
|
||||
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createTitledBorder(title));
|
||||
_placeOrder = new JButton("Place Order", Images.START);
|
||||
_placeOrder.setHorizontalTextPosition(SwingConstants.LEADING);
|
||||
|
||||
|
||||
_placeOrder.setEnabled(false);
|
||||
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||
_items[i] = new JLabel("");
|
||||
|
@ -410,7 +410,7 @@ public final class BuyBookPage extends JPanel {
|
|||
add(buttonPanel);
|
||||
_placeOrder.addActionListener(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given book to the cart. Updates the display.
|
||||
*/
|
||||
|
@ -418,7 +418,7 @@ public final class BuyBookPage extends JPanel {
|
|||
_cart.addItem(book, quantity);
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
|
||||
void updateDisplay() {
|
||||
Map<Book, Integer> items = _cart.getItems();
|
||||
int i = 0;
|
||||
|
@ -431,7 +431,7 @@ public final class BuyBookPage extends JPanel {
|
|||
}
|
||||
_placeOrder.setEnabled(items.size()>0);
|
||||
super.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
|
|
@ -36,9 +36,9 @@ import openbook.server.OpenBookService;
|
|||
|
||||
/**
|
||||
* A page to control delivery of pending orders.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DeliveryPage extends JPanel {
|
||||
|
@ -147,7 +147,7 @@ public class DeliveryPage extends JPanel {
|
|||
* Gets the orders in a background (i.e. not AWT event dispatch thread)
|
||||
* thread. <br>
|
||||
* But blocks painting anyway, because that is what is intended.
|
||||
*
|
||||
*
|
||||
*/
|
||||
private List<PurchaseOrder> getOrders(final PurchaseOrder.Status status) {
|
||||
SwingWorker<List<PurchaseOrder>, Void> worker = new SwingWorker<List<PurchaseOrder>, Void>() {
|
||||
|
|
|
@ -73,7 +73,7 @@ import org.apache.openjpa.persistence.OpenJPAPersistence;
|
|||
|
||||
/**
|
||||
* A graphical user interface based client of OpenBooks for demonstration.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -90,12 +90,12 @@ public class Demo extends JFrame {
|
|||
private Action _about;
|
||||
private Action _buyBook;
|
||||
private Action _deliver;
|
||||
private Action _supply;
|
||||
private Action _viewConfig;
|
||||
private Action _viewDomain;
|
||||
private Action _supply;
|
||||
private Action _viewConfig;
|
||||
private Action _viewDomain;
|
||||
private Action _viewSource;
|
||||
private Action _viewQuery;
|
||||
|
||||
|
||||
/**
|
||||
* The primary graphic widgets used to invoke and display the results of the actions.
|
||||
*/
|
||||
|
@ -109,14 +109,14 @@ public class Demo extends JFrame {
|
|||
private SourceCodeBrowser _sourceBrowser;
|
||||
private static Demo _instance;
|
||||
private static final String SRC_ROOT = "source/";
|
||||
|
||||
|
||||
/**
|
||||
* The handle to the service.
|
||||
*/
|
||||
private OpenBookService _service;
|
||||
private Customer _customer;
|
||||
private Map<String, Object> _config;
|
||||
|
||||
|
||||
/**
|
||||
* Runs the demo.
|
||||
*/
|
||||
|
@ -134,14 +134,14 @@ public class Demo extends JFrame {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public synchronized static Demo getInstance() {
|
||||
if (_instance == null) {
|
||||
_instance = new Demo();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
static void adjustWidgetSize() {
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int sw = (int)(95*screen.getWidth()/100);
|
||||
|
@ -151,13 +151,13 @@ public class Demo extends JFrame {
|
|||
OUT_VIEW = new Dimension(75*sw/100, 35*sh/100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Demo() {
|
||||
Thread.currentThread().setUncaughtExceptionHandler(new ErrorHandler());
|
||||
_config = PropertyHelper.load(System.getProperty("openbook.client.config", "demo.properties"));
|
||||
setIconImage(((ImageIcon)Images.LOGO_OPENBOOKS).getImage());
|
||||
setTitle("OpenBooks: A Sample JPA 2.0 Application");
|
||||
|
||||
|
||||
_root = new WelcomeAction("OpenBooks", Images.LOGO_OPENBOOKS, "OpenBooks");
|
||||
_about = new AboutAction("About OpenBooks", Images.LOGO_OPENBOOKS, "About OpenBooks");
|
||||
_buyBook = new BuyBookAction("Buy", Images.BUY, "Browse and Buy Books");
|
||||
|
@ -167,13 +167,13 @@ public class Demo extends JFrame {
|
|||
_viewDomain = new ViewDomainAction("Domain", Images.VIEW_DOMAIN, "View Domain Model");
|
||||
_viewSource = new ViewSourceAction("Source", Images.VIEW_CODE, "View Source Code");
|
||||
_viewQuery = new ViewQueryCacheAction("Query", Images.VIEW_QUERY, "View Queries");
|
||||
|
||||
|
||||
_toolBar = createToolBar();
|
||||
_navigator = createNavigator();
|
||||
_tabbedPane = createTabbedView();
|
||||
_outputPane = createOutputView();
|
||||
_statusBar = createStatusBar();
|
||||
|
||||
|
||||
JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
horizontalSplitPane.setContinuousLayout(true);
|
||||
horizontalSplitPane.setDividerSize(5);
|
||||
|
@ -181,29 +181,29 @@ public class Demo extends JFrame {
|
|||
scrollPane.setMinimumSize(new Dimension(NAV_VIEW.width/4, NAV_VIEW.height));
|
||||
scrollPane.setPreferredSize(NAV_VIEW);
|
||||
horizontalSplitPane.add(scrollPane);
|
||||
|
||||
|
||||
JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
verticalSplitPane.setContinuousLayout(true);
|
||||
verticalSplitPane.setDividerSize(5);
|
||||
verticalSplitPane.add(_tabbedPane);
|
||||
verticalSplitPane.add(_outputPane);
|
||||
horizontalSplitPane.add(verticalSplitPane);
|
||||
|
||||
|
||||
Container content = getContentPane();
|
||||
content.add(_toolBar, BorderLayout.PAGE_START);
|
||||
content.add(horizontalSplitPane, BorderLayout.CENTER);
|
||||
content.add(_statusBar, BorderLayout.SOUTH);
|
||||
|
||||
|
||||
_root.actionPerformed(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the handle to OpenBooks service.
|
||||
* Gets the handle to OpenBooks service.
|
||||
*/
|
||||
public OpenBookService getService() {
|
||||
if (_service == null) {
|
||||
final String unitName = getConfiguration("openbook.unit", OpenBookService.DEFAULT_UNIT_NAME);
|
||||
|
||||
|
||||
SwingWorker<OpenBookService, Void> getService = new SwingWorker<OpenBookService, Void> () {
|
||||
@Override
|
||||
protected OpenBookService doInBackground() throws Exception {
|
||||
|
@ -213,7 +213,7 @@ public class Demo extends JFrame {
|
|||
service.initialize(null);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
getService.execute();
|
||||
try {
|
||||
|
@ -227,7 +227,7 @@ public class Demo extends JFrame {
|
|||
}
|
||||
return _service;
|
||||
}
|
||||
|
||||
|
||||
public Customer getCustomer() {
|
||||
if (_customer == null) {
|
||||
SwingWorker<Customer, Void> task = new SwingWorker<Customer, Void> () {
|
||||
|
@ -235,7 +235,7 @@ public class Demo extends JFrame {
|
|||
protected Customer doInBackground() throws Exception {
|
||||
return getService().login("guest");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
task.execute();
|
||||
try {
|
||||
|
@ -246,7 +246,7 @@ public class Demo extends JFrame {
|
|||
}
|
||||
return _customer;
|
||||
}
|
||||
|
||||
|
||||
private JToolBar createToolBar() {
|
||||
JToolBar toolBar = new JToolBar();
|
||||
toolBar.add(_buyBook);
|
||||
|
@ -254,28 +254,28 @@ public class Demo extends JFrame {
|
|||
toolBar.add(_supply);
|
||||
Dimension d = new Dimension(40, 32);
|
||||
toolBar.addSeparator(d);
|
||||
|
||||
|
||||
toolBar.add(_viewConfig);
|
||||
toolBar.add(_viewDomain);
|
||||
toolBar.add(_viewSource);
|
||||
toolBar.add(_viewQuery);
|
||||
|
||||
|
||||
toolBar.addSeparator(d);
|
||||
|
||||
|
||||
toolBar.add(Box.createHorizontalGlue());
|
||||
toolBar.add(_about);
|
||||
toolBar.add(Box.createHorizontalStrut(2));
|
||||
return toolBar;
|
||||
}
|
||||
|
||||
|
||||
private StatusBar createStatusBar() {
|
||||
return new StatusBar();
|
||||
}
|
||||
|
||||
|
||||
public String getConfiguration(String key, String def) {
|
||||
return PropertyHelper.getString(_config, key, def);
|
||||
}
|
||||
|
||||
|
||||
private SourceCodeBrowser getSourceCodeBrowser() {
|
||||
if (_sourceBrowser == null) {
|
||||
String root = getConfiguration("openbook.source.root", SRC_ROOT);
|
||||
|
@ -297,7 +297,7 @@ public class Demo extends JFrame {
|
|||
/**
|
||||
* Abstract root of all Action objects helps to locate/configure visual action parameters such as
|
||||
* tooltip text or image.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -308,13 +308,13 @@ public class Demo extends JFrame {
|
|||
putValue(Action.SMALL_ICON, icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class BuyBookAction extends OpenBookAction {
|
||||
BuyBookPage _buyBookPage;
|
||||
public BuyBookAction(String name, Icon icon, String tooltip) {
|
||||
super(name, icon, tooltip);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (_buyBookPage == null) {
|
||||
_buyBookPage = new BuyBookPage(getService(), getCustomer());
|
||||
|
@ -322,7 +322,7 @@ public class Demo extends JFrame {
|
|||
showTab(_tabbedPane, "Buy Books", _buyBookPage);
|
||||
switchTab(_outputPane, _sqlLog);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public class DeliveryAction extends OpenBookAction {
|
||||
DeliveryPage _deliveryPage;
|
||||
|
@ -336,9 +336,9 @@ public class Demo extends JFrame {
|
|||
showTab(_tabbedPane, "Deliver Books", _deliveryPage);
|
||||
switchTab(_outputPane, _sqlLog);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class SupplyAction extends OpenBookAction {
|
||||
SupplyPage _supplyPage;
|
||||
public SupplyAction(String name, Icon icon, String tooltip) {
|
||||
|
@ -351,9 +351,9 @@ public class Demo extends JFrame {
|
|||
showTab(_tabbedPane, "Supply Books", _supplyPage);
|
||||
switchTab(_outputPane, _sqlLog);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ViewConfigAction extends OpenBookAction {
|
||||
ConfigurationViewer _configView;
|
||||
public ViewConfigAction(String name, Icon icon, String tooltip) {
|
||||
|
@ -367,9 +367,9 @@ public class Demo extends JFrame {
|
|||
showTab(_tabbedPane, "Configuration", _configView);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ViewDomainAction extends OpenBookAction {
|
||||
MetamodelView _domainView;
|
||||
AttributeLegendView _legends;
|
||||
|
@ -384,7 +384,7 @@ public class Demo extends JFrame {
|
|||
}
|
||||
showTab(_tabbedPane, "Domain Model", _domainView);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ViewDataAction extends OpenBookAction {
|
||||
|
@ -394,9 +394,9 @@ public class Demo extends JFrame {
|
|||
public void actionPerformed(ActionEvent e) {
|
||||
showTab(_tabbedPane, "Buy Books", null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ViewQueryCacheAction extends OpenBookAction {
|
||||
PreparedQueryViewer _queryView;
|
||||
public ViewQueryCacheAction(String name, Icon icon, String tooltip) {
|
||||
|
@ -409,19 +409,19 @@ public class Demo extends JFrame {
|
|||
}
|
||||
showTab(_tabbedPane, "JPQL Queries", _queryView);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ViewSourceAction extends OpenBookAction {
|
||||
public ViewSourceAction(String name, Icon icon, String tooltip) {
|
||||
super(name, icon, tooltip);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
getSourceCodeBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An action to show a piece of code in an internal or external browser.
|
||||
*
|
||||
|
@ -429,24 +429,24 @@ public class Demo extends JFrame {
|
|||
public class ShowCodeAction extends OpenBookAction {
|
||||
private String _key;
|
||||
private String _page;
|
||||
|
||||
|
||||
public ShowCodeAction() {
|
||||
super("View Code", Images.VIEW_CODE, "View Java Source Code");
|
||||
}
|
||||
|
||||
|
||||
public void setPage(String key, String page) {
|
||||
_key = key;
|
||||
_page = page;
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
getSourceCodeBrowser().showPage(_key, _page);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays the "welcome" page.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -454,15 +454,15 @@ public class Demo extends JFrame {
|
|||
PowerPointViewer _powerpoint;
|
||||
JLabel _logoLabel = new JLabel(Images.LOGO_OPENBOOKS);
|
||||
boolean _showPresentation = true;
|
||||
|
||||
|
||||
public WelcomeAction(String name, Icon icon, String tooltip) {
|
||||
super(name, icon, tooltip);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (_powerpoint == null && _showPresentation) {
|
||||
String dir = getConfiguration("openbook.slides.dir", "slides/");
|
||||
String[] defaultSlides = {
|
||||
String[] defaultSlides = {
|
||||
"Slide1.JPG",
|
||||
"Slide2.JPG",
|
||||
"Slide3.JPG",
|
||||
|
@ -486,19 +486,19 @@ public class Demo extends JFrame {
|
|||
_showPresentation = false;
|
||||
System.err.println("Error while opening slide deck at " + dir + ". \r\n"+ e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
showTab(_tabbedPane, "Home", _powerpoint != null ? _powerpoint : _logoLabel);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class AboutAction extends OpenBookAction {
|
||||
AboutDialog _dialog;
|
||||
|
||||
|
||||
public AboutAction(String name, Icon icon, String tooltip) {
|
||||
super(name, icon, tooltip);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (_dialog == null) {
|
||||
_dialog = new AboutDialog(Images.LOGO_OPENBOOKS);
|
||||
|
@ -507,7 +507,7 @@ public class Demo extends JFrame {
|
|||
_dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the given tab in the given pane.
|
||||
* @param pane the tabbed pane
|
||||
|
@ -525,22 +525,22 @@ public class Demo extends JFrame {
|
|||
pane.setSelectedComponent(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void switchTab(JTabbedPane pane, Component tab) {
|
||||
if (tab == null)
|
||||
return;
|
||||
Component c = locateTab(pane, tab);
|
||||
if (c == null) {
|
||||
pane.setSelectedComponent(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component locateTab(JTabbedPane pane, Component tab) {
|
||||
int index = pane.indexOfComponent(tab);
|
||||
if (index == -1) {
|
||||
Component[] components = pane.getComponents();
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
if (components[i] instanceof JScrollPane
|
||||
if (components[i] instanceof JScrollPane
|
||||
&& (((JScrollPane)components[i]).getViewport().getView() == tab)) {
|
||||
return components[i];
|
||||
}
|
||||
|
@ -550,38 +550,38 @@ public class Demo extends JFrame {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private JTabbedPane createTabbedView() {
|
||||
JTabbedPane pane = new JTabbedPane();
|
||||
pane.setPreferredSize(TAB_VIEW);
|
||||
pane.setMinimumSize(new Dimension(TAB_VIEW.width, TAB_VIEW.height));
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
private JTabbedPane createOutputView() {
|
||||
JTabbedPane pane = new JTabbedPane();
|
||||
pane.setPreferredSize(OUT_VIEW);
|
||||
|
||||
|
||||
_sqlListener = new SQLLogger();
|
||||
_sqlLog = new ScrollingTextPane();
|
||||
|
||||
|
||||
GraphicOutputStream stream = new GraphicOutputStream(_sqlLog);
|
||||
_sqlLog.setPreferredSize(TAB_VIEW);
|
||||
_sqlListener.setOutput(stream);
|
||||
pane.addTab("SQL Log", new JScrollPane(_sqlLog));
|
||||
|
||||
|
||||
ScrollingTextPane consoleLog = new ScrollingTextPane();
|
||||
GraphicOutputStream console = new GraphicOutputStream(consoleLog);
|
||||
System.setErr(new PrintStream(console, true));
|
||||
pane.addTab("Console", new JScrollPane(consoleLog));
|
||||
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the navigation tree and adds the tree nodes. Each tree node is attached with an action
|
||||
* that fires when the node is selected.
|
||||
* that fires when the node is selected.
|
||||
*/
|
||||
private JTree createNavigator() {
|
||||
ActionTreeNode root = new ActionTreeNode(_root);
|
||||
|
@ -589,21 +589,21 @@ public class Demo extends JFrame {
|
|||
DefaultMutableTreeNode views = new DefaultMutableTreeNode("Views");
|
||||
root.add(app);
|
||||
root.add(views);
|
||||
|
||||
|
||||
|
||||
|
||||
app.add(new ActionTreeNode(_buyBook));
|
||||
app.add(new ActionTreeNode(_deliver));
|
||||
app.add(new ActionTreeNode(_supply));
|
||||
|
||||
|
||||
views.add(new ActionTreeNode(_viewConfig));
|
||||
views.add(new ActionTreeNode(_viewDomain));
|
||||
views.add(new ActionTreeNode(_viewQuery));
|
||||
views.add(new ActionTreeNode(_viewSource));
|
||||
|
||||
|
||||
|
||||
|
||||
JTree tree = new JTree(root);
|
||||
tree.setShowsRootHandles(true);
|
||||
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
Object treeNode = _navigator.getLastSelectedPathComponent();
|
||||
|
@ -613,17 +613,17 @@ public class Demo extends JFrame {
|
|||
}
|
||||
});
|
||||
tree.setCellRenderer(new TypedTreeCellRenderer());
|
||||
|
||||
|
||||
for (int i = 0; i < tree.getRowCount(); i++) {
|
||||
tree.expandRow(i);
|
||||
}
|
||||
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A tree node which may have an associated action.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -632,30 +632,30 @@ public class Demo extends JFrame {
|
|||
public ActionTreeNode(Action action) {
|
||||
_action = action;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return _action.getValue(Action.SHORT_DESCRIPTION).toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class TypedTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
|
||||
boolean leaf, int row, boolean hasFocus) {
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
|
||||
boolean leaf, int row, boolean hasFocus) {
|
||||
return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AboutDialog extends JDialog {
|
||||
public AboutDialog(Icon logo) {
|
||||
setModal(true);
|
||||
setLayout(new BorderLayout());
|
||||
JButton button = new JButton("<html>"
|
||||
+ "<b>OpenBooks</b> "
|
||||
JButton button = new JButton("<html>"
|
||||
+ "<b>OpenBooks</b> "
|
||||
+ "<p>"
|
||||
+ "<br> by JPA Team, SWG"
|
||||
+ "<br> IBM Corporation"
|
||||
+ "<br> by JPA Team, SWG"
|
||||
+ "<br> IBM Corporation"
|
||||
+ "<p>"
|
||||
+ "</html>");
|
||||
button.setIcon(logo);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.client;
|
||||
|
||||
|
@ -24,20 +24,20 @@ import jpa.tools.swing.ErrorDialog;
|
|||
|
||||
/**
|
||||
* Handles error.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class ErrorHandler implements Thread.UncaughtExceptionHandler{
|
||||
|
||||
|
||||
static {
|
||||
System.setProperty("sun.awt.exception.handler", ErrorHandler.class.getName());
|
||||
}
|
||||
|
||||
|
||||
public void handle(Throwable e) {
|
||||
uncaughtException(Thread.currentThread(), e);
|
||||
}
|
||||
|
||||
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
new ErrorDialog(null, Images.ERROR, e).setVisible(true);
|
||||
|
|
|
@ -24,35 +24,35 @@ import javax.swing.ImageIcon;
|
|||
/**
|
||||
* Utility to load and cache images.
|
||||
* Maintains a list of <em>known</em> images.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class Images {
|
||||
|
||||
|
||||
private static Map<String, Icon> images = new HashMap<String, Icon>();
|
||||
|
||||
|
||||
public static Icon NEXT = getIcon("images/arrow_right.jpg", 24, -1);
|
||||
public static Icon BACK = getIcon("images/arrow_left.jpg", 24, -1);
|
||||
public static Icon DONE = getIcon("images/done.png");
|
||||
public static Icon ERROR = getIcon("images/error.png");
|
||||
public static Icon START = getIcon("images/start_task.gif");
|
||||
|
||||
|
||||
public static final Icon BUY = Images.getIcon("images/buy.jpg", 32, -1);
|
||||
public static final Icon DELIVERY = Images.getIcon("images/delivery.jpg", 32, -1);
|
||||
public static final Icon SUPPLY = Images.getIcon("images/supply.jpg", 32, -1);
|
||||
public static final Icon SEARCH = Images.getIcon("images/search.jpg", 24, -1);
|
||||
public static final Icon CART = Images.getIcon("images/cart.jpg", 24, -1);
|
||||
|
||||
|
||||
public static Icon VIEW_UNIT = Images.getIcon("images/view_unit.jpg", 32, -1);
|
||||
public static Icon VIEW_DOMAIN = Images.getIcon("images/view_domain.jpg", 32, -1);
|
||||
public static Icon VIEW_CODE = Images.getIcon("images/view_code.jpg", 32, -1);
|
||||
public static Icon VIEW_QUERY = Images.getIcon("images/view_query.jpg", 32, -1);
|
||||
|
||||
|
||||
public static final Icon LOGO_OPENBOOKS = Images.getIcon("images/OpenBooks.jpg", 32, -1);
|
||||
public static final Icon LOGO_OPENJPA = Images.getIcon("images/openjpa-logo-small.png");
|
||||
|
||||
|
||||
|
||||
|
||||
public static Icon getIcon(String name) {
|
||||
Icon icon = images.get(name);
|
||||
if (icon == null) {
|
||||
|
@ -61,11 +61,11 @@ public class Images {
|
|||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
public static Icon getIcon(String name, boolean scale) {
|
||||
return getIcon(name, 32, -1);
|
||||
}
|
||||
|
||||
|
||||
public static Icon getIcon(String name, int width, int height) {
|
||||
Icon icon = getIcon(name);
|
||||
if (icon == null) {
|
||||
|
@ -74,10 +74,10 @@ public class Images {
|
|||
icon = new ImageIcon(((ImageIcon)icon).getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH));
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ImageIcon, or null if the path was invalid.
|
||||
*
|
||||
|
||||
/**
|
||||
* Returns an ImageIcon, or null if the path was invalid.
|
||||
*
|
||||
**/
|
||||
protected static ImageIcon createImageIcon(String path) {
|
||||
if (path == null)
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.apache.openjpa.lib.jdbc.JDBCEvent;
|
|||
|
||||
/**
|
||||
* Logs SQL statement to a graphic console.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -45,7 +45,7 @@ public class SQLLogger extends AbstractJDBCListener {
|
|||
blue = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.BLUE);
|
||||
magenta = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.MAGENTA);
|
||||
}
|
||||
|
||||
|
||||
public void setOutput(GraphicOutputStream o) {
|
||||
out = new PrintStream(o, true);
|
||||
o.registerStyle("INSERT", green);
|
||||
|
@ -53,7 +53,7 @@ public class SQLLogger extends AbstractJDBCListener {
|
|||
o.registerStyle("UPDATE", magenta);
|
||||
o.registerStyle("DELETE", red);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void beforeExecuteStatement(final JDBCEvent event) {
|
||||
if (out == null)
|
||||
|
|
|
@ -30,9 +30,9 @@ import jpa.tools.swing.SourceCodeViewer;
|
|||
* Browses source code.
|
||||
* The source code URI is resolved with respect to a root URI.
|
||||
* The source code is expected to be in HTML format.
|
||||
* The actual rendering of the source code can be either through an
|
||||
* {@linkplain SourceCodeViewer internal} or an external browser.
|
||||
*
|
||||
* The actual rendering of the source code can be either through an
|
||||
* {@linkplain SourceCodeViewer internal} or an external browser.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -41,10 +41,10 @@ public class SourceCodeBrowser {
|
|||
private SourceCodeViewer _internal = new SourceCodeViewer();
|
||||
private URI _rootURI;
|
||||
private File _rootDir;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a browser.
|
||||
*
|
||||
*
|
||||
* @param root a path to be resolved as an URI to root of source tree.
|
||||
* @param useDesktop flags to use external or internal browser.
|
||||
*/
|
||||
|
@ -52,11 +52,11 @@ public class SourceCodeBrowser {
|
|||
_rootURI = convertToURI(root);
|
||||
_useExternal = useDesktop;
|
||||
}
|
||||
|
||||
|
||||
public URI getRootURI() {
|
||||
return _rootURI;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the root source directory if the sources are being serverd from a local
|
||||
* file system directory.
|
||||
|
@ -72,17 +72,17 @@ public class SourceCodeBrowser {
|
|||
public void showPage(String key, String page) {
|
||||
showPage(key, URI.create(_rootURI.toString() + page));
|
||||
}
|
||||
|
||||
|
||||
public void addPage(String key, String path) {
|
||||
_internal.addPage(key, URI.create(_rootURI.toString() + path));
|
||||
}
|
||||
|
||||
|
||||
public SourceCodeViewer getViewer() {
|
||||
return _internal;
|
||||
}
|
||||
/**
|
||||
* Shows the given page.
|
||||
*
|
||||
*
|
||||
* @param key a user visible moniker for the page.
|
||||
* @param uri the URI of the page content.
|
||||
*/
|
||||
|
@ -98,7 +98,7 @@ public class SourceCodeBrowser {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private URI convertToURI(String srcPath) {
|
||||
try {
|
||||
URI uri = URI.create(srcPath);
|
||||
|
@ -120,7 +120,7 @@ public class SourceCodeBrowser {
|
|||
_rootDir = srcDir;
|
||||
return convertForWindows(_rootDir.toURI());
|
||||
}
|
||||
|
||||
|
||||
URI convertForWindows(URI uri) {
|
||||
String os = System.getProperty("os.name");
|
||||
boolean windows = os.toLowerCase().indexOf("windows") != -1;
|
||||
|
|
|
@ -35,52 +35,52 @@ import openbook.server.OpenBookService;
|
|||
|
||||
/**
|
||||
* A page to view and supply low inventory items.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SupplyPage extends JPanel {
|
||||
private final OpenBookService _service;
|
||||
|
||||
private final EntityTableView<Inventory> _lowInventories;
|
||||
|
||||
|
||||
private final JButton _supply;
|
||||
private final JButton _view;
|
||||
private final JLabel _title;
|
||||
|
||||
|
||||
private static int REORDER_LIMIT = 10;
|
||||
private static int REORDER_QUANTITY = 40;
|
||||
|
||||
public SupplyPage(final OpenBookService service) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
|
||||
_service = service;
|
||||
|
||||
|
||||
_title = new JLabel(REORDER_LIMIT + " lowest inventory items");
|
||||
_view = new JButton("Show " + REORDER_LIMIT + " lowest inventory items");
|
||||
_supply = new JButton("Supply " + REORDER_QUANTITY + " to each item");
|
||||
|
||||
|
||||
List<Inventory> orders = getInventory(REORDER_LIMIT);
|
||||
_lowInventories = new EntityTableView<Inventory>(Inventory.class,
|
||||
orders,
|
||||
EntityDataModel.BASIC_ATTR | EntityDataModel.ASSOCIATION_ATTR,
|
||||
_lowInventories = new EntityTableView<Inventory>(Inventory.class,
|
||||
orders,
|
||||
EntityDataModel.BASIC_ATTR | EntityDataModel.ASSOCIATION_ATTR,
|
||||
service.getUnit());
|
||||
|
||||
|
||||
add(_title, BorderLayout.NORTH);
|
||||
add(_lowInventories, BorderLayout.CENTER);
|
||||
JPanel buttons = new JPanel();
|
||||
buttons.add(_view);
|
||||
buttons.add(_supply);
|
||||
add(buttons, BorderLayout.SOUTH);
|
||||
|
||||
|
||||
|
||||
|
||||
_view.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
_lowInventories.getDataModel().updateData(getInventory(REORDER_LIMIT));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Supplies each inventory displayed.
|
||||
*/
|
||||
|
@ -98,7 +98,7 @@ public class SupplyPage extends JPanel {
|
|||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
public void done() {
|
||||
try {
|
||||
_lowInventories.getDataModel().updateData(get(1, TimeUnit.SECONDS));
|
||||
|
@ -107,23 +107,23 @@ public class SupplyPage extends JPanel {
|
|||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the orders in a background (i.e. not AWT event dispatch thread) thread.
|
||||
* <br>
|
||||
* But blocks painting anyway, because that is what is intended.
|
||||
*
|
||||
*
|
||||
*/
|
||||
private List<Inventory> getInventory(final Integer limit) {
|
||||
SwingWorker<List<Inventory>, Void> worker = new SwingWorker<List<Inventory>, Void>() {
|
||||
@Override
|
||||
protected List<Inventory> doInBackground() throws Exception {
|
||||
return _service.getReorderableBooks(REORDER_LIMIT);
|
||||
return _service.getReorderableBooks(REORDER_LIMIT);
|
||||
}
|
||||
};
|
||||
worker.execute();
|
||||
|
|
|
@ -31,7 +31,7 @@ import javax.persistence.Version;
|
|||
* <LI><b>Identity</b>:Generated value as identity.
|
||||
* <LI><b>Mapping</b>:Many-to-Many mapping to Books.
|
||||
* <LI><b>Version</b>: Yes.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -40,37 +40,37 @@ public class Author {
|
|||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
@ManyToMany(mappedBy="authors")
|
||||
private Set<Book> books;
|
||||
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public Set<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
|
||||
public void addBook(Book book) {
|
||||
if (books == null)
|
||||
books = new HashSet<Book>();
|
||||
books.add(book);
|
||||
}
|
||||
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
|
|
@ -33,14 +33,14 @@ import javax.persistence.Version;
|
|||
* The mutable properties of the book such as number of items in stock etc.
|
||||
* are factored out in a separate {@link Inventory} instance.
|
||||
* <br>
|
||||
* The state of inventory is mutable, but the relation to inventory is immutable.
|
||||
*
|
||||
* The state of inventory is mutable, but the relation to inventory is immutable.
|
||||
*
|
||||
* <LI><b>Identity</b>: Application-defined identity.
|
||||
* <LI><b>Mapping</b>: One-to-One bi-directional, immutable mapping to {@link Inventory}.
|
||||
* Many-to-Many bi-directional mapping to {@linkplain Author}.
|
||||
* <LI><b>Version</b>: No.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -49,35 +49,35 @@ import javax.persistence.Version;
|
|||
public class Book implements Serializable {
|
||||
@Id
|
||||
private String ISBN;
|
||||
|
||||
|
||||
private String title;
|
||||
|
||||
|
||||
private double price;
|
||||
|
||||
|
||||
@OneToOne(mappedBy="book",
|
||||
fetch=FetchType.LAZY,
|
||||
cascade=CascadeType.ALL,
|
||||
optional=false,
|
||||
orphanRemoval=true)
|
||||
private Inventory inventory;
|
||||
|
||||
|
||||
/**
|
||||
* <A name="authors">
|
||||
* A many-to-many <em>eager</em> relation.
|
||||
* A many-to-many <em>eager</em> relation.
|
||||
* By default, many-to-many relations are lazily fetched.
|
||||
*/
|
||||
@ManyToMany(fetch=FetchType.EAGER)
|
||||
private List<Author> authors;
|
||||
|
||||
|
||||
/**
|
||||
* A no-arg constructor is required for JPA Specification.
|
||||
*/
|
||||
public Book() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a book with given parameters.
|
||||
*
|
||||
*
|
||||
* @param ISBN primary identity of this Book
|
||||
* @param title Title of the book.
|
||||
* @param price price of the book.
|
||||
|
@ -89,23 +89,23 @@ public class Book implements Serializable {
|
|||
this.price = price;
|
||||
inventory = new Inventory(this, initialSupply);
|
||||
}
|
||||
|
||||
|
||||
public String getISBN() {
|
||||
return ISBN;
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
public List<Author> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
|
||||
public void addAuthor(Author...authors) {
|
||||
if (this.authors == null)
|
||||
this.authors = new ArrayList<Author>();
|
||||
|
@ -114,18 +114,18 @@ public class Book implements Serializable {
|
|||
this.authors.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setAuthors(List<Author> authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
|
||||
|
||||
public Inventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@ import javax.persistence.Version;
|
|||
|
||||
/**
|
||||
* A persistent entity represents a Customer.
|
||||
*
|
||||
*
|
||||
* <br><b>Persistent Identity</b>: auto-generated identity.
|
||||
* <br><b>Mapping</b>:
|
||||
*
|
||||
*
|
||||
* <br><b>Design Notes</b>: No setter for identity value.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -40,22 +40,22 @@ public class Customer implements Serializable {
|
|||
private long id;
|
||||
private String name;
|
||||
private String email;
|
||||
|
||||
|
||||
public Customer() {
|
||||
}
|
||||
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
@ -63,21 +63,21 @@ public class Customer implements Serializable {
|
|||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link ShoppingCart} for this customer.
|
||||
*/
|
||||
public ShoppingCart newCart() {
|
||||
return new ShoppingCart(this);
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.persistence.Version;
|
|||
|
||||
/**
|
||||
* A mutable persistent entity.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -34,18 +34,18 @@ public class Inventory implements Serializable {
|
|||
@Id
|
||||
@OneToOne(fetch=FetchType.EAGER, optional=false)
|
||||
private Book book;
|
||||
|
||||
|
||||
private int supplied;
|
||||
|
||||
|
||||
private int sold;
|
||||
|
||||
|
||||
protected Inventory() {
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Construct with the given Book and initial inventory count.
|
||||
* Package protected because only a Book can create its own inventory.
|
||||
*
|
||||
*
|
||||
* @param book non-null Book.
|
||||
* @param initialSupply must be greater than zero.
|
||||
*/
|
||||
|
@ -58,16 +58,16 @@ public class Inventory implements Serializable {
|
|||
this.book = book;
|
||||
increment(initialSupply);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Book that this inventory represents.
|
||||
*
|
||||
*
|
||||
* @return non-null Book.
|
||||
*/
|
||||
public Book getBook() {
|
||||
return book;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the available quantity.
|
||||
* This is an <em>in-flight</em> value representing the difference between the quantity supplied and quantity sold
|
||||
|
@ -76,52 +76,52 @@ public class Inventory implements Serializable {
|
|||
public int getInStock() {
|
||||
return supplied - sold;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the quantity supplied so far.
|
||||
*
|
||||
*
|
||||
* @return a monotonically increasing positive number.
|
||||
*/
|
||||
public int getSupplied() {
|
||||
return supplied;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the quantity sold so far.
|
||||
*
|
||||
*
|
||||
* @return a monotonically increasing positive number.
|
||||
*/
|
||||
public int getSold() {
|
||||
return sold;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increment this inventory by the given quantity.
|
||||
*
|
||||
*
|
||||
* @param supplied must be positive.
|
||||
*/
|
||||
public void increment(int supplied) {
|
||||
if (supplied < 1)
|
||||
throw new IllegalArgumentException("Can not add " + supplied + " supplies to " + this +
|
||||
throw new IllegalArgumentException("Can not add " + supplied + " supplies to " + this +
|
||||
" Suuplied quanlity must be greater than zero.");
|
||||
this.supplied += supplied;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrement this inventory by the given quantity.
|
||||
*
|
||||
*
|
||||
* @param sold must be positive.
|
||||
*/
|
||||
public void decrement(int sold) {
|
||||
if (sold < 1)
|
||||
throw new IllegalArgumentException("can not sell " + sold + "quantity to " + this
|
||||
throw new IllegalArgumentException("can not sell " + sold + "quantity to " + this
|
||||
+ "Sold quantity Must be greater than zero.");
|
||||
this.sold += sold;
|
||||
}
|
||||
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import javax.persistence.OrderColumn;
|
|||
* An immutable persistent entity with complex primary key.
|
||||
* The primary key is combination of the primary identity of {@linkplain PurchaseOrder} and
|
||||
* an 1-based integer index.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -43,29 +43,29 @@ public class LineItem implements Serializable {
|
|||
@Id
|
||||
@OneToOne
|
||||
private PurchaseOrder order;
|
||||
|
||||
|
||||
@Id
|
||||
@OrderColumn
|
||||
@Column(name="IDX") // index is keyword
|
||||
private int index;
|
||||
|
||||
|
||||
@ManyToOne(optional=false)
|
||||
private Book book;
|
||||
|
||||
|
||||
private int quantity;
|
||||
|
||||
|
||||
protected LineItem() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructed as a line item for the given PurchaseOrder for the given Book for the given quantity.
|
||||
* Package protected because only the PurchaseOrder can create its own LineItem.
|
||||
*
|
||||
*
|
||||
* @param order non-null PurchaseOrder
|
||||
* @param i the 1-based index of this line item in its parent PurchaseOrder
|
||||
* @param i the 1-based index of this line item in its parent PurchaseOrder
|
||||
* @param book non-null Book of this line item
|
||||
* @param quantity no. of books must be greater than zero.
|
||||
* @param quantity no. of books must be greater than zero.
|
||||
*/
|
||||
LineItem(PurchaseOrder order, int i, Book book, int quantity) {
|
||||
if (order == null)
|
||||
|
@ -76,13 +76,13 @@ public class LineItem implements Serializable {
|
|||
throw new NullPointerException("Can not create LineItem for null Book");
|
||||
if (quantity < 1)
|
||||
throw new IllegalArgumentException("Can not create LineItem with quantity " + i + ". Must be > 0");
|
||||
|
||||
|
||||
this.order = order;
|
||||
this.index = i;
|
||||
this.book = book;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Book for this line item.
|
||||
* @return non-null Book.
|
||||
|
@ -114,17 +114,17 @@ public class LineItem implements Serializable {
|
|||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separate identity class.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public static class LineItemId implements Serializable {
|
||||
long order;
|
||||
long order;
|
||||
int index;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this)
|
||||
|
@ -135,7 +135,7 @@ public class LineItem implements Serializable {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) (31 ^ order + index);
|
||||
|
|
|
@ -32,7 +32,7 @@ import javax.persistence.Temporal;
|
|||
import javax.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
* A persistent entity to demonstrate Master in a Master-Details or Composite pattern for
|
||||
* A persistent entity to demonstrate Master in a Master-Details or Composite pattern for
|
||||
* persistent domain model.
|
||||
* <br>
|
||||
* The Purchase Order - Line Items relationship typically demonstrates a Master-Details pattern.
|
||||
|
@ -42,15 +42,15 @@ import javax.persistence.TemporalType;
|
|||
* the Master's identity.
|
||||
* <LI> Orphan Delete or Dependent relation: This feature allows to impose composite relation semantics to
|
||||
* normally associative relation semantics implied in Java. Composite relation in persistence terms also
|
||||
* translates to deletion of Details record from database when the details lose their relation to master.
|
||||
* <br>
|
||||
* translates to deletion of Details record from database when the details lose their relation to master.
|
||||
* <br>
|
||||
* Besides the above two key features, this persistent type also shows usage of
|
||||
* <LI>Auto-generated identity.
|
||||
* <LI>Enum type persistent attribute.
|
||||
* <LI>Date type persistent attribute.
|
||||
* <LI>One-to-One uni-directional, immutable mapping to Customer.
|
||||
* <LI>One-to-Many bi-directional, immutable mapping to LineItem.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -62,7 +62,7 @@ public class PurchaseOrder implements Serializable {
|
|||
*
|
||||
*/
|
||||
public enum Status {PENDING, DELIVERED};
|
||||
|
||||
|
||||
/**
|
||||
* <A name="id">
|
||||
* Persistent Identity is generated by the provider.
|
||||
|
@ -70,48 +70,48 @@ public class PurchaseOrder implements Serializable {
|
|||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
|
||||
@OneToOne(optional=false)
|
||||
private Customer customer;
|
||||
|
||||
|
||||
/**
|
||||
* <A name="items">
|
||||
* A composite relation.
|
||||
* All persistence operation on this order are cascaded to its line items.
|
||||
* Moreover, a line item ceases to exist even in the database if it is no
|
||||
* more referred to by a order. This is known as <em>orphan delete</em>
|
||||
* and can be termed as <em>persistent garbage collection</em>.
|
||||
*
|
||||
* Moreover, a line item ceases to exist even in the database if it is no
|
||||
* more referred to by a order. This is known as <em>orphan delete</em>
|
||||
* and can be termed as <em>persistent garbage collection</em>.
|
||||
*
|
||||
*/
|
||||
@OneToMany(mappedBy="order", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
|
||||
private List<LineItem> items;
|
||||
|
||||
|
||||
private Status status;
|
||||
|
||||
|
||||
private int total;
|
||||
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Timestamp placedOn;
|
||||
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Timestamp deliveredOn;
|
||||
|
||||
|
||||
/**
|
||||
* A protected constructor satisfies two purposes:<br>
|
||||
* <LI>i) Status and creation time is set consistently.
|
||||
* <LI>i) Status and creation time is set consistently.
|
||||
* <LI>ii) OpenJPA Bytecode Enhancer requires an empty constructor for the domain classes.
|
||||
* The public constructor of Purchase Order takes a Shopping Cart as argument.
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected PurchaseOrder() {
|
||||
status = Status.PENDING;
|
||||
placedOn = new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="init"/>
|
||||
* Construct a new order by transferring the content of the given {@linkplain ShoppingCart}.
|
||||
*
|
||||
*
|
||||
* @param cart a non-null, non-empty Shopping cart
|
||||
* @exception NullPointerException if the cart is null
|
||||
* @exception IllegalStateException if the cart is empty
|
||||
|
@ -128,7 +128,7 @@ public class PurchaseOrder implements Serializable {
|
|||
addItem(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the immutable, auto-generated persistent identity of this Purchase Order.
|
||||
*/
|
||||
|
@ -138,32 +138,32 @@ public class PurchaseOrder implements Serializable {
|
|||
|
||||
/**
|
||||
* Gets the customer who placed this Purchase Order.
|
||||
*
|
||||
*
|
||||
* @return immutable Customer.
|
||||
*/
|
||||
public Customer getCustomer() {
|
||||
return customer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the status of this Purchase Order.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDelivered() {
|
||||
return Status.DELIVERED.equals(status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="setDelivered"/>
|
||||
* Sets the status of this Purchase Order as delivered.
|
||||
* Setting an order status as delivered nullifies the association to Line Items.
|
||||
* Nullifying this association has the important side-effect of Line Item records
|
||||
* be deleted from the database because the relation is annotated as orphan delete.
|
||||
*
|
||||
*
|
||||
* @exception IllegalStateException if this order has already been delivered.
|
||||
*/
|
||||
public void setDelivered() {
|
||||
|
@ -173,17 +173,17 @@ public class PurchaseOrder implements Serializable {
|
|||
this.deliveredOn = new Timestamp(System.currentTimeMillis());
|
||||
this.items = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the items for this Purchase Order.
|
||||
*
|
||||
*
|
||||
* @return the line items of this order. The line items for a delivered order is always null.
|
||||
* @see #setDelivered()
|
||||
*/
|
||||
public List<LineItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds an item to this Purchase Order.
|
||||
* The total is adjusted as a side-effect.
|
||||
|
@ -192,21 +192,21 @@ public class PurchaseOrder implements Serializable {
|
|||
if (book == null)
|
||||
throw new NullPointerException("Can not add Line Item to Purchase Order for null Book");
|
||||
if (quantity < 1)
|
||||
throw new IllegalArgumentException("Can not add Line Item to Purchase Order for negative (=" +
|
||||
throw new IllegalArgumentException("Can not add Line Item to Purchase Order for negative (=" +
|
||||
quantity + ") number of Book " + book);
|
||||
if (items == null)
|
||||
items = new ArrayList<LineItem>();
|
||||
items.add(new LineItem(this, items.size()+1, book, quantity));
|
||||
total += (book.getPrice() * quantity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the total cost of all the items in this order.
|
||||
*/
|
||||
public double getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the time when this order was placed.
|
||||
*/
|
||||
|
@ -216,7 +216,7 @@ public class PurchaseOrder implements Serializable {
|
|||
|
||||
/**
|
||||
* Gets the time when this order was delivered.
|
||||
*
|
||||
*
|
||||
* @return null if the order has not been delivered yet.
|
||||
*/
|
||||
public Date getDeliveredOn() {
|
||||
|
|
|
@ -17,7 +17,7 @@ package openbook.domain;
|
|||
/**
|
||||
* A simple numeric range.
|
||||
* Minimum value is included, maximum value is excluded.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@ public class Range<N extends Number> {
|
|||
private N min;
|
||||
private N max;
|
||||
private final Class<N> type;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Range(Object min, Object max) {
|
||||
this((N)min, (N)max);
|
||||
|
@ -33,7 +33,7 @@ public class Range<N extends Number> {
|
|||
|
||||
/**
|
||||
* Creates a range. Empty range i.e. where minimum equals maximum is allowed.
|
||||
*
|
||||
*
|
||||
* @param min non-null minimum value.
|
||||
* @param max non-null maximum value.
|
||||
*/
|
||||
|
@ -47,53 +47,53 @@ public class Range<N extends Number> {
|
|||
this.max = max;
|
||||
type = (Class<N>)min.getClass();
|
||||
}
|
||||
|
||||
|
||||
public Class<N> type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the given value is within this range.
|
||||
* Minimum is included, maximum is excluded.
|
||||
*
|
||||
*
|
||||
* @param x a non-null value
|
||||
* @return true if the given value is greater than or equals to minimum and less than the maximum.
|
||||
*/
|
||||
public boolean contains(Number x) {
|
||||
return x != null && x.doubleValue() >= min.doubleValue() && x.doubleValue() < max.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the given range is within this range.
|
||||
* Minimum is included, maximum is excluded.
|
||||
*
|
||||
*
|
||||
* @param x a non-null value
|
||||
* @return true if the given value is greater than or equals to minimum and less than the maximum.
|
||||
*/
|
||||
public <X extends Number> boolean contains(Range<X> r) {
|
||||
return r != null && r.getMinimum().doubleValue() >= min.doubleValue() &&
|
||||
return r != null && r.getMinimum().doubleValue() >= min.doubleValue() &&
|
||||
r.getMaximum().doubleValue() <= max.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the minimum value.
|
||||
*/
|
||||
public N getMinimum() {
|
||||
return min;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the maximum value.
|
||||
*/
|
||||
public N getMaximum() {
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adjusts this range by the given number.
|
||||
*
|
||||
*
|
||||
* @param x a non-null value.
|
||||
*
|
||||
*
|
||||
* @return if this range is adjusted by this value.
|
||||
*/
|
||||
public boolean adjust(N x) {
|
||||
|
@ -109,7 +109,7 @@ public class Range<N extends Number> {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Map;
|
|||
* A non-persistent entity holds the content of a shopping session for a {@linkplain Customer}.
|
||||
* Used to create a persistent PurchaseOrder.
|
||||
* Books can be added or removed from this cart.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -33,60 +33,60 @@ public class ShoppingCart implements Serializable {
|
|||
* The owner of this cart.
|
||||
*/
|
||||
private Customer customer;
|
||||
|
||||
|
||||
/**
|
||||
* <A name="items"/>
|
||||
* The items in the cart and their respective quantity.
|
||||
*/
|
||||
private Map<Book, Integer> items;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a cart for the given Customer.
|
||||
*
|
||||
*
|
||||
* @param c non-null Customer.
|
||||
*/
|
||||
ShoppingCart(Customer c) {
|
||||
customer = c;
|
||||
items = new HashMap<Book, Integer>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Customer who owns this cart.
|
||||
*
|
||||
*
|
||||
* @return non-null Customer.
|
||||
*/
|
||||
public Customer getCustomer() {
|
||||
return customer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the books with their corresponding quantity in this cart.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public Map<Book, Integer> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given book with the given quantity in the cart.
|
||||
* If the book already exists then the quantity is added to the existing quantity.
|
||||
*
|
||||
*
|
||||
* @param book non-null Book
|
||||
* @param quantity a positive quantity.
|
||||
* @param quantity a positive quantity.
|
||||
*/
|
||||
public void addItem(Book book, int quantity) {
|
||||
if (book == null)
|
||||
throw new NullPointerException("Can not add null Book to " + this);
|
||||
if (quantity < 1)
|
||||
throw new IllegalArgumentException("Can not add " + quantity + " " + book + " to " + this +
|
||||
throw new IllegalArgumentException("Can not add " + quantity + " " + book + " to " + this +
|
||||
" Added qunatity must be greater than zero");
|
||||
int current = items.containsKey(book) ? items.get(book) : 0;
|
||||
items.put(book, current + quantity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the quantity of the given book by the given delta.
|
||||
*
|
||||
*
|
||||
* @param book a non-null Book that must exist in this cart.
|
||||
* @param delta no. of quantity to change. Can be positive or negative.
|
||||
* If the resultant quantity becomes zero of negative, the book is removed from the cart.
|
||||
|
@ -104,10 +104,10 @@ public class ShoppingCart implements Serializable {
|
|||
items.put(book, current + delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the given book from this cart.
|
||||
*
|
||||
*
|
||||
* @param book book a non-null Book that must exist in this cart.
|
||||
*/
|
||||
public void remove(Book book) {
|
||||
|
@ -118,15 +118,15 @@ public class ShoppingCart implements Serializable {
|
|||
"exist in " + this);
|
||||
items.remove(book);
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
items.clear();
|
||||
}
|
||||
|
||||
|
||||
public boolean isEmpty() {
|
||||
return items.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public int getTotalCount() {
|
||||
int sum = 0;
|
||||
for (Integer q : items.values())
|
||||
|
|
|
@ -19,18 +19,18 @@ import openbook.util.PropertyHelper;
|
|||
|
||||
/**
|
||||
* Cleans and loads a new OpenBooks database.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class DataLoader {
|
||||
|
||||
|
||||
/**
|
||||
* Load data.
|
||||
*
|
||||
*
|
||||
* @param args 0-th argument is the name of persistence unit
|
||||
* 1-st argument is the path to the data file
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
|
|
@ -27,57 +27,57 @@ import openbook.domain.ShoppingCart;
|
|||
/**
|
||||
* A simple service to select Books, purchase them and manage their inventory.
|
||||
* A service handle can be obtained from {@link ServiceFactory#getService(String)
|
||||
* Service Factory}.
|
||||
*
|
||||
* Service Factory}.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public interface OpenBookService {
|
||||
public static final String DEFAULT_UNIT_NAME = "OpenBooks";
|
||||
|
||||
|
||||
/**
|
||||
* Starts a session for the given named Customer.
|
||||
* If no record of the given name exists, a new Customer record is created.
|
||||
*
|
||||
*
|
||||
* @param name name of a possibly existing customer. Or a new one.
|
||||
*
|
||||
*
|
||||
* @return a Customer
|
||||
*/
|
||||
public Customer login(String name);
|
||||
|
||||
|
||||
/**
|
||||
* Selects a list of Books matching the given conditions.
|
||||
* Each of the conditional parameter can be null.
|
||||
* A null parameter implies that the resultant query should ignore that parameter.
|
||||
*
|
||||
*
|
||||
* @param title title of the Book
|
||||
* @param min minimum price
|
||||
* @param max maximum price
|
||||
* @param author name of author
|
||||
* @param decorators to modify the executable query such as its range.
|
||||
*/
|
||||
public List<Book> select(String title,
|
||||
Double min, Double max,
|
||||
String author,
|
||||
public List<Book> select(String title,
|
||||
Double min, Double max,
|
||||
String author,
|
||||
QueryDecorator...decorators);
|
||||
/**
|
||||
* Gets the query String for the given parameters.
|
||||
* Each of the conditional parameter can be null.
|
||||
* A null parameter implies that the resultant query should ignore that parameter.
|
||||
*
|
||||
*
|
||||
* @param title title of the Book
|
||||
* @param min minimum price
|
||||
* @param max maximum price
|
||||
* @param author name of author
|
||||
* @param decorators to modify the executable query such as its range.
|
||||
*/
|
||||
public String getQuery(String title,
|
||||
Double min, Double max,
|
||||
public String getQuery(String title,
|
||||
Double min, Double max,
|
||||
String author);
|
||||
|
||||
|
||||
/**
|
||||
* Runs an arbitrary JPQL query to return a list of result.
|
||||
*
|
||||
*
|
||||
* @param jpql a valid JPQL query string.
|
||||
* @param resultClass type of the result.
|
||||
* @param decorators zero or more QueryDecorators to be applied before Query is executed.
|
||||
|
@ -88,93 +88,93 @@ public interface OpenBookService {
|
|||
|
||||
/**
|
||||
* Buys the content of the given cart.
|
||||
*
|
||||
*
|
||||
* @param cart a non-empty cart.
|
||||
* @return a PurchaseOrder for the content of the cart.
|
||||
*/
|
||||
public PurchaseOrder placeOrder(ShoppingCart cart);
|
||||
|
||||
public PurchaseOrder placeOrder(ShoppingCart cart);
|
||||
|
||||
/**
|
||||
* Delivers the given order. Delivery changes the status of the order, decrements
|
||||
* inventory and finally removes the line items.
|
||||
*
|
||||
*
|
||||
* @param order a PENDING order to be delivered.
|
||||
* @return the PurchaseOrder after delivery.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public PurchaseOrder deliver(PurchaseOrder order);
|
||||
|
||||
|
||||
/**
|
||||
* Add inventory of the given Book by the given quantity.
|
||||
*
|
||||
*
|
||||
* @param b a Book whose inventory is to be incremented
|
||||
* @param quantity positive number.
|
||||
*
|
||||
*
|
||||
* @return the Book after incrementing its inventory.
|
||||
*/
|
||||
public Book supply(Book b, int quantity);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of orders of given status.
|
||||
*
|
||||
*
|
||||
* @param status status of the orders. null implies all orders.
|
||||
*
|
||||
*
|
||||
* @return list of orders sorted by their placement dates.
|
||||
*/
|
||||
public List<PurchaseOrder> getOrders(PurchaseOrder.Status status, Customer customer);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of Books whose inventory is lower than the given limit.
|
||||
*
|
||||
*
|
||||
* @param limit reorder limit. null implies all inventory.
|
||||
*
|
||||
*
|
||||
* @return list of Books with inventory lower than the given limit.
|
||||
*/
|
||||
public List<Inventory> getReorderableBooks(int limit);
|
||||
|
||||
|
||||
/**
|
||||
* Count the number of instances of the given persistent type.
|
||||
*
|
||||
*
|
||||
* @param cls a persistent type.
|
||||
* @return number of persistent entity of the given type.
|
||||
*/
|
||||
public long count(Class<?> cls);
|
||||
|
||||
|
||||
/**
|
||||
* Populates the underlying data repository with sample values, only if
|
||||
* the data repository is empty.
|
||||
*
|
||||
*
|
||||
* @param loadParameters control the number of Books etc. to be created.
|
||||
* null is allowed.
|
||||
*
|
||||
*
|
||||
* @return true if the repository is initialized by this invocation.
|
||||
*/
|
||||
public boolean initialize(Map<String,Object> loadParameters);
|
||||
|
||||
|
||||
/**
|
||||
* Cleans everything. Be careful.
|
||||
*/
|
||||
public void clean();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the underlying persistence unit.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public EntityManagerFactory getUnit();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the underlying persistence unit.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public String getUnitName();
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the transaction on this persistence unit is managed by a container.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public boolean isManaged();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -52,45 +52,45 @@ import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
|
|||
/**
|
||||
* A demonstrative example of a transaction service with persistent entity using Java Persistence API.
|
||||
* <br>
|
||||
* This example service operates on a persistent domain model to browse {@linkplain Book books},
|
||||
* occasionally {@linkplain #placeOrder(ShoppingCart) placing} {@linkplain PurchaseOrder purchase orders},
|
||||
* while {@linkplain Inventory inventory} gets updated either by {@linkplain #deliver() delivery} or
|
||||
* by {@linkplain #supply() supply}.
|
||||
* This example service operates on a persistent domain model to browse {@linkplain Book books},
|
||||
* occasionally {@linkplain #placeOrder(ShoppingCart) placing} {@linkplain PurchaseOrder purchase orders},
|
||||
* while {@linkplain Inventory inventory} gets updated either by {@linkplain #deliver() delivery} or
|
||||
* by {@linkplain #supply() supply}.
|
||||
* <br>
|
||||
* The operational model as well as the persistent domain model is influenced by the fact that
|
||||
* a JPA based application can benefit from
|
||||
* a JPA based application can benefit from
|
||||
* <LI>Mostly Immutable Persistent Data Model
|
||||
* <LI>Optimistic Transaction Model
|
||||
* <LI>Optimistic Transaction Model
|
||||
* <br>for better scalability and throughput.
|
||||
* <br>
|
||||
*
|
||||
* <br>
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class OpenBookServiceImpl extends PersistenceService implements OpenBookService {
|
||||
|
||||
|
||||
public static final int CUSTOMER_COUNT = 10;
|
||||
public static final int BOOK_COUNT = 100;
|
||||
public static final int AUTHOR_COUNT = 40;
|
||||
public static final int AUTHOR_PER_BOOK = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Range of number of queries executed for a {@linkplain #shop() shopping} trip.
|
||||
*/
|
||||
public static final Range<Double> PRICE_RANGE = new Range<Double>(4.99, 120.99);
|
||||
public static final Range<Integer> STOCK_RANGE = new Range<Integer>(5, 50);
|
||||
public static final int REORDER_LEVEL = 10;
|
||||
|
||||
|
||||
OpenBookServiceImpl(String unit, EntityManagerFactory emf, boolean managed,
|
||||
PersistenceContextType scope) {
|
||||
super(unit, emf, managed, scope);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize service by populating inventory of Books and Customers.
|
||||
* If the inventory exists, then returns immediately without creating any new inventory.
|
||||
*
|
||||
*
|
||||
* @return true if new inventory is created. false otherwise.
|
||||
*/
|
||||
public boolean initialize(Map<String,Object> config) {
|
||||
|
@ -111,7 +111,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
|
||||
Integer stockMax = PropertyHelper.getInteger(config, "openbook.Inventory.Max", STOCK_RANGE.getMaximum());
|
||||
Integer stockMin = PropertyHelper.getInteger(config, "openbook.Inventory.Min", STOCK_RANGE.getMinimum());
|
||||
|
||||
|
||||
System.err.println("Creating " + nCustomer + " new Customer");
|
||||
for (int i = 1; i < nCustomer; i++) {
|
||||
Customer customer = new Customer();
|
||||
|
@ -130,11 +130,11 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
System.err.println("Creating " + nBook + " new Books");
|
||||
System.err.println("Linking at most " + nAuthorPerBook + " Authors per Book");
|
||||
for (int i = 1; i <= nBook; i++) {
|
||||
Book book = new Book(Randomizer.randomString(4,2),
|
||||
"Book-" + i,
|
||||
Randomizer.random(priceMin, priceMax),
|
||||
Book book = new Book(Randomizer.randomString(4,2),
|
||||
"Book-" + i,
|
||||
Randomizer.random(priceMin, priceMax),
|
||||
Randomizer.random(stockMin, stockMax));
|
||||
List<Author> authors = Randomizer.selectRandom(allAuthors,
|
||||
List<Author> authors = Randomizer.selectRandom(allAuthors,
|
||||
Math.max(1, Randomizer.random(nAuthorPerBook)));
|
||||
for (Author author : authors) {
|
||||
author.addBook(book);
|
||||
|
@ -142,31 +142,31 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
}
|
||||
em.persist(book);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms whether the database is loaded with some records.
|
||||
*/
|
||||
public boolean isInitialized() {
|
||||
return count(Book.class) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="login">
|
||||
* Provide a name to login a Customer.
|
||||
* If such a customer exists, return it. Otherwise creates a new one.
|
||||
*
|
||||
*
|
||||
* @param name name of an existing or a new Customer
|
||||
*
|
||||
*
|
||||
* @return a Customer
|
||||
*/
|
||||
public Customer login(String name) {
|
||||
EntityManager em = begin();
|
||||
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
|
||||
Customer customer = null;
|
||||
|
@ -187,7 +187,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return customer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find books that match title and price range.
|
||||
*/
|
||||
|
@ -200,22 +200,22 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="getQuery">
|
||||
* Gets the string representation of a Criteria Query.
|
||||
* The string form of a Criteria Query is not specified in JPA specification.
|
||||
* But OpenJPA produces a readable form that is quite <em>similar</em> to
|
||||
* But OpenJPA produces a readable form that is quite <em>similar</em> to
|
||||
* equivalent JPQL.
|
||||
*/
|
||||
public String getQuery(String title, Double minPrice, Double maxPrice, String author) {
|
||||
CriteriaQuery<Book> q = buildQuery(title, minPrice, maxPrice, author);
|
||||
return q.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="buildQuery">
|
||||
* Creates a Query based on the values of the user input form.
|
||||
* Creates a Query based on the values of the user input form.
|
||||
* The user may or may not have filled a value for each form field
|
||||
* and accordingly the query will be different.<br>
|
||||
* This is typical of a form-based query. To account for all possible
|
||||
|
@ -224,20 +224,20 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
* conditional be alternatively developed using {@link CriteriaQuery}
|
||||
* introduced in JPA version 2.0.
|
||||
* <br>
|
||||
*
|
||||
*
|
||||
* @return a typed query
|
||||
*/
|
||||
private CriteriaQuery<Book> buildQuery(String title, Double minPrice, Double maxPrice, String author) {
|
||||
// builder generates the Criteria Query as well as all the expressions
|
||||
CriteriaBuilder cb = getUnit().getCriteriaBuilder();
|
||||
// The query declares what type of result it will produce
|
||||
// The query declares what type of result it will produce
|
||||
CriteriaQuery<Book> q = cb.createQuery(Book.class);
|
||||
// Which type will be searched
|
||||
Root<Book> book = q.from(Book.class);
|
||||
// of course, the projection term must match the result type declared earlier
|
||||
q.select(book);
|
||||
|
||||
// Builds the predicates conditionally for the filled-in input fields
|
||||
|
||||
// Builds the predicates conditionally for the filled-in input fields
|
||||
List<Predicate> predicates = new ArrayList<Predicate>();
|
||||
if (!isEmpty(title)) {
|
||||
Predicate matchTitle = cb.like(book.get(Book_.title), title);
|
||||
|
@ -248,7 +248,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
predicates.add(matchAuthor);
|
||||
}
|
||||
// for price fields, also the comparison operation changes based on whether
|
||||
// minimum or maximum price or both have been filled.
|
||||
// minimum or maximum price or both have been filled.
|
||||
if (minPrice != null && maxPrice != null) {
|
||||
Predicate matchPrice = cb.between(book.get(Book_.price), minPrice, maxPrice);
|
||||
predicates.add(matchPrice);
|
||||
|
@ -259,18 +259,18 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
Predicate matchPrice = cb.le(book.get(Book_.price), maxPrice);
|
||||
predicates.add(matchPrice);
|
||||
}
|
||||
// Sets the evaluation criteria
|
||||
// Sets the evaluation criteria
|
||||
if (!predicates.isEmpty())
|
||||
q.where(predicates.toArray(new Predicate[predicates.size()]));
|
||||
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
boolean isEmpty(String s) {
|
||||
return s == null || s.trim().isEmpty();
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <A name="deliver"/>
|
||||
* Delivers the given order, if it is pending.
|
||||
|
@ -292,7 +292,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
public List<PurchaseOrder> getOrders(PurchaseOrder.Status status, Customer customer) {
|
||||
EntityManager em = begin();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
|
@ -309,13 +309,13 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
if (!predicates.isEmpty())
|
||||
q.where(predicates.toArray(new Predicate[predicates.size()]));
|
||||
q.orderBy(cb.desc(order.get(PurchaseOrder_.placedOn)));
|
||||
|
||||
|
||||
TypedQuery<PurchaseOrder> query = em.createQuery(q);
|
||||
List<PurchaseOrder> result = query.getResultList();
|
||||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <A name="placeOrder"/>
|
||||
* Creates a new {@linkplain PurchaseOrder} from the content of the given {@linkplain ShoppingCart}.
|
||||
|
@ -323,7 +323,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
* <br>
|
||||
* The transaction is not expected to fail because the inventory is
|
||||
* not modified by placing an order.
|
||||
*
|
||||
*
|
||||
* @param cart a non-null Shopping cart.
|
||||
*/
|
||||
public PurchaseOrder placeOrder(ShoppingCart cart) {
|
||||
|
@ -334,13 +334,13 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
cart.clear();
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supply books that have low inventory.
|
||||
* <br>
|
||||
* Queries for books with low inventory and supply each book in separate
|
||||
* transaction. Some of the transactions may fail due to concurrent modification on
|
||||
* the {@linkplain Inventory} by the {@linkplain #deliver() delivery} process.
|
||||
* the {@linkplain Inventory} by the {@linkplain #deliver() delivery} process.
|
||||
*/
|
||||
public Book supply(Book b, int quantity) {
|
||||
EntityManager em = begin();
|
||||
|
@ -349,7 +349,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
public List<Inventory> getReorderableBooks(int limit) {
|
||||
EntityManager em = begin();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
|
@ -357,17 +357,17 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
Root<Inventory> inv = q.from(Inventory.class);
|
||||
q.select(inv);
|
||||
Expression<Integer> inStock = cb.diff(
|
||||
inv.get(Inventory_.supplied),
|
||||
inv.get(Inventory_.supplied),
|
||||
inv.get(Inventory_.sold));
|
||||
q.orderBy(cb.asc(inStock));
|
||||
|
||||
|
||||
List<Inventory> result = em.createQuery(q)
|
||||
.setMaxResults(limit)
|
||||
.getResultList();
|
||||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public long count(Class<?> cls) {
|
||||
EntityManager em = getEntityManager();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
|
@ -376,11 +376,11 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
c.select(cb.count(from));
|
||||
return em.createQuery(c).getSingleResult();
|
||||
}
|
||||
|
||||
|
||||
public List<Book> selectByExample(Book b, QueryDecorator...decorators) {
|
||||
return queryByTemplate(Book.class, b);
|
||||
}
|
||||
|
||||
|
||||
private <T> List<T> queryByTemplate(Class<T> type, T template) {
|
||||
EntityManager em = begin();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
|
@ -390,7 +390,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public <T> List<T> getExtent(Class<T> entityClass) {
|
||||
EntityManager em = begin();
|
||||
CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
|
||||
|
@ -399,7 +399,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public <T> List<T> query(String jpql, Class<T> resultClass, QueryDecorator... decorators) {
|
||||
EntityManager em = begin();
|
||||
TypedQuery<T> query = em.createQuery(jpql, resultClass);
|
||||
|
@ -412,7 +412,7 @@ class OpenBookServiceImpl extends PersistenceService implements OpenBookService
|
|||
commit();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void clean() {
|
||||
EntityManager em = begin();
|
||||
Set<EntityType<?>> entities = em.getMetamodel().getEntities();
|
||||
|
|
|
@ -21,16 +21,16 @@ import javax.persistence.EntityManagerFactory;
|
|||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
/**
|
||||
* An abstract utility for JPA based service.
|
||||
* An abstract utility for JPA based service.
|
||||
* This thin wrapper over a {@link EntityManagerFactory Persistence Unit} maintains
|
||||
* <LI>per-thread persistence context
|
||||
* <LI>relinquishes direct transaction control under a managed environment
|
||||
*
|
||||
* <LI>relinquishes direct transaction control under a managed environment
|
||||
*
|
||||
* @see #getEntityManager()
|
||||
* @see #newEntityManager()
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
abstract class PersistenceService implements Serializable {
|
||||
|
@ -38,18 +38,18 @@ abstract class PersistenceService implements Serializable {
|
|||
private final String unitName;
|
||||
private final boolean isManaged;
|
||||
private final PersistenceContextType scope;
|
||||
|
||||
|
||||
private ThreadLocal<EntityManager> thread = new ThreadLocal<EntityManager>();
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
protected PersistenceService(String unit, EntityManagerFactory emf, boolean managed,
|
||||
protected PersistenceService(String unit, EntityManagerFactory emf, boolean managed,
|
||||
PersistenceContextType scope) {
|
||||
this.unitName = unit;
|
||||
this.emf = emf;
|
||||
this.isManaged = managed;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
|
||||
public final EntityManagerFactory getUnit() {
|
||||
return emf;
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ abstract class PersistenceService implements Serializable {
|
|||
public final String getUnitName() {
|
||||
return unitName;
|
||||
}
|
||||
|
||||
|
||||
public final boolean isManaged() {
|
||||
return isManaged;
|
||||
}
|
||||
|
||||
|
||||
public final PersistenceContextType getContextType() {
|
||||
return scope;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ abstract class PersistenceService implements Serializable {
|
|||
* current thread is not associated with any entity manager or the
|
||||
* associated entity manager has been closed, creates a new entity manager
|
||||
* and associates with the current thread.
|
||||
*
|
||||
*
|
||||
* @return an entity manager associated with the current thread.
|
||||
*/
|
||||
protected EntityManager getEntityManager() {
|
||||
|
@ -102,7 +102,7 @@ abstract class PersistenceService implements Serializable {
|
|||
* If the thread is not associated with a persistence context, then a new
|
||||
* context is created, associated with the thread, new transaction is
|
||||
* started.
|
||||
*
|
||||
*
|
||||
* @see #getEntityManager()
|
||||
*/
|
||||
protected EntityManager begin() {
|
||||
|
@ -151,7 +151,7 @@ abstract class PersistenceService implements Serializable {
|
|||
lock.lock();
|
||||
EntityManager em = getEntityManager();
|
||||
if (isManaged) {
|
||||
|
||||
|
||||
} else {
|
||||
em.getTransaction().rollback();
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ abstract class PersistenceService implements Serializable {
|
|||
assertTrue("No persistent context is associated with " + thread, em != null);
|
||||
assertTrue("Persistent context " + em + " associated with " + thread + " has been closed", em.isOpen());
|
||||
if (!isManaged) {
|
||||
assertTrue("Persistent context " + em + " associated with " + thread + " has no active transaction",
|
||||
assertTrue("Persistent context " + em + " associated with " + thread + " has no active transaction",
|
||||
em.getTransaction().isActive());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import javax.persistence.Query;
|
|||
/**
|
||||
* Decorates an executable query.
|
||||
* Concrete decorative action can be binding parameters, limiting the result range etc.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -17,20 +17,20 @@ import javax.persistence.Query;
|
|||
|
||||
/**
|
||||
* Decorates a query by binding parameters.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class QueryParameterBinder implements QueryDecorator {
|
||||
private final Object[] params;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a parameter binder with the given parameters.
|
||||
*/
|
||||
public QueryParameterBinder(Object...params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void decorate(Query query) {
|
||||
if (params == null)
|
||||
|
@ -41,7 +41,7 @@ public class QueryParameterBinder implements QueryDecorator {
|
|||
} else if (params[i] instanceof String) {
|
||||
query.setParameter((String)params[i], params[i+1]);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Parameter index " + params[i] +
|
||||
throw new IllegalArgumentException("Parameter index " + params[i] +
|
||||
" is neither and integer nor String");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,23 +22,23 @@ import javax.persistence.PersistenceContextType;
|
|||
|
||||
/**
|
||||
* A container of persistence units. Typically a JEE container will create, manage and inject
|
||||
* the persistence units to the user artifacts.
|
||||
*
|
||||
* the persistence units to the user artifacts.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class ServiceFactory {
|
||||
private static final Map<String, OpenBookService> _services = new HashMap<String, OpenBookService>();
|
||||
|
||||
|
||||
public synchronized static OpenBookService getService(String unit) {
|
||||
return getService(unit, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a persistence unit of given name configured with the given
|
||||
* name-value parameters.
|
||||
*
|
||||
* @param unit name of the persistence unit. A <code>META-INF/persistence.xml</code> must be
|
||||
* name-value parameters.
|
||||
*
|
||||
* @param unit name of the persistence unit. A <code>META-INF/persistence.xml</code> must be
|
||||
* available with the same unit name in the classpath.
|
||||
*/
|
||||
public synchronized static OpenBookService getService(String unit, Map<String,Object> config) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools;
|
||||
|
||||
|
@ -31,7 +31,7 @@ import java.util.Set;
|
|||
* User can register a set of command options. Then this processor will parse a set of Strings to
|
||||
* store the values for each of the registered options as well as optionally any unrecognized
|
||||
* option values.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -39,39 +39,39 @@ public class CommandProcessor {
|
|||
private final Map<Option, String> registeredOptions = new HashMap<Option,String>();
|
||||
private final Set<Option> unregisteredOptions = new HashSet<Option>();
|
||||
private boolean allowsUnregisteredOption = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set the option values from the given arguments.
|
||||
* All elements of the given array is <em>not</em> consumed,
|
||||
* only till the index that appears to be a valid option.
|
||||
*
|
||||
*
|
||||
* @see #lastIndex(String[])
|
||||
*
|
||||
*
|
||||
* @param args an array of arguments.
|
||||
*
|
||||
*
|
||||
* @return the array elements that are not consumed.
|
||||
*/
|
||||
public String[] setFrom(String[] args) {
|
||||
return setFrom(args, 0, args != null ? lastIndex(args) : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the option values from the given arguments between the given indices.
|
||||
*
|
||||
*
|
||||
* @see #lastIndex(String[])
|
||||
*
|
||||
*
|
||||
* @param args an array of arguments.
|
||||
*
|
||||
*
|
||||
* @return the array elements that are not consumed.
|
||||
*/
|
||||
public String[] setFrom(String[] args, int from, int to) {
|
||||
if (args == null)
|
||||
if (args == null)
|
||||
return null;
|
||||
if (args.length == 0)
|
||||
return new String[0];
|
||||
assertValidIndex(from, args, "Initial index " + from + " is an invalid index to " + Arrays.toString(args));
|
||||
assertValidIndex(to, args, "Last index " + to + " is an invalid index to " + Arrays.toString(args));
|
||||
|
||||
|
||||
int i = from;
|
||||
for (; i < to; i++) {
|
||||
String c = args[i];
|
||||
|
@ -91,14 +91,14 @@ public class CommandProcessor {
|
|||
System.arraycopy(args, i, remaining, 0, remaining.length);
|
||||
return remaining;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last index in the given array that can be processed as an option.
|
||||
* The array elements are sequentially tested if they are a valid option name
|
||||
* The array elements are sequentially tested if they are a valid option name
|
||||
* (i.e. starts with - character) and if valid then the next element is consumed
|
||||
* as value, if the option requires a value. The search ends when either
|
||||
* the array is exhausted or encounters elements that are not options.
|
||||
*
|
||||
* as value, if the option requires a value. The search ends when either
|
||||
* the array is exhausted or encounters elements that are not options.
|
||||
*
|
||||
* @param args an array of arguments
|
||||
* @return the last index that will/can be consumed by this processor.
|
||||
*/
|
||||
|
@ -118,13 +118,13 @@ public class CommandProcessor {
|
|||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register the given aliases as a command option.
|
||||
*
|
||||
*
|
||||
* @param requiresValue if true then the option must be specified with a value.
|
||||
* @param aliases strings to recognize this option. Each must begin with a dash character.
|
||||
*
|
||||
*
|
||||
* @return the command that is registered
|
||||
*/
|
||||
public Option register(boolean requiresValue, String...aliases) {
|
||||
|
@ -132,17 +132,17 @@ public class CommandProcessor {
|
|||
registeredOptions.put(option, null);
|
||||
return option;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a command with the given name.
|
||||
* If no command has been registered with the given name, but this processor
|
||||
* allows unrecognized options, then as a result of this call, the
|
||||
* unknown name is registered as an option.
|
||||
*
|
||||
*
|
||||
* @param option a command alias.
|
||||
*
|
||||
*
|
||||
* @return null if the given String is not a valid command option name.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public Option findCommand(String option) {
|
||||
if (!Option.isValidName(option))
|
||||
|
@ -163,38 +163,38 @@ public class CommandProcessor {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all the unrecognized command options.
|
||||
*
|
||||
*
|
||||
* @return empty set if no commands are unrecognized.
|
||||
*/
|
||||
public Set<Option> getUnregisteredCommands() {
|
||||
return Collections.unmodifiableSet(unregisteredOptions);
|
||||
}
|
||||
|
||||
|
||||
<T> void assertValidIndex(int i, T[] a, String message) {
|
||||
if (i <0 || (a != null && i >= a.length))
|
||||
throw new ArrayIndexOutOfBoundsException(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets value of the option matching the given alias.
|
||||
*
|
||||
*
|
||||
* @param alias an alias.
|
||||
*
|
||||
*
|
||||
* @return value of the given option.
|
||||
*/
|
||||
public String getValue(String alias) {
|
||||
Option cmd = findCommand(alias);
|
||||
return getValue(cmd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets value of the given option.
|
||||
*
|
||||
*
|
||||
* @param opt an option.
|
||||
*
|
||||
*
|
||||
* @return value of the given option.
|
||||
*/
|
||||
String getValue(Option opt) {
|
||||
|
@ -203,7 +203,7 @@ public class CommandProcessor {
|
|||
val = opt.getDefaultValue();
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the allowsUnregisteredOption
|
||||
*/
|
||||
|
@ -217,16 +217,16 @@ public class CommandProcessor {
|
|||
public void setAllowsUnregisteredOption(boolean allowsUnregisteredOption) {
|
||||
this.allowsUnregisteredOption = allowsUnregisteredOption;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple immutable object represents meta-data about a command option.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public static class Option {
|
||||
private static final String DASH = "-";
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the given string can be a valid option name.
|
||||
* An option name always starts with dash and must be followed by at least one character.
|
||||
|
@ -234,42 +234,42 @@ public class CommandProcessor {
|
|||
public static boolean isValidName(String s) {
|
||||
return s != null && s.startsWith(DASH) && s.length() > 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Possible names of this command option.
|
||||
* All aliases must start with a dash (<code>-</code>).
|
||||
* All aliases must start with a dash (<code>-</code>).
|
||||
*/
|
||||
private String[] aliases;
|
||||
|
||||
|
||||
/**
|
||||
* Does the option require a value?
|
||||
*/
|
||||
private boolean requiresInput;
|
||||
|
||||
|
||||
/**
|
||||
* A default value for this option.
|
||||
*/
|
||||
private String defValue;
|
||||
|
||||
|
||||
/**
|
||||
* A description String.
|
||||
*/
|
||||
private String _description = "";
|
||||
|
||||
|
||||
/**
|
||||
* Create a command with given aliases. This option requires a value.
|
||||
*
|
||||
* @param aliases strings each must start with a dash (<code>-</code>).
|
||||
*
|
||||
* @param aliases strings each must start with a dash (<code>-</code>).
|
||||
*/
|
||||
public Option(String... aliases) {
|
||||
this(true, aliases);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a option with given aliases.
|
||||
*
|
||||
*
|
||||
* @param requiresInput does it require a value?
|
||||
* @param aliases strings each must start with a dash (<code>-</code>).
|
||||
* @param aliases strings each must start with a dash (<code>-</code>).
|
||||
*/
|
||||
public Option(boolean requiresInput, String...aliases) {
|
||||
super();
|
||||
|
@ -284,21 +284,21 @@ public class CommandProcessor {
|
|||
this.aliases = aliases;
|
||||
this.requiresInput = requiresInput;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the first alias as the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return aliases[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the default value for this option.
|
||||
*
|
||||
*
|
||||
* @param v a default value.
|
||||
*
|
||||
*
|
||||
* @return this command itself.
|
||||
*
|
||||
*
|
||||
* @exception IllegalStateException if this option does not require a value.
|
||||
*/
|
||||
public Option setDefault(String v) {
|
||||
|
@ -309,18 +309,18 @@ public class CommandProcessor {
|
|||
defValue = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Option setDescription(String desc) {
|
||||
if (desc != null) {
|
||||
_description = desc;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getDescription() {
|
||||
return _description;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if the given name any of the aliases.
|
||||
*/
|
||||
|
@ -331,23 +331,23 @@ public class CommandProcessor {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Affirms if this option requires a value.
|
||||
*/
|
||||
public boolean requiresInput() {
|
||||
return requiresInput;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the default value of this option.
|
||||
*
|
||||
*
|
||||
* @return the default value. null if no default value has been set.
|
||||
*/
|
||||
public String getDefaultValue() {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.ant;
|
||||
|
||||
|
@ -30,7 +30,7 @@ import org.apache.tools.ant.taskdefs.MatchingTask;
|
|||
|
||||
/**
|
||||
* An ant task to run {@linkplain Java2HTMLConverter Java2HTML Converter}.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -45,9 +45,9 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
private boolean addExplicitSpace = true;
|
||||
private String lineNumberFormat = "%04d";
|
||||
private boolean verbose = false;
|
||||
|
||||
|
||||
private List<Arg> _args = new ArrayList<Arg>();
|
||||
|
||||
|
||||
public String getSourcepath() {
|
||||
return sourcepath;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
public void setSourcepath(String sourcepath) {
|
||||
this.sourcepath = sourcepath;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
List<String> files = getFiles();
|
||||
|
@ -71,7 +71,7 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
args.add("-addExplicitSpace"); args.add(""+addExplicitSpace);
|
||||
args.add("-lineNumberFormat"); args.add(lineNumberFormat);
|
||||
args.add("-anchorLineNumber"); args.add(""+anchorLineNumber);
|
||||
|
||||
|
||||
for (Arg a : _args) {
|
||||
args.add(a.getName());
|
||||
args.add(a.getValue());
|
||||
|
@ -85,7 +85,7 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
throw new BuildException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<String> getFiles() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
DirectoryScanner scanner = getDirectoryScanner(new File(getSourcepath()));
|
||||
|
@ -97,13 +97,13 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public Arg createArg() {
|
||||
Arg arg = new Arg();
|
||||
_args.add(arg);
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getDestDir() {
|
||||
return destDir;
|
||||
|
@ -120,7 +120,7 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
public void setVerbose(boolean verbose) {
|
||||
this.verbose = verbose;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the extension
|
||||
*/
|
||||
|
@ -218,11 +218,11 @@ public class Java2HTMLConverterTask extends MatchingTask {
|
|||
public void setLineNumberFormat(String lineNumberFormat) {
|
||||
this.lineNumberFormat = lineNumberFormat;
|
||||
}
|
||||
|
||||
|
||||
public static class Arg {
|
||||
String name;
|
||||
String value;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -32,19 +32,19 @@ import org.antlr.runtime.Token;
|
|||
* The styles of the tokens are determined by their types such as Java keywords, identifiers,
|
||||
* comments etc. Moreover, an identifier can be a <em>custom</em> type if it matched a given
|
||||
* list of identifiers. The actual HTML text is enclosed in <span id="style">token<\span>
|
||||
* to apply the style. The styles are defined in a Cascaded Style Sheet (CSS).
|
||||
* to apply the style. The styles are defined in a Cascaded Style Sheet (CSS).
|
||||
* The cascaded style sheet by default is named <code>java.css</code>.
|
||||
* <br>
|
||||
* The rendering takes care of line breaks and white space in the following way to work
|
||||
* around some limitations of Swing based HTML editor kit's usage of CSS attributes.
|
||||
* <LI> Line Breaks: Swing Editor seems to require an explicit carriage return-line feed
|
||||
* character to render in separate line. While a normal browser works with <br>
|
||||
* tag alone.
|
||||
* tag alone.
|
||||
* <LI> White space: The CSS property <code>white-space</code> is sufficient for browsers
|
||||
* to preserve white space within <span> tags. But Swing Editor seems to require
|
||||
* to preserve white space within <span> tags. But Swing Editor seems to require
|
||||
* explicit <code>nbsp;</code> for white spaces within <span> tags.
|
||||
* <br>
|
||||
* Two boolean properties are provided to control these two properties.
|
||||
* Two boolean properties are provided to control these two properties.
|
||||
* <br>
|
||||
* <LI>Line Numbering: A boolean property controls whether line numbers will be printed.
|
||||
* Line numbers are printed in 4 digits with leading zeros, by default.
|
||||
|
@ -56,8 +56,8 @@ import org.antlr.runtime.Token;
|
|||
* JavaDoc tags that define an anchor in the source code or creates a hyperlink should
|
||||
* be preserved in the HTML output. The capacity and limitation of processing HTML tages
|
||||
* inside JavaDoc comments are described in {@linkplain TextProcessingUtility here}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -68,7 +68,7 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
private boolean addLineBreak = true;
|
||||
private boolean addExplicitSpace = true;
|
||||
private String lineNumberFormat = "%04d";
|
||||
|
||||
|
||||
/**
|
||||
* The CSS named styles.
|
||||
*/
|
||||
|
@ -80,13 +80,13 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
public static final String CSS_LITERAL = "literal";
|
||||
public static final String CSS_DECIMAL = "decimal";
|
||||
public static final String CSS_LINE_NO = "lineno";
|
||||
|
||||
|
||||
private Set<String> customIdentifiers = new HashSet<String>();
|
||||
|
||||
public static final String NEW_LINE = "\r\n";
|
||||
public static final String HTML_BR_TAG = "<br>";
|
||||
public static final String HTML_SPACE = " ";
|
||||
|
||||
|
||||
/**
|
||||
* Gets a end-of-line string: a HTML <br> tag followed by carriage return and line feed.
|
||||
*/
|
||||
|
@ -95,7 +95,7 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a string for beginning of a new line.
|
||||
* Gets a string for beginning of a new line.
|
||||
*/
|
||||
public String newLine(int line) {
|
||||
String result = "";
|
||||
|
@ -156,15 +156,15 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
String span(String id, String txt) {
|
||||
return "<span id=" + quote(id) + ">" + txt + "</span>";
|
||||
}
|
||||
|
||||
|
||||
String quote(String s) {
|
||||
return "\""+s+"\"";
|
||||
}
|
||||
|
||||
|
||||
boolean isWhiteSpace(String txt) {
|
||||
for (int i = 0; i < txt.length(); i++) {
|
||||
if (!Character.isWhitespace(txt.charAt(i)))
|
||||
|
@ -172,7 +172,7 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
String fillWhiteSpace(String txt) {
|
||||
StringBuilder space = new StringBuilder();
|
||||
for (int i = 0; i < txt.length(); i++) {
|
||||
|
@ -182,20 +182,20 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
return space.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the opening <BODY> and <HTML> tags and the <link type="stylesheet"> clause.
|
||||
*/
|
||||
public String getPrologue() {
|
||||
return insertLines(
|
||||
"<HTML>",
|
||||
"<HEAD>",
|
||||
"<HTML>",
|
||||
"<HEAD>",
|
||||
"<link rel="+ quote("stylesheet")+ " type=" + quote("text/css") + " href=" + quote(stylesheet) + ">",
|
||||
"</HEAD>",
|
||||
"<BODY>");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the closing <BODY> and <HTML> tags
|
||||
*/
|
||||
|
@ -213,9 +213,9 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
|
||||
// Bean Style setters for auto-configuration
|
||||
|
||||
|
||||
/**
|
||||
* Gets the stylesheet to be linked at HTML output.
|
||||
* Gets the stylesheet to be linked at HTML output.
|
||||
*/
|
||||
public String getStylesheet() {
|
||||
return stylesheet;
|
||||
|
@ -257,9 +257,9 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Affirms if explicit line break (carriage return and line feed) will be added
|
||||
* Affirms if explicit line break (carriage return and line feed) will be added
|
||||
* at the HTML output.
|
||||
*
|
||||
*
|
||||
* @see #endLine(int)
|
||||
*/
|
||||
public boolean getAddLineBreak() {
|
||||
|
@ -267,9 +267,9 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets if explicit line break (carriage return and line feed) will be added
|
||||
* Sets if explicit line break (carriage return and line feed) will be added
|
||||
* at the HTML output.
|
||||
*
|
||||
*
|
||||
* @see #endLine(int)
|
||||
*/
|
||||
public void setAddLineBreak(boolean addLineBreak) {
|
||||
|
@ -300,9 +300,9 @@ public class HTMLTokenRenderer implements TokenRenderer {
|
|||
|
||||
/**
|
||||
* Sets the format string to format line number such as <code>"%%0%4d"</code>
|
||||
* for a 4-digit number with leading zeros.
|
||||
* for a 4-digit number with leading zeros.
|
||||
*/
|
||||
public void setLineNumberFormat(String lineNumberFormat) {
|
||||
this.lineNumberFormat = lineNumberFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -24,13 +24,13 @@ import openbook.tools.CommandProcessor;
|
|||
import openbook.tools.util.URIUtils;
|
||||
|
||||
public class Java2HTMLConverter extends SourceRenderer {
|
||||
|
||||
|
||||
private final HTMLTokenRenderer _renderer = new HTMLTokenRenderer();
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Java2HTMLConverter().run(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerOptions(CommandProcessor options) {
|
||||
options.register(true, "-stylesheet").setDefault("java.css");
|
||||
|
@ -40,18 +40,18 @@ public class Java2HTMLConverter extends SourceRenderer {
|
|||
options.register(true, "-showLineNumber").setDefault("true");
|
||||
options.register(true, "-lineNumberFormat").setDefault("%%0%4d");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TokenRenderer createRenderer(CommandProcessor options, File outFile) {
|
||||
File styleFile = null;
|
||||
styleFile = new File(getDestinationDirectory(), options.getValue("-stylesheet"));
|
||||
if (!styleFile.exists()) {
|
||||
throw new IllegalArgumentException("Stylesheet file " + styleFile.getAbsolutePath() +
|
||||
" does not exist. Ensure that the file is available under destination directory" +
|
||||
" does not exist. Ensure that the file is available under destination directory" +
|
||||
getDestinationDirectory().getAbsolutePath());
|
||||
}
|
||||
_renderer.setStylesheet(getRelativeStylesheet(styleFile, outFile));
|
||||
|
||||
|
||||
_renderer.setAddLineBreak("true".equals(options.getValue("-addLineBreak")));
|
||||
_renderer.setAddExplicitSpace("true".equals(options.getValue("-addExplicitSpace")));
|
||||
_renderer.setAnchorLineNumber("true".equals(options.getValue("-anchorLineNumber")));
|
||||
|
@ -59,8 +59,8 @@ public class Java2HTMLConverter extends SourceRenderer {
|
|||
_renderer.setShowLineNumber("true".equals(options.getValue("-showLineNumber")));
|
||||
return _renderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String getRelativeStylesheet(File styleFile, File outFile) {
|
||||
String stylesheetPath = styleFile.getAbsolutePath().replace(File.separatorChar, FORWARD_SLASH);
|
||||
String outPath = outFile.getAbsolutePath().replace(File.separatorChar, FORWARD_SLASH);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -24,24 +24,24 @@ import openbook.tools.CommandProcessor;
|
|||
|
||||
/**
|
||||
* Converts Java Source code to plain text with optional line number.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class Java2TextConverter extends SourceRenderer {
|
||||
|
||||
|
||||
private final PlainTokenRenderer _renderer = new PlainTokenRenderer();
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Java2TextConverter().run(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerOptions(CommandProcessor options) {
|
||||
options.register(true, "-showLineNumber").setDefault("true");
|
||||
options.register(true, "-lineNumberFormat").setDefault("%%0%4d");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TokenRenderer createRenderer(CommandProcessor options, File outFile) {
|
||||
_renderer.setLineNumberFormat(options.getValue("-lineNumberFormat"));
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -29,11 +29,11 @@ import org.antlr.runtime.debug.BlankDebugEventListener;
|
|||
|
||||
/**
|
||||
* A token processor to render the ANTLR tokens.
|
||||
*
|
||||
*
|
||||
* This token processor is notified as ANTLR parses every token.
|
||||
* This processor controls a {@linkplain TokenRenderer renderer}
|
||||
* This processor controls a {@linkplain TokenRenderer renderer}
|
||||
* that renders the token.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -43,26 +43,26 @@ public class ParseTokenListener extends BlankDebugEventListener {
|
|||
private int decision;
|
||||
private TokenRenderer _renderer;
|
||||
private PrintStream _stream;
|
||||
|
||||
|
||||
/**
|
||||
* By default, uses a {@linkplain PlainTokenRenderer}.
|
||||
*/
|
||||
ParseTokenListener() {
|
||||
this(new PlainTokenRenderer());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uses the given renderer and outputs to System output.
|
||||
*
|
||||
*
|
||||
* @param renderer a renderer to render the tokens.
|
||||
*/
|
||||
ParseTokenListener(TokenRenderer renderer) {
|
||||
this(renderer, System.out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uses the given renderer and given outputs stream.
|
||||
*
|
||||
*
|
||||
* @param renderer a renderer to render the tokens.
|
||||
* @param stream a output stream where the rendered strings are streamed.
|
||||
*/
|
||||
|
@ -70,18 +70,18 @@ public class ParseTokenListener extends BlankDebugEventListener {
|
|||
_renderer = renderer;
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enterDecision(int d) {
|
||||
backtracking += 1;
|
||||
backtracking += 1;
|
||||
decision = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitDecision(int i) {
|
||||
backtracking -= 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void exitDecision(int i) {
|
||||
backtracking -= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A regular token is delegated to the renderer for a string representation
|
||||
* and the resultant string is sent to the output stream.
|
||||
|
@ -92,14 +92,14 @@ public class ParseTokenListener extends BlankDebugEventListener {
|
|||
changeLine(token.getLine());
|
||||
_stream.print(_renderer.render(decision, token));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hidden tokens are tokens that are not processed at lexical processing
|
||||
* stage. The most important hidden token for rendering are the tokens
|
||||
* that represent multi-line or single line comments. The multi-line
|
||||
* comments must be broken into individual lines for line numbering to
|
||||
* remain consistent.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void consumeHiddenToken(Token token) {
|
||||
|
@ -115,15 +115,15 @@ public class ParseTokenListener extends BlankDebugEventListener {
|
|||
i++;
|
||||
}
|
||||
} else {
|
||||
changeLine(token.getLine());
|
||||
changeLine(token.getLine());
|
||||
_stream.print(_renderer.render(decision, token));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the given line is different than the current line, then asks the
|
||||
* renderer to end the current line and start a new line. Otherwise, does nothing.
|
||||
*
|
||||
*
|
||||
* @param newline
|
||||
*/
|
||||
void changeLine(int newline) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -22,7 +22,7 @@ package openbook.tools.converter;
|
|||
import org.antlr.runtime.Token;
|
||||
/**
|
||||
* A default implementation of {@linkplain TokenRenderer} that simply prints the token.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
|
@ -30,7 +30,7 @@ public class PlainTokenRenderer implements TokenRenderer {
|
|||
private static final String EMPTY = "";
|
||||
private boolean showLineNumber = true;
|
||||
private String lineNumberFormat = "%04d";
|
||||
|
||||
|
||||
public String endLine(int line) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -34,17 +34,17 @@ import org.antlr.runtime.debug.DebugEventListener;
|
|||
|
||||
/**
|
||||
* Renders Java Source Code.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class SourceRenderer {
|
||||
public final static char FORWARD_SLASH = '/';
|
||||
public final static String DOT = ".";
|
||||
public final static String CURRENT_DIRECTORY = ".";
|
||||
|
||||
public final static char FORWARD_SLASH = '/';
|
||||
public final static String DOT = ".";
|
||||
public final static String CURRENT_DIRECTORY = ".";
|
||||
|
||||
private File _sourceDir, _destinationDir;
|
||||
|
||||
|
||||
boolean verbose = false;
|
||||
/**
|
||||
* Renders the given source files. The syntax of the command is
|
||||
|
@ -54,27 +54,27 @@ public abstract class SourceRenderer {
|
|||
* <pre> $ java SourceRenderer -stylesheet mystyle.css -sourcepath test
|
||||
* -d generated/html acme/foo/SomeClass.java</pre>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* Recognized options are<br>
|
||||
* <table>
|
||||
* <TR><TD><pre>-format</pre></TD> <TD>the format of the converted output. Recognized monikers are
|
||||
* <TR><TD><pre>-format</pre></TD> <TD>the format of the converted output. Recognized monikers are
|
||||
* <code>html</code> and <code>text</code>. A fully qualified class name that implements {@link TokenRenderer} is
|
||||
* allowed. Default is <code>html</code></TD></tr>
|
||||
* <TR><TD><pre>-sourcepath</pre><TD>the root of the source files. Default is the current directory</tr>
|
||||
* <TR><TD><pre>-d</pre><TD>the root of the generated files. Default is the current directory</tr>
|
||||
* allowed. Default is <code>html</code></TD></tr>
|
||||
* <TR><TD><pre>-sourcepath</pre><TD>the root of the source files. Default is the current directory</tr>
|
||||
* <TR><TD><pre>-d</pre><TD>the root of the generated files. Default is the current directory</tr>
|
||||
* </table>
|
||||
* Besides these options, a renderer can accept more options. Any option <code>-someProperty</code>
|
||||
* will configure the renderer if a bean-style setter method <code>setSomeProperty(String|boolean|int)</code>
|
||||
* is available. See available documentation on the specific {@link HTMLTokenRenderer renderer}.
|
||||
* <br>
|
||||
* <br>
|
||||
* Stylesheet file must be under destination directory.
|
||||
* <pre>-stylesheet</pre> is relative to destination directory.
|
||||
*
|
||||
*
|
||||
* @param args command-line arguments.
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
|
||||
protected final void run(String[] args) throws Exception {
|
||||
CommandProcessor options = new CommandProcessor();
|
||||
options.register(true, "-sourcepath").setDefault(CURRENT_DIRECTORY);
|
||||
|
@ -82,9 +82,9 @@ public abstract class SourceRenderer {
|
|||
options.register(true, "-extension").setDefault("");
|
||||
options.register(true, "-verbose").setDefault("false");
|
||||
registerOptions(options);
|
||||
|
||||
String[] inputs = options.setFrom(args);
|
||||
|
||||
|
||||
String[] inputs = options.setFrom(args);
|
||||
|
||||
_sourceDir = new File(options.getValue("-sourcepath"));
|
||||
_destinationDir = new File(options.getValue("-d"));
|
||||
verbose = "true".equalsIgnoreCase(options.getValue("-verbose"));
|
||||
|
@ -94,7 +94,7 @@ public abstract class SourceRenderer {
|
|||
if (fin == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
File outFile = new File(_destinationDir, suffix(path, options.getValue("-extension")));
|
||||
FileOutputStream fout = createOutput(outFile);
|
||||
if (fout == null) {
|
||||
|
@ -112,7 +112,7 @@ public abstract class SourceRenderer {
|
|||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public File getDestinationDirectory() {
|
||||
return _destinationDir;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public abstract class SourceRenderer {
|
|||
}
|
||||
public abstract void registerOptions(CommandProcessor options);
|
||||
public abstract TokenRenderer createRenderer(CommandProcessor options, File outFile);
|
||||
|
||||
|
||||
private void render(InputStream is, TokenRenderer renderer, PrintStream out) throws Exception {
|
||||
ANTLRInputStream input = new ANTLRInputStream(is);
|
||||
JavaLexer lexer = new JavaLexer(input);
|
||||
|
@ -131,15 +131,15 @@ public abstract class SourceRenderer {
|
|||
// launch the parser starting at compilation unit
|
||||
parser.compilationUnit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the input stream.
|
||||
*
|
||||
*
|
||||
* @param srcDir the root source directory.
|
||||
* @param path the path to input file.
|
||||
*/
|
||||
protected InputStream getInputStream(File srcDir, String path) {
|
||||
File file = new File(srcDir, path);
|
||||
File file = new File(srcDir, path);
|
||||
if (!file.exists()) {
|
||||
warn("Input file " + file.getAbsolutePath() + " does not exist");
|
||||
return null;
|
||||
|
@ -151,7 +151,7 @@ public abstract class SourceRenderer {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the output stream to write to.
|
||||
*/
|
||||
|
@ -169,21 +169,21 @@ public abstract class SourceRenderer {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private String suffix(String s, String suffix) {
|
||||
if (suffix == null || suffix.isEmpty())
|
||||
return s;
|
||||
if (suffix.startsWith("."))
|
||||
if (suffix.startsWith("."))
|
||||
return s + suffix;
|
||||
return s + "." + suffix;
|
||||
}
|
||||
|
||||
|
||||
protected void verbose(String s) {
|
||||
if (verbose)
|
||||
System.err.println(s);
|
||||
}
|
||||
|
||||
|
||||
protected void warn(String s) {
|
||||
System.err.println(s);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package openbook.tools.converter;
|
||||
|
||||
|
@ -23,17 +23,17 @@ import org.antlr.runtime.debug.DebugEventListener;
|
|||
|
||||
/**
|
||||
* Renders a runtime ANTLR token.
|
||||
* {@linkplain ParseTokenListener} controls a renderer and streams the rendered Strings
|
||||
* to appropriate output.
|
||||
* {@linkplain ParseTokenListener} controls a renderer and streams the rendered Strings
|
||||
* to appropriate output.
|
||||
* <br>
|
||||
* A renderer can define additional bean-style setter methods. They will be set before
|
||||
* renderer is used.
|
||||
* <br>
|
||||
* A concrete renderer should have a no argument constructor.
|
||||
* A concrete renderer should have a no argument constructor.
|
||||
* <br>
|
||||
* {@linkplain ParseTokenListener} or the <em>framework</em> calls a renderer in following sequence:
|
||||
* <pre>
|
||||
* bean-style setter methods as per the user configured
|
||||
* bean-style setter methods as per the user configured
|
||||
* getPrologue()
|
||||
* for each token {
|
||||
* if (line is changing) {
|
||||
|
@ -57,47 +57,47 @@ public interface TokenRenderer {
|
|||
* the <HEAD> tag to include the style sheet.
|
||||
*/
|
||||
public String getPrologue();
|
||||
|
||||
|
||||
/**
|
||||
* Gets a string to be added after token processing ends.
|
||||
* For example, a HTML renderer may return the closing HTML and BODY tags.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public String getEpilogue();
|
||||
|
||||
|
||||
/**
|
||||
* Produce a string representation of the given token.
|
||||
*
|
||||
*
|
||||
* @param decision the index of the decision (or the context) in which
|
||||
* the current token is being processed. The index refers to ANTLR
|
||||
* {@link DebugEventListener#enterDecision(int)}.
|
||||
*
|
||||
*
|
||||
* @param token the token to be rendered. Can be a hidden token as well.
|
||||
*
|
||||
*
|
||||
* @return a string representation of the given token.
|
||||
*/
|
||||
public String render(int decision, Token token);
|
||||
|
||||
|
||||
/**
|
||||
* Produce a string to signal beginning of a line.
|
||||
* <br>
|
||||
* For example, a renderer printing line numbers can produce a String with the given line number.
|
||||
*
|
||||
* @param line the current line number
|
||||
*
|
||||
*
|
||||
* @param line the current line number
|
||||
*
|
||||
* @return a String can be a blank
|
||||
*/
|
||||
public String newLine(int line);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Produce a string to signal end of a line.
|
||||
* <br>
|
||||
* For example, a renderer can produce a newline.
|
||||
*
|
||||
* @param line the line being ended
|
||||
*
|
||||
*
|
||||
* @param line the line being ended
|
||||
*
|
||||
* @return a String can be a blank
|
||||
*/
|
||||
public String endLine(int line);
|
||||
public String endLine(int line);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue