diff --git a/JSearchClient_nbproject/build.xml b/JSearchClient_nbproject/build.xml new file mode 100644 index 0000000000000000000000000000000000000000..68df2ba7d4d34df73802e7d1d9d2b5535f5566a0 --- /dev/null +++ b/JSearchClient_nbproject/build.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 only, as +published by the Free Software Foundation. Sun designates this +particular file as subject to the "Classpath" exception as provided +by Sun in the LICENSE file that accompanied this code. + +This code is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +version 2 for more details (a copy is included in the LICENSE file that +accompanied this code). + +You should have received a copy of the GNU General Public License version +2 along with this work; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +CA 95054 USA or visit www.sun.com if you need additional information or +have any questions. + --> +<project name="JSearchClient" default="default" basedir="."> + <description>Builds, tests, and runs the project JSearchClient.</description> + <import file="nbproject/build-impl.xml"/> +</project> diff --git a/JSearchClient_nbproject/manifest.mf b/JSearchClient_nbproject/manifest.mf new file mode 100644 index 0000000000000000000000000000000000000000..1574df4a2de5d2884f33a5d3e30ae3daa5affee1 --- /dev/null +++ b/JSearchClient_nbproject/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/JSearchClient_nbproject/nbproject/build-impl.xml b/JSearchClient_nbproject/nbproject/build-impl.xml new file mode 100644 index 0000000000000000000000000000000000000000..d6ce517eab8819c7b5057c17b05f5c3e34bfa27d --- /dev/null +++ b/JSearchClient_nbproject/nbproject/build-impl.xml @@ -0,0 +1,545 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** + +For the purpose of easier reading the script +is divided into following sections: + + - initialization + - compilation + - jar + - execution + - debugging + - javadoc + - junit compilation + - junit execution + - junit debugging + - applet + - cleanup + +--> +<project name="JSearchClient-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1"> + <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/> + <!-- + ====================== + INITIALIZATION SECTION + ====================== + --> + <target name="-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-private" depends="-pre-init"> + <property file="nbproject/private/config.properties"/> + <property file="nbproject/private/configs/${config}.properties"/> + <property file="nbproject/private/private.properties"/> + </target> + <target name="-init-user" depends="-pre-init,-init-private"> + <property file="${user.properties.file}"/> + <!-- The two properties below are usually overridden --> + <!-- by the active platform. Just a fallback. --> + <property name="default.javac.source" value="1.4"/> + <property name="default.javac.target" value="1.4"/> + </target> + <target name="-init-project" depends="-pre-init,-init-private,-init-user"> + <property file="nbproject/configs/${config}.properties"/> + <property file="nbproject/project.properties"/> + </target> + <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property"> + <available file="${manifest.file}" property="manifest.available"/> + <condition property="manifest.available+main.class"> + <and> + <isset property="manifest.available"/> + <isset property="main.class"/> + <not> + <equals arg1="${main.class}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition property="manifest.available+main.class+mkdist.available"> + <and> + <istrue value="${manifest.available+main.class}"/> + <isset property="libs.CopyLibs.classpath"/> + </and> + </condition> + <condition property="have.tests"> + <or/> + </condition> + <condition property="have.sources"> + <or> + <available file="${src.dir}"/> + </or> + </condition> + <condition property="netbeans.home+have.tests"> + <and> + <isset property="netbeans.home"/> + <isset property="have.tests"/> + </and> + </condition> + <condition property="no.javadoc.preview"> + <isfalse value="${javadoc.preview}"/> + </condition> + <property name="run.jvmargs" value=""/> + <property name="javac.compilerargs" value=""/> + <property name="work.dir" value="${basedir}"/> + <condition property="no.deps"> + <and> + <istrue value="${no.dependencies}"/> + </and> + </condition> + <property name="javac.debug" value="true"/> + <property name="javadoc.preview" value="true"/> + <property name="application.args" value=""/> + </target> + <target name="-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init"> + <fail unless="src.dir">Must set src.dir</fail> + <fail unless="build.dir">Must set build.dir</fail> + <fail unless="dist.dir">Must set dist.dir</fail> + <fail unless="build.classes.dir">Must set build.classes.dir</fail> + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> + <fail unless="dist.jar">Must set dist.jar</fail> + </target> + <target name="-init-macrodef-property"> + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-javac"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="srcdir" default="${src.dir}"/> + <attribute name="destdir" default="${build.classes.dir}"/> + <attribute name="classpath" default="${javac.classpath}"/> + <attribute name="debug" default="${javac.debug}"/> + <element name="customize" optional="true"/> + <sequential> + <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </depend> + <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false"> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${javac.compilerargs}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-junit"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="includes" default="**/*Test.java"/> + <sequential> + <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed"> + <batchtest todir="${build.test.results.dir}"/> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper type="glob" from="test-sys-prop.*" to="*"/> + </syspropertyset> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${run.jvmargs}"/> + </junit> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-nbjpda"> + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <attribute name="stopclassname" default=""/> + <sequential> + <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </nbjpdastart> + </sequential> + </macrodef> + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="dir" default="${build.classes.dir}"/> + <sequential> + <nbjpdareload> + <fileset includes="${fix.includes}*.class" dir="@{dir}"/> + </nbjpdareload> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-debug"> + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="classname" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xnoagent"/> + <jvmarg value="-Djava.compiler=none"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-java"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="classname" default="${main.class}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="${run.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-presetdef-jar"> + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> + <jar jarfile="${dist.jar}" compress="${jar.compress}"> + <j2seproject1:fileset dir="${build.classes.dir}"/> + </jar> + </presetdef> + </target> + <target name="init" depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar"/> + <!-- + =================== + COMPILATION SECTION + =================== + --> + <target name="deps-jar" depends="init" unless="no.deps"> + <ant target="jar" inheritall="false" antfile="${project.JavaHelp}/build.xml"/> + </target> + <target name="-pre-pre-compile" depends="init,deps-jar"> + <mkdir dir="${build.classes.dir}"/> + </target> + <target name="-pre-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources"> + <j2seproject3:javac/> + <copy todir="${build.classes.dir}"> + <fileset dir="${src.dir}" excludes="${build.classes.excludes}"/> + </copy> + </target> + <target name="-post-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/> + <target name="-pre-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + </target> + <target name="-post-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/> + <!-- + ==================== + JAR BUILDING SECTION + ==================== + --> + <target name="-pre-pre-jar" depends="init"> + <dirname property="dist.jar.dir" file="${dist.jar}"/> + <mkdir dir="${dist.jar.dir}"/> + </target> + <target name="-pre-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available"> + <j2seproject1:jar/> + </target> + <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class"> + <j2seproject1:jar manifest="${manifest.file}"/> + </target> + <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" unless="manifest.available+main.class+mkdist.available"> + <j2seproject1:jar manifest="${manifest.file}"> + <j2seproject1:manifest> + <j2seproject1:attribute name="Main-Class" value="${main.class}"/> + </j2seproject1:manifest> + </j2seproject1:jar> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <pathconvert property="run.classpath.with.dist.jar"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> + </pathconvert> + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> + </target> + <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available"> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert property="jar.classpath" pathsep=" "> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" name="copylibs" classpath="${libs.CopyLibs.classpath}"/> + <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}"> + <fileset dir="${build.classes.dir}"/> + <manifest> + <attribute name="Main-Class" value="${main.class}"/> + <attribute name="Class-Path" value="${jar.classpath}"/> + </manifest> + </copylibs> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <echo>java -jar "${dist.jar.resolved}"</echo> + </target> + <target name="-post-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="jar" depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/> + <!-- + ================= + EXECUTION SECTION + ================= + --> + <target name="run" depends="init,compile" description="Run a main class."> + <j2seproject1:java> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject1:java> + </target> + <target name="run-single" depends="init,compile-single"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}"/> + </target> + <!-- + ================= + DEBUGGING SECTION + ================= + --> + <target name="-debug-start-debugger" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart name="${debug.class}"/> + </target> + <target name="-debug-start-debuggee" depends="init,compile"> + <j2seproject3:debug> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/> + <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart stopclassname="${main.class}"/> + </target> + <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/> + <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}"/> + </target> + <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/> + <target name="-pre-debug-fix" depends="init"> + <fail unless="fix.includes">Must set fix.includes</fail> + <property name="javac.includes" value="${fix.includes}.java"/> + </target> + <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single"> + <j2seproject1:nbjpdareload/> + </target> + <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/> + <!-- + =============== + JAVADOC SECTION + =============== + --> + <target name="-javadoc-build" depends="init"> + <mkdir dir="${dist.javadoc.dir}"/> + <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true"> + <classpath> + <path path="${javac.classpath}"/> + </classpath> + <sourcepath> + <pathelement location="${src.dir}"/> + </sourcepath> + <packageset dir="${src.dir}" includes="*/**"/> + <fileset dir="${src.dir}" includes="*.java"/> + </javadoc> + </target> + <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build"> + <nbbrowse file="${dist.javadoc.dir}/index.html"/> + </target> + <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/> + <!-- + ========================= + JUNIT COMPILATION SECTION + ========================= + --> + <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile"> + <mkdir dir="${build.test.classes.dir}"/> + </target> + <target name="-pre-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test"> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test"/> + <target name="-pre-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/> + <!-- + ======================= + JUNIT EXECUTION SECTION + ======================= + --> + <target name="-pre-test-run" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run"> + <j2seproject3:junit/> + </target> + <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-report" if="have.tests" depends="init"/> + <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/> + <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/> + <target name="-pre-test-run-single" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <j2seproject3:junit includes="${test.includes}"/> + </target> + <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/> + <!-- + ======================= + JUNIT DEBUGGING SECTION + ======================= + --> + <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}"> + <customize> + <arg line="${test.class}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test"> + <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/> + </target> + <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/> + <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single"> + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> + </target> + <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/> + <!-- + ========================= + APPLET EXECUTION SECTION + ========================= + --> + <target name="run-applet" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject1:java classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject1:java> + </target> + <!-- + ========================= + APPLET DEBUGGING SECTION + ========================= + --> + <target name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject3:debug classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/> + <!-- + =============== + CLEANUP SECTION + =============== + --> + <target name="deps-clean" depends="init" unless="no.deps"> + <ant target="clean" inheritall="false" antfile="${project.JavaHelp}/build.xml"/> + </target> + <target name="-do-clean" depends="init"> + <delete dir="${build.dir}"/> + <delete dir="${dist.dir}"/> + </target> + <target name="-post-clean"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/> +</project> diff --git a/JSearchClient_nbproject/nbproject/genfiles.properties b/JSearchClient_nbproject/nbproject/genfiles.properties new file mode 100644 index 0000000000000000000000000000000000000000..da3fc0161ff92acd7ba33a233abc72010e4a19d0 --- /dev/null +++ b/JSearchClient_nbproject/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=c5c19be1 +build.xml.script.CRC32=3f707102 +build.xml.stylesheet.CRC32=a12b3d02 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=c5c19be1 +nbproject/build-impl.xml.script.CRC32=36526266 +nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1 diff --git a/JSearchClient_nbproject/nbproject/project.properties b/JSearchClient_nbproject/nbproject/project.properties new file mode 100644 index 0000000000000000000000000000000000000000..9e510f59bdf3b126aadd3d1b39a2f8ee9ead2772 --- /dev/null +++ b/JSearchClient_nbproject/nbproject/project.properties @@ -0,0 +1,80 @@ +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form,**/*.html,GNUmakefile +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/jsearch-client.jar +dist.javadoc.dir=${dist.dir}/javadoc +file.reference.JSearch-client=../jhMaster/JSearch/client +jar.compress=false +javac.classpath=\ + ${reference.JavaHelp.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.4 +javac.target=1.4 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.JavaHelp=../javahelp_nbproject +reference.JavaHelp.jar=${project.JavaHelp}/dist/lib/jh-client.jar +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +src.dir=${file.reference.JSearch-client} diff --git a/JSearchClient_nbproject/nbproject/project.xml b/JSearchClient_nbproject/nbproject/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..81af24d06b651085a9f92ae6cfd24f9299f3e717 --- /dev/null +++ b/JSearchClient_nbproject/nbproject/project.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>JSearchClient</name> + <minimum-ant-version>1.6.5</minimum-ant-version> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots/> + </data> + <references xmlns="http://www.netbeans.org/ns/ant-project-references/1"> + <reference> + <foreign-project>JavaHelp</foreign-project> + <artifact-type>jar</artifact-type> + <script>build.xml</script> + <target>jar</target> + <clean-target>clean</clean-target> + <id>jar</id> + </reference> + </references> + </configuration> +</project> diff --git a/JSearchIndexer_nbproject/build.xml b/JSearchIndexer_nbproject/build.xml new file mode 100644 index 0000000000000000000000000000000000000000..b7da7d3972b65ef966ef61437aa41354626f1791 --- /dev/null +++ b/JSearchIndexer_nbproject/build.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 only, as +published by the Free Software Foundation. Sun designates this +particular file as subject to the "Classpath" exception as provided +by Sun in the LICENSE file that accompanied this code. + +This code is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +version 2 for more details (a copy is included in the LICENSE file that +accompanied this code). + +You should have received a copy of the GNU General Public License version +2 along with this work; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +CA 95054 USA or visit www.sun.com if you need additional information or +have any questions. + --> +<project name="JSearchIndexer" default="default" basedir="."> + <description>Builds, tests, and runs the project JSearchIndexer.</description> + <import file="nbproject/build-impl.xml"/> + + <target name="-post-jar"> + <echo>Creating merged jsearch.jar</echo> + <jar jarfile="${basedir}/dist/jsearch.jar" excludes="${build.classes.excludes}"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + </fileset> + <fileset dir="../JSearchClient_nbproject/build/classes/"> + <include name="**/*"/> + </fileset> + <fileset dir="../javahelp_nbproject/build/classes/"> + <include name="com/sun/java/help/impl/HeaderParser.class"/> + <include name="javax/help/HelpUtilities*.class"/> + <include name="javax/help/event/EventListenerList.class"/> + <include name="javax/help/search/ConfigFile.class"/> + <include name="javax/help/search/ConfigFile.class"/> + <include name="javax/help/search/IndexBuilder.class"/> + <include name="javax/help/search/IndexerKit.class"/> + <include name="javax/help/search/SearchEngine.class"/> + <include name="javax/help/search/SearchEvent.class"/> + <include name="javax/help/search/SearchItem.class"/> + <include name="javax/help/search/SearchQuery.class"/> + <include name="javax/help/search/SearchListener.class"/> + </fileset> + </jar> + <echo>Creating jsearch-misc.jar</echo> + + <jar jarfile="${basedir}/dist/jsearch-misc.jar"> + <fileset dir="../javahelp_nbproject/build/classes/"> + <include name="com/sun/java/help/impl/HeaderParser.class"/> + <include name="javax/help/HelpUtilities*.class"/> + <include name="javax/help/event/EventListenerList.class"/> + <include name="javax/help/search/ConfigFile.class"/> + <include name="javax/help/search/ConfigFile.class"/> + <include name="javax/help/search/IndexBuilder.class"/> + <include name="javax/help/search/IndexerKit.class"/> + <include name="javax/help/search/SearchEngine.class"/> + <include name="javax/help/search/SearchEvent.class"/> + <include name="javax/help/search/SearchItem.class"/> + <include name="javax/help/search/SearchQuery.class"/> + <include name="javax/help/search/SearchListener.class"/> + </fileset> + </jar> + </target> +</project> diff --git a/JSearchIndexer_nbproject/manifest.mf b/JSearchIndexer_nbproject/manifest.mf new file mode 100644 index 0000000000000000000000000000000000000000..1574df4a2de5d2884f33a5d3e30ae3daa5affee1 --- /dev/null +++ b/JSearchIndexer_nbproject/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/JSearchIndexer_nbproject/nbproject/build-impl.xml b/JSearchIndexer_nbproject/nbproject/build-impl.xml new file mode 100644 index 0000000000000000000000000000000000000000..e1072fd67d48463e2b434be167f567fe2a23af1f --- /dev/null +++ b/JSearchIndexer_nbproject/nbproject/build-impl.xml @@ -0,0 +1,547 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** + +For the purpose of easier reading the script +is divided into following sections: + + - initialization + - compilation + - jar + - execution + - debugging + - javadoc + - junit compilation + - junit execution + - junit debugging + - applet + - cleanup + +--> +<project name="JSearchIndexer-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1"> + <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/> + <!-- + ====================== + INITIALIZATION SECTION + ====================== + --> + <target name="-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-private" depends="-pre-init"> + <property file="nbproject/private/config.properties"/> + <property file="nbproject/private/configs/${config}.properties"/> + <property file="nbproject/private/private.properties"/> + </target> + <target name="-init-user" depends="-pre-init,-init-private"> + <property file="${user.properties.file}"/> + <!-- The two properties below are usually overridden --> + <!-- by the active platform. Just a fallback. --> + <property name="default.javac.source" value="1.4"/> + <property name="default.javac.target" value="1.4"/> + </target> + <target name="-init-project" depends="-pre-init,-init-private,-init-user"> + <property file="nbproject/configs/${config}.properties"/> + <property file="nbproject/project.properties"/> + </target> + <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property"> + <available file="${manifest.file}" property="manifest.available"/> + <condition property="manifest.available+main.class"> + <and> + <isset property="manifest.available"/> + <isset property="main.class"/> + <not> + <equals arg1="${main.class}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition property="manifest.available+main.class+mkdist.available"> + <and> + <istrue value="${manifest.available+main.class}"/> + <isset property="libs.CopyLibs.classpath"/> + </and> + </condition> + <condition property="have.tests"> + <or/> + </condition> + <condition property="have.sources"> + <or> + <available file="${src.dir}"/> + </or> + </condition> + <condition property="netbeans.home+have.tests"> + <and> + <isset property="netbeans.home"/> + <isset property="have.tests"/> + </and> + </condition> + <condition property="no.javadoc.preview"> + <isfalse value="${javadoc.preview}"/> + </condition> + <property name="run.jvmargs" value=""/> + <property name="javac.compilerargs" value=""/> + <property name="work.dir" value="${basedir}"/> + <condition property="no.deps"> + <and> + <istrue value="${no.dependencies}"/> + </and> + </condition> + <property name="javac.debug" value="true"/> + <property name="javadoc.preview" value="true"/> + <property name="application.args" value=""/> + </target> + <target name="-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init"> + <fail unless="src.dir">Must set src.dir</fail> + <fail unless="build.dir">Must set build.dir</fail> + <fail unless="dist.dir">Must set dist.dir</fail> + <fail unless="build.classes.dir">Must set build.classes.dir</fail> + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> + <fail unless="dist.jar">Must set dist.jar</fail> + </target> + <target name="-init-macrodef-property"> + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-javac"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="srcdir" default="${src.dir}"/> + <attribute name="destdir" default="${build.classes.dir}"/> + <attribute name="classpath" default="${javac.classpath}"/> + <attribute name="debug" default="${javac.debug}"/> + <element name="customize" optional="true"/> + <sequential> + <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </depend> + <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false"> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${javac.compilerargs}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-junit"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="includes" default="**/*Test.java"/> + <sequential> + <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed"> + <batchtest todir="${build.test.results.dir}"/> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper type="glob" from="test-sys-prop.*" to="*"/> + </syspropertyset> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${run.jvmargs}"/> + </junit> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-nbjpda"> + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <attribute name="stopclassname" default=""/> + <sequential> + <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </nbjpdastart> + </sequential> + </macrodef> + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="dir" default="${build.classes.dir}"/> + <sequential> + <nbjpdareload> + <fileset includes="${fix.includes}*.class" dir="@{dir}"/> + </nbjpdareload> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-debug"> + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="classname" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xnoagent"/> + <jvmarg value="-Djava.compiler=none"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-java"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="classname" default="${main.class}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="${run.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-presetdef-jar"> + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> + <jar jarfile="${dist.jar}" compress="${jar.compress}"> + <j2seproject1:fileset dir="${build.classes.dir}"/> + </jar> + </presetdef> + </target> + <target name="init" depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar"/> + <!-- + =================== + COMPILATION SECTION + =================== + --> + <target name="deps-jar" depends="init" unless="no.deps"> + <ant target="jar" inheritall="false" antfile="${project.JSearchClient}/build.xml"/> + <ant target="jar" inheritall="false" antfile="${project.JavaHelp}/build.xml"/> + </target> + <target name="-pre-pre-compile" depends="init,deps-jar"> + <mkdir dir="${build.classes.dir}"/> + </target> + <target name="-pre-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources"> + <j2seproject3:javac/> + <copy todir="${build.classes.dir}"> + <fileset dir="${src.dir}" excludes="${build.classes.excludes}"/> + </copy> + </target> + <target name="-post-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/> + <target name="-pre-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + </target> + <target name="-post-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/> + <!-- + ==================== + JAR BUILDING SECTION + ==================== + --> + <target name="-pre-pre-jar" depends="init"> + <dirname property="dist.jar.dir" file="${dist.jar}"/> + <mkdir dir="${dist.jar.dir}"/> + </target> + <target name="-pre-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available"> + <j2seproject1:jar/> + </target> + <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class"> + <j2seproject1:jar manifest="${manifest.file}"/> + </target> + <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" unless="manifest.available+main.class+mkdist.available"> + <j2seproject1:jar manifest="${manifest.file}"> + <j2seproject1:manifest> + <j2seproject1:attribute name="Main-Class" value="${main.class}"/> + </j2seproject1:manifest> + </j2seproject1:jar> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <pathconvert property="run.classpath.with.dist.jar"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> + </pathconvert> + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> + </target> + <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available"> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert property="jar.classpath" pathsep=" "> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" name="copylibs" classpath="${libs.CopyLibs.classpath}"/> + <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}"> + <fileset dir="${build.classes.dir}"/> + <manifest> + <attribute name="Main-Class" value="${main.class}"/> + <attribute name="Class-Path" value="${jar.classpath}"/> + </manifest> + </copylibs> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <echo>java -jar "${dist.jar.resolved}"</echo> + </target> + <target name="-post-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="jar" depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/> + <!-- + ================= + EXECUTION SECTION + ================= + --> + <target name="run" depends="init,compile" description="Run a main class."> + <j2seproject1:java> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject1:java> + </target> + <target name="run-single" depends="init,compile-single"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}"/> + </target> + <!-- + ================= + DEBUGGING SECTION + ================= + --> + <target name="-debug-start-debugger" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart name="${debug.class}"/> + </target> + <target name="-debug-start-debuggee" depends="init,compile"> + <j2seproject3:debug> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/> + <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart stopclassname="${main.class}"/> + </target> + <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/> + <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}"/> + </target> + <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/> + <target name="-pre-debug-fix" depends="init"> + <fail unless="fix.includes">Must set fix.includes</fail> + <property name="javac.includes" value="${fix.includes}.java"/> + </target> + <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single"> + <j2seproject1:nbjpdareload/> + </target> + <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/> + <!-- + =============== + JAVADOC SECTION + =============== + --> + <target name="-javadoc-build" depends="init"> + <mkdir dir="${dist.javadoc.dir}"/> + <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true"> + <classpath> + <path path="${javac.classpath}"/> + </classpath> + <sourcepath> + <pathelement location="${src.dir}"/> + </sourcepath> + <packageset dir="${src.dir}" includes="*/**"/> + <fileset dir="${src.dir}" includes="*.java"/> + </javadoc> + </target> + <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build"> + <nbbrowse file="${dist.javadoc.dir}/index.html"/> + </target> + <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/> + <!-- + ========================= + JUNIT COMPILATION SECTION + ========================= + --> + <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile"> + <mkdir dir="${build.test.classes.dir}"/> + </target> + <target name="-pre-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test"> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test"/> + <target name="-pre-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/> + <!-- + ======================= + JUNIT EXECUTION SECTION + ======================= + --> + <target name="-pre-test-run" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run"> + <j2seproject3:junit/> + </target> + <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-report" if="have.tests" depends="init"/> + <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/> + <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/> + <target name="-pre-test-run-single" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <j2seproject3:junit includes="${test.includes}"/> + </target> + <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/> + <!-- + ======================= + JUNIT DEBUGGING SECTION + ======================= + --> + <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}"> + <customize> + <arg line="${test.class}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test"> + <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/> + </target> + <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/> + <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single"> + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> + </target> + <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/> + <!-- + ========================= + APPLET EXECUTION SECTION + ========================= + --> + <target name="run-applet" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject1:java classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject1:java> + </target> + <!-- + ========================= + APPLET DEBUGGING SECTION + ========================= + --> + <target name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject3:debug classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/> + <!-- + =============== + CLEANUP SECTION + =============== + --> + <target name="deps-clean" depends="init" unless="no.deps"> + <ant target="clean" inheritall="false" antfile="${project.JSearchClient}/build.xml"/> + <ant target="clean" inheritall="false" antfile="${project.JavaHelp}/build.xml"/> + </target> + <target name="-do-clean" depends="init"> + <delete dir="${build.dir}"/> + <delete dir="${dist.dir}"/> + </target> + <target name="-post-clean"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/> +</project> diff --git a/JSearchIndexer_nbproject/nbproject/genfiles.properties b/JSearchIndexer_nbproject/nbproject/genfiles.properties new file mode 100644 index 0000000000000000000000000000000000000000..aaa2ff465fe29bf7f4e24c299979e4b5a91fc98d --- /dev/null +++ b/JSearchIndexer_nbproject/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=bb874861 +build.xml.script.CRC32=615eaab7 +build.xml.stylesheet.CRC32=a12b3d02 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=bb874861 +nbproject/build-impl.xml.script.CRC32=cce01068 +nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1 diff --git a/JSearchIndexer_nbproject/nbproject/project.properties b/JSearchIndexer_nbproject/nbproject/project.properties new file mode 100644 index 0000000000000000000000000000000000000000..40f127f6afb9d13338e9c2a4460718d7c4a1282d --- /dev/null +++ b/JSearchIndexer_nbproject/nbproject/project.properties @@ -0,0 +1,83 @@ +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form,**/*.html,GNUmakefile +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/jsearch-indexer.jar +dist.javadoc.dir=${dist.dir}/javadoc +file.reference.JSearch-indexer=../jhMaster/JSearch/indexer +jar.compress=false +javac.classpath=\ + ${reference.JSearchClient.jar}:\ + ${reference.JavaHelp.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.4 +javac.target=1.4 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.JavaHelp=../javahelp_nbproject +project.JSearchClient=../JSearchClient_nbproject +reference.JavaHelp.jar=${project.JavaHelp}/dist/lib/jh-client.jar +reference.JSearchClient.jar=${project.JSearchClient}/dist/jsearch-client.jar +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +src.dir=${file.reference.JSearch-indexer} diff --git a/JSearchIndexer_nbproject/nbproject/project.xml b/JSearchIndexer_nbproject/nbproject/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..e40bc77541084b5911b24156ea38aa728e1deb06 --- /dev/null +++ b/JSearchIndexer_nbproject/nbproject/project.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>JSearchIndexer</name> + <minimum-ant-version>1.6.5</minimum-ant-version> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots/> + </data> + <references xmlns="http://www.netbeans.org/ns/ant-project-references/1"> + <reference> + <foreign-project>JSearchClient</foreign-project> + <artifact-type>jar</artifact-type> + <script>build.xml</script> + <target>jar</target> + <clean-target>clean</clean-target> + <id>jar</id> + </reference> + <reference> + <foreign-project>JavaHelp</foreign-project> + <artifact-type>jar</artifact-type> + <script>build.xml</script> + <target>jar</target> + <clean-target>clean</clean-target> + <id>jar</id> + </reference> + </references> + </configuration> +</project> diff --git a/javahelp_nbproject/build.xml b/javahelp_nbproject/build.xml new file mode 100644 index 0000000000000000000000000000000000000000..c76e88529db92496b2a541d75474ea536c3502c8 --- /dev/null +++ b/javahelp_nbproject/build.xml @@ -0,0 +1,239 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 only, as +published by the Free Software Foundation. Sun designates this +particular file as subject to the "Classpath" exception as provided +by Sun in the LICENSE file that accompanied this code. + +This code is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +version 2 for more details (a copy is included in the LICENSE file that +accompanied this code). + +You should have received a copy of the GNU General Public License version +2 along with this work; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +CA 95054 USA or visit www.sun.com if you need additional information or +have any questions. + --> +<project name="JavaHelp" default="release" basedir="."> + <description>Builds, tests, and runs the project JavaHelp.</description> + <import file="nbproject/build-impl.xml"/> + + <property name="dist.dir" value="dist/lib"/> <!-- XXX --> + + <property name="servlet-jar" value="${basedir}/lib/servlet-api.jar"/> + <available property="servlet-jar-present" file="${servlet-jar}"/> + + <property name="jsp-jar" value="${basedir}/lib/jsp-api.jar"/> + <available property="jsp-jar-present" file="${jsp-jar}"/> + + <property name="jdic-jar" value="${basedir}/lib/jdic.jar"/> + <available property="jdic-jar-present" file="${jdic-jar}"/> + + <property name="tomcat-zip" value="${java.io.tmpdir}/apache-tomcat-5.5.20.zip"/> + <available property="tomcat-zip-present" file="${tomcat-zip}"/> + + <property name="jdic-zip" value="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows.zip"/> + <available property="jdic-zip-present" file="${jdic-zip}"/> + + <target name="-pre-init" + depends="unpack-servlet-jar,unpack-jsp-jar,unpack-jdic-jar"/> + + <target name="release" description="Build the full JavaHelp JARs" + depends="build-jsearch-jars,copy-jsearch-jars,create-javahelp-jars"/> + + + <target name="release-source" description="Build the source zip file"> + <property name="version" value="2.0.05"/> + <mkdir dir="dist"/> + <zip destfile="dist/javahelp2-src-${version}.zip" filesonly="true"> + <zipfileset dir=".." prefix="javahelp2-${version}"> + <and> + <filename name="**/*"/> + <none> + <filename name="**/dist/**/*"/> + <filename name="**/build/**/*"/> + <filename name="www/**/*"/> + <filename name="**/*.jar"/> + <filename name="**/*.zip"/> + </none> + <or> + <contains text="GNU General Public License"/> + <filename name="**/nbproject/*.xml"/> + <filename name="**/nbproject/*.properties"/> + <filename name="**/manifest.mf"/> + <filename name="jhMaster/JavaHelp/javahelp/bin/jhindexer"/> + <filename name="jhMaster/JavaHelp/javahelp/bin/jhsearch"/> + </or> + </and> + </zipfileset> + </zip> + </target> + + <target name="unpack-servlet-jar" unless="servlet-jar-present" depends="download-tomcat-zip"> + <echo message="Unpacking ${tomcat-zip}"/> + <unzip src="${tomcat-zip}" dest="${java.io.tmpdir}/"/> + <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/servlet-api.jar" + tofile="${servlet-jar}"/> + </target> + + <target name="unpack-jsp-jar" depends="download-tomcat-zip" unless="jsp-jar-present"> + <echo message="Copying ${jsp-jar}"/> + <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/jsp-api.jar" + tofile="${jsp-jar}"/> + </target> + + <target name="download-tomcat-zip" unless="tomcat-zip-present"> + <echo message="Downloading Apache Tomcat for servlet-api.jar and jsp-api.jar"/> + <get src="http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip" + dest="${tomcat-zip}"/> + </target> + + <target name="unpack-jdic-jar" description="Download JDIC Jar" unless="jdic-jar-present" + depends="download-jdic-zip"> + <unzip src="${jdic-zip}" dest="${java.io.tmpdir}"/> + <copy failonerror="true" file="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows/jdic.jar" + tofile="${jdic-jar}"/> + </target> + + <target name="download-jdic-zip" unless="jdic-zip-present"> + <echo> +Downloading JDIC. If you get an error like 'Server redirected too many times' download it manually from +https://jdic.dev.java.net/servlets/ProjectDocumentView?documentID=5715&showInfo=true +Then copy the zip file to ${jdic-zip} and re-build + </echo> + <get src="https://jdic.dev.java.net/files/documents/880/5715/jdic-0.8.4.1-bin-windows.zip" + dest="${jdic-zip}"/> + </target> + + <target name="build-jsearch-jars"> + <ant inheritall="false" inheritrefs="false" + antfile="${basedir}/../JSearchIndexer_nbproject/build.xml" target="jar"/> + <ant inheritall="false" inheritrefs="false" + antfile="${basedir}/../JSearchClient_nbproject/build.xml" target="jar"/> + <delete file="../JSearchIndexer_nbproject/BUILD_LOCK"/> + </target> + + <target name="copy-jsearch-jars"> + <property name="jsearch-client-jar" value="../JSearchClient_nbproject/dist/jsearch-client.jar"/> + <available property="jsearch-client-jar-present" file="${jsearch-client-jar}"/> + + <property name="jsearch-indexer-jar" value="../JSearchIndexer_nbproject/dist/jsearch-indexer.jar"/> + <available property="jsearch-indexer-jar-present" file="${jsearch-client-jar}"/> + + <property name="jsearch-jar" value="../JSearchIndexer_nbproject/dist/jsearch.jar"/> + <available property="jsearch-jar-present" file="${jsearch-jar}"/> + + <property name="jsearch-misc-jar" value="../JSearchIndexer_nbproject/dist/jsearch-misc.jar"/> + <available property="jsearch-misc-jar-present" file="${jsearch-misc-jar}"/> + + <fail unless="jsearch-client-jar-present" message="${jsearch-client-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-indexer-jar-present" message="${jsearch-indexer-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-misc-jar-present" message="${jsearch-misc-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-jar-present" message="${jsearch-jar} missing. Build JSearchIndexer and JSearchClient first."/> + + <copy file="${jsearch-indexer-jar}" tofile="${dist.dir}/jsearch-indexer.jar"/> + <copy file="${jsearch-client-jar}" tofile="${dist.dir}/jsearch-client.jar"/> + <copy file="${jsearch-misc-jar}" tofile="${dist.dir}/jsearch-misc.jar"/> + <copy file="${jsearch-jar}" tofile="${dist.dir}/jsearch.jar"/> + </target> + + <target name="create-javahelp-jars"> + <delete file="${dist.dir}/jhbasic.jar"/> + <jar jarfile="${dist.dir}/jhbasic.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + <exclude name="javax/help/plaf/basic/BasicSearch*.class"/> + <exclude name="javax/help/search/**"/> + <include name="javax/help/tagext/NavigatorsTEI.class"/> + <exclude name="javax/help/SearchHit.class"/> + <exclude name="javax/help/SearchTOC*.class"/> + <exclude name="javax/help/JHelpSearchNavigator.class"/> + </fileset> + </jar> + + <delete file="${dist.dir}/jh.jar"/> + <jar jarfile="${dist.dir}/jh.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes"> + <include name="com/sun/java/help/search/**"/> + <exclude name="**/package.html"/> + </fileset> + </jar> + + <copy todir="${basedir}/build/allclasses"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes"> + <include name="com/sun/java/help/search/**"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchIndexer_nbproject/build/classes"> + <include name="*/**"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + + <jar jarfile="${dist.dir}/jhall.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/allclasses"> + <include name="**/*"/> + </fileset> + </jar> + + <mkdir dir="${dist.dir}/../bin"/> + <copy todir="${dist.dir}/../bin"> + <fileset dir="${basedir}/../jhMaster/JavaHelp/javahelp/bin"> + <include name="**"/> + </fileset> + </copy> + + <jar jarfile="${dist.dir}/../bin/jhindexer.jar"> + <manifest> + <attribute name="Class-Path" value="../lib/jhall.jar"/> + <attribute name="Main-Class" value="com.sun.java.help.search.Indexer"/> + </manifest> + </jar> + + <jar jarfile="${dist.dir}/../bin/jhsearch.jar"> + <manifest> + <attribute name="Class-Path" value="../lib/jhall.jar"/> + <attribute name="Main-Class" value="com.sun.java.help.search.QueryEngine"/> + </manifest> + </jar> + </target> + + <available property="post.clean.needed" file="${basedir}/build/allclasses"/> + <target name="-post-clean" if="post.clean.needed"> + <delete dir="dist"/> + <delete dir="${basedir}/build/allclasses"/> + <subant target="clean"> + <dirset dir=".."> + <include name="JSearchClient_nbproject"/> + <include name="JSearchIndexer_nbproject"/> + </dirset> + </subant> + </target> + + <target name="-post-jar"> + <echo> + + +To build the entire javahelp distribution, run the "release" ant target. + + </echo> + </target> +</project> diff --git a/javahelp_nbproject/build.xml.orig b/javahelp_nbproject/build.xml.orig new file mode 100644 index 0000000000000000000000000000000000000000..c99d3f5baeaa921cbb428f68ab0fd8ad35a94a1b --- /dev/null +++ b/javahelp_nbproject/build.xml.orig @@ -0,0 +1,237 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 only, as +published by the Free Software Foundation. Sun designates this +particular file as subject to the "Classpath" exception as provided +by Sun in the LICENSE file that accompanied this code. + +This code is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +version 2 for more details (a copy is included in the LICENSE file that +accompanied this code). + +You should have received a copy of the GNU General Public License version +2 along with this work; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +CA 95054 USA or visit www.sun.com if you need additional information or +have any questions. + --> +<project name="JavaHelp" default="release" basedir="."> + <description>Builds, tests, and runs the project JavaHelp.</description> + <import file="nbproject/build-impl.xml"/> + + <property name="dist.dir" value="dist/lib"/> <!-- XXX --> + + <property name="servlet-jar" value="${basedir}/lib/servlet-api.jar"/> + <available property="servlet-jar-present" file="${servlet-jar}"/> + + <property name="jsp-jar" value="${basedir}/lib/jsp-api.jar"/> + <available property="jsp-jar-present" file="${jsp-jar}"/> + + <property name="jdic-jar" value="${basedir}/lib/jdic.jar"/> + <available property="jdic-jar-present" file="${jdic-jar}"/> + + <property name="tomcat-zip" value="${java.io.tmpdir}/apache-tomcat-5.5.20.zip"/> + <available property="tomcat-zip-present" file="${tomcat-zip}"/> + + <property name="jdic-zip" value="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows.zip"/> + <available property="jdic-zip-present" file="${jdic-zip}"/> + + <target name="-pre-init" + depends="unpack-servlet-jar,unpack-jsp-jar,unpack-jdic-jar"/> + + <target name="release" description="Build the full JavaHelp JARs" + depends="build-jsearch-jars,copy-jsearch-jars,create-javahelp-jars"/> + + + <target name="release-source" description="Build the source zip file"> + <property name="version" value="2.0.05"/> + <mkdir dir="dist"/> + <zip destfile="dist/javahelp2-src-${version}.zip" filesonly="true"> + <zipfileset dir=".." prefix="javahelp2-${version}"> + <and> + <filename name="**/*"/> + <none> + <filename name="**/dist/**/*"/> + <filename name="**/build/**/*"/> + <filename name="www/**/*"/> + <filename name="**/*.jar"/> + <filename name="**/*.zip"/> + </none> + <or> + <contains text="GNU General Public License"/> + <filename name="**/nbproject/*.xml"/> + <filename name="**/nbproject/*.properties"/> + <filename name="**/manifest.mf"/> + </or> + </and> + </zipfileset> + </zip> + </target> + + <target name="unpack-servlet-jar" unless="servlet-jar-present" depends="download-tomcat-zip"> + <echo message="Unpacking ${tomcat-zip}"/> + <unzip src="${tomcat-zip}" dest="${java.io.tmpdir}/"/> + <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/servlet-api.jar" + tofile="${servlet-jar}"/> + </target> + + <target name="unpack-jsp-jar" depends="download-tomcat-zip" unless="jsp-jar-present"> + <echo message="Copying ${jsp-jar}"/> + <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/jsp-api.jar" + tofile="${jsp-jar}"/> + </target> + + <target name="download-tomcat-zip" unless="tomcat-zip-present"> + <echo message="Downloading Apache Tomcat for servlet-api.jar and jsp-api.jar"/> + <get src="http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip" + dest="${tomcat-zip}"/> + </target> + + <target name="unpack-jdic-jar" description="Download JDIC Jar" unless="jdic-jar-present" + depends="download-jdic-zip"> + <unzip src="${jdic-zip}" dest="${java.io.tmpdir}"/> + <copy failonerror="true" file="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows/jdic.jar" + tofile="${jdic-jar}"/> + </target> + + <target name="download-jdic-zip" unless="jdic-zip-present"> + <echo> +Downloading JDIC. If you get an error like 'Server redirected too many times' download it manually from +https://jdic.dev.java.net/servlets/ProjectDocumentView?documentID=5715&showInfo=true +Then copy the zip file to ${jdic-zip} and re-build + </echo> + <get src="https://jdic.dev.java.net/files/documents/880/5715/jdic-0.8.4.1-bin-windows.zip" + dest="${jdic-zip}"/> + </target> + + <target name="build-jsearch-jars"> + <ant inheritall="false" inheritrefs="false" + antfile="${basedir}/../JSearchIndexer_nbproject/build.xml" target="jar"/> + <ant inheritall="false" inheritrefs="false" + antfile="${basedir}/../JSearchClient_nbproject/build.xml" target="jar"/> + <delete file="../JSearchIndexer_nbproject/BUILD_LOCK"/> + </target> + + <target name="copy-jsearch-jars"> + <property name="jsearch-client-jar" value="../JSearchClient_nbproject/dist/jsearch-client.jar"/> + <available property="jsearch-client-jar-present" file="${jsearch-client-jar}"/> + + <property name="jsearch-indexer-jar" value="../JSearchIndexer_nbproject/dist/jsearch-indexer.jar"/> + <available property="jsearch-indexer-jar-present" file="${jsearch-client-jar}"/> + + <property name="jsearch-jar" value="../JSearchIndexer_nbproject/dist/jsearch.jar"/> + <available property="jsearch-jar-present" file="${jsearch-jar}"/> + + <property name="jsearch-misc-jar" value="../JSearchIndexer_nbproject/dist/jsearch-misc.jar"/> + <available property="jsearch-misc-jar-present" file="${jsearch-misc-jar}"/> + + <fail unless="jsearch-client-jar-present" message="${jsearch-client-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-indexer-jar-present" message="${jsearch-indexer-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-misc-jar-present" message="${jsearch-misc-jar} missing. Build JSearchIndexer and JSearchClient first."/> + <fail unless="jsearch-jar-present" message="${jsearch-jar} missing. Build JSearchIndexer and JSearchClient first."/> + + <copy file="${jsearch-indexer-jar}" tofile="${dist.dir}/jsearch-indexer.jar"/> + <copy file="${jsearch-client-jar}" tofile="${dist.dir}/jsearch-client.jar"/> + <copy file="${jsearch-misc-jar}" tofile="${dist.dir}/jsearch-misc.jar"/> + <copy file="${jsearch-jar}" tofile="${dist.dir}/jsearch.jar"/> + </target> + + <target name="create-javahelp-jars"> + <delete file="${dist.dir}/jhbasic.jar"/> + <jar jarfile="${dist.dir}/jhbasic.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + <exclude name="javax/help/plaf/basic/BasicSearch*.class"/> + <exclude name="javax/help/search/**"/> + <include name="javax/help/tagext/NavigatorsTEI.class"/> + <exclude name="javax/help/SearchHit.class"/> + <exclude name="javax/help/SearchTOC*.class"/> + <exclude name="javax/help/JHelpSearchNavigator.class"/> + </fileset> + </jar> + + <delete file="${dist.dir}/jh.jar"/> + <jar jarfile="${dist.dir}/jh.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes"> + <include name="com/sun/java/help/search/**"/> + <exclude name="**/package.html"/> + </fileset> + </jar> + + <copy todir="${basedir}/build/allclasses"> + <fileset dir="${basedir}/build/classes"> + <include name="**/*"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes"> + <include name="com/sun/java/help/search/**"/> + <exclude name="**/package.html"/> + </fileset> + <fileset dir="${basedir}/../JSearchIndexer_nbproject/build/classes"> + <include name="*/**"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + + <jar jarfile="${dist.dir}/jhall.jar" manifest="manifest.mf"> + <fileset dir="${basedir}/build/allclasses"> + <include name="**/*"/> + </fileset> + </jar> + + <mkdir dir="${dist.dir}/../bin"/> + <copy todir="${dist.dir}/../bin"> + <fileset dir="${basedir}/../jhMaster/JavaHelp/javahelp/bin"> + <include name="**"/> + </fileset> + </copy> + + <jar jarfile="${dist.dir}/../bin/jhindexer.jar"> + <manifest> + <attribute name="Class-Path" value="../lib/jhall.jar"/> + <attribute name="Main-Class" value="com.sun.java.help.search.Indexer"/> + </manifest> + </jar> + + <jar jarfile="${dist.dir}/../bin/jhsearch.jar"> + <manifest> + <attribute name="Class-Path" value="../lib/jhall.jar"/> + <attribute name="Main-Class" value="com.sun.java.help.search.QueryEngine"/> + </manifest> + </jar> + </target> + + <available property="post.clean.needed" file="${basedir}/build/allclasses"/> + <target name="-post-clean" if="post.clean.needed"> + <delete dir="dist"/> + <delete dir="${basedir}/build/allclasses"/> + <subant target="clean"> + <dirset dir=".."> + <include name="JSearchClient_nbproject"/> + <include name="JSearchIndexer_nbproject"/> + </dirset> + </subant> + </target> + + <target name="-post-jar"> + <echo> + + +To build the entire javahelp distribution, run the "release" ant target. + + </echo> + </target> +</project> diff --git a/javahelp_nbproject/manifest.mf b/javahelp_nbproject/manifest.mf new file mode 100644 index 0000000000000000000000000000000000000000..7a00441593f89e502fca7bf31fda5526f5a3c2a0 --- /dev/null +++ b/javahelp_nbproject/manifest.mf @@ -0,0 +1,27 @@ +Manifest-Version: 1.0 +Created-By: 1.5.0_08 (Sun Microsystems Inc.) +Specification-Version: 2.0 +Specification-Vendor: Sun Microsystems, Inc +Implementation-Vendor-Id: com.sun +Extension-Name: javax.help +Implementation-Version: 2.0_03 +Implementation-Vendor: Sun Microsystems, Inc + +Name: javax/help/JHelpContentViewer.class +Java-Bean: True + +Name: javax/help/JHelpTOCNavigator.class +Java-Bean: True + +Name: javax/help/ +Package-Sealed: true + +Name: javax/help/JHelpIndexNavigator.class +Java-Bean: True + +Name: javax/help/JHelpSearchNavigator.class +Java-Bean: True + +Name: javax/help/JHelp.class +Java-Bean: True + diff --git a/javahelp_nbproject/nbproject/build-impl.xml b/javahelp_nbproject/nbproject/build-impl.xml new file mode 100644 index 0000000000000000000000000000000000000000..03d65a6227193534efed9e470a35bfd5429f768b --- /dev/null +++ b/javahelp_nbproject/nbproject/build-impl.xml @@ -0,0 +1,547 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** + +For the purpose of easier reading the script +is divided into following sections: + + - initialization + - compilation + - jar + - execution + - debugging + - javadoc + - junit compilation + - junit execution + - junit debugging + - applet + - cleanup + +--> +<project name="JavaHelp-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1"> + <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/> + <!-- + ====================== + INITIALIZATION SECTION + ====================== + --> + <target name="-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-private" depends="-pre-init"> + <property file="nbproject/private/config.properties"/> + <property file="nbproject/private/configs/${config}.properties"/> + <property file="nbproject/private/private.properties"/> + </target> + <target name="-init-user" depends="-pre-init,-init-private"> + <property file="${user.properties.file}"/> + <!-- The two properties below are usually overridden --> + <!-- by the active platform. Just a fallback. --> + <property name="default.javac.source" value="1.4"/> + <property name="default.javac.target" value="1.4"/> + </target> + <target name="-init-project" depends="-pre-init,-init-private,-init-user"> + <property file="nbproject/configs/${config}.properties"/> + <property file="nbproject/project.properties"/> + </target> + <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property"> + <available file="${manifest.file}" property="manifest.available"/> + <condition property="manifest.available+main.class"> + <and> + <isset property="manifest.available"/> + <isset property="main.class"/> + <not> + <equals arg1="${main.class}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition property="manifest.available+main.class+mkdist.available"> + <and> + <istrue value="${manifest.available+main.class}"/> + <isset property="libs.CopyLibs.classpath"/> + </and> + </condition> + <condition property="have.tests"> + <or/> + </condition> + <condition property="have.sources"> + <or> + <available file="${src.impl.dir}"/> + <available file="${src.new.dir}"/> + </or> + </condition> + <condition property="netbeans.home+have.tests"> + <and> + <isset property="netbeans.home"/> + <isset property="have.tests"/> + </and> + </condition> + <condition property="no.javadoc.preview"> + <isfalse value="${javadoc.preview}"/> + </condition> + <property name="run.jvmargs" value=""/> + <property name="javac.compilerargs" value=""/> + <property name="work.dir" value="${basedir}"/> + <condition property="no.deps"> + <and> + <istrue value="${no.dependencies}"/> + </and> + </condition> + <property name="javac.debug" value="true"/> + <property name="javadoc.preview" value="true"/> + <property name="application.args" value=""/> + </target> + <target name="-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init"> + <fail unless="src.impl.dir">Must set src.impl.dir</fail> + <fail unless="src.new.dir">Must set src.new.dir</fail> + <fail unless="build.dir">Must set build.dir</fail> + <fail unless="dist.dir">Must set dist.dir</fail> + <fail unless="build.classes.dir">Must set build.classes.dir</fail> + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> + <fail unless="dist.jar">Must set dist.jar</fail> + </target> + <target name="-init-macrodef-property"> + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-javac"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="srcdir" default="${src.impl.dir}:${src.new.dir}"/> + <attribute name="destdir" default="${build.classes.dir}"/> + <attribute name="classpath" default="${javac.classpath}"/> + <attribute name="debug" default="${javac.debug}"/> + <element name="customize" optional="true"/> + <sequential> + <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </depend> + <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false"> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${javac.compilerargs}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-junit"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="includes" default="**/*Test.java"/> + <sequential> + <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed"> + <batchtest todir="${build.test.results.dir}"/> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper type="glob" from="test-sys-prop.*" to="*"/> + </syspropertyset> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${run.jvmargs}"/> + </junit> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-nbjpda"> + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <attribute name="stopclassname" default=""/> + <sequential> + <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </nbjpdastart> + </sequential> + </macrodef> + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="dir" default="${build.classes.dir}"/> + <sequential> + <nbjpdareload> + <fileset includes="${fix.includes}*.class" dir="@{dir}"/> + </nbjpdareload> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-debug"> + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="classname" default="${main.class}"/> + <attribute name="classpath" default="${debug.classpath}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xnoagent"/> + <jvmarg value="-Djava.compiler=none"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-java"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="classname" default="${main.class}"/> + <element name="customize" optional="true"/> + <sequential> + <java fork="true" classname="@{classname}" dir="${work.dir}"> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="${run.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper type="glob" from="run-sys-prop.*" to="*"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-presetdef-jar"> + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> + <jar jarfile="${dist.jar}" compress="${jar.compress}"> + <j2seproject1:fileset dir="${build.classes.dir}"/> + </jar> + </presetdef> + </target> + <target name="init" depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar"/> + <!-- + =================== + COMPILATION SECTION + =================== + --> + <target name="deps-jar" depends="init" unless="no.deps"/> + <target name="-pre-pre-compile" depends="init,deps-jar"> + <mkdir dir="${build.classes.dir}"/> + </target> + <target name="-pre-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources"> + <j2seproject3:javac/> + <copy todir="${build.classes.dir}"> + <fileset dir="${src.impl.dir}" excludes="${build.classes.excludes}"/> + <fileset dir="${src.new.dir}" excludes="${build.classes.excludes}"/> + </copy> + </target> + <target name="-post-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/> + <target name="-pre-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + </target> + <target name="-post-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/> + <!-- + ==================== + JAR BUILDING SECTION + ==================== + --> + <target name="-pre-pre-jar" depends="init"> + <dirname property="dist.jar.dir" file="${dist.jar}"/> + <mkdir dir="${dist.jar.dir}"/> + </target> + <target name="-pre-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available"> + <j2seproject1:jar/> + </target> + <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class"> + <j2seproject1:jar manifest="${manifest.file}"/> + </target> + <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" unless="manifest.available+main.class+mkdist.available"> + <j2seproject1:jar manifest="${manifest.file}"> + <j2seproject1:manifest> + <j2seproject1:attribute name="Main-Class" value="${main.class}"/> + </j2seproject1:manifest> + </j2seproject1:jar> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <pathconvert property="run.classpath.with.dist.jar"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> + </pathconvert> + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> + </target> + <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available"> + <property name="build.classes.dir.resolved" location="${build.classes.dir}"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert property="jar.classpath" pathsep=" "> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" name="copylibs" classpath="${libs.CopyLibs.classpath}"/> + <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}"> + <fileset dir="${build.classes.dir}"/> + <manifest> + <attribute name="Main-Class" value="${main.class}"/> + <attribute name="Class-Path" value="${jar.classpath}"/> + </manifest> + </copylibs> + <echo>To run this application from the command line without Ant, try:</echo> + <property name="dist.jar.resolved" location="${dist.jar}"/> + <echo>java -jar "${dist.jar.resolved}"</echo> + </target> + <target name="-post-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="jar" depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/> + <!-- + ================= + EXECUTION SECTION + ================= + --> + <target name="run" depends="init,compile" description="Run a main class."> + <j2seproject1:java> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject1:java> + </target> + <target name="run-single" depends="init,compile-single"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}"/> + </target> + <!-- + ================= + DEBUGGING SECTION + ================= + --> + <target name="-debug-start-debugger" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart name="${debug.class}"/> + </target> + <target name="-debug-start-debuggee" depends="init,compile"> + <j2seproject3:debug> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/> + <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init"> + <j2seproject1:nbjpdastart stopclassname="${main.class}"/> + </target> + <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/> + <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}"/> + </target> + <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/> + <target name="-pre-debug-fix" depends="init"> + <fail unless="fix.includes">Must set fix.includes</fail> + <property name="javac.includes" value="${fix.includes}.java"/> + </target> + <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single"> + <j2seproject1:nbjpdareload/> + </target> + <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/> + <!-- + =============== + JAVADOC SECTION + =============== + --> + <target name="-javadoc-build" depends="init"> + <mkdir dir="${dist.javadoc.dir}"/> + <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true"> + <classpath> + <path path="${javac.classpath}"/> + </classpath> + <sourcepath> + <pathelement location="${src.impl.dir}"/> + <pathelement location="${src.new.dir}"/> + </sourcepath> + <packageset dir="${src.impl.dir}" includes="*/**"/> + <packageset dir="${src.new.dir}" includes="*/**"/> + <fileset dir="${src.impl.dir}" includes="*.java"/> + <fileset dir="${src.new.dir}" includes="*.java"/> + </javadoc> + </target> + <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build"> + <nbbrowse file="${dist.javadoc.dir}/index.html"/> + </target> + <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/> + <!-- + ========================= + JUNIT COMPILATION SECTION + ========================= + --> + <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile"> + <mkdir dir="${build.test.classes.dir}"/> + </target> + <target name="-pre-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test"> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test"/> + <target name="-pre-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"> + <customize> + <patternset includes="${javac.includes}"/> + </customize> + </j2seproject3:javac> + <copy todir="${build.test.classes.dir}"/> + </target> + <target name="-post-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/> + <!-- + ======================= + JUNIT EXECUTION SECTION + ======================= + --> + <target name="-pre-test-run" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run"> + <j2seproject3:junit/> + </target> + <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-report" if="have.tests" depends="init"/> + <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/> + <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/> + <target name="-pre-test-run-single" if="have.tests" depends="init"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <j2seproject3:junit includes="${test.includes}"/> + </target> + <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single"> + <fail if="tests.failed">Some tests failed; see details above.</fail> + </target> + <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/> + <!-- + ======================= + JUNIT DEBUGGING SECTION + ======================= + --> + <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}"> + <customize> + <arg line="${test.class}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test"> + <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/> + </target> + <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/> + <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single"> + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> + </target> + <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/> + <!-- + ========================= + APPLET EXECUTION SECTION + ========================= + --> + <target name="run-applet" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject1:java classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject1:java> + </target> + <!-- + ========================= + APPLET DEBUGGING SECTION + ========================= + --> + <target name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject3:debug classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject3:debug> + </target> + <target name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/> + <!-- + =============== + CLEANUP SECTION + =============== + --> + <target name="deps-clean" depends="init" unless="no.deps"/> + <target name="-do-clean" depends="init"> + <delete dir="${build.dir}"/> + <delete dir="${dist.dir}"/> + </target> + <target name="-post-clean"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/> +</project> diff --git a/javahelp_nbproject/nbproject/genfiles.properties b/javahelp_nbproject/nbproject/genfiles.properties new file mode 100644 index 0000000000000000000000000000000000000000..b645296f628140f109a4c62c3ba3b1bc23a8ae90 --- /dev/null +++ b/javahelp_nbproject/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=bc1e27e0 +build.xml.script.CRC32=079caa17 +build.xml.stylesheet.CRC32=a12b3d02 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=74a01f5f +nbproject/build-impl.xml.script.CRC32=357bfc33 +nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1 diff --git a/javahelp_nbproject/nbproject/project.properties b/javahelp_nbproject/nbproject/project.properties new file mode 100644 index 0000000000000000000000000000000000000000..1ce731494ee4e01f60aadd9082d91aaee8ba7129 --- /dev/null +++ b/javahelp_nbproject/nbproject/project.properties @@ -0,0 +1,86 @@ +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form,**/*.html +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist/lib +dist.jar=${dist.dir}/jh-client.jar +dist.javadoc.dir=${dist.dir}/javadoc +file.reference.jdic.jar=lib/jdic.jar +file.reference.jsp-api.jar=lib/jsp-api.jar +file.reference.servlet-api.jar=lib/servlet-api.jar +file.reference.space-javahelp=.. +file.reference.src-impl=../jhMaster/JavaHelp/src/impl +file.reference.src-new=../jhMaster/JavaHelp/src/new +jar.compress=false +javac.classpath=\ + ${file.reference.servlet-api.jar}:\ + ${file.reference.jsp-api.jar}:\ + ${file.reference.jdic.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.4 +javac.target=1.4 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +src.impl.dir=${file.reference.src-impl} +src.new.dir=${file.reference.src-new} diff --git a/javahelp_nbproject/nbproject/project.xml b/javahelp_nbproject/nbproject/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ebc689964053776f61389d5de16cdea61f542d0 --- /dev/null +++ b/javahelp_nbproject/nbproject/project.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>JavaHelp</name> + <minimum-ant-version>1.6.5</minimum-ant-version> + <source-roots> + <root id="src.impl.dir"/> + <root id="src.new.dir"/> + </source-roots> + <test-roots/> + </data> + </configuration> +</project> diff --git a/jhMaster/GNUmakefile b/jhMaster/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..9622291379ae025a523723643c91d93505eb4140 --- /dev/null +++ b/jhMaster/GNUmakefile @@ -0,0 +1,44 @@ +# +# @(#)GNUmakefile 1.14 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +all: + java -fullversion + cd JSearch ; $(MAKE) all + cd JavaHelp/build ; $(MAKE) all + cd JavaHelp/demos ; $(MAKE) all validate + +release: all docs + +docs: all + cd JavaHelp/build ; $(MAKE) docs + cd JavaHelp/doc/jhug; $(MAKE) all + cd JavaHelp/doc/public-spec/V2.0; $(MAKE) all + +clean: + cd JSearch ; $(MAKE) clean + cd JavaHelp/build ; $(MAKE) clean + cd JavaHelp/demos ; $(MAKE) clean diff --git a/jhMaster/JSearch/GNUmakefile b/jhMaster/JSearch/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..b926cbfbbecd071a9a39e77572a6fd1d3092874c --- /dev/null +++ b/jhMaster/JSearch/GNUmakefile @@ -0,0 +1,92 @@ +# +# @(#)GNUmakefile 1.31 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# This is a bare-bones Makefile just to build the engine from scratch. +# +# It should be replaced by a real Makefile. + +TOP := $(shell pwd) + +ifeq ($(JHHOMEWS),) +TOP=$(shell pwd) +JHHOMEWS=$(TOP)/../JavaHelp +endif + +CP=/bin/cp -f + +PKG = com/sun/java/help/search +JARS = lib/jsearch-misc.jar \ + lib/jsearch-client.jar \ + lib/jsearch-indexer.jar \ + lib/jsearch.jar + +all: lib ${JARS} binaries demos + +clean: + rm -rf lib + cd client ; $(MAKE) clean + cd indexer ; $(MAKE) clean + cd misc ; $(MAKE) clean + +# simple scripts + +binaries: jhindexer jhsearch + - chmod a+x jhindexer + - chmod a+x jhsearch + +# a test case + +demos: demos/holidays + +demos/holidays: + mkdir -p demos/holidays + cd demos/holidays ; export to ; to=`pwd` ; \ + cd ${JHHOMEWS}/demos/hs/holidays ; \ + tar cFFf - hol | ( cd $${to} ; tar xvf - ) + + +## JAR files + +lib/jsearch.jar: lib/jsearch-client.jar lib/jsearch-indexer.jar lib/jsearch-misc.jar + /bin/csh -f jarinto FORCE lib/jsearch.jar \ + lib/jsearch-client.jar lib/jsearch-indexer.jar lib/jsearch-misc.jar + +lib/jsearch-misc.jar: FORCE + cd misc ; $(MAKE) JHHOMEWS=$(JHHOMEWS) jar + +lib/jsearch-client.jar: lib/jsearch-misc.jar FORCE + cd client ; $(MAKE) jar + +lib/jsearch-indexer.jar: lib/jsearch-misc.jar FORCE + cd indexer ; $(MAKE) jar + +## Directories + +lib: + mkdir -p lib + +FORCE: diff --git a/jhMaster/JSearch/client/GNUmakefile b/jhMaster/JSearch/client/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..09ad6f29677bb880b6ad9fef828709ff11a936cb --- /dev/null +++ b/jhMaster/JSearch/client/GNUmakefile @@ -0,0 +1,47 @@ +# +# @(#)GNUmakefile 1.8 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +CLIENT_SRC := $(shell find . -name 'SCCS*' -prune -o -name '*.java' -print) +CLIENT_CLASSES=$(CLIENT_SRC:%.java=classes/%.class) + +RM=/bin/rm + +jar: ../lib/jsearch-client.jar + +../lib/jsearch-client.jar: $(CLIENT_CLASSES) + cd classes ; \ + jar cf ../../lib/jsearch-client.jar com + +classes/%.class: %.java classes + export CLASSPATH ; CLASSPATH=../lib/jsearch-misc.jar:. ; \ + javac -d classes $< + +classes: + mkdir classes + +clean: + $(RM) -rf classes diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java b/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..150baa3ebe49c34a7f42d2f8a151bfa6aa5ac71f --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java @@ -0,0 +1,177 @@ +/* + * @(#)BitBuffer.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 2/17/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +/* + BitBuffer's client has to stick to a usage protocol: + + - start with new or cleared BitBuffer + - do appends for a while + - finish w/ close() + + */ + +package com.sun.java.help.search; +import java.io.*; + +class BitBuffer +{ + private static final int InitSize = 256; + private static final int NBits = 32; + private static final int BitsInByte = 8; + private static final int BytesInInt = 4; + + private int _avail = NBits; + private int _word = 0; + private int _free = 0; + private int _size = InitSize; + private int[] _array = new int[InitSize]; + + public void close() + { + if (_avail < NBits) + store(_word << _avail); + else + _avail = 0; + } + + public void write(DataOutput out) throws IOException + { + for (int i = 0; i < _free - 1; i++) + out.writeInt(_array[i]); + int word = _array[_free - 1]; + int bytes = BytesInInt - _avail/BitsInByte; + int shift = NBits; + while (bytes-- > 0) + out.writeByte((word >>> (shift -= BitsInByte)) & 0xFF); + } + + public void clear() + { + _word = 0; + _avail = NBits; + _free = 0; + } + + public int byteCount() { + return _free*BytesInInt - _avail/BitsInByte; + } + + public int bitCount() { + return NBits*_free - _avail; + } + + public void setFrom(BitBuffer rhs) + { + _word = rhs._word; + _avail = rhs._avail; + if ((_free = rhs._free) > _size) + _array = new int[_size = rhs._free]; + System.arraycopy(rhs._array, 0, _array, 0, _free); + } + + private void growArray(int newSize) + { + int[] newArray = new int[_size = newSize]; + System.arraycopy(_array, 0, newArray, 0, _free); + _array = newArray; + } + + private void store(int value) + { + if (_free == _size) + growArray(_size * 2); + _array[_free++] = value; + } + + public void append(int bit) + { + _word = (_word << 1) | bit; + if (--_avail == 0) + { + store(_word); + _word = 0; + _avail = NBits; + } + } + + public void append(int source, int kBits) + { + if (kBits < _avail) + { + _word = (_word << kBits) | source; + _avail -= kBits; + } + else if (kBits > _avail) + { + int leftover = kBits - _avail; + store((_word << _avail) | (source >>> leftover)); + _word = source; + _avail = NBits - leftover; + } + else + { + store((_word << kBits) | source); + _word = 0; + _avail = NBits; + } + } + + public void concatenate(BitBuffer bb) + { + if (NBits*(_size - _free) + _avail < bb.bitCount()) + growArray(_free + bb._free + 1); + + if (_avail == 0) + { + System.arraycopy(bb._array, 0, _array, _free, bb._free); + _avail = bb._avail; + _free += bb._free; + } + else + { + int tp = _free - 1; // target + int sp = 0; // source + do { + _array[tp++] |= bb._array[sp] >>> (NBits - _avail); + _array[tp] = bb._array[sp++] << _avail; + } + while (sp < bb._free); + _free += bb._free; + if ((_avail += bb._avail) >= NBits) + { + _avail -= NBits; + _free--; + } + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Block.java b/jhMaster/JSearch/client/com/sun/java/help/search/Block.java new file mode 100644 index 0000000000000000000000000000000000000000..6790c6f7874f552b173e77ca659657ce04209574 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Block.java @@ -0,0 +1,109 @@ +/* + * @(#)Block.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) Block.java 1.3 - last change made 03/20/98 + */ + +package com.sun.java.help.search; + +import java.io.IOException; + +/** + * This class represents a Block of information in DictBlock + * + * @author Jacek Ambroziak + * @author Roger D. Brinkley + * @version 1.3 03/20/98 + */ + +class Block +{ + public static final int HEADERLEN = 8; + public static final int IDLEN = 4; + public int number; + public boolean isLeaf = true; + public int free = 0; + public byte[] data = null; + + public Block(int blocksize) { + data = new byte[blocksize - HEADERLEN]; + } + + public void setBlockNumber(int n) { + number = n; + } + + public void setFree(int free) { + free = free; + } + + public int integerAt(int i) { + return ((((((data[i++]&0xFF)<<8) + |data[i++]&0xFF)<<8) + |data[i++]&0xFF)<<8) + |data[i]&0xFF; + } + + public void setIntegerAt(int i, int value) + { + for (int j = i + 3; j >= i; j--, value >>>= 8) + data[j] = (byte)(value & 0xFF); + } + + public static Block readIn(RAFFile in, Block block) + throws IOException + { + debug("readIn"); + block.number = in.readInt(); + int twoFields = in.readInt(); + block.isLeaf = (twoFields & 0x80000000) != 0; + block.free = twoFields & 0x7FFFFFFF; + in.readFully(block.data); + return block; + } + + public void writeOut(RAFFile out) throws IOException + { + out.writeInt(number); + out.writeInt(free | (isLeaf ? 0x80000000 : 0)); + out.write(data); + } + + /** + * Debug code + */ + + private static boolean debug=false; + private static void debug(String msg) { + if (debug) { + System.err.println("Block: "+msg); + } + } + +} + diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..25864b7705a884be3e73faa9bfcd4ad7328182b5 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java @@ -0,0 +1,33 @@ +/* + * @(#)BlockFactory.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.search; + +interface BlockFactory +{ + public Block makeBlock(); +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e249c0880e9507e39774e62fecc63bd3c1aa54c0 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java @@ -0,0 +1,249 @@ +/* + * @(#)BlockManager.java 1.14 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) BlockManager.java 1.5 - last change made 03/20/98 + */ +package com.sun.java.help.search; + +import java.io.*; + +/** + * This class manages Block(s) of information in DictBlock + * + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + * @version 1.5 03/20/98 + */ + +class BlockManager +{ + /* the Dict file factory. It handles both retrieval and caching. + */ + private static RAFFileFactory factory = RAFFileFactory.create(); + + //!! not sure if the double list is still correct after many changes + private class BlockDescriptor + { + public Block block = null; + public boolean lock = false; + public boolean modf = false; + public int prev = 0; + public int next = 0; + + public void reset() + { + lock = modf = false; + block = null; + } + } + + private RAFFile file; + private long blockSize; + private boolean update; + final private int nBlocksLimit = 64; + private int blockTableSize; + private BlockDescriptor[] blockTab; + private int nBlocks = 0; + private int oldest = 0; + private int newest = 0; + private BlockFactory bfactory = null; + private final static int INCR = 256; // size increment + private Block dummy; + + public BlockManager(BlockManagerParameters params, + boolean update, + BlockFactory bfactory) throws IOException + { + this.bfactory = bfactory; + this.update = update; + // params.readState(); + blockSize = (long)params.getBlockSize(); + debug(params.getURL().toString()); + file = factory.get(params.getURL(), update); + debug(file.toString()); + dummy = bfactory.makeBlock(); + if (file.length() == 0 && update) { + dummy.setBlockNumber(0); + writeBlock(dummy); + } + blockTableSize = (int)(file.length()/blockSize); + blockTab = new BlockDescriptor[blockTableSize]; + mapBlock(0, new BlockDescriptor(), bfactory.makeBlock()); + } + + public void lockBlock(int blNum) { + blockTab[blNum].lock = true; + } + + public void unlockBlock(int blNum) { + blockTab[blNum].lock = false; + } + + public void setModified(int blNum) { + blockTab[blNum].modf = true; + } + + public void close() throws IOException + { + if (update) + for (int i = 0; i < blockTableSize; i++) + if (blockTab[i] != null && blockTab[i].modf) + writeBlock(blockTab[i].block); + file.close(); + } + + public Block accessBlock(int blockNumber) throws Exception + { + if (blockTab[blockNumber] != null) + moveToFront(blockNumber); + else if (nBlocks < nBlocksLimit) + mapBlock(blockNumber, new BlockDescriptor(), bfactory.makeBlock()); + else + remapSomeBlock(blockNumber); + return blockTab[blockNumber].block; + } + + public Block getNewBlock() throws Exception + { + int number = (int)(file.length()/blockSize); + if (number > blockTableSize - 1) + { + BlockDescriptor[] newArray = + new BlockDescriptor[blockTableSize + INCR]; + System.arraycopy(blockTab, 0, newArray, 0, blockTableSize); + blockTab = newArray; + blockTableSize += INCR; + } + if (nBlocks < nBlocksLimit) + { + Block bl = bfactory.makeBlock(); + bl.setBlockNumber(number); + writeBlock(bl); + addDescriptor(bl, number, new BlockDescriptor()); + } + else + { + dummy.setBlockNumber(number); + writeBlock(dummy); + remapSomeBlock(number); + } + return blockTab[number].block; + } + + private void mapBlock(int blockNumber, BlockDescriptor desc, Block block) + throws IOException + { + file.seek(blockSize * blockNumber); + Block.readIn(file, block); + addDescriptor(block, blockNumber, desc); + } + + private void addDescriptor(Block block, int blockNumber, + BlockDescriptor desc) + { + blockTab[blockNumber] = desc; + desc.block = block; + blockTab[desc.prev = newest].next = blockNumber; + newest = blockNumber; + nBlocks++; + } + + private void remapSomeBlock(int blockNumber) throws Exception + { + int index = oldest; + while (blockTab[index].lock && index != newest) + index = blockTab[index].next; + if (blockTab[index].lock) + throw new Exception("everything locked"); + if (blockTab[index].modf) + writeBlock(blockTab[index].block); + + nBlocks--; + Block reused = blockTab[index].block; + // delete from double-linked list + if (index == oldest) + oldest = blockTab[index].next; + else if (index == newest) + newest = blockTab[index].prev; + else + { + blockTab[blockTab[index].next].prev = blockTab[index].prev; + blockTab[blockTab[index].prev].next = blockTab[index].next; + } + blockTab[index].reset(); + mapBlock(blockNumber, blockTab[index], reused); + // System.err.println("reuse "+index+" --> "+blockNumber+" "+nBlocks); + blockTab[index] = null; + } + + private void moveToFront(int index) + { + if (index == oldest) + { + oldest = blockTab[index].next; + blockTab[index].prev = newest; + blockTab[newest].next = index; + newest = index; + } + else if (index != newest) + { + blockTab[blockTab[index].next].prev = blockTab[index].prev; + blockTab[blockTab[index].prev].next = blockTab[index].next; + blockTab[index].prev = newest; + blockTab[newest].next = index; + newest = index; + } + } + + public void writeBlock(Block bl) throws IOException + { + file.seek(blockSize * bl.number); + bl.writeOut(file); + } + + public void mapBlocks(BlockProcessor processor) throws IOException + { + long nBlocks = file.length()/blockSize; + Block block = bfactory.makeBlock(); + file.seek(0); + for (int i = 0; i < nBlocks; i++) + processor.process(Block.readIn(file, block)); + } + + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("Block Manager: "+msg); + } + } + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..44bdeed2e46eda88fbcae5a0a76bb0c1e1ca1244 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java @@ -0,0 +1,112 @@ +/* + * @(#)BlockManagerParameters.java 1.11 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) BlockManagerParameters.java 1.3 - last change made 03/17/98 + */ + +package com.sun.java.help.search; + +import java.net.URL; + +/** + * This class contains the parameters necessary for Dict BlockManager + * + * @date 2/3/98 + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + */ + +class BlockManagerParameters extends DBPartParameters +{ + private URL url; + + private int blockSize; + protected int root; + + public BlockManagerParameters(Schema schema, String partName) + throws Exception + { + super(schema, partName); + url = schema.getURL(partName); + debug(url.toString()); + } + + public boolean readState() + { + if (parametersKnown()) + { + blockSize = integerParameter("bs"); + // System.err.println("blockSize " + blockSize); + root = integerParameter("rt"); + return true; + } + else + return false; + } + + public void updateSchema(String params) { + super.updateSchema("bs="+blockSize+" rt="+root+" fl=-1 " + params); + } + + public BlockManagerParameters(URL url, int blockSize, int root) + { + this.url = url; + this.blockSize = blockSize; + this.root = root; + } + + public URL getURL() { + return url; + } + + public int getBlockSize() { + return blockSize; + } + + public void setBlockSize(int size) { + blockSize = size; + } + + public int getRootPosition() { + return root; + } + + public void setRoot(int root) { + this.root = root; + } + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("Block Manager Parameters: "+msg); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..0b1494f079fc48c73b9831b6d99825a08b295098 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java @@ -0,0 +1,33 @@ +/* + * @(#)BlockProcessor.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.search; + +interface BlockProcessor +{ + public void process(Block block); +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java new file mode 100644 index 0000000000000000000000000000000000000000..c84f8467aa76ac716dc33f585948e044b8e1fca3 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java @@ -0,0 +1,327 @@ +/* + * @(#)BtreeDict.java 1.14 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) BtreeDict.java 1.5 - last change made 03/18/98 + */ + +package com.sun.java.help.search; + +import java.io.*; + +/** + * @version 1.5 03/18/98 + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + */ + +public class BtreeDict +{ + protected static final int ENTHEADERLEN = 6; + protected static final int BLOCKSIZE = 2048; + protected static final int DATALEN = BLOCKSIZE - Block.HEADERLEN; + protected static final int MaxKeyLength = 255; + //!!! Careful with that number, Eugene + protected static final int lastPtrIndex = 508; + + protected class DictBlock extends Block + { + public DictBlock() { + super(BLOCKSIZE); + } + + public int free() { + return free + firstEntry(); + } + + public int numberOfEntries() { + return integerAt(0); + } + + public int nthPointer(int n) { + return integerAt(4*(n + 1)); + } + + public int getChildIdx(int index) { + return nthPointer(lastPtrIndex - index); + } + + public int entryKeyLength(int i) { + return data[i] & 0xFF; + } + + public int entryCompression(int i) { + return data[i + 1] & 0xFF; + } + + public int entryID(int i) { + return integerAt(i + 2); + } + + public int entryLength(int entry) { + return ENTHEADERLEN + entryKeyLength(entry); + } + + public int entryKey(int entry) { + return entry + ENTHEADERLEN; + } + + public int firstEntry() { + return 4; + } + + public int nextEntry(int entry) { + return entry + entryLength(entry); + } + + public void restoreKeyInBuffer(int entry, byte[] buffer) + { + int howMany = entryKeyLength(entry); + int where = entryCompression(entry); + int from = entryKey(entry); + while (howMany-- > 0) + buffer[where++] = data[from++]; + } + + public String restoreKey(int entry, byte[] buffer) + { + int howMany = entryKeyLength(entry); + int where = entryCompression(entry); + int from = entryKey(entry); + while (howMany-- > 0) + buffer[where++] = data[from++]; + String string = null; + try { + string = new String(buffer, 0, where, "UTF8"); + } catch (java.io.UnsupportedEncodingException e) { + // ignore + } + return string; + } + + public String findID(int id) throws Exception + { + byte[] buffer = new byte[MaxKeyLength]; + int freeSpace = free(); + for (int ent = firstEntry(); ent < freeSpace; ent = nextEntry(ent)) + if (entryID(ent) == id) // found + return restoreKey(ent, buffer); + else + restoreKeyInBuffer(ent, buffer); + throw new Exception("ID not found in block"); + } + + protected void setBlockNumbers(final int[] blocks) + { + for (int e = firstEntry(); e < free; e = nextEntry(e)) + blocks[entryID(e)] = number; + } + + /* + protected void doMap(BtreeDict owner, EntryProcessor processor) + throws Exception + { + byte[] buffer = new byte[MaxKeyLength]; + final int freeSpace = free(); + int entryPtr = firstEntry(); + if (isLeaf) + while (entryPtr < freeSpace) { + processor.processEntry(restoreKey(entryPtr, buffer), + entryID(entryPtr)); + entryPtr = nextEntry(entryPtr); + } + else + { + owner.lock(this); + int entryIdx = 0; + while (entryPtr < freeSpace) { + owner.accessBlock(getChildIdx(entryIdx)).doMap(owner,processor); + processor.processEntry(restoreKey(entryPtr, buffer), + entryID(entryPtr)); + entryPtr = nextEntry(entryPtr); + ++entryIdx; + } + owner.accessBlock(getChildIdx(entryIdx)).doMap(owner, processor); + owner.unlock(this); + } + } + */ + } + // end of internal class + + protected BlockManager blockManager; + protected int root; + protected int[] blocks; + + protected BtreeDict() {/*empty*/} + + public BtreeDict(BtreeDictParameters params) throws Exception + { + init(params, false, new BlockFactory() { + public Block makeBlock() { return new DictBlock(); } + }); + blocks = new int[params.getFreeID()]; + setBlocks(blocks); + } + + public int fetch(String key) throws Exception + { + // System.err.println("fetching " + key); + byte[] bytes = key.getBytes("UTF8"); + byte[] Key = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, Key, 0, bytes.length); + Key[bytes.length] = 0; // sentinel + return find(accessBlock(root), Key); + } + + public String fetch(int conceptID) throws Exception { + return findID(blocks[conceptID], conceptID); + } + + public void close() throws Exception { + blockManager.close(); + } + + protected void init(BtreeDictParameters params, boolean update, + BlockFactory bfactory) throws Exception + { + blockManager = new BlockManager(params, update, bfactory); + root = params.getRootPosition(); + } + + protected void lock(Block bl) { + blockManager.lockBlock(bl.number); + } + + protected void unlock(Block bl) { + blockManager.unlockBlock(bl.number); + } + + protected DictBlock accessBlock(int index) throws Exception { + return (DictBlock)blockManager.accessBlock(index); + } + + protected DictBlock child(DictBlock bl, int index) throws Exception { + return accessBlock(bl.getChildIdx(index)); + } + + private String findID(int blNum, int id) throws Exception { + return accessBlock(blNum).findID(id); + } + + private int find(DictBlock bl, byte[] key, int index) throws Exception { + return bl.isLeaf ? 0 : find(child(bl, index), key); + } + + private int find(DictBlock bl, byte[] key) throws Exception + { + int inputKeyLen = key.length - 1; + int entryPtr = bl.firstEntry(); + int freeSpace = bl.free(); + int nCharsEqual = 0; + int compression = 0; + + for (int entryIdx = 0;;) + { + if (entryPtr == freeSpace) + return find(bl, key, bl.numberOfEntries()); + else if (compression == nCharsEqual) + { + int keyLen = bl.entryKeyLength(entryPtr); + int keyPtr = bl.entryKey(entryPtr), i; + for (i = 0; + i < keyLen && key[nCharsEqual] == bl.data[keyPtr + i]; + i++) + ++nCharsEqual; + if (i == keyLen) + { + if (nCharsEqual == inputKeyLen) + return bl.entryID(entryPtr); + } + else if ((key[nCharsEqual]&0xFF) < (bl.data[keyPtr + i]&0xFF)) + return find(bl, key, entryIdx); + } + else if (compression < nCharsEqual) // compression dropped + return find(bl, key, entryPtr == freeSpace + ? bl.numberOfEntries() : entryIdx); + do { + entryPtr = bl.nextEntry(entryPtr); + ++entryIdx; + } + while (bl.entryCompression(entryPtr) > nCharsEqual); + compression = bl.entryCompression(entryPtr); + } + } + + private void setBlocks(final int[] blocks) throws Exception + { + long start = System.currentTimeMillis(); + blockManager.mapBlocks(new BlockProcessor() { + public void process(Block block) { + ((DictBlock)block).setBlockNumbers(blocks); + } + }); + debug((System.currentTimeMillis() - start) + " msec; TMAP"); + } + + /* + can go to Full + public void map(EntryProcessor processor) throws Exception { + accessBlock(root).doMap(this, processor); + } + */ + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("BtreeDict: "+msg); + } + } + + public static void main(String[] args) + { + try { + Schema schema = new Schema(null, args[0], false); + BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP"); + BtreeDict source = new BtreeDict(params); + /* + source.map(new EntryProcessor() { + public void processEntry(String key, int id) { + System.out.println(key + " " + id); + } + }); + */ + } + catch (Exception e) { + System.err.println(e); + e.printStackTrace(); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..2a99f415a1629fcb3429eb91e9cc69a294ededb9 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java @@ -0,0 +1,205 @@ +/* + * @(#)BtreeDictParameters.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) BtreeDictParameters.java 1.5 - last change made 04/01/98 + */ + +package com.sun.java.help.search; + +import java.net.URL; +import java.net.URLConnection; +import java.util.StringTokenizer; +import java.io.*; + +/** + * + * @version 1.5 04/01/98 + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + */ + +class BtreeDictParameters extends BlockManagerParameters +{ + private int id1; + private String dirName; + + // some form of this is needed for starting new DBs + public BtreeDictParameters(URL fileName, int blockSize, int root, + int freeID) + { + super(fileName, blockSize, root); + id1 = freeID; + } + + public BtreeDictParameters(Schema schema, String partName) + throws Exception + { + super(schema, partName); + } + + public boolean readState() + { + if (super.readState()) + { + setFreeID(integerParameter("id1")); + return true; + } + else + return false; + } + + public void writeState() { + } + + public int getFreeID() { + return id1; + } + + public final void setFreeID(int id) { + id1 = id; + } + + private void setDirName(String dirName) { + this.dirName = dirName; + } + + public static BtreeDictParameters create(URL dirName) + { + try { + URL url = new URL(dirName, "TMAP"); + BtreeDictParameters bdp = null; + // new BtreeDictParameters(url, 2048, 0, 1); + bdp.setDirName(dirName.getFile()); + return bdp; + } catch (java.net.MalformedURLException e) { + System.out.println ("Couldn't create " + dirName + File.separator + "TMAP"); + } + return null; + } + + public static BtreeDictParameters read(String dir, URL hsBase) + throws Exception + { + URL baseURL=null, url, tmapURL=null; + URLConnection connect; + BufferedReader in; + File file; + + int blockSize = -1; + int rootPosition = -1; + int freeID = -1; + + if (hsBase == null) { + file = new File(dir); + if (file.exists()) { + // On Win32 we need to convert all "\" to "/" + if (File.separatorChar != '/') { + dir = dir.replace(File.separatorChar, '/'); + } + // Make sure the last character is a file separator + if (dir.lastIndexOf(File.separatorChar) + != dir.length() - 1) { + dir = dir.concat(File.separator); + } + debug ("file:" + dir); + // Use a file protocol + baseURL = new URL("file", "", dir); + } else { + // Assume that some protocol was specified and try it + baseURL = new URL(dir); + } + } + + // Read the SCHEMA data + if (hsBase != null) { + url = new URL(hsBase, dir + "/SCHEMA"); + } else { + url = new URL(baseURL, "SCHEMA"); + } + connect = url.openConnection(); + + in = new BufferedReader + (new InputStreamReader(connect.getInputStream())); + + // This needs to be replaced with our XML Parser + String line; + do { + line = in.readLine(); + } + while (!line.startsWith("TMAP")); + in.close(); + StringTokenizer tokens = new StringTokenizer(line, " ="); + tokens.nextToken(); // skip over 'TMAP' + while (tokens.hasMoreTokens()) + { + String token = tokens.nextToken(); + if (token.equals("bs")) + blockSize = Integer.parseInt(tokens.nextToken()); + else if (token.equals("rt")) + rootPosition = Integer.parseInt(tokens.nextToken()); + else if (token.equals("id1")) + freeID = Integer.parseInt(tokens.nextToken()); + } + + if (hsBase != null) { + tmapURL = new URL(hsBase, dir + "/TMAP"); + } else { + tmapURL = new URL(baseURL, "TMAP"); + } + BtreeDictParameters bdp = null; + // new BtreeDictParameters(tmapURL, blockSize, rootPosition, freeID); + + if (hsBase == null) { + bdp.setDirName(Utilities.URLDecoder(baseURL.getFile())); + } + return bdp; + } + + public void updateSchema() { + super.updateSchema("id1="+id1+" id2=1"); + } + + public void write() throws java.io.IOException + { + FileWriter out = new FileWriter(dirName + "/SCHEMA"); + out.write("JavaSearch 1.0\n"); + out.write("TMAP bs=2048 rt="+root+" fl=-1 id1="+id1+" id2=1\n"); + out.close(); + } + + /** + * For printf debugging. + */ + private static boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("BtreeDictParamters: " + str); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java new file mode 100644 index 0000000000000000000000000000000000000000..38c7f6c19d0cebca50459e0032ed39eccdbfee73 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java @@ -0,0 +1,60 @@ +/* + * @(#)ByteArrayDecompressor.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class ByteArrayDecompressor extends Decompressor +{ + private byte[] _array; + private int _index; + private int _index0; + + public ByteArrayDecompressor(byte[] array, int index) { + initReading(array, index); + } + + public void initReading(byte[] array, int index) + { + _array = array; + _index = _index0 = index; + initReading(); + } + + public int bytesRead() { + return _index - _index0; + } + + protected int getNextByte() throws Exception { + return _array[_index++] & 0xFF; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java new file mode 100644 index 0000000000000000000000000000000000000000..c551c2e95c722740d2edc17e902b462dcd0a143f --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java @@ -0,0 +1,201 @@ +/* + * @(#)Compressor.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 2/17/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; + +class Compressor +{ + private static final int NBits = 32; + private static final int BeginK = 5; + + private BitBuffer _buffer = new BitBuffer(); + + public void write(DataOutput out) throws IOException { + _buffer.write(out); + } + + public int byteCount() { + return _buffer.byteCount(); + } + + public void clear() { + _buffer.clear(); + } + + public void concatenate(Compressor other) { + _buffer.concatenate(other._buffer); + } + + public void encode(IntegerArray pos, int k) + { + int power = 1 << k, n1 = 0; + for (int i = 0; i < pos.cardinality(); i++) + { + int n2 = pos.at(i) >>> k; + int rem = pos.at(i) % power; + if (n2 != n1) + { + int min = n1, a = n1; + int lev = 0, power2 = 1; + if (n2 > n1) + for (int max = n1; max < n2; a >>>= 1, power2 <<= 1, lev++) + if ((a & 1) != 0) + min -= power2; + else + max += power2; + else + for ( ; min > n2; a >>>= 1, power2 <<= 1, lev++) + if ((a & 1) != 0) + min -= power2; + // lev 0s, 1, lev bits of (n2 - min) plus following value + // no 'V' symbol needed here + if (lev*2 + 1 + k <= NBits) + _buffer.append((1<<lev | (n2 - min)) << k | rem, lev*2+1+k); + else + { + if (lev*2 + 1 <= NBits) + _buffer.append(1 << lev | (n2 - min), lev*2 + 1); + else + { + _buffer.append(0, lev); + _buffer.append(1 << lev | (n2 - min), lev + 1); + } + _buffer.append(rem, k); + } + n1 = n2; + } + else + _buffer.append(rem | power, k + 1); // 'V' + value + } + _buffer.append(2 | n1 & 1, 3); // marking end + _buffer.close(); + } + + public void encode(IntegerArray pos, IntegerArray len, int k, int k2) + { + int power = 1 << k, n1 = 0; + for (int i = 0; i < pos.cardinality(); i++) + { + int n2 = pos.at(i) >>> k; + int rem = pos.at(i) % power; + if (n2 != n1) + { + int min = n1, a = n1; + int lev = 0, power2 = 1; + if (n2 > n1) + for (int max = n1; max < n2; a >>>= 1, power2 <<= 1, lev++) + if ((a & 1) != 0) + min -= power2; + else + max += power2; + else + for ( ; min > n2; a >>>= 1, power2 <<= 1, lev++) + if ((a & 1) != 0) + min -= power2; + // lev 0s, 1, lev bits of (n2 - min) plus following value + if (lev*2 + 1 + k <= NBits) + _buffer.append((1<<lev | (n2 - min)) << k | rem, lev*2+1+k); + else + { + if (lev*2 + 1 <= NBits) + _buffer.append(1 << lev | (n2 - min), lev*2 + 1); + else + { + _buffer.append(0, lev); + _buffer.append(1 << lev | (n2 - min), lev + 1); + } + _buffer.append(rem, k); + } + _buffer.append(len.at(i), k2); + n1 = n2; + } + else + _buffer.append((rem|power)<<k2 | len.at(i), k+k2+1); // 'V' + v1,v2 + } + _buffer.append(2 | n1 & 1, 3); // marking end + _buffer.close(); + } + + // k: starting value for minimization + public int minimize(IntegerArray array, int startK) + { + BitBuffer saved = new BitBuffer(); + int minK = startK; + _buffer.clear(); + encode(array, startK); + int min = _buffer.bitCount(); // init w/ first value + saved.setFrom(_buffer); + + _buffer.clear(); + encode(array, startK + 1); + + if (_buffer.bitCount() < min) + { + int k = startK + 1; + do { + saved.setFrom(_buffer); + min = _buffer.bitCount(); + minK = k; + _buffer.clear(); + encode(array, ++k); + } + while (_buffer.bitCount() < min); + } + else // try smaller values through 1 + for (int k = startK - 1; k > 0; k--) + { + _buffer.clear(); + encode(array, k); + if (_buffer.bitCount() < min) + { + saved.setFrom(_buffer); + min = _buffer.bitCount(); + minK = k; + } + else + break; + } + + _buffer.setFrom(saved); + return minK; + } + + public int compressAscending(IntegerArray array) + { + IntegerArray differences = new IntegerArray(array.cardinality()); + array.toDifferences(differences); + return minimize(differences, BeginK); + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java b/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..f40ee6badc9ac81dbbd6a178e866fb5e44e126fa --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java @@ -0,0 +1,40 @@ +/* + * @(#)CompressorIterator.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +interface CompressorIterator +{ + public void value(int value); +} + diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java new file mode 100644 index 0000000000000000000000000000000000000000..d78023ed6c3f8f923386910ae19c90625963e18c --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java @@ -0,0 +1,150 @@ +/* + * @(#)ConceptData.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class ConceptData +{ + private final byte _query; + private final byte _nColumns; + private final byte _role; + private final int _concept; + private int _conceptLength; + private final int _proximity; + private final double _penalty; + private ConceptData _next; + + private static final int ProxPerTerm = 100; + + public ConceptData(int id, int role, double score, int query, int nColumns) + { + _query = (byte)query; + _nColumns = (byte)nColumns; + _concept = id; + _proximity = nColumns * ProxPerTerm; + _role = (byte)role; + _penalty = score; + _next = null; + } + + public int getConcept() { + return _concept; + } + + public double getPenalty() { + return _penalty; + } + + public int getConceptLength() { + return _conceptLength; + } + + public byte getRole() { + return _role; + } + + public byte getQuery() { + return _query; + } + + public byte getNColumns() { + return _nColumns; + } + + public double getScore() { + return _penalty; + } + + public ConceptData getNext() { + return _next; + } + + public int getQueryMask() { + return (_next != null ? _next.getQueryMask() : 0) | (1 << _query); + } + + public void setConceptLength(int length) + { + _conceptLength = length; + if (_next != null) + _next.setConceptLength(length); + } + + public void setNext(ConceptData next) { + _next = next; + } + + boolean cEquals(ConceptData other) { + return _concept == other._concept; + } + + boolean crEquals(ConceptData other) { + return _concept == other._concept && _role == other._role; + } + + boolean crqEquals(ConceptData other) { + return _concept == other._concept && _role == other._role && + _query == other._query; + } + + void addLast(ConceptData other) + { + if (_next != null) + _next.addLast(other); + else + _next = other; + } + + boolean compareWith(ConceptData other) { + return _concept < other._concept + || cEquals(other) && _role < other._role + || crEquals(other) && _penalty < other._penalty; + } + + public void runBy(Query[] queries) + { + ConceptData cd = this; + do + queries[cd._query].updateEstimate(cd._role, cd._penalty); + while ((cd = cd._next) != null); + } + + public void generateFillers(RoleFiller[] array, int pos) + { + if (array[_query] != RoleFiller.STOP) // 'prohibited' + (new RoleFiller(_nColumns, this, _role, pos, pos + _proximity)) + .use(array, _query); + if (_next != null) + _next.generateFillers(array, pos); + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..465be3692032c4f388a94793178f518e9d80b3ba --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java @@ -0,0 +1,112 @@ +/* + * @(#)ConceptGroupGenerator.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.InputStream; + +class ConceptGroupGenerator implements CompressorIterator +{ + private static final int NConceptsInGroup = + DocumentCompressor.NConceptsInGroup; + private static final int BitsInLabel = + DocumentCompressor.BitsInLabel; + + private int _last; + private ConceptData[] _table; + private Decompressor _bits; + private int _k1; + private final int _k2 = BitsInLabel; + private ConceptData _cData; + + public ConceptGroupGenerator() + { + _k1 = 0; + _table = new ConceptData[NConceptsInGroup]; + _last = 0; + _bits = null; + } + + public ConceptGroupGenerator(byte[] bytes, int index, int k) + { + _k1 = k; + _table = new ConceptData[NConceptsInGroup]; + _last = 0; + _bits = new ByteArrayDecompressor(bytes, index); + } + + public void init(byte[] bytes, int index, int k) + { + _k1 = k; + _bits = new ByteArrayDecompressor(bytes, index); + _last = 0; + for (int i = 0; i < NConceptsInGroup; i++) + _table[i] = null; + } + + public void addTerms(int index, ConceptData terms) { + _table[index] = terms; + } + + public int decodeConcepts(int k, int shift, int[] concepts) throws Exception { + return _bits.ascendingDecode(k, shift, concepts); + } + + public int position() { + return _last; + } + + public void value(int value) { + _last += value; + } + + boolean next() throws Exception + { + try { + while (_bits.readNext(_k1, this)) + if ((_cData = _table[_bits.read(_k2)]) != null) + return true; + return false; + } + catch (Exception e) { + e.printStackTrace(); + System.err.println(_bits); + System.err.println(_table); + throw e; + } + } + + public void generateFillers(RoleFiller[] array) { + _cData.generateFillers(array, _last); + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java new file mode 100644 index 0000000000000000000000000000000000000000..4cc01d45ebfaa1833f8ee15520d264a71c2eb94d --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java @@ -0,0 +1,61 @@ +/* + * @(#)ConceptList.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class ConceptList implements NonnegativeIntegerGenerator, CompressorIterator +{ + private ByteArrayDecompressor _list; + private byte _k; + private int _value = 0; + + public ConceptList(byte[] array, int index) + { + _k = array[index]; + _list = new ByteArrayDecompressor(array, index + 1); + } + + // callback + public void value(int val) { + _value += val; + } + + public int first() throws Exception { + _value = 0; + return _list.readNext(_k, this) ? _value : END; + } + + public int next() throws Exception { + return _list.readNext(_k, this) ? _value : END; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java new file mode 100644 index 0000000000000000000000000000000000000000..a171c12658173f127a5e5d25006aefbce4a05773 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java @@ -0,0 +1,167 @@ +/* + * @(#)ConceptLocation.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 3/5/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class ConceptLocation +{ + private int _concept; + private int _begin; + private int _end; + + private abstract class ConceptLocationSorter + { + abstract public boolean smallerThan(ConceptLocation a, ConceptLocation b); + // part of quicksearch + private int partition(ConceptLocation[] array, int p, int r) + { + ConceptLocation x = array[p]; + int i = p - 1, j = r + 1; + while (true) + { + while (smallerThan(x, array[--j])) + ; + while (smallerThan(array[++i], x)) + ; + if (i < j) + { + ConceptLocation t = array[i]; + array[i] = array[j]; + array[j] = t; + } + else + return j; + } + } + + public void quicksort(ConceptLocation[] array, int p, int r) + { + if (p < r) + { + int q = partition(array, p, r); + quicksort(array, p, q); + quicksort(array, q + 1, r); + } + } + } + + private class ConceptSorter extends ConceptLocationSorter + { + public boolean smallerThan(ConceptLocation a, ConceptLocation b) { + return a._concept < b._concept; + } + } + + private class PositionSorter extends ConceptLocationSorter + { + public boolean smallerThan(ConceptLocation a, ConceptLocation b) { + return a._begin < b._begin || a._begin == b._begin && a._end < b._end; + } + } + // sorter by concept ID + private static ConceptLocationSorter _cComp; + // sorter by position + private static ConceptLocationSorter _pComp; + + private ConceptLocation() + { + _cComp = new ConceptSorter(); + _pComp = new PositionSorter(); + } + + static { new ConceptLocation(); } + + public ConceptLocation(int conceptID, int begin, int end) + { + _concept = conceptID; + _begin = begin; + _end = end; + } + + public boolean equals(ConceptLocation other) { + return _concept==other._concept&&_begin==other._begin&&_end==other._end; + } + + public void setConcept(int concept) { + _concept = concept; + } + + public int getConcept() { + return _concept; + } + + public int getBegin() { + return _begin; + } + + public int getEnd() { + return _end; + } + + public int getLength() { + return _end - _begin; + } + + public static void sortByConcept(ConceptLocation[] array, int i1, int i2) { + _cComp.quicksort(array, i1, i2 - 1); + } + + public static void sortByPosition(ConceptLocation[] array, int i1, int i2) { + _pComp.quicksort(array, i1, i2 - 1); + } + + public void print() { + System.out.println(_concept+"\t"+_begin+"\t"+_end); + } + + public static void main(String[] args) + { + int limit = 30, b; + ConceptLocation[] array = new ConceptLocation[limit]; + for (int i = 0; i < limit; i++) + array[i] = new ConceptLocation((int)(Math.random()*1000), + b = (int)(Math.random()*1000), + b + (int)(Math.random()*10)); + for (int i = 0; i < limit; i++) + array[i].print(); + ConceptLocation.sortByConcept(array, 0, limit); + System.out.println("----------------------------------"); + for (int i = 0; i < limit; i++) + array[i].print(); + ConceptLocation.sortByPosition(array, 0, limit); + System.out.println("----------------------------------"); + for (int i = 0; i < limit; i++) + array[i].print(); + } +} + diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..3da0b24796ed5aa6088b5e7e1ce7cf50e34f4632 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java @@ -0,0 +1,68 @@ +/* + * @(#)DBPartParameters.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @version 1.5 03/18/98 + * @author Jacek R. Ambroziak + */ + +package com.sun.java.help.search; + +import java.util.Hashtable; +import java.net.URL; + +public class DBPartParameters +{ + protected Schema _schema; + private String _partName; + private Hashtable _parameters; + + protected DBPartParameters() {} + + public DBPartParameters(Schema schema, String partName) + { + _schema = schema; + _partName = partName; + _parameters = schema.parameters(partName); + } + + protected boolean parametersKnown() { + return _parameters != null; + } + + protected void updateSchema(String parameters) { + _schema.update(_partName, parameters); + } + + public int integerParameter(String name) { + return Integer.parseInt(((String)_parameters.get(name))); + } + + public URL getURL() throws Exception { + return _schema.getURL(_partName); + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java new file mode 100644 index 0000000000000000000000000000000000000000..acf51c9d1532a17eb68a5057b67f7ae54bc0b7e5 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java @@ -0,0 +1,185 @@ +/* + * @(#)Decompressor.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +abstract class Decompressor +{ + private static final int BitsInByte = 8; + private static final int NBits = 32; + + private int _readByte; + private int _toRead = 0; + private int _path = 0; + + abstract protected int getNextByte() throws Exception; + + protected void initReading() { + _toRead = 0; + } + + private int countZeroes() throws Exception + { + for (int count = 0;; _readByte = getNextByte(), _toRead = BitsInByte) + while (_toRead-- > 0) + if ((_readByte & (1 << _toRead)) != 0) + return count; + else + ++count; + } + + // reads 1 bit; returns non-0 for bit "1" + private int read() throws Exception + { + if (_toRead-- > 0) + return _readByte & (1 << _toRead); + else + { // get next word + _toRead = BitsInByte - 1; + return (_readByte = getNextByte()) & 0x80; + } + } + + public int read(int kBits) throws Exception + { + int shift = BitsInByte - _toRead; + if (kBits <= _toRead) + return ((_readByte<<shift) & 0xFF) >>> (shift + (_toRead-=kBits)); + else + { + int result = _toRead > 0 + ? ((_readByte << shift) & 0xFF) >>> shift + : 0; + for (kBits -= _toRead; kBits >= BitsInByte; kBits -= BitsInByte) + result = (result << BitsInByte) | getNextByte(); + if (kBits > 0) + return (result << kBits) + | ((_readByte = getNextByte()) >>> (_toRead = BitsInByte - kBits)); + else + { + _toRead = 0; + return result; + } + } + } + + public void beginIteration() { + _path = 0; + } + + public boolean readNext(int k, CompressorIterator it) throws Exception + { + if (read() != 0) + { + it.value(_path | read(k)); + return true; + } + else + for (int count = 1;; _readByte = getNextByte(), _toRead = BitsInByte) + while (_toRead-- > 0) + if ((_readByte & (1 << _toRead)) != 0) + { + int saved = _path; + _path = ((_path >>> (k + count) << count) | read(count)) << k; + if (_path != saved) + { + it.value(_path | read(k)); + return true; + } + else + return false; + } + else + ++count; + } + + public void decode(int k, IntegerArray array) throws Exception + { + for (int path = 0;;) + if (read() != 0) + array.add(path | read(k)); + else + { + int count = countZeroes() + 1; + int saved = path; + path = ((path >>> (k + count) << count) | read(count)) << k; + if (path != saved) // convention for end + array.add(path | read(k)); + else + break; + } + } + + public void ascDecode(int k, IntegerArray array) throws Exception + { + for (int path = 0, start = 0;;) + if (read() != 0) + array.add(start += path | read(k)); + else + { + int count = countZeroes() + 1; + int saved = path; + path = ((path >>> (k + count) << count) | read(count)) << k; + if (path != saved) // convention for end + array.add(start += path | read(k)); + else + break; + } + } + + public int ascendingDecode(int k, int start, int[] array) throws Exception + { + int path = 0, index = 0; + LOOP: + while (true) + if (read() != 0) + array[index++] = (start += path | read(k)); + else + for (int cnt = 0;; _readByte = getNextByte(), _toRead = BitsInByte) + while (_toRead-- > 0) + if ((_readByte & (1 << _toRead)) != 0) + { + ++cnt; + int Path = ((path >>> (k + cnt) << cnt) | read(cnt)) << k; + if (Path != path) + { + array[index++] = (start += (path = Path) | read(k)); + continue LOOP; + } + else + return index; + } + else + ++cnt; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..af87dc844e131f7127fe69888f21fe2c9eaa7427 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java @@ -0,0 +1,108 @@ +/* + * @(#)DefaultSearchEngine.java 1.21 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) DefaultSearchEngine.java 1.21 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.net.*; +import java.text.*; +import java.util.Vector; +import java.util.Hashtable; +import java.util.EventListener; +import java.util.Locale; +import javax.help.search.*; +import com.sun.java.help.search.*; +import java.security.InvalidParameterException; + +/** + * DefaultSearchEngine is the default search engine. + * + * Search results are returned through SearchEvents to + * listeners that + * register with a SearchEngine instance through the Search Query. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.21 10/30/06 + * + * @see javax.help.search.SearchEngine + * @see javax.help.search.SearchEvent + * @see javax.help.search.SearchListener + */ +public class DefaultSearchEngine extends SearchEngine { + + private String urldata; // just for debugging really + protected QueryEngine qe; + + /** + * Create a DefaultSearchEngine + */ + public DefaultSearchEngine(URL base, Hashtable params) + throws InvalidParameterException + { + super(base, params); + + debug("Loading Search Database"); + debug(" base: "+base); + debug(" params: "+params); + + // Load the Query Engine and Search DB here + try { + urldata = (String) params.get("data"); + qe = new QueryEngine(urldata, base); + } catch (Exception e) { + if (debugFlag) { + System.err.println(" =========== "); + e.printStackTrace(); + } + throw new InvalidParameterException(); + } + } + + public SearchQuery createQuery() { + return new DefaultSearchQuery(this); + } + + protected QueryEngine getQueryEngine() { + return qe; + } + + /** + * For printf debugging. + */ + private static final boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("DefaultSearchEngine: " + str); + } + } + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..e2357c4954aacd3a7387ae897a94eccb8858c8de --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java @@ -0,0 +1,141 @@ +/* + * @(#)DefaultSearchQuery.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) DefaultSearchQuery.java 1.7 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.net.*; +import java.text.*; +import java.util.Vector; +import java.util.Hashtable; +import java.util.EventListener; +import java.util.Locale; +import javax.help.search.*; +import com.sun.java.help.search.*; +import java.security.InvalidParameterException; + +/** + * DefaultSearchQuery is the query using the default search engine. + * + * Search results are returned through SearchEvents to + * listeners that register with this instance. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.7 10/30/06 + * + * @see javax.help.search.SearchEngine + * @see javax.help.search.SearchQuery + * @see javax.help.search.SearchEvent + * @see javax.help.search.SearchListener + */ +public class DefaultSearchQuery extends SearchQuery implements Runnable { + + private Thread thread = null; + private DefaultSearchEngine dhs; + + /** + * Create a DefaultSearchEngine + */ + public DefaultSearchQuery(SearchEngine hs) { + super(hs); + if (hs instanceof DefaultSearchEngine) { + dhs = (DefaultSearchEngine) hs; + } + } + + + /** + * Starts the search. The implementation is up to subclasses of SearchEngine. + * This method will invoke searchStarted on SearchListeners. + * @exception IllegalArgumentException The parameters are not + * understood by this engine + * @exception IllegalStateException There is an active search in progress in this instance + */ + public void start(String searchparams, Locale l) + throws IllegalArgumentException, IllegalStateException + { + debug ("Starting Search"); + if (isActive()) { + throw new IllegalStateException(); + } + + // initialization + super.start(searchparams, l); + + // Actually do the search + thread = new Thread(this, "QueryThread"); + thread.start(); + } + + /** + * Stops the search. The implementation is up to the subcalsses of + * SearchEngine. This method will invoke searchStopped on + * SearchListeners. + */ + public void stop() throws IllegalArgumentException, IllegalStateException { + debug ("Stop Search"); + // Can no longer do a stop + // Let it continue to operate until it's completed + // on it's own. This is due to to the enherent problem + // with thread.stop + } + + public boolean isActive() { + if (thread == null) { + return false; + } + return thread.isAlive(); + } + + public void run() throws IllegalArgumentException{ + QueryEngine qe = dhs.getQueryEngine(); + try { + qe.processQuery(searchparams, l, this); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException(); + } + fireSearchFinished(); + thread = null; + } + + /** + * For printf debugging. + */ + private static final boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("DefaultSearchQuery: " + str); + } + } + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java new file mode 100644 index 0000000000000000000000000000000000000000..e6fa13becf0b4590590e35dd24d8b48c4ffb73de --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java @@ -0,0 +1,385 @@ +/* + * @(#)DocumentCompressor.java 1.16 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; + +class DocumentCompressor +{ + static public final int NConceptsInGroup = 16; + static public final int BitsInLabel = 4; + static public final int DefaultSize = 32; + + private int _nGroups; + private int _nExtents; + private int _freeComp; + private int _sizeComp = DefaultSize; + private int _kk; + private Compressor _currentCompressor = null; + private Compressor[] _compressors = new Compressor[DefaultSize]; + private Compressor _kCompr = new Compressor(); + private Compressor _lCompr = new Compressor(); + private Compressor _mCompr = new Compressor(); + private Compressor _posCompressor = new Compressor(); + private IntegerArray _kTable = new IntegerArray();// k's for the series + private IntegerArray _lTable = new IntegerArray();// lengths of the C/P groups + private IntegerArray _maxConcepts = new IntegerArray();// maximal concepts in CP + private IntegerArray _concepts = new IntegerArray(); + private IntegerArray _documents = new IntegerArray(); + private IntegerArray _offsets = new IntegerArray(); + private IntegerArray _titles = new IntegerArray(); + + private IntegerArray _positions = new IntegerArray(); + private IntegerArray _labels = new IntegerArray(); + private RandomAccessFile _posFile; + + public DocumentCompressor(URL url) throws Exception + { + URL posURL = new URL(url, "POSITIONS"); + if (isFileURL(posURL)) + { + // this code should not be repeated + try { + URL offURL = new URL(url, "OFFSETS"); + URLConnection connect = offURL.openConnection(); + BufferedInputStream in = + new BufferedInputStream(connect.getInputStream()); + + int k1 = in.read(); + StreamDecompressor sddocs = new StreamDecompressor(in); + sddocs.ascDecode(k1, _documents); + int k2 = in.read(); + StreamDecompressor sdoffsets = new StreamDecompressor(in); + sdoffsets.ascDecode(k2, _offsets); + // decompress titles' ids table + int k3 = in.read(); + StreamDecompressor sdtitles = new StreamDecompressor(in); + sdtitles.decode(k3, _titles); + in.close(); + } + catch (java.io.FileNotFoundException e) {;} + _posFile = + new RandomAccessFile(Utilities.URLDecoder(posURL.getFile()), + "rw"); + } + else + throw new IOException(); + } + + private boolean isFileURL(URL url) { + return url.getProtocol().equalsIgnoreCase("file"); + } + + public void close(String indexFile) throws java.io.IOException + { + _posFile.close(); + writeOutOffsets(indexFile); + } + + public void compress(int docID, int titleID, + ConceptLocation[] locations, int count, + ConceptLocation[] extents, int extCount) + throws java.io.IOException + { + long start = System.currentTimeMillis(); + encode(locations, count, NConceptsInGroup); + if (extCount > 0) + encodeExtents(extents, extCount); + finalizeEncoding(); + debug((System.currentTimeMillis() - start) + " msec proc"); + + int nBytes = byteCount(); + + start = System.currentTimeMillis(); + long currentEnd = _posFile.length(); + _documents.add(docID); + _offsets.add((int)currentEnd); + _titles.add(titleID); + _posFile.seek(currentEnd); + writeOut(_posFile); + debug((System.currentTimeMillis() - start) + " msec file"); + debug("nGroups = " + _nGroups); + } + + private void writeOutOffsets(String indexFile) throws java.io.IOException + { + Compressor documents = new Compressor(); + int k1 = documents.compressAscending(_documents); + Compressor offsets = new Compressor(); + int k2 = offsets.compressAscending(_offsets); + Compressor titles = new Compressor(); + int k3 = titles.minimize(_titles, 8); // the starting k + int nBytes = documents.byteCount(); + RandomAccessFile out = new RandomAccessFile(indexFile, "rw"); + out.seek(0); // position at beginning + out.write(k1); + documents.write(out); + out.write(k2); + offsets.write(out); + out.write(k3); + titles.write(out); + out.close(); + } + + private void encode(ConceptLocation[] locations, int count, int nConcepts) + { + final int initK = 4; + // first sort by concept only + ConceptLocation.sortByConcept(locations, 0, count); + // using the fact that concepts are already sorted + // count of groups of 'nConcepts' + // go for differences directly + clear(); + int conceptCounter = 0; + int fromIndex = 0; + int prevMax = 0; + int last = locations[0].getConcept(); // init w/ first ID + nextCompressor(); + _concepts.add(last); + for (int i = 0;;) + { + for (; i < count && locations[i].getConcept() == last; i++) + locations[i].setConcept(conceptCounter); + if (i == count) + { + if (_concepts.cardinality() > 0) + { + ++_nGroups; + _kTable.add(_currentCompressor.minimize(_concepts, initK)); + } + encodePositions(locations, fromIndex, i, BitsInLabel); + break; + } + else // new concept (group?) + { + if (++conceptCounter == nConcepts) + { + ++_nGroups; + // we are looking at the beginning of a new group + // last is maximal for the group just finished + // it won't be stored in concepts array but maxConcepts + _concepts.popLast(); + _maxConcepts.add(last - prevMax); + prevMax = last; + _kTable.add(_currentCompressor.minimize(_concepts, initK)); + encodePositions(locations, fromIndex, i, BitsInLabel); + fromIndex = i; + nextCompressor(); + _concepts.clear(); + conceptCounter = 0; + } + _concepts.add(locations[i].getConcept() - last); + last = locations[i].getConcept(); + } + } + } + + private void encodePositions(ConceptLocation[] locations, int from, int to, + int cK) + { + final int initK = 3; + int lastPos, k; + // sort in place by positions only + ConceptLocation.sortByPosition(locations, from, to); + _positions.clear(); + _labels.clear(); + _positions.add(lastPos = locations[from].getBegin()); + _labels.add(locations[from].getConcept()); // now: a label + // skip duplicates + for (int i = from, j = from + 1; j < to; j++) + if (locations[i].equals(locations[j]) == false) + { + i = j; + _positions.add(locations[i].getBegin() - lastPos); + lastPos = locations[i].getBegin(); + _labels.add(locations[i].getConcept()); // now: a label + } + // first find k by minimizing just positions w/o labels + _kTable.add(k = _posCompressor.minimize(_positions, initK)); + _posCompressor.clear(); + _posCompressor.encode(_positions, _labels, k, cK); + _currentCompressor.concatenate(_posCompressor); + } + + private void encodeExtents(ConceptLocation[] extents, int extCount) + { + // side effects: + // 'k3' added to _kTable + // a number of compressors populated: header + lengths' lists + final int initK = 4; + int c = 0; + IntegerArray concepts = new IntegerArray(extCount); // differences + IntegerArray lengths = new IntegerArray(); + IntegerArray kTable = new IntegerArray(); + IntegerArray lTable = new IntegerArray(); + // reserve a compressor for concatenated tables + nextCompressor(); + Compressor extentsHeader = _currentCompressor; + for (int i = 0; i < extCount; i++) + if (extents[i].getConcept() != c) + { + if (c != 0) + { + _nExtents++; + nextCompressor(); + kTable.add(_currentCompressor.minimize(lengths, initK)); + lTable.add(_currentCompressor.byteCount()); + } + concepts.add(extents[i].getConcept() - c); + c = extents[i].getConcept(); + lengths.clear(); + lengths.add(extents[i].getLength()); + } + else + lengths.add(extents[i].getLength()); + // last table of lengths + nextCompressor(); + kTable.add(_currentCompressor.minimize(lengths, initK)); + lTable.add(_currentCompressor.byteCount()); + Compressor compressor1 = new Compressor(); + kTable.add(compressor1.minimize(lTable, initK)); + Compressor compressor2 = new Compressor(); + kTable.add(compressor2.minimize(concepts, initK)); + _kTable.add(extentsHeader.minimize(kTable, initK)); // k3 + extentsHeader.concatenate(compressor1); + extentsHeader.concatenate(compressor2); + } + + private void finalizeEncoding() + { + if (_nGroups > 1) + { + // if extents follow C/P groups we need the length of the last group + int limit = _nExtents > 0 ? _freeComp : _freeComp - 1; + for (int j = 0; j < limit; j++) // length of last not saved + _lTable.add(_compressors[j].byteCount()); + + _kTable.add(_mCompr.minimize(_maxConcepts, 3)); + _kTable.add(_lCompr.minimize(_lTable, 3)); + _kk = _kCompr.minimize(_kTable, 3); + _kCompr.concatenate(_lCompr); + _kCompr.concatenate(_mCompr); + } + else if (_nGroups == 1 && _nExtents > 0) + { + // length of the single C/P group packed with k-s + _kTable.add(_compressors[0].byteCount()); + _kk = _kCompr.minimize(_kTable, 3); + } + debug("compr: "+byteCount()+" bytes"); + } + + private void writeOut(DataOutput out) throws java.io.IOException + { + if (_nExtents == 0) + if (_nGroups > 1) + { + out.write(0x80 | _kk); + _kCompr.write(out); // concatenated k,l,m + for (int j = 0; j < _freeComp; j++) + _compressors[j].write(out); + } + else // single group, no extents; code: 00 + { + out.write(_kTable.at(0)); // k1 + out.write(_kTable.at(1)); // k2 + _compressors[0].write(out); // C/P + } + else // extents + { + out.write((_nGroups > 1 ? 0xC0 : 0x40) | _kk); + _kCompr.write(out); + for (int j = 0; j < _freeComp; j++) + _compressors[j].write(out); + } + } + + private Compressor nextCompressor() + { + if (_freeComp == _sizeComp) + { + Compressor[] newArray = new Compressor[_sizeComp *= 2]; + System.arraycopy(_compressors, 0, newArray, 0, _freeComp); + _compressors = newArray; + } + if (_compressors[_freeComp] == null) + _compressors[_freeComp] = new Compressor(); + return _currentCompressor = _compressors[_freeComp++]; + } + + private int byteCount() + { + if (_nGroups == 1 && _nExtents == 0) + return 2 + _compressors[0].byteCount(); + else + { + int result = 1; // initial kk + result += _kCompr.byteCount(); + for (int j = 0; j < _freeComp; j++) + result += _compressors[j].byteCount(); + return result; + } + } + + private void clear() + { + _nGroups = 0; + _nExtents = 0; + _kTable.clear(); + _lTable.clear(); + _concepts.clear(); + _maxConcepts.clear(); + _kCompr.clear(); + _lCompr.clear(); + _mCompr.clear(); + for (int i = 0; i < _sizeComp; i++) + if (_compressors[i] != null) + _compressors[i].clear(); + _freeComp = 0; + _currentCompressor = null; + } + /** + * Debug code + */ + + private static boolean debug=false; + private static void debug(String msg) { + if (debug) { + System.err.println("DocumentCompressor: "+msg); + } + } + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java b/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java new file mode 100644 index 0000000000000000000000000000000000000000..9c54ed61a16a78f8759a2906e9c6200d5357e6a4 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java @@ -0,0 +1,59 @@ +/* + * @(#)Entry.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.search; + +class Entry +{ + public byte[] key; + public int id; + public int block = -1; + + public Entry(byte[] key, int length, int id) + { + this.key = new byte[length + 1]; + System.arraycopy(key, 0, this.key, 0, length); + this.key[length] = 0; + this.id = id; + } + + public byte[] getKey() { + return key; + } + + public int getID() { + return id; + } + + public boolean smallerThan(Entry other) + { + for (int i = 0; i < Math.min(key.length, other.key.length); i++) + if (key[i] != other.key[i]) + return (key[i]&0xFF) - (other.key[i]&0xFF) < 0; + return false; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java b/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..17d0c881853541e070801247edba76fd4af47c40 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java @@ -0,0 +1,33 @@ +/* + * @(#)EntryProcessor.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.search; + +interface EntryProcessor +{ + public void processEntry(String string, int id); +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java b/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java new file mode 100644 index 0000000000000000000000000000000000000000..621a6d750a68ce5279039e7cdae0625e3da20bd6 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java @@ -0,0 +1,119 @@ +/* + * @(#)GeneratorHeap.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class GeneratorHeap +{ + private static final int InitSize = 128; + private int _heapSize = 0; + private ConceptGroupGenerator[] _heap; + private int _size = InitSize; + private int _free = 0; + + public GeneratorHeap() { + _heap = new ConceptGroupGenerator[InitSize]; + } + + public void reset() { + _free = 0; + } + + public void addGenerator(ConceptGroupGenerator gen) + { + if (_free == _size) + { + ConceptGroupGenerator[] newArray = + new ConceptGroupGenerator[_size *= 2]; + System.arraycopy(_heap, 0, newArray, 0, _free); + _heap = newArray; + } + _heap[_free++] = gen; + } + + private void buildHeap() + { + for (int i = _heapSize/2; i >= 0; i--) + heapify(i); + } + + private void heapify(int i) + { + int r = (i + 1) << 1, l = r - 1; + int smallest = l<_heapSize&&_heap[l].position()<_heap[i].position()?l:i; + + if (r < _heapSize && _heap[r].position() < _heap[smallest].position()) + smallest = r; + if (smallest != i) + { + ConceptGroupGenerator temp = _heap[smallest]; + _heap[smallest] = _heap[i]; + _heap[i] = temp; + heapify(smallest); + } + } + + public boolean start(RoleFiller[] array) throws Exception + { + if ((_heapSize = _free) > 0) + { + for (int i = 0; i < _free; i++) + _heap[i].next(); + buildHeap(); + _heap[0].generateFillers(array); + return true; + } + else + return false; + } + + public boolean next(RoleFiller[] array) throws Exception + { + if (_heapSize > 0) + { + if (!_heap[0].next()) // no more + if (_heapSize > 1) + _heap[0] = _heap[--_heapSize]; + else + { + _heapSize = 0; + return false; + } + heapify(0); + _heap[0].generateFillers(array); + return true; + } + else + return false; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java b/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java new file mode 100644 index 0000000000000000000000000000000000000000..d3188c98fac961d967f0092c04860a021f3c1cda --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java @@ -0,0 +1,274 @@ +/* + * @(#)HitStore.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.util.Vector; + +class HitStoreNode +{ + private int _free = 0; + private int _size; + private QueryHit[] _array; + private int _hitCount = 0; + private double _divider = 0.0; + private double _min = 10000000.0; + private double _max = 0.0; + private HitStoreNode[] _children = new HitStoreNode[2]; // left & right + private int _index = 0; + + public HitStoreNode(int size) { + _array = new QueryHit[_size = size]; + } + + public QueryHit getNextHit() { + return _index < _free ? _array[_index++] : null; + } + + private void fastAdd(QueryHit hit) + { + _hitCount++; + _divider += hit.getScore(); + if (hit.getScore() > _max) + _max = hit.getScore(); + if (hit.getScore() < _min) + _min = hit.getScore(); + _array[_free++] = hit; + } + + public boolean add(QueryHit hit) + { + if (_array != null) + { + if (_free < _size) + { + fastAdd(hit); + return false; + } + else if (_min != _max) + { + split(); + _hitCount++; + _children[hit.getScore() > _divider ? 1 : 0].fastAdd(hit); + return true; + } + else + { + QueryHit[] newArray = new QueryHit[_size *= 2]; + System.arraycopy(_array, 0, newArray, 0, _free); + _array = newArray; + fastAdd(hit); + return true; + } + } + else + { + _hitCount++; + return _children[hit.getScore() > _divider ? 1 : 0].add(hit); + } + } + + private void split() + { + _children[0] = new HitStoreNode(_size); + _children[1] = new HitStoreNode(_size); + _divider /= _hitCount; // becomes average + for (int i = 0; i < _free; i++) + _children[_array[i].getScore() > _divider ? 1 : 0].fastAdd(_array[i]); + _array = null; // becomes internal + } + public int getCount() { + return _hitCount; + } + public double getDivider() { + return _divider; + } + public HitStoreNode getLChild() { + return _children[0]; + } + public HitStoreNode getRChild() { + return _children[1]; + } + public void setLChild(HitStoreNode node) { + _children[0] = node; + } + public void setRChild(HitStoreNode node) { + _children[1] = node; + } + public void decrementCount(int delta) { + _hitCount -= delta; + } + public boolean isLeaf() { + return _array != null; + } + + public void sort() { + quicksort(0, _free - 1); + } + + public void gatherLeaves(Vector vector) + { + if (isLeaf()) + vector.addElement(this); + else + { + getLChild().gatherLeaves(vector); + getRChild().gatherLeaves(vector); + } + } + + // part of quicksearch + private int partition(int p, int r) + { + QueryHit x = _array[p]; + int i = p - 1, j = r + 1; + while (true) + { + while (x.betterThan(_array[--j])) + ; + while (_array[++i].betterThan(x)) + ; + if (i < j) + { + QueryHit t = _array[i]; + _array[i] = _array[j]; + _array[j] = t; + } + else + return j; + } + } + + private void quicksort(int p, int r) + { + if (p < r) + { + int q = partition(p, r); + quicksort(p, q); + quicksort(q + 1, r); + } + } +} + + +class HitStore +{ + private static final int ArraySize = 128; + private static final int DefaultLimit = 300; + + private HitStoreNode _root = new HitStoreNode(ArraySize); + private int _limit; + private double _standard; + private Vector _leaves = null; + private HitStoreNode _current = null; + + public HitStore(double initialStandard) { + this(initialStandard, DefaultLimit); + } + + public HitStore(double initialStandard, int limit) + { + _limit = limit; + _standard = initialStandard; + } + + public void addQueryHit(QueryHit hit) { + if(_root.add(hit)) + adapt(); + } + + private HitStoreNode getNextNode() + { + if (_leaves.size() > 0) + { + HitStoreNode node = (HitStoreNode)_leaves.firstElement(); + _leaves.removeElementAt(0); + node.sort(); + return node; + } + else + return null; + } + + public QueryHit firstBestQueryHit() + { + _leaves = new Vector(); + _root.gatherLeaves(_leaves); + _current = getNextNode(); + return _current.getNextHit(); + } + + public QueryHit nextBestQueryHit() + { + QueryHit result = _current.getNextHit(); + if (result != null) + return result; + else if ((_current = getNextNode()) != null) + return _current.getNextHit(); + else + return null; + } + + double getCurrentStandard() { + return _standard; + } + + private void adapt() + { + if (_root.getCount() > _limit) + if (!_root.isLeaf()) + { + HitStoreNode ptr = _root; + // find rightmost internal + while (!ptr.getRChild().isLeaf()) + ptr = ptr.getRChild(); + + _standard = ptr.getDivider(); + + if (ptr == _root) + _root = ptr.getLChild(); + else + { + int count = ptr.getRChild().getCount(); + HitStoreNode ptr2 = _root; + while (ptr2.getRChild() != ptr) + { + ptr2.decrementCount(count); + ptr2 = ptr2.getRChild(); + } + ptr2.setRChild(ptr.getLChild()); + } + ptr.setLChild(null); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java b/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java new file mode 100644 index 0000000000000000000000000000000000000000..dc4929c40bb039c3d84823685621f1d8b505a575 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java @@ -0,0 +1,115 @@ +/* + * @(#)IntegerArray.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class IntegerArray +{ + private int[] _array; + private int _size; + private int _free = 0; + private static final int InitialSize = 128; + + public IntegerArray() { + _array = new int[_size = InitialSize]; + } + + public IntegerArray(int size) { + _array = new int[_size = size]; + } + + public void clear() { + _free = 0; + } + + public int at(int index) { + return _array[index]; + } + + public void add(int value) + { + if (_free == _size) + growArray(_size * 2); + _array[_free++] = value; + } + + private void growArray(int size) + { + int[] newArray = new int[_size = size]; + System.arraycopy(_array, 0, newArray, 0, _free); + _array = newArray; + } + + public int popLast() { + return _array[--_free]; + } + + public int cardinality() { + return _free; + } + + public void toDifferences(IntegerArray result) + { + if (result._size < _size) + result.growArray(_size); + if ((result._free = _free) > 0) + { + result._array[0] = _array[0]; + for (int i = 1; i < _free; i++) + result._array[i] = _array[i] - _array[i - 1]; + } + } + + public int indexOf(int value) + { + int i = 0, j = _free, k; + while (i <= j) + if (_array[k = (i + j)/2] < value) + i = k + 1; + else if (value < _array[k]) + j = k - 1; + else + return k; + return -1; + } + + public void print(java.io.PrintStream out) + { + for (int i = 0; i < _free - 1; i++) + { + out.print(_array[i]); + out.print(' '); + } + out.println(_array[_free - 1]); + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java new file mode 100644 index 0000000000000000000000000000000000000000..eeff2b6f71dbebcfd617bdb534bb34c890da52a5 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java @@ -0,0 +1,276 @@ +/* + * @(#)LiteMorph.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) LiteMorph.java 1.7 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Hashtable; +import java.util.Enumeration; + +/** + * This class will generate an array of morphological variants of a word + * to use in search-and-retrieval applications where a user wants to find + * other words morphologically related to words in a query. For example, + * a request such as "electrical fixtures" should also retrieve "electric + * fixtures," "electrical fixture," etc. Given a word of a query, these + * rules generate alternative variations of that word that should also be + * considered. This generation of variant forms of a word fills a role + * similar to that often filled by the use of wild card characters or by + * stemming rules that produce truncated stems in traditional information + * retrieval systems. The approach of generating alternative variations + * has advantages over a truncated stemming approach for many applications, + * because it does not require stemming operations during the indexing + * process, does not require extra indexing space for stems, nor does it + * lose information by storing only stems. Rather, the variation rules + * are applied to the query to produce additional forms to check against + * the index. + * <p> + * Compared to the use of wild card characters, this approach has two + * advantages: first, it does not require the user to think about where + * the wild cards should be placed, and secondly, it deals with irregular + * variations such as irregular verbs (e.g., "break," "broke," "broken"), + * and with stem ending effects such as silent e's and doubling of final + * consonants (e.g., "dig," "digs," "digging"). The rules presented here, + * together with a table of exceptions, provided at the end, deal with + * a wide range of such effects, without requiring any more attention on + * the part of the user than to turn on the facility. + * <p> + * These rules generate regular morphological variants of words using the + * suffixes s, er, ers, est, ed, ing, ly, ful, less, ness, and ment. Rules + * are included for dealing with some words ending in -ize, -ise, -ic and + * -ical, and for some words requiring irregular forms, such as -leaf and + * -man compounds (flyleaf, footman), and Latin words ending in -um and -a, + * such as datum. The rules are supplemented by a list of exceptions for + * words that do not inflect regularly. They are not intended to apply to + * function words or to proper names. When expanding queries, you may not + * want to apply them to capitalized words or to hyphenated words like + * day-to-day and low-level. + * <p> + * The rules treat almost all words as if they were multiply meaningful + * as nouns, verbs, and adjectives. Hence, the rules will often generate + * spurious forms that should never occur in a text -- e.g., fix -> + * fixest, happy -> happied. The rules are suitable for applications + * such as searching text using inverted files, where a quick test + * suffices to determine that a given candidate does not occur in the + * corpus. In such applications, it is preferable to overgenerate + * candidates than to miss possible retrievals. + * <p> + * The program uses rules developed by W. A. Woods and Ellen Hays in 1992. + * An original C program for using them was developed by Jacek Ambroziak + * and was included in Sun's SearchIt product. + * + * @author Roger D. Brinkley + * @author W. A. Woods + * @author Jacek Ambroziak + * @version 1.7 10/30/06 + * + * @see Rule + */ + +public abstract class LiteMorph { + + protected static Vector variants; + protected static Hashtable rulesTable; + protected static Hashtable blockedVariants; + protected static Hashtable exceptions; + + public LiteMorph() { + initialize(); + } + + + public static LiteMorph getMorph() { + return null; + } + + /** + * Subclasses of this class (generally locale specific) + * need to set up exceptions and rules. At a minium + * implementations + * need to initialize the size of the exceptions HashTable + * and the establish the rules HashTable. + * Implementations have the option of filling exceptions + * directly in this method or calling intialize(String []). + * After initialization the exceptionTable shoudl be garbage + * collected + */ + protected abstract void initialize(); + + /** + * One time initialization of exceptions Hashtable using an + * array of Strings. Each String is a list of variation groups. + * The words in the groups are space delimited. Any matching + * word in the exceptions will cause all of the words in the + * group to be added to the variant list + */ + protected void initialize (String [] exceptionTable) { + + // Firewall + if (exceptions == null || exceptionTable == null) { + return; + } + String tempWord, tempVal; + for (int i = 0; i < exceptionTable.length; i++) { + StringTokenizer tokens = new StringTokenizer(exceptionTable[i], " "); + while (tokens.hasMoreTokens()) { + tempWord = tokens.nextToken(); + tempVal = (String)exceptions.get(tempWord); + if (tempVal == null) { + exceptions.put(tempWord, exceptionTable[i]); + } else { + //the same form can occur in several groups that must be appended + exceptions.put(tempWord, tempVal + " " + exceptionTable[i]); + } + } + } + } + + /** + * Get the variants of given word. This is locale + * specific variants of a word as supplied by the locale + * implementation of this class + * + * @return String[] an array of words that are variations of word + */ + public synchronized String[] variantsOf(String word) { + + // intialize variants and blockedVariants + variants = new Vector(); + blockedVariants = new Hashtable (); + // this blocks adding the input word itself + blockedVariants.put(word, word); + + // Go get the morphological variantes of the word. + morphWord(word, 0); + + // don't need this anymore; release it for gc + blockedVariants = null; + String[] result = new String[variants.size()]; + variants.copyInto(result); + //release this for garbage collection + variants = null; + return result; + } + + /** + * Morph the word into other words if possible + */ + protected void morphWord(String word, int depth) { + + debug(" analyzing: " +word+" at depth "+depth); + + if (depth > 2) + return; + + // if a word is found among exceptions, don't try rules + + String exceptionList = (String)exceptions.get(word); + if (exceptionList == null) { + exceptionList = ""; + } + if (exceptionList.length() > 0) { + StringTokenizer tokens = new StringTokenizer(exceptionList, " "); + while (tokens.hasMoreTokens()) + addVariant(tokens.nextToken()); + debug(" "+word+": found match in exceptions -- "+ + exceptionList+", at depth "+depth); + return; + } + + if (word.indexOf("-") >= 0) + return; + //don't apply rules to words with internal hyphens (but check exceptions) + + Rule[] rules = null; + int skipnum = 0; + + // See if the word ends with one of the keys in the rulesTable + Enumeration keys = rulesTable.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + if (word.endsWith(key) && !key.equals("default")) { + rules = (Rule[]) rulesTable.get(key); + skipnum = key.length(); + break; + } + } + if (rules == null) { + // no match try to get the "default" rules. + rules = (Rule[]) rulesTable.get("default"); + skipnum = 0; + } + + + for (int i = 0; i < rules.length; i++) { + debug(" "+word+": trying rule: " + rules[i]+ + ", at depth "+depth); + String [] results = rules[i].match(word, depth, skipnum); + if (results.length > 0) { + debug(" "+word+": found match for: "+rules[i]+ + ", at depth "+depth); + addVariant(word); //do this here -- i.e., only when a rule matches + for (int j=0; j < results.length; j++) { + addVariant(results[j]); + } + break; + } + } + } + + /** + * Add the variant of the word to the list of words + */ + private void addVariant(String word) { + if (blockedVariants.get(word) == null) { // word is not blocked + variants.addElement(word); + blockedVariants.put(word, word); // block it from being added again + } + } + + /** + * Convenience method for creating Rules + */ + protected static Rule r(String expression, String expansions, LiteMorph morph) { + return new Rule(expression, expansions, morph); + } + + /** + * For printf debugging. + */ + private static final boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("LiteMorph: " + str); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java new file mode 100644 index 0000000000000000000000000000000000000000..c7150e562d8b0794cdfb22d4528d20a4e4a34ae8 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java @@ -0,0 +1,1578 @@ +/* + * @(#)LiteMorph_en.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) LiteMorph_en.java 1.6 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + + +import java.io.*; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Hashtable; + +/** + * This is the English version of LiteMorph + * + * @see LiteMorph + */ +public class LiteMorph_en extends LiteMorph{ + + + private static LiteMorph morph = new LiteMorph_en(); + + /** + * Make this a singleton class + */ + private LiteMorph_en() { + } + + /** + * Return the LiteMorph for this class + */ + public synchronized static LiteMorph getMorph() { + return morph; + } + + /** + * This is a locale specific intialization. + * Create the exceptions HashTable for the size needed. + * the call intialize(String []). + */ + protected synchronized void initialize() { + if (exceptions != null) { + return; + } + exceptions = new Hashtable(2800, (float)0.7); + + // The exceptions: + // current statistics: approx 700 variation groups + // approx 2800 words) + String[] exceptionTable = { + "a", + //opt//"aardwolf aardwolves", + "abandoner abandon abandons abandoned abandoning abandonings abandoners", + "abdomen abdomens", + "about", + "above", + //opt//"abscissa abscissas abscissae", + "acid acids acidic acidity acidities", + "across", + "act acts acted acting actor actors", + //opt//"acumen", + "ad ads", + "add adds added adding addings addition additions adder adders", + //opt//"addendum addenda addendums", + //opt//"adieu adieux adieus", + "advertise advertises advertised advertising advertiser advertisers " + +"advertisement advertisements advertisings", + "after", + "again", + "against", + "ago", + //opt//"agoutis agouti", + //opt//"alias aliases", + "all", + "almost", + "along", + "already", + "also", + "although", + "alumna alumnae alumnus alumni", + //opt//"alveolus alveoli alveolar", + "always", + "amen amens", + "amidships", + "amid amidst", + "among amongst", + //opt//"ampulla ampullae", + //opt//"amygdala amygdalae", + "an", + "analysis analyses", + "and", + //opt//"annulus annuluses annuli annular", + "another other others", + "antenna antennas antennae", + "antitheses antithesis", + "any", + "anyone anybody", + "anything", + "appendix appendixes appendices", + "apropos", + "aquarium aquariums aquaria", + "argument arguments argue argues argued arguing arguings arguer arguers", + "arise arises arose arisen ariser arisers arising arisings", + "around", + "as", + "asbestos", + "at", + "atlas atlases", + //opt//"atrium atriums atria", + "auger augers augered augering augerings augerer augerers", + "augment augments augmented augmenting augmentings augmentation " + +"augmentations augmenter augmenters", + "automata automaton automatons", + "automation automating automate automates automated automatic", + "avoirdupois", + "awake awakes awoke awaked awoken awaker awakers awaking awakings " + +"awakening awakenings", + "away", + "awful awfully awfulness", + "axis axes axises", + "bacillus bacilli", + "bacterium bacteria", + "bad worse worst badly badness", + //opt//"balladier balladiers", + //opt//"bandolier bandoliers", + "bas", + "bases basis", + "bases base based basing basings basely baseness basenesses basement " + +"basements baseless basic basics", + //opt//"bateau bateaux", + //opt//"bathos", + //opt//"bayou bayous", + "be am are is was were been being", + "bear bears bore borne bearing bearings bearer bearers", + "beat beats beaten beating beatings beater beaters", + //opt//"beau beaux beaus", + "because", + "become becomes became becoming", + //opt//"bedesman bedesmans", + "beef beefs beeves beefed beefing", + "beer beers", + "before", + //opt//"beget begets begat begot begotten begetting begettings begetter begetters", + "begin begins began begun beginning beginnings beginner beginners", + "behalf behalves", + "being beings", + "bend bends bent bending bendings bender benders", + "bereave bereaves bereaved bereft bereaving bereavings bereavement " + +"bereavements", + "beside besides", + "best bests bested besting", + "bet bets betting bettor bettors", + "betimes", + "between", + "beyond", + "bid bids bade bidden bidding biddings bidder bidders", + "bier biers", + "bind binds bound binding bindings binder binders", + "bit bits", + "bite bites bit bitten biting bitings biter biters", + "blackfoot blackfeet", + "bleed bleeds bled bleeding bleedings bleeder bleeders", + "blow blows blew blown blowing blowings blower blowers", + "bookshelf bookshelves", + //opt//"borzois borzoi", + "both", + "bound bounds bounded bounding boundings bounder bounders boundless", + "bourgeois bourgeoisie", + "bra bras", + "brahman brahmans", + "break breaks broke broken breaking breakings breaker breakers", + "breed breeds bred breeding breedings breeder breeders", + "bring brings brought bringing bringings bringer bringers", + //opt//"bronchus bronchi bronchial bronchially", + "build builds built building buildings builder builders", + //opt//"bum bums bummed bumming bummings bummer bummers", + //opt//"bursa bursae bursas bursal", + "bus buses bused bussed busing bussing busings bussings buser busers " + +"busser bussers", + "buss busses bussed bussing bussings busser bussers", + "but", + "buy buys bought buying buyings buyer buyers", + "by", + //opt//"caiman caimans cayman caymans", + //opt//"calculus calculi", + "calf calves calved calving calvings calver calvers", + "can cans canned canning cannings canner canners", + "can could cannot", + //opt//"candelabrum candelabra candelabrums", + "canoes canoe canoed canoeing canoeings canoer canoers", + //opt//"caribou caribous", + "catch catches caught catching catchings catcher catchers", + //opt//"catharsis catharses", + "cement cements cemented cementing cementings cementer cementers", + "cent cents", + "center centers centered centering centerings centerless", + //opt//"chablis", + //opt//"chamois", + //opt//"chapattis chapatti", + //opt//"chateau chateaus chateaux", + //opt//"cherub cherubs cherubim", + "child children childless childish childishly", + "choose chooses chose chosen choosing choosings chooser choosers", + //opt//"cicatrix cicatrices cicatricial cicatricose cicatrize cicatrizes " + //opt//+"cicatrized cicatrizing cicatrizings cicatrization cicatrixes", + //opt//"clement", + //opt//"cliches cliche", + "cling clings clung clinging clingings clinger clingers", + //opt//"codex codices", + //opt//"cognomen", + "colloquium colloquia colloquiums", + //opt//"colossus colossi colossuses", + "come comes came coming comings comer comers", + "comment comments commented commenting commentings commenter commenters", + "compendium compendia compendiums", + "complement complements complemented complementing complementings " + +"complementer complementers complementary", + "compliment compliments complimented complimenting complimentings " + +"complimenter complimenters complimentary", + "concerto concertos concerti", + "condiment condiments", + //opt//"continuum continua continuums", + "corps", + //opt//"corrigendum corrigenda", + "cortex cortices cortexes cortical", + "couscous", + "creep creeps crept creeping creepings creeper creepers creepy", + "crisis crises", + "criterion criteria criterial", + "cryptanalysis cryptanalyses", + "curriculum curricula curriculums curricular", + //opt//"cyclamen cyclamens", + //opt//"czech czechs czechoslovakia czechoslovak czechoslovaks czechoslovakian " + //opt//+"czechoslovakians Czech Czechs Czechoslovakia Czechoslovak Czechoslovaks " + //opt//+"Czechoslovakian Czechoslovakians", + //opt//"dais daises", + "datum data", + "day days daily", + "deal deals dealt dealing dealings dealer dealers", + "decrement decrements decremented decrementing decrementings " + +"decrementer decrementers decremental", + "deer deers", + //opt//"deixis deixes", + "demented dementia", + "desideratum desiderata", + //opt//"desman desmans", + "diagnosis diagnoses diagnose diagnosed diagnosing diagnostic", + "dialysis dialyses", + "dice dices diced dicing dicings dicer dicers", + "die dice", + "die dies died dying dyings", + "dig digs dug digging diggings digger diggers", + "dive dives diver divers dove dived diving divings", + "divest divests divester divesters divested divesting divestings " + +"divestment divestments", + "do does did done doing doings doer doers", + "document documents documented documenting documentings documenter " + +"documenters documentation documentations documentary", + //opt//"dodecahedron dodecahedra dodecahedrons", + "doe does", + //opt//"dormouse dormice", + "dove doves", + "downstairs", + "dozen", + "draw draws drew drawn drawing drawings drawer drawers", + "drink drinks drank drunk drinking drinkings drinker drinkers", + "drive drives drove driven driving drivings driver drivers driverless", + "due dues duly", + "during", + "e", + "each", + "eager eagerer eagerest eagerly eagerness eagernesses", + "early earlier earliest", + "easement easements", + "eat eats ate eaten eating eatings eater eaters", + "effluvium effluvia", + "either", + "element elements elementary", + "elf elves elfen", + "ellipse ellipses elliptic elliptical elliptically", + "ellipsis ellipses elliptic elliptical elliptically", + "else", + "embolus emboli embolic embolism", + "emolument emoluments", + "emphasis emphases", + "employ employs employed employing employer employers employee " + +"employees employment employments employable", + "enough", + "equilibrium equilibria equilibriums", + "erratum errata", + "ever", + "every", + "everything", + //opt//"exegeses exegesis", + "exotic exotically exoticness exotica", + "experiment experiments experimented experimenting experimentings " + +"experimenter experimenters experimentation experimental", + "extra extras", + //opt//"extremum extrema extremums extreme extremely extremeness extremist extremism", + "fall falls fell fallen falling fallings faller fallers", + "far farther farthest", + "fee fees feeless", + "feed feeds fed feeding feedings feeder feeders", + "feel feels felt feeling feelings feeler feelers", + "ferment ferments fermented fermenting fermentings fermentation " + +"fermentations fermenter fermenters", + "few fewer fewest", + //opt//"fez fezzes fezes", + "fight fights fought fighting fightings fighter fighters", + "figment figments", + "filament filaments", + "find finds found finding findings finder finders", + "firmament firmaments", + "flee flees fled fleeing fleeings", + "fling flings flung flinging flingings flinger flingers", + "floe floes", + "fly flies flew flown flying flyings flier fliers flyer flyers", + "focus foci focuses focused focusing focusses focussed focussing focuser focal", + "foment foments fomented fomenting fomentings fomenter fomenters", + "foot feet", + "foot foots footed footing footer footers", + "footing footings footer footers", + "for", + "forbid forbids forbade forbidden forbidding forbiddings forbidder forbidders", + "foresee foresaw foreseen foreseeing foreseeings foreseer foreseers", + "forest forests forester foresting forestation forestations", + "forget forgets forgot forgotten forgetting forgettings forgetter " + +"forgetters forgetful", + "forsake forsakes forsook forsaken forsaking forsakings forsaker forsakers", + "found founds founded founding foundings founder founders", + "fragment fragments fragmented fragmenting fragmentings fragmentation " + +"fragmentations fragmenter fragmenters", + "free frees freer freest freed freeing freely freeness freenesses", + "freeze freezes froze frozen freezing freezings freezer freezers", + "from", + "full fully fuller fullest", + "fuller fullers full fulls fulled fulling fullings", + "fungus fungi funguses fungal", + "gallows", + "ganglion ganglia ganglions ganglionic", + "garment garments", + "gas gasses gassed gassing gassings gasser gassers", + "gas gases gasses gaseous gasless", + "gel gels gelled gelling gellings geller gellers", + //opt//"geneses genesis", + "german germans germanic germany German Germans Germanic Germany", + "get gets got gotten getting gettings getter getters", + "give gives gave given giving givings giver givers", + "gladiolus gladioli gladioluses gladiola gladiolas gladiolae", + "glans glandes", + //opt//"glissando glissandi glissandos", + "gluiness gluey glue glues glued gluing gluings gluer gluers", + //opt//"glum glummer glummest", + "go goes went gone going goings goer goers", + "godchild godchildren", + "good better best goodly goodness goodnesses", + "goods", + "goose geese", + "goose gooses goosed goosing goosings gooser goosers", + "grandchild grandchildren", + "grind grinds ground grinding grindings grinder grinders", + "ground grounds grounded grounding groundings grounder grounders groundless", + "grow grows grew grown growing growings grower growers growth", + "gum gums gummed gumming gummings gummer gummers", + "half halves", + "halve halves halved halving halvings halver halvers", + "hang hangs hung hanged hanging hangings hanger hangers", + //opt//"hanuman hanumans", + "have has had having havings haver havers", + "he him his himself", + "hear hears heard hearing hearings hearer hearers", + "here", + //opt//"herr herren Herr Herren", + //opt//"hiatus hiatuses", + "hide hides hid hidden hiding hidings hider hiders", + //opt//"hie hies hied hieing hying hieings hyings hier hiers", + "hippopotamus hippopotami hippopotamuses", + "hold holds held holding holdings holder holders", + "honorarium honoraria honorariums", + "hoof hoofs hooves hoofed hoofing hoofer hoofers", + "how", + "hum hums hummed humming hummings hummer hummers", + "hymen hymens hymenal", + "hypotheses hypothesis hypothesize hypothesizes hypothesized hypothesizer " + +"hypothesizing hypothetical hypothetically", + "i", + //opt//"icosahedron icosahedra icosahedrons", + "if iffy", + "impediment impediments", + "implement implements implemented implementing implementings implementation " + +"implementations implementer implementers", + "imply implies implied implying implyings implier impliers", + "in inner", + "inclement", + "increment increments incremented incrementing incrementings incrementer " + +"incrementers incremental incrementally", + "index indexes indexed indexing indexings indexer indexers", + "index indexes indices indexical indexicals", + "indoor indoors", + "instrument instruments instrumented instrumenting instrumentings " + +"instrumenter instrumenters instrumentation instrumentations instrumental", + "integument integumentary", + "into", + "it its itself", + "july julys", + "keep keeps kept keeping keepings keeper keepers", + "knife knifes knifed knifing knifings knifer knifers", + "knife knives", + "know knows knew known knowing knowings knower knowers knowledge", + "lament laments lamented lamenting lamentings lamentation lamentations " + +"lamenter lamenters lamentable lamentably", + "larva larvae larvas larval", + "late later latest lately lateness", + "latter latterly", + "lay lays laid laying layer layers", + "layer layers layered layering layerings", + "lead leads led leading leadings leader leaders leaderless", + "leaf leafs leafed leafing leafings leafer leafers", + "leaf leaves leafless", + "leave leaves left leaving leavings leaver leavers", + //opt//"legume legumes", + "lend lends lent lending lendings lender lenders", + "less lesser least", + "let lets letting lettings", + //opt//"libretto librettos libretti", + "lie lies lay lain lying lier liers", + "lie lies lied lying liar liars", + "life lives lifeless", + "light lights lit lighted lighting lightings lightly lighter lighters " + +"lightness lightnesses lightless", + "likely likelier likeliest", + "limen limens", + "lineament lineaments", + "liniment liniments", + "live alive living", + "live lives lived living livings", + "liver livers", + //opt//"llamela llamelae", + "loaf loafs loafed loafing loafings loafer loafers", + "loaf loaves", + //opt//"locus loci", + "logic logics logical logically", + "lose loses lost losing loser losers loss losses", + "louse lice", + "lumen lumens", + "make makes made making makings maker makers", + "man mans manned manning mannings", + "man men", + "manly manlier manliest manliness manful manfulness manhood", + "manic manically", + "manner manners mannered mannerly mannerless mannerful", + //opt//"mantra mantras", + "many", + "matrix matrices matrixes", + "may might", + "maximum maxima maximums maximal maximize maximizes maximized maximizing", + "mean means meant meaning meanings meaningless meaningful", + "mean meaner meanest meanly meanness meannesses", + "median medians medianly medial", + "medium media mediums", + "meet meets met meeting meetings", + "memorandum memoranda memorandums", + "mere merely", + "metal metals metallic", + "might mighty mightily", + //opt//"milieu milieus milieux", + "millenium millennia milleniums millennial", + "mine mines mined mining minings miner miners", + "mine my our ours", + "minimum minima minimums minimal", + "minus minuses", + "miscellaneous miscellanea miscellaneously miscellaneousness miscellany", + //opt//"modulus moduli", + "molest molests molested molesting molestings molester molesters", + "moment moments", + "monument monuments monumental", + //opt//"mooncalf mooncalves", + "more most", + "mouse mice mouseless", + "much", + "multiply multiplies multiplier multipliers multiple multiples " + +"multiplying multiplyings multiplication multiplications", + "mum mums mummed mumming mummings mummer mummers", + "must musts", + "neither", + "nemeses nemesis", + "neurosis neuroses neurotic neurotics", + "nomen", + "none", + "nos no noes", + "not", + "nothing nothings nothingness", + "now", + "nowadays", + "nucleus nuclei nucleuses nuclear", + //opt//"nucleolus nucleoli nucleolar", + "number numbers numbered numbering numberings numberless", + "nutriment nutriments nutrient nutrients nutrition nutritions", + "oasis oases", + //opt//"octahedron octahedra octahedrons", + "octopus octopi octopuses", + "of", + "off", + "offer offers offered offering offerings offerer offerers offeror offerors", + "often", + "oftentimes", + "ointment ointments", + "omen omens", + "on", + "once", + "only", + //opt//"operetta operettas operetti", + "ornament ornaments ornamented ornamenting ornamentings ornamentation " + +"ornamenter ornamenters ornamental", + "outdoor outdoors", + "outlay outlays", + "outlie outlies outlay outlied outlain outlying outlier outliers", + "ovum ova", + "ox oxen", + //opt//"palazzo palazzi palazzos", + "parentheses parenthesis", + "parliament parliaments parliamentary", + "passerby passer-by passersby passers-by", + "past pasts", + //opt//"patois", + "pay pays paid paying payings payer payers payee payees payment payments", + //opt//"pediment pediments", + "per", + "perhaps", + "person persons people", + //opt//"phallus phalli phalluses phallic", + //opt//"phylum phyla phylums", + "phenomenon phenomena phenomenal", + //opt//"phosphorus", + "pi", + "picnic picnics picnicker picnickers picnicked picnicking picnickings", + "pigment pigments pigmented pigmenting pigmentings pigmenter pigmenters " + +"pigmentation pigmentations", + "please pleases pleased pleasing pleasings pleaser pleasers pleasure " + +"pleasures pleasuring pleasurings pleasant pleasantly pleasureless " + +"pleasureful", + "plus pluses plusses", + "polyhedra polyhedron polyhedral", + "priest priests priestly priestlier priestliest priestliness priestless", + "prognosis prognoses", + "prostheses prosthesis", + "prove proves proved proving provings proofs proof prover provers provable", + "psychosis psychoses psychotic psychotics", + //opt//"pupa pupae pupas pupal", + "qed", + "quiz quizzes quizzed quizzing quizzings quizzer quizzers", + "raiment", + "rather", + "re", + "real really", + "redo redoes redid redone redoing redoings redoer redoers", + "regiment regiments regimented regimenting regimenter regimenters " + +"regimentation regimental", + "rendezvous", + "requiz requizzes requizzed requizzing requizzings requizzer requizzers", + "ride rides rode ridden riding ridings rider riders rideless", + "ring rings rang rung ringing ringings ringer ringers ringless", + "rise rises rose risen rising risings riser risers", + //opt//"roof roofs roofed roofing roofings roofer roofers roofless", + "rose roses", + "rudiment rudiments rudimentary", + "rum rums rummed rumming rummings rummer rummers", + "run runs ran running runnings runner runners", + "sacrament sacraments sacramental", + "same sameness", + "sans", + "saw saws sawed sawn sawing sawings sawyer sawyers", + "say says said saying sayings sayer sayers", + "scarf scarfs scarves scarfless", + "schema schemata schemas", + //opt//"scherzo scherzi scherzos", + //opt//"scrotum scrota scrotums", + "sediment sediments sedimentary sedimentation sedimentations", + "see sees saw seen seeing seeings seer seers", + "seek seeks sought seeking seekings seeker seekers", + "segment segments segmented segmenting segmentings segmenter segmenters " + +"segmentation segmentations", + "self selves selfless", + "sell sells sold selling sellings seller sellers", + "semen", + "send sends sent sending sendings sender senders", + "sentiment sentiments sentimental", + //opt//"seraph seraphs seraphim", + "series", + "set sets setting settings", + "several severally", + "sew sews sewed sewn sewing sewings sewer sewers", + "sewer sewers sewerless", + "shake shakes shook shaken shaking shakings shaker shakers", + "shall should", + "shaman shamans", + "shave shaves shaved shaven shaving shavings shaver shavers shaveless", + "she her hers herself", + "sheaf sheaves sheafless", + "sheep", + "shelf shelves shelved shelfing shelvings shelver shelvers shelfless", + "shine shines shined shone shining shinings shiner shiners shineless", + "shoe shoes shoed shod shoeing shoeings shoer shoers shoeless", + "shoot shoots shot shooting shootings shooter shooters", + "shot shots", + "show shows showed shown showing showings shower showers", + "shower showers showery showerless", + "shrink shrinks shrank shrunk shrinking shrinkings shrinker shrinkers " + +"shrinkable", + "sideways", + //opt//"simplex simplexes simplices", + "simply simple simpler simplest", + "since", + "sing sings sang sung singing singings singer singers singable", + "sink sinks sank sunk sinking sinkings sinker sinkers sinkable", + "sit sits sat sitting sittings sitter sitters", + "ski skis skied skiing skiings skier skiers skiless skiable", + "sky skies", + "slay slays slew slain slaying slayings slayer slayers", + "sleep sleeps slept sleeping sleepings sleeper sleepers sleepless", + "so", + "some", + "something", + "sometime sometimes", + "soon", + "spa spas", + "speak speaks spoke spoken speaking speakings speaker speakers", + "species specie", + "spectrum spectra spectrums", + "speed speeds sped speeded speeding speedings speeder speeders", + "spend spends spent spending spendings spender spenders spendable", + "spin spins spun spinning spinnings spinner spinners", + "spoke spokes", + "spring springs sprang sprung springing springings springer springers " + +"springy springiness", + "staff staffs staves staffed staffing staffings staffer staffers", + "stand stands stood standing standings", + "stasis stases", + "steal steals stole stolen stealing stealings stealer stealers", + "stick sticks stuck sticking stickings sticker stickers", + "stigma stigmata stigmas stigmatize stigmatizes stigmatized stigmatizing", + "stimulus stimuli", + "sting stings stung stinging stingings stinger stingers", + "stink stinks stank stunk stinking stinkings stinker stinkers", + "stomach stomachs", + "stratum strata stratums", + "stride strides strode stridden striding stridings strider striders", + "string strings strung stringing stringings stringer stringers stringless", + "strive strives strove striven striving strivings striver strivers", + "strum strums strummed strumming strummings strummer strummers strummable", + //opt//"stylus styli styluses", + //opt//"succubus succubi", + "such", + "suffer suffers suffered suffering sufferings sufferer sufferers sufferable", + "suggest suggests suggested suggesting suggestings suggester suggesters " + +"suggestor suggestors suggestive suggestion suggestions suggestible " + +"suggestable", + "sum sums summed summing summings summer summers", + "summer summers summered summering summerings", + "supplement supplements supplemented supplementing supplementings " + +"supplementation supplementer supplementers supplementary supplemental", + "supply supplies supplied supplying supplyings supplier suppliers", + "swear swears swore sworn swearing swearings swearer swearers", + "sweep sweeps swept sweeping sweepings sweeper sweepers", + "swell swells swelled swollen swelling swellings", + "swim swims swam swum swimming swimmings swimmer swimmers swimable", + "swine", + "swing swings swung swinging swingings swinger swingers", + "syllabus syllabi syllabuses", + "symposium symposia symposiums", + "synapse synapses", + "synapsis synapses", + "synopsis synopses", + "synthesis syntheses", + "tableau tableaux tableaus", + "take takes took taken taking takings taker takers takable", + "teach teaches taught teaching teachings teacher teachers teachable", + "tear tears tore torn tearing tearings tearer tearers tearable", + "tegument teguments", + "tell tells told telling tellings teller tellers tellable", + "temperament temperaments temperamental temperamentally", + "tenement tenements", + //opt//"terminus termini", + //opt//"than thans", + //opt//"that thats", + "the", + "there theres", + "theses thesis", + "they them their theirs themselves", + "thief thieves thieving thievings", + "think thinks thought thinking thinker thinkers thinkable", + "this that these those", + "thought thoughts thougtful thoughtless", + "throw throws threw thrown throwing throwings thrower throwers throwable", + //opt//"thus thuses", + "tic tics", + "tie ties tied tying tyings tier tiers tieable tieless", + "tier tiers tiered tiering tierings tierer tierers", + "to", + "toe toes toed toeing toeings toer toers toeless", + "together togetherness", + "too", + "tooth teeth toothless", + "topaz topazes", + "torment torments tormented tormenting tormentings tormenter tormenters " + +"tormentable", + "toward towards", + "tread treads trod trodden treading treadings treader treaders", + "tread treads treadless retread retreads", + "true truly trueness", + "two twos", + "u", + "under", + "underlay underlays underlaid underlaying underlayings underlayer " + +"underlayers", + "underlie underlies underlay underlain underlying underlier underliers", + "undo undoes undid undone undoing undoings undoer undoers undoable", + "unrest unrestful", + "until", + "unto", + "up", + "upon", + "upstairs", + "use uses user users used using useful useless", + "various variously", + "vehement vehemently vehemence", + "versus", + "very", + "visit visits visited visiting visitings visitor visitors", + "vortex vortexes vortices", + "wake wakes woke waked woken waking wakings waker wakers wakeful " + +"wakefulness wakefulnesses wakeable", + "wear wears wore worn wearing wearings wearer wearers wearable", + "weather weathers weathered weathering weatherly", + "weave weaves wove woven weaving weavings weaver weavers weaveable", + "weep weeps wept weeping weepings weeper weepers", + "wharf wharfs wharves", + //opt//"what whats", + //opt//"when whens", + "where wheres", + "whereas whereases", + "whether whethers", + //opt//"which whiches", + "while whiles whilst whiled whiling", + "whiz whizzes whizzed whizzing whizzings whizzer whizzers", + "who whom whos whose whoses", + "why whys", + "wife wives wifeless", + "will wills willed willing willings willful", + "will would", + "win wins won winning winnings winner winners winnable", + "wind winds wound winding windings winder winders windable", + "wind winds windy windless", + "with", + "within", + "without", + "wolf wolves", + "woman women womanless womanly", + "wound wounds wounded wounding woundings", + "write writes wrote written writing writings writer writers writeable", + "yeses yes", + "yet yets", + "you your yours yourself"}; + + initialize(exceptionTable); + + // The rules: + + // For words ending in -s (s-rules): + + Rule[] sRules = { + r(".aeiouy bcdfghjklmnpqrstvwxyz + i n e s s", + "y,ies,ier,iers,iest,ied,ying,yings,ily,inesses,iment,iments,iless,iful", + this), + // (e.g., happiness, business) + + r(".aeiouy + e l e s s", + "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements," + +"eness,enesses,eful", + this), + // (e.g., baseless, shoeless) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + l e s s", + "_,s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,ful", + this), + // (e.g., gutless, hatless, spotless) + + r(".aeiouy + l e s s", + "_,s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,ful", + this), + // (e.g., thoughtless, worthless) + + r(".aeiouy + e n e s s", + "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,enesses,ement,ements," + +"eless,eful", + this), + // (e.g., baseness, toeness) + + r(".aeiouy + n e s s", + "_,s,er,ers,est,ed,ing,ings,ly,nesses,ment,ments,less,ful", + this), + // (e.g., bluntness, grayness) + + r(".aeiouy s s +", + "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., albatross, kiss) + + r(".aeiouy o u s +", + "ly,ness", + this), + // (e.g., joyous, fractious, gaseous) + + r("+ i e s", + "y,ie,yer,yers,ier,iers,iest,ied,ying,yings,yness,iness,ieness,ynesses," + +"inesses,ienesses,iment,iement,iments,iements,yless,iless,ieless,yful," + +"iful,ieful", + this), + // (e.g., tries, unties, jollies, beauties) + + r(".aeiouy + s i s", + "ses,sises,sisness,sisment,sisments,sisless,sisful", + this), + // (e.g., crisis, kinesis) + + r(".aeiouy i s +", + "es,ness,ment,ments,less,ful", + this), + // (e.g., bronchitis, bursitis) + + r(".aeiouy c h + e s", + "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment," + +"ement,ments,ements,less,eless,ful,eful", + this), + + r(".aeiouy s h + e s", + "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment," + +"ement,ments,ements,less,eless,ful,eful", + this), + + r(".aeiouy bcdfghjklmnpqrstvwxz + i z e s", + "ize,izer,izers,ized,izing,izings,ization,izations," + +"ise,ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenizes) // adds British variations + + r(".aeiouy bcdfghjklmnpqrstvwxz + i s e s", + "ize,izes,izer,izers,ized,izing,izings,ization,izations," + +"ise,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenises) // British variant // ~expertise + + r(".aeiouy jsxz + e s", + "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment," + +"ement,ments,ements,less,eless,ful,eful", + this), + // (e.g., aches, arches) + // v is not in this set because ve words can keep the e before ing + // NB: we are not handling -is plurals like crises + + r(".aeiouy d g + e s", + "e,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,ement,ements," + +"eless,eful", + this), + // (e.g., judges, abridges) + + r("e + s", + "*_", + this), + // (e.g., trees, races, likes, agrees) + // covers all other -es words + + r("s e g m e n t + s", + "*_", + this), + // (e.g., segments, bisegments, cosegments) + + r("p i g m e n t + s", + "*_", + this), + // (e.g., pigments, depigments, repigments) + + r(".aeiouy d g + m e n t s", + "ment,*ment", + this), + // (e.g., judgments, abridgments) + + r(".aeiouy bcdfghjklmnpqrstvwxyz i m e n t + s", + "*_", + this), + // (e.g., merriments, embodiments) + // -iment in turn will generate y and *y (redo y) + + r(".aeiouy m e n t + s", + "*_", + this), + // (e.g., atonements, entrapments) + + r(".aeiouy e r + s", + "*_", + this), + // (e.g., viewers, meters, traders, transfers) + + r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt + s", + "*_", + this), + // (e.g., unflags) + // polysyllables + + r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt + s", + "*_", + this), + // (e.g., frogs) + // monosyllables + + r(".aeiouy i n g + s", + "*_", + this), + // (e.g., killings, muggings) + + r(".aeiouy l l + s", + "*_", + this), + // (e.g., hulls, tolls) + + r(".bcdfghjklmnpqrstvwxyz + s", + "*_", + this), + // (e.g., beads, toads, zoos) + }; + + // For words ending in -e (e-rules): + + Rule[] eRules = { + r(".aeiouy bcdfghjklmnpqrstvwxyz l + e", + "es,er,ers,est,ed,ing,ings,y,ely,eness,enesses,ement,ements,eless,eful", + this), + // (e.g., able, abominable, fungible, table, enable, idle, subtle) + + r("+ i e", + "ies,ier,iers,iest,ied,ying,yings,iely,ieness,ienesses,iement,iements," + +"ieless,ieful", + this), + // (e.g., bookie, magpie, vie) + + r("y e +", + "s,r,rs,st,d,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., dye, redye, redeye) + + r(".aeiouy d g + e", + "es,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,less,ful,ement," + +"ements,eless,eful", + this), + // (e.g., judge, abridge) + + r("u + e", + "es,er,ers,est,ed,ing,ings,eing,eings,ly,ely,eness,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful", + this), + // (e.g., true, due, imbue) + + r(".aeiouy bcdfghjklmnpqrstvwxz + i z e", + "izes,izer,izers,ized,izing,izings,ization,izations," + +"ise,ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenize) // adds British variations + + r(".aeiouy bcdfghjklmnpqrstvwxz + i s e", + "ize,izes,izer,izers,ized,izing,izings,ization,izations," + +"ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenise) // British variant // ~expertise + + r("+ e", + "es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements," + +"eless,eful", + this), + // (e.g., tree, agree, rage, horse, hoarse) + }; + + // For words ending in -ed (ed-rules): + + Rule[] edRules = { + r("r e e + d", + "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful,*_", + this), + // (e.g., agreed, freed, decreed, treed) + + r("e e + d", + "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful", + this), + // (e.g., feed, seed, Xweed) + + r("bcdfghjklmnpqrstvwxyz + i e d", + "y,ie,ies,ier,iers,iest,ying,yings,ily,yly,iness,yness,inesses,ynesses," + +"iment,iments,iless,iful,yment,yments,yless,yful", + this), + // (e.g., tried) + + r(".aeiouy .bcdfghjklmnpqrstvwxyz l + l e d", + "_,s,er,ers,est,ing,ings,ly,ness,nesses,ment,ments,less,ful,&,&s," + +"&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful", + this), + // (e.g., controlled, fulfilled, rebelled) + // both double and single l forms + + r(".aeiouy l + l e d", + "&,&s,&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful", + this), + // (e.g., pulled, filled, fulled) + + r(".aeiouy s + s e d", + "&,&es,&er,&ers,&est,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful", + this), + // (e.g., hissed, grossed) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + & e d", + "_,s,&er,&ers,&est,&ing,&ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., hugged, trekked) + + r(".aeiouy bcdfghjklmnpqrstvwxz + i z e d", + "izes,izer,izers,ize,izing,izings,ization,izations," + +"ise,ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenize) // adds British variations + + r(".aeiouy bcdfghjklmnpqrstvwxz + i s e d", + "ize,izes,izer,izers,ized,izing,izings,ization,izations," + +"ises,iser,isers,ise,ising,isings,isation,isations", + this), + // (e.g., tokenise) // British variant // ~expertise + + r(".aeiouy + e d", + "_,e,s,es,er,ers,est,ing,ings,ly,ely,ness,eness,nesses,enesses," + +"ment,ement,ments,ements,less,eless,ful,eful", + this), + // (e.g., spoiled, tooled, tracked, roasted, atoned, abridged) + + r("e d +", + "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., bed, sled) + // words with a single e as the only vowel + }; + + // For words ending in -er (er-rules): + + Rule[] erRules = { + r("m e t e r +", + "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., altimeter, ammeter, odometer, perimeter) + + r("+ e e r", + "eers,eered,eering,eerings,eerly,eerness,eernesses,eerment,eerments," + +"eerless,eerful,ee,ees,eest,eed,eeing,eeings,eely,eeness,eenesses," + +"eement,eements,eeless,eeful,eerer,eerers,eerest", + this), + // (e.g., agreer, beer, budgeteer, engineer, freer) + + r("bcdfghjklmnpqrstvwxyz + i e r", + "y,ie,ies,iest,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses," + +"yment,yments,yless,yful,iment,iments,iless,iful,iers,iered," + +"iering,ierings,ierly,ierness,iernesses,ierment,ierments," + +"ierless,ierful,ierer,ierers,ierest", + this), + // (e.g., acidifier, tier) + + r(".aeiouy l + l e r", + "&,&s,&est,&ed,&ing,&ings,ly,lely,&ness,&nesses,&ment,&ments,&ful," + +"&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erments," + +"&erless,&erful", + this), + // (e.g., puller, filler, fuller) + // did not add: &erer, &erest, &errer, &errers, &errest, + // since i think the &er here is always an ending (?) + + r(".aeiouy s + s e r", + "&,&es,&est,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful," + +"&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erment,&erments," + +"&erless,&erful", + this), + // (e.g., hisser, grosser) + // did not add: &erer, &erest, &errer, &errers, &errest, + // since i think the &er here is always an ending (?) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdgkmnprt + & e r", + "_,s,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful,&ers,&ered," + +"&ering,&erings,&erly,&erness,&ernesses,&erments,&erless,&erful", + this), + // (e.g., bigger, trekker, hitter) + // did not add: &erer, &erest, &errer, &errers, &errest, + // since i think the &er here is always an ending (?) + + r(".aeiouy bcdfghjklmnpqrstvwxz + i z e r", + "izes,ize,izers,ized,izing,izings,ization,izations," + +"ise,ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenize) // adds British variations + + r(".aeiouy bcdfghjklmnpqrstvwxz + i s e r", + "ize,izes,izer,izers,ized,izing,izings,ization,izations," + +"ises,ise,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenise) // British variant // ~expertise + + r(".aeiouy + e r", + "_,e,s,es,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful,ers,ered,erred,ering,erring,erings," + +"errings,erly,erness,ernesses,erment,erments,erless,erful,erer,erers," + +"erest,errer,errers,errest", + this), + // (e.g., actioner, atoner, icer, trader, accruer, churchgoer, prefer) + }; + + // For words ending in -est (est-rules): + + Rule[] estRules = { + r("bcdfghjklmnpqrstvwxyz + i e s t", + "y,ies,ier,iers,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses," + +"iment,iments,iless,iful", + this), + // (e.g., sliest, happiest, wittiest) + + r(".aeiouy l + l e s t", + "&,&s,&er,&ers,&ed,&ing,&ings,ly,&ness,&nesses,&ment,&ments,&ful", + this), + // (e.g., fullest) + + r(".aeiouy s + s e s t", + "&,&es,&er,&ers,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful", + this), + // (e.g., grossest) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprst + & e s t", + "_,s,&er,&ers,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., biggest) + + r(".aeiouy c h + e s t", + "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested," + +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful", + this), + + r(".aeiouy s h + e s t", + "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested," + +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful", + this), + + r(".aeiouy jxsz + e s t", + "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested," + +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful", + this), + // (e.g., basest, archest, rashest) + + r("e r + e s t", + "e,es,er,ers,ed,eing,eings,ely,eness,enesses,ement,ements,eless,eful," + +"ests,ester,esters,ested,esting,estings,estly,estness,estnesses," + +"estment,estments,estless,estful", + this), + // (e.g., severest, Xinterest, merest) + + r(".aeiouy + e s t", + "_,e,s,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments," + +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested,esting,estings," + +"estly,estness,estnesses,estment,estments,estless,estful", + this), + // (e.g., slickest, coolest, ablest, amplest, protest, quest) + // polysyllables - note that this picks up quest because of the + // u but the forms generated are harmless + + r("e s t +", + "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., rest, test) + // monosyllables + }; + + // For words ending in -ful (ful-rules ): + + Rule[] fulRules = { + r(".aeiouy bcdfghjklmnpqrstvwxyz + i f u l", + "ifully,ifulness,*y", + this), + // (e.g., beautiful, plentiful) + + r(".aeiouy + f u l", + "fully,fulness,*_", + this), + // (e.g., hopeful, sorrowful) + }; + + // For words ending in -ical: + + Rule[] icalRules = { + r(".aeiouy + i c a l", + "ic,ics,ically", + this), + // (e.g., academical, electrical, theatrical) + }; + + // For words ending in -ic: + + Rule[] icRules = { + r(".aeiouy + i c", + "ics,ical,ically", + this), + // (e.g., academic, clinic, mechanic, methodic) + // we're now booting on all redos (w/ or w/out e) as too risky + }; + + // For words ending in -ing (ing-rules): + + Rule[] ingRules = { + r("bcdfghjklmnpqrstvwxyz + y i n g", + "yings,ie,y,ies,ier,iers,iest,ied,iely,yly,ieness,yness,ienesses,ynesses," + +"iment,iments,iless,iful", + this), + // (e.g., dying, crying, supplying) + // did not add -ing forms (see last 8 ing-rules) + + r(".aeiouy l + l i n g", + "*_,&,&s,&er,&ers,&est,&ed,&ings,&ness,&nesses,&ment,&ments,&ful", + this), + // (e.g., pulling, filling, fulling) + // did not add -ing forms (see last 8 ing-rules) + // note that -ly has been dropped from this rule, as i believe + // that only a verb can be the stem here + + r(".aeiouy s + s i n g", + "&,&s,&er,&ers,&est,&ed,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful", + this), + // (e.g., hissing, grossing, processing) + // did not add -ing forms (see last 8 ing-rules) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + & i n g", + "_,s,&er,&ers,&est,&ed,&ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., hugging, trekking) + // did not add -ing forms (see last 8 ing-rules) + + r("+ e e i n g", + "ee,ees,eer,eers,eest,eed,eeings,eely,eeness,eenesses,eement,eements," + +"eeless,eeful", + this), + // (e.g., freeing, agreeing) + // did not add -ing forms (see last 8 ing-rules) + + r("+ e i n g", + "e,es,er,ers,est,ed,eings,ely,eness,enesses,ement,ements,eless,eful", + this), + // (e.g., ageing, aweing) + // did not add -ing forms (see last 8 ing-rules) + + r("aeiou y + i n g", + "_,s,er,ers,est,ed,ings,ly,ingly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., toying, playing) + // did not add -ing forms (see last 8 ing-rules) + + r(".aeiou bcdfghjklmnpqrstvwxyz eio t + i n g", + "*_,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., editing, crediting, expediting, siting, exciting + // deleting, completing, coveting, interpreting + // piloting, pivoting, devoting) + + r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmt + i n g", + "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., robing, siding, doling, translating, flaking) + // these consonants would double if there were no e in the stem + // removed p from this group: developing, galloping, etc. + // removed r from this group: monitoring, coloring, motoring + // removed n from this group: happening + + r(".aeiouy bcdfghjklmnpqrstvwxz + i z i n g", + "izes,izer,izers,ized,ize,izings,ization,izations," + +"ise,ises,iser,isers,ised,ising,isings,isation,isations", + this), + // (e.g., tokenize) // adds British variations + + r(".aeiouy bcdfghjklmnpqrstvwxz + i s i n g", + "ize,izes,izer,izers,ized,izing,izings,ization,izations," + +"ises,iser,isers,ised,ise,isings,isation,isations", + this), + // (e.g., tokenise) // British variant // ~expertise + + r("aeiouy cgsvz + i n g", + "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., icing, aging, achieving, amazing, housing) + // we had k in this list, but that's only right if the vowel + // is single - looking needs to be redone with _ + + r("bcdfghjklmnpqrstvwxyz clsuv + i n g", + "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., dancing, troubling, arguing, bluing, carving) + + r("lr g + i n g", + "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., charging, bulging) + + r(".aeiouy bcdfghjklmnpqrstvwxyz bdfjkmnpqrtwxz + i n g", + "*_,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., farming, harping, interesting, bedspring, redwing) + + r(".aeiouy + i n g", + "*_,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., spoiling, reviling, autoing, egging, hanging, hingeing, + // judging, breathing, mothing) + // these are the cases where we can't tell if e is needed or not + + r("+ i n g", + "ings,inger,ingers,ingest,inged,inging,ingings,ingly," + +"ingness,ingnesses,ingment,ingments,ingless,ingful", + this), + // (e.g., wing, thing) + // monosyllables + }; + + // For words ending in -leaf (leaf-rules): + + Rule[] leafRules = { + r("+ l e a f", + "leaves", + this), + // (e.g., cloverleaf, flyleaf) + // leaf itself is in the exceptions list + }; + + // For words ending in -man: + + Rule[] manRules = { + r("+ m a n", + "men,mans,maner,manner,manners,maners,manest,maned,manned,maning," + +"manning,manings,mannings,manly,manness,mannesses,manless,manful", + this), + // (e.g., woman, policeman, cayman, unman) + }; + + // For words ending in -men: + + Rule[] menRules = { + r("+ m e n", + "man,mens,mener,meners,menest,mened,mening,menings,menly," + +"menness,mennesses,menless,menful", + this), + // (e.g., policewomen, hatchetmen, dolmen) + }; + + // For words ending in -ment (ment-rules): + + Rule[] mentRules = { + r("s e g m e n t +", + "s,ed,ing,ings,er,ers,ly,ness,nesses,less,ful", + this), + // (e.g., segment, bisegment, cosegment) + + r("p i g m e n t +", + "s,ed,ing,ings,er,ers,ly,ness,nesses,less,ful", + this), + // (e.g., pigment, depigment, repigment) + + r(".aeiouy d g + m e n t", + "*e", + this), + // (e.g., judgment, abridgment) + + r(".aeiouy bcdfghjklmnpqrstvwxyz + i m e n t", + "*y", + this), + // (e.g., merriment, embodiment) + + r(".aeiouy + m e n t", + "*_", + this), + // (e.g., atonement, entrapment) + }; + + // For words ending in -o (o-rules): + + Rule[] oRules = { + r("aeiou o +", + "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., taboo, rodeo) + // no need to generate an es form + + r(".aeiouy o +", + "s,es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., tomato, bonito) + // make both s and es plurals + }; + + // For words ending in -um (um-rules): + + Rule[] umRules = { + r("+ u m", + "a,ums,umer,ummer,umers,ummers,umed,ummed,uming,umming,umings," + +"ummings,umness,umments,umless,umful", + this), + // (e.g., datum, quantum, tedium, strum, [oil]drum, vacuum) + }; + + // For words ending in -y (y-rules): + + Rule[] yRules = { + r(".aeiouy b + l y", + "le,les,ler,lers,lest,led,ling,lings,leness,lenesses,lement,lements," + +"leless,leful", + this), + // (e.g., ably, horribly, wobbly) + + r(".aeiouy bcdfghjklmnpqrstvwxyz + i l y", + "y,ies,ier,iers,iest,ied,ying,yings,yness,iness,ynesses,inesses," + +"iment,iments,iless,iful", + this), + // (e.g., happily, dizzily) + + r(".aeiouy f u l + l y", + "*_", + this), + // (e.g., peaceful+ly) + + r(".aeiouy l + l y", + "*_,lies,lier,liers,liest,lied,lying,lyings,liness,linesses," + +"liment,liments,liless,liful,*l", + this), + // (e.g., fully, folly, coolly, fatally, dally) + // both -l and -ll words + + r("aou + l y", + "lies,lier,liers,liest,lied,lying,lyings,liness,linesses," + +"liment,liments,liless,liful", + this), + // (e.g., monopoly, Xcephaly, holy) + // i.e., treat ly as part of the stem + + r("+ l y", + "*_,lies,lier,liers,liest,lied,lying,lyings,liness,linesses,lyless,lyful", + this), + // (e.g., frequently, comely, deeply, apply, badly) + // i.e., redo stem AND generate all forms with ly as part of stem + + r("bcdfghjklmnpqrstvwxyz + y", + "ies,ier,iers,iest,ied,ying,yings,ily,yness,iness,ynesses,inesses," + +"iment,iments,iless,iful,yment,yments,yless,yful", + this), + // (e.g., happy, spy, cry) + + r("aeiou y +", + "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., betray, gay, stay) + }; + + // For other words (root-rules): + + Rule[] rootRules = { + r(".aeiouy c h +", + "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + + r(".aeiouy s h +", + "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + + r(".aeiouy jxz +", + "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., fix, arch, rash) + + r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt +", + "s,er,ers,est,ed,ing,ings,&er,&ers,&est,&ed,&ing,&ings,ly," + +"ness,nesses,ment,ments,less,ful", + this), + // (e.g., unflag, open, besot) + // both possibilities for multisyllables + + r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt +", + "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., bed, cop) + + r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy m a + t a", + "_, s,tas,tum,tums,ton,tons,tic,tical", + this), + // (e.g., schemata, automata) + + r(".aeiouy t + a", + "as,ae,um,ums,on,ons,ic,ical", + this), + // (e.g., chordata, data, errata, sonata, toccata) + + r(".aeiouy .bcdfghjklmnpqrstvwxyz + a", + "as,ae,ata,um,ums,on,ons,al,atic,atical", + this), + // (e.g., schema, ova, polyhedra) + + r(".aeiouy l l +", + "s,er,ers,est,ed,ing,ings,y,ness,nesses,ment,ments,-less,ful", + this), + // (e.g., full) + // note: adds a hyphen before less + + r(".aeiouy +", + "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful", + this), + // (e.g., spoon, rhythm) + }; + + rulesTable = new Hashtable(); + rulesTable.put("s", sRules); + rulesTable.put("e", eRules); + rulesTable.put("ed", edRules); + rulesTable.put("er", erRules); + rulesTable.put("est", estRules); + rulesTable.put("ful", fulRules); + rulesTable.put("ic", icRules); + rulesTable.put("ical", icalRules); + rulesTable.put("ing", ingRules); + rulesTable.put("man", manRules); + rulesTable.put("men", menRules); + rulesTable.put("ment", mentRules); + rulesTable.put("leaf", leafRules); + rulesTable.put("o", oRules); + rulesTable.put("um", umRules); + rulesTable.put("y", yRules); + rulesTable.put("default", rootRules); + } + + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Location.java b/jhMaster/JSearch/client/com/sun/java/help/search/Location.java new file mode 100644 index 0000000000000000000000000000000000000000..701d0ad44e816195f579d03325e6a57a3c175b23 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Location.java @@ -0,0 +1,60 @@ +/* + * @(#)Location.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class Location +{ + private final int _docID; + private final int _begin; + private final int _end; + + public Location(int doc, int begin, int end) + { + _docID = doc; + _begin = begin; + _end = end; + } + + public int getDocument() { + return _docID; + } + + public int getBegin() { + return _begin; + } + + public int getEnd() { + return _end; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java new file mode 100644 index 0000000000000000000000000000000000000000..6c66ad7f11611e52894efe6eb3ec8ca449119e78 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java @@ -0,0 +1,158 @@ +/* + * @(#)MemoryRAFFile.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) MemoryRAFFile.java 1.12 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +/** + * A DICT (Dictionary) file cached in memory. + * + * @author Roger D. Brinkley + * @version 1.12 10/30/06 + */ + +import java.net.URL; +import java.net.URLConnection; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; + +public class MemoryRAFFile extends RAFFile { + + private URL url; + private byte[] data; + private int size; + private int filePointer; + + public MemoryRAFFile(URLConnection connection) throws IOException { + this.url = connection.getURL(); + + InputStream in = new BufferedInputStream(connection.getInputStream()); + ByteArrayOutputStream data = new ByteArrayOutputStream(); + + byte[] buf = new byte[512]; + int i = 0; + while((i = in.read(buf)) != -1) { + data.write(buf, 0, i); + } + this.data = data.toByteArray(); + size = data.size(); + filePointer = 0; + } + + public long length() { + return size; + } + + public void close() throws IOException { + filePointer = 0; + data = null; + size = 0; + } + + public long getFilePointer() throws IOException { + return filePointer; + } + + public void seek(long pos) throws IOException { + if (pos > size) { + throw new IOException(); + } + filePointer = (int)pos; + } + + public int read() throws IOException { + if (filePointer >= size) { + return -1; + } + filePointer += 1; + return data[filePointer - 1] & 0xFF; + } + + private int readBytes(byte b[], int off, int len) throws IOException { + debug ("readBytes"); + if (filePointer + off + len > size) { + throw new IOException(); + } + filePointer += off; + System.arraycopy(data, filePointer, b, 0, (int)len); + filePointer += len; + return len; + } + + public int read(byte b[], int off, int len) throws IOException { + return readBytes(b, off, len); + } + + public int readInt() throws IOException { + debug ("readInt"); + int ch1 = this.read(); + int ch2 = this.read(); + int ch3 = this.read(); + int ch4 = this.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) + throw new EOFException(); + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + public final void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + private void readFully (byte b[], int off, int len) + throws IOException { + int n = 0; + do { + int count = this.read(b, off + n, len - n); + if (count < 0) + throw new EOFException(); + n += count; + } while (n < len); + } + + public void writeInt(int v) throws IOException { + throw new IOException("Unsupported Operation"); + } + + public void write(byte b[]) throws IOException { + throw new IOException("Unsupported Operation"); + } + /** + * For printf debugging. + */ + private static boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("MemoryRAFFile: " + str); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..ca79beac31724c1ab4d5bbe0acccca7cc86c81ac --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java @@ -0,0 +1,90 @@ +/* + * @(#)NextDocGenerator.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class NextDocGenerator +{ + private int _document; + private final int _concept; + private final int _queryMask; + private final ConceptData _terms; + private final NonnegativeIntegerGenerator _iterator; + + public NextDocGenerator(ConceptData cd, SearchEnvironment env) + { + _document = 0; + _concept = cd.getConcept(); + _queryMask = cd.getQueryMask(); + _terms = cd; + _iterator = env.getDocumentIterator(_concept); + } + + public int first() throws Exception { + return _document = + _iterator != null ? _iterator.first() : NonnegativeIntegerGenerator.END; + } + + public int next() throws Exception { + return _document = _iterator.next(); + } + + public int getDocument() { + return _document; + } + + public int getConcept() { + return _concept; + } + + public ConceptData getTerms() { + return _terms; + } + + public int getQueryMask() { + return _queryMask; + } + + // for sorting + public boolean compareWith(NextDocGenerator other) + { + return _document > other._document + || _document == other._document && _concept > other._concept; + } + + public boolean smallerThan(NextDocGenerator other) + { + return _document < other._document + || _document == other._document && _concept < other._concept; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java new file mode 100644 index 0000000000000000000000000000000000000000..fd4f157d401d0ef7efca1ca58dbd59032ef1541f --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java @@ -0,0 +1,127 @@ +/* + * @(#)NextDocGeneratorHeap.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class NextDocGeneratorHeap +{ + private static final int InitSize = 1024; + + private int _heapSize = 0; + private int _size = InitSize; + private NextDocGenerator[] _heap = new NextDocGenerator[InitSize]; + private int _free = 0; + private boolean _nonEmpty = false; + + public boolean isNonEmpty() { + return _nonEmpty; + } + + public void addGenerator(NextDocGenerator gen) + { + if (_free == _size) + { + NextDocGenerator[] newArray = new NextDocGenerator[_size *= 2]; + System.arraycopy(_heap, 0, newArray, 0, _free); + _heap = newArray; + } + _heap[_free++] = gen; + } + + public void start() + { + if ((_heapSize = _free) > 0) + { + // build heap + for (int i = _heapSize/2; i >= 0; i--) + heapify(i); + _nonEmpty = true; + } + else + _nonEmpty = false; + } + + public void step() throws Exception + { + if (_heap[0].next() != NonnegativeIntegerGenerator.END) + heapify(0); + else if (_heapSize > 1) + { + _heap[0] = _heap[--_heapSize]; + heapify(0); + } + else + _nonEmpty = false; + } + + public int getDocument() { + return _heap[0].getDocument(); + } + + public int getConcept() { + return _heap[0].getConcept(); + } + + public ConceptData getTerms() { + return _heap[0].getTerms(); + } + + public int getQueryMask() { + return _heap[0].getQueryMask(); + } + + public void reset() + { + _nonEmpty = false; + _free = 0; + } + + public boolean atDocument(int document) { + return _nonEmpty && _heap[0].getDocument() == document; + } + + private void heapify(int i) + { + int r = (i + 1) << 1, l = r - 1; + int smallest = l < _heapSize && _heap[l].smallerThan(_heap[i]) ? l : i; + if (r < _heapSize && _heap[r].smallerThan(_heap[smallest])) + smallest = r; + if (smallest != i) + { + NextDocGenerator temp = _heap[smallest]; + _heap[smallest] = _heap[i]; + _heap[i] = temp; + heapify(smallest); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..76cdb9a7ac0244aadf3725728d4d77ea03a65b33 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java @@ -0,0 +1,42 @@ +/* + * @(#)NonnegativeIntegerGenerator.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +interface NonnegativeIntegerGenerator +{ + int END = -1; + + int first() throws Exception; + int next() throws Exception; +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Query.java b/jhMaster/JSearch/client/com/sun/java/help/search/Query.java new file mode 100644 index 0000000000000000000000000000000000000000..170eed32eac7ea245b78eefe5a911971fc59a5c3 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Query.java @@ -0,0 +1,177 @@ +/* + * @(#)Query.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.util.*; +import javax.help.search.SearchQuery; +import javax.help.search.SearchItem; + +class Query +{ + + private double _currentStandard; + private final int _nColumns; + private double[] _missingPenalty; + private double[] _upperboundTemplate; + private double[] _penalties; + + private final SearchEnvironment _env; + private int _hitCounter; + private boolean _vote; + + private HitStore _store; + + public Query(SearchEnvironment env, int nColumns, double[] missingPenalties) + { + _env = env; + _nColumns = nColumns; + _missingPenalty = new double[nColumns]; + _upperboundTemplate = new double[nColumns]; + _penalties = missingPenalties; + _hitCounter = 0; + _vote = false; + _currentStandard = (nColumns - 1) * 10.0 + 9.9999; + _store = new HitStore(_currentStandard); + for (int i = 0; i < _nColumns; i++) + _missingPenalty[i] = missingPenalties != null + ? missingPenalties[i] + : 10.0; + makePenaltiesTable(); + } + + public void makeEvent(int n, SearchQuery searchQuery) + { + Vector hits = new Vector(n); + + if (n > 0) + { + int N = n; + QueryHit qh = _store.firstBestQueryHit(); + n = N; + for ( ; qh != null; qh = --n > 0 ? _store.nextBestQueryHit() : null) + try { + hits.addElement(_env.makeItem(qh)); + } + catch (Exception e) { + System.err.println(e + "hit not translated"); + } + } + // Params not know at this time + searchQuery.itemsFound(true, hits); + } + + public double lookupPenalty(int pattern) { + return _penalties[pattern]; + } + + public double getOutOufOrderPenalty() { + return 0.25; + } + + public double getGapPenalty() { + return 0.005; + } + + public int getNColumns() { + return _nColumns; + } + + public boolean goodEnough(double penalty) { + return penalty <= _currentStandard; + } + + public int[] getConceptArrayOfNewHit(double penalty, Location loc) + { + QueryHit hit = new QueryHit(loc, penalty, _nColumns); + _store.addQueryHit(hit); + _hitCounter++; + return hit.getArray(); + } + + public void resetForNextDocument() + { + _currentStandard = _store.getCurrentStandard(); + // "everything's missing" + for (int i = 0; i < _nColumns; i++) + _upperboundTemplate[i] = _missingPenalty[i]; + _vote = false; + } + + public boolean vote() + { + double sum = 0.0; + for (int i = 0; i < _nColumns; i++) + sum += _upperboundTemplate[i]; + return _vote = (sum <= _currentStandard); + } + + public void updateEstimate(int role, double penalty) { + if (penalty < _upperboundTemplate[role]) + _upperboundTemplate[role] = penalty; + } + + public void printHits(int n) + { + if (n > 0) + { + int N = n; + QueryHit qh = _store.firstBestQueryHit(); + n = N; + for ( ; qh != null; qh = --n > 0 ? _store.nextBestQueryHit() : null) + try { + System.out.println(_env.hitToString(qh)); + } + catch (Exception e) { + System.err.println(e + "hit not translated"); + } + } + } + + private void makePenaltiesTable() + { + int nPatterns = 1 << _nColumns; + _penalties = new double[nPatterns]; + for (int i = 0; i < nPatterns; i++) + _penalties[i] = computePenalty(i); + } + + private double computePenalty(int n) + { + double penalty = 0.0; + for (int i = 0; i < _nColumns; i++) + if ((n & 1 << i) == 0) + penalty += _missingPenalty[i]; + return penalty; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java b/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..a3b14a548d34bd5110b1de6b9d3c9dea5220da01 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java @@ -0,0 +1,235 @@ +/* + * @(#)QueryEngine.java 1.25 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @version 1.25 10/30/06 + */ + +package com.sun.java.help.search; + +import java.text.BreakIterator; +import java.util.Vector; +import java.util.Locale; +import java.util.Enumeration; +import java.lang.reflect.Method; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.File; +import java.net.URL; +import javax.help.search.SearchQuery; +import javax.help.HelpUtilities; + +/** + * This class is the initial interface into the search engine. It can be + * run as a standalone search engine or instantiated as a class. + * + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.25 10/30/06 + */ + +public class QueryEngine +{ + private SearchEnvironment _env; + + public QueryEngine(String indexDir, URL hsBase) throws Exception { + _env = new SearchEnvironment(indexDir, hsBase); + } + + public void processQuery(String query, Locale l, SearchQuery searchQuery) throws Exception + { + BreakIterator boundary; + int start; + String term; + Vector ids = new Vector();; + LiteMorph morph = getMorphForLocale(l); + int col=-1; + + try { + boundary = BreakIterator.getWordInstance(l); + boundary.setText(query); + start = boundary.first(); + for (int end = boundary.next(); + end != BreakIterator.DONE; + start = end, end = boundary.next()) { + term = new String(query.substring(start,end)); + term = term.trim(); + term = term.toLowerCase(l); + if (term.length() > 1) { + col += 1; + int id = _env.fetch(term); + if (id > 0) { + ids.addElement(new SearchIds(col, id, 0.0)); + } + if (morph != null) { + String [] morphs = morph.variantsOf(term); + for (int i=0; i < morphs.length ; i++) { + int id2 = _env.fetch(morphs[i]); + if (id2 > 0) { + ids.addElement(new SearchIds(col, id2, 0.1)); + } + } + } + } else if (term.length() == 1) { + int charType = Character.getType(term.charAt(0)); + if ((charType == Character.DECIMAL_DIGIT_NUMBER) || + (charType == Character.LETTER_NUMBER) || + (charType == Character.LOWERCASE_LETTER) || + (charType == Character.OTHER_LETTER) || + (charType == Character.OTHER_NUMBER) || + (charType == Character.TITLECASE_LETTER) || + (charType == Character.UNASSIGNED) || + (charType == Character.UPPERCASE_LETTER)) { + col += 1; + int id = _env.fetch(term); + if (id > 0) { + ids.addElement(new SearchIds(col, id, 0.0)); + } + if (morph != null) { + String [] morphs = morph.variantsOf(term); + for (int i=0; i < morphs.length ; i++) { + int id2 = _env.fetch(morphs[i]); + if (id2 > 0) { + ids.addElement(new SearchIds(col, id2, 0.1)); + } + } + } + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + int size = ids.size(); + Search search = new Search(_env, col + 1); + IntegerArray children = new IntegerArray(); + + // add the terms and any children of a given term to the list of + // searched items. Penalize the children slightly + for (int i = 0; i < size; i++) + { + SearchIds id = (SearchIds) ids.elementAt(i); + search.addTerm(id.col, id.concept, id.score, 0); + children.clear(); + _env.getChildren(id.concept, children); + if (children.cardinality() > 0) + for (int j = 0; j < children.cardinality(); j++) + { + search.addTerm(id.col, children.at(j), + id.score + 0.1, 0); + // appending (grand)+children + //!!! as it is too many duplicates are added + _env.getChildren(children.at(j), children); + } + } + + search.startSearch(searchQuery); + } + + private LiteMorph getMorphForLocale(Locale l) { + // In the event that nolocale has been defined try English + if (l == null) { + l = Locale.ENGLISH; + } + //Try to find a locale version of LiteMorph + Enumeration enum1 = HelpUtilities.getCandidates(l); + String front = "com.sun.java.help.search.LiteMorph"; + ClassLoader cl = QueryEngine.class.getClassLoader(); + while (enum1.hasMoreElements()) { + String tail = (String) enum1.nextElement(); + String name = new String(front + tail); + try { + Class klass; + if (cl == null) { + klass = Class.forName(name); + } else { + klass = cl.loadClass(name); + } + Method method = klass.getMethod ("getMorph", + (java.lang.Class[]) null); + return (LiteMorph) method.invoke(null, + (java.lang.Object[]) null); + } catch (Exception e) { + continue; + } + } + // couldn't find a match + return null; + } + + + public static void main(String[] args) + { + try { + // BufferedReader is needed for readLine() method + BufferedReader in = + // but we'll make it a degenerate buffer of 1 + // to workaround a problem with some PC implementation + // which wouldn't start to read before a lot of chars + // were typed + new BufferedReader(new InputStreamReader(System.in), 1); + String file = new String (args[0]); + QueryEngine qe = new QueryEngine(file, null); + System.out.println("initialized; enter query"); + while(true) + { + String line = in.readLine(); + if (line.equals(".")) + break; + else + { + long start = System.currentTimeMillis(); + qe.processQuery(line, Locale.getDefault(), null); + System.out.println((System.currentTimeMillis()-start) + +" msec search"); + } + System.out.println("enter next query or . to quit"); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private class SearchIds { + public int col; + public int concept; + public double score; + + public SearchIds (int col, int concept, double score) { + this.col = col; + this.concept = concept; + this.score = score; + } + + public String toString() { + return "col=" + col + " concept=" + concept + " score=" + score; + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java b/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java new file mode 100644 index 0000000000000000000000000000000000000000..b99a27b7ef32d440f810efc262fdfa43d6684fae --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java @@ -0,0 +1,87 @@ +/* + * @(#)QueryHit.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +class QueryHit +{ + private int _doc; + private int _begin; + private int _end; + private double _score; + private final int[] _concepts; + + public QueryHit(Location loc, double penalty, int nColumns) + { + _score = penalty; + _doc = loc.getDocument(); + _begin = loc.getBegin(); + _end = loc.getEnd(); + _concepts = new int[nColumns]; + } + + public String toString() { + return "[doc = "+_doc+", "+_begin+", "+_end+", "+_score+"]"; + } + + public int getDocument() { + return _doc; + } + + public int getBegin() { + return _begin; + } + + public int getEnd() { + return _end; + } + + public double getScore() { + return _score; + } + + public int[] getArray() { + return _concepts; + } + + public boolean betterThan(QueryHit x) + { + if (_score < x._score) return true; + if (_score > x._score) return false; + if (_begin < x._begin) return true; + if (_begin > x._begin) return false; + if (_end < x._end) return true; + if (_end > x._end) return false; + return false; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java new file mode 100644 index 0000000000000000000000000000000000000000..cd066537727c887e7185ad29fec7c20d15569c2c --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java @@ -0,0 +1,116 @@ +/* + * @(#)RAFFile.java 1.14 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) RAFFile.java 1.14 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.IOException; + +/** + * This class can be used to read/write the contents of a RAF type files + * (i.e. DICT (Dictionary) & POSITIONS (Positions)) + * file as part of JavaHelp Search Database. It uses RandamAccessFile for + * quick access to dictionary blocks (DictBlock). + * </p> + * Extension of this class serve include memory resident or unwriteable + * RAFFile. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.14 10/30/06 + */ + +import java.net.URL; +import java.io.RandomAccessFile; +import java.io.File; +import java.io.IOException; + +public class RAFFile { + private RandomAccessFile raf; + + protected RAFFile() { + } + + public RAFFile(String name, boolean update) throws IOException { + debug("RAFFile " + name); + raf = new RandomAccessFile(name, update?"rw":"r"); + } + + public long length() throws IOException { + return raf.length(); + } + + public long getFilePointer() throws IOException { + return raf.getFilePointer(); + } + + public void close() throws IOException { + raf.close(); + } + + public void seek(long pos) throws IOException { + raf.seek(pos); + } + + public int readInt() throws IOException { + return raf.readInt(); + } + + public int read() throws IOException { + return raf.read(); + } + + public void readFully (byte b[]) throws IOException { + raf.readFully(b); + } + + public int read(byte[] b, int off, int len) throws IOException { + return raf.read(b, off, len); + } + + public void writeInt(int v) throws IOException { + raf.writeInt(v); + } + + public void write(byte b[]) throws IOException { + raf.write(b); + } + + /** + * Debug code + */ + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("RAFFile: "+msg); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..1d80b0db99155d6dd94fab0d736caf73c17c255c --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java @@ -0,0 +1,171 @@ +/* + * @(#)RAFFileFactory.java 1.27 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) RAFFileFactory.java 1.27 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.lang.reflect.*; + +/** + * A factory for files that can be accessed as Random Access file from a URL. + * RAFFiles can either be an acutall RAF file or a memory version of the + * RAF file. When a URL is it is opened as a RAF file, otherwise it is moved + * to a temporary file if possible or into a memory resident version. + * + * + * @author Roger D. Brinkley + * @version 1.27 10/30/06 + */ +class RAFFileFactory { + + /** + * Cannot create these, need to go through the factory method + */ + private RAFFileFactory() { + } + + static RAFFileFactory theFactory; + + public static synchronized RAFFileFactory create() { + if (theFactory == null) { + theFactory = new RAFFileFactory(); + } + return theFactory; + } + + /* For this connection, when to cache in memory and when to disk */ + private int memoryCacheLimit = 10000; + + private boolean isFileURL(URL url) { + return url.getProtocol().equalsIgnoreCase("file"); + } + + public int getMemoryCacheLimit() { + return memoryCacheLimit; + } + + public void setMemoryCacheLimit(int limit) { + this.memoryCacheLimit = limit; + } + + public synchronized RAFFile get(URL url, boolean update) + throws IOException { + + RAFFile result = null; + + if (isFileURL(url)) { + try { + String f = url.getFile(); + + // Normalize the string. This is required because of a + // backwards incompatability change in JDK 1.4.0 and later + // releases. + f = Utilities.URLDecoder(f); + + // refactor so it runs with verification on... + + // Object o = new FilePermission(f, update ? "write":"read"); + // here -- check if AccessController.checkPermission(p); + + result = new RAFFile(f, update); + debug ("Opened Dict file with file protocol:" + f); + } catch (SecurityException e) { + // cannot do "it" -- code is not yet in place + } + } + if (result == null) { + result = createLocalRAFFile(url); + } + if (result == null) { + throw new FileNotFoundException(url.toString()); + } + return result; + } + + + /** + * Given a URL, retrieves a DICT file and creates a cached DICT + * file object. If the file is larger than the size limit, + * and if temp files are supported by the Java virtual machine, + * the DICT file is it is cached to disk. Otherwise the DICT file + * is cached in memory. + */ + private static RAFFile createLocalRAFFile(URL url) throws IOException { + + RAFFile result = null; + URLConnection connection = url.openConnection(); + + // We should be able to just do a catch on missing method but + // IE4.0 does not like this + // + // try { + // Object foo = connection.getPermission(); + // + // result = RAFFileFactoryOn12.get(connection); + // + // } catch (NoSuchMethodError ex) { + // // on 1.1 all we can do is create a memory file + // result = new MemoryRAFFile(connection); + // debug ("Opening a Dict file in Memory"); + // } + // + + try { + Class types[] = {}; + Method m = URLConnection.class.getMethod("getPermission", types); + result = RAFFileFactoryOn12.get(connection); + } catch (NoSuchMethodError ex) { + // as in JDK1.1 + } catch (NoSuchMethodException ex) { + // as in JDK1.1 + } + + if (result == null) { + // on 1.1 all we can do is create a memory file + result = new MemoryRAFFile(connection); + debug ("Opening a Dict file in Memory"); + } + return result; + } + + /** + * Debug code + */ + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("RAFFileFactory: "+msg); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java new file mode 100644 index 0000000000000000000000000000000000000000..8d5fa55e0ab2919fb3a2ae6d7c17a7f27f67b163 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java @@ -0,0 +1,121 @@ +/* + * @(#)RAFFileFactoryOn12.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) RAFFileFactoryOn12.java 1.4 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.net.URLConnection; +import java.security.Permission; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +/** + * This Factory assumes we are on JDK 1.2 + */ + +final public class RAFFileFactoryOn12 { + /** + * Creata a RAFFile from a URLConnection. Try to use a temporary file + * if possible. This is a static public method + * + * @param url The URL with the data to the file + * @return the RAFFile for this data + * @exception IOException if there is problem reading from the file + */ + public static RAFFile get(final URLConnection connection) throws IOException { + RAFFile topBack = null; + + debug("get on "+connection); + final Permission permission = connection.getPermission(); + + /* get the permission after the connection is established */ + int dictLength = connection.getContentLength(); + + try { + topBack = (RAFFile) + AccessController.doPrivileged(new PrivilegedExceptionAction() { + + RAFFile back = null; + public Object run() throws IOException { + InputStream in = null; + OutputStream out = null; + try { + File tmpFile = File.createTempFile("dict_cache", null); + tmpFile.deleteOnExit(); + + if (tmpFile != null) { + in = connection.getInputStream(); + out = new FileOutputStream(tmpFile); + int read = 0; + byte[] buf = new byte[BUF_SIZE]; + while ((read = in.read(buf)) != -1) { + out.write(buf, 0, read); + } + back = new TemporaryRAFFile(tmpFile, permission); + } else { + back = new MemoryRAFFile(connection); + } + } finally { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + return back; + } + }); + } catch (PrivilegedActionException pae) { + topBack = new MemoryRAFFile(connection); + } catch (SecurityException se) { + topBack = new MemoryRAFFile(connection); + } + return topBack; + } + + // The size of the buffer + private static int BUF_SIZE = 2048; + + /** + * Debug code + */ + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("RAFFileFactoryOn12: "+msg); + } + } +} + diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java b/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java new file mode 100644 index 0000000000000000000000000000000000000000..f29b00c8e85dc87de6eae68a3e6ced34a6825541 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java @@ -0,0 +1,198 @@ +/* + * @(#)RoleFiller.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.PrintStream; + +class RoleFiller +{ + static int Threshold = 300; + + private ConceptData _conceptData; + private byte _fixedRole; + private short _filled; + private int _begin; + private int _end; + private int _limit; + private RoleFiller _next; + private RoleFiller[] _fillers; + + public static final RoleFiller STOP = new RoleFiller(); + + private RoleFiller() {} + + public RoleFiller(int nColumns, ConceptData first, int role, + int pos, int limit) + { + _conceptData = first; + _fixedRole = (byte)role; // primary/constitutive concept/role + _filled = (short)(1 << _fixedRole); + _begin = pos; // offset in file + _end = _begin + first.getConceptLength(); + _limit = limit; + _next = null; + _fillers = new RoleFiller[nColumns]; + _fillers[role] = this; + } + + public void print(PrintStream out) { + out.println(_begin + ", " + _end); + } + + void makeQueryHit(Query q, int nColumns, int doc, double penalty) + { + if (q.goodEnough(penalty)) + { + int[] array = + q.getConceptArrayOfNewHit(penalty, + new Location(doc, _begin, _end)); + for (int i = 0; i < nColumns; i++) + array[i] = (_filled & 1 << i) != 0 ? _fillers[i].getConcept() : 0; + } + } + + boolean isHit() { + return _filled > (1 << _fixedRole); + } + + double getScore() { + return _conceptData.getScore(); + } + + int getConcept() { + return _conceptData.getConcept(); + } + + RoleFiller next() { + return _next; + } + + void use(RoleFiller[] place, int index) + { + if (place[index] != null) + { + RoleFiller rf = place[index]; + place[index] = this; + _next = rf; + while (rf._limit >= _begin) + { + // check if we can grow/improve a hit + // we don't ever replace filler's fixed role + if (_fixedRole != rf._fixedRole) + { + if ((rf._filled & (1 << _fixedRole)) == 0) // not filled yet + { + rf._filled |= 1 << _fixedRole; + rf._fillers[_fixedRole] = this; + rf._end = _end; + } + else + rf.considerReplacementWith(this); + } + + if (rf._next != null) + rf = rf._next; + else + return; + } + } + else + place[index] = this; + } + + private void considerReplacementWith(RoleFiller replacement) + { + // !!! simplistic for now + // needs gap and out of order + int role = replacement._fixedRole; + if (replacement.getScore() > _fillers[role].getScore()) + _fillers[role] = replacement; + } + + private double penalty(Query query, int nColumns) + { + int length = _end - _begin + 1; + double penalty = query.lookupPenalty(_filled); + // !!! here is a chance to check against query if hit worth scoring further + // might not be if query already has lots of good hits + for (int i = 0; i < nColumns; i++) + if ((_filled & (1 << i)) != 0) + { + penalty += _fillers[i]._conceptData.getPenalty(); + length -= _fillers[i]._conceptData.getConceptLength() + 1; + if ((_filled >> (i + 1)) != 0) + for (int j = i + 1; j < nColumns; j++) + if ((_filled & 1 << j) != 0 && _fillers[j]._begin < _begin) + penalty += query.getOutOufOrderPenalty(); + } + return penalty + length*query.getGapPenalty(); + } + + public void scoreList(Query query, int document) + { + int nColumns = query.getNColumns(); + RoleFiller candidateHit = this; // function called for the head of list + RoleFiller next; // lookahead: if overlap, if so, is it better + + // 'candidateHit' always points at the current candidate to be converted to a QueryHit + // 'penalty' is its penalty + // 'next' is used to explore earlier overlapping fillers + // the decision to emit a QueryHit is made when either there's no next + // or next doesn't overlap the current candidate + // the loop's logic makes sure that at emit time there's no better/earlier filler + // to overlap with the candidate + + double penalty = candidateHit.penalty(query, nColumns); + + for (next = candidateHit._next; next != null; next = next._next) + if (next._end < candidateHit._begin) // no overlap + { + candidateHit.makeQueryHit(query, nColumns, document, penalty); + candidateHit = next; + penalty = candidateHit.penalty(query, nColumns); + } + else + { + // !!! can be computed in two steps + double penalty2 = next.penalty(query, nColumns); + if (penalty2 <= penalty) // prefer next, disregard candidateHit + { + penalty = penalty2; + candidateHit = next; + } + } + candidateHit.makeQueryHit(query, nColumns, document, penalty); + } + +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java b/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java new file mode 100644 index 0000000000000000000000000000000000000000..39204bcbfecc4e6c31d3102607b07be1b65bb2c2 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java @@ -0,0 +1,245 @@ +/* + * @(#)Rule.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) Rule.java 1.3 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.util.Vector; +import java.util.StringTokenizer; + +/** + * A Rule matches a pattern at the right ends of a word, removes an indicated + * number of characters from the end to produce a stem, and generate a list + * of alternative forms of the word by adding each of a specified list of + * endings to the stem. + * <p> + * Each rule specifies an ending pattern and a list + * of endings to be added to the stem to produce different variant forms + * of the input word. The ending pattern consists of a string of letters + * or letter groups separated by spaces to be matched against corresponding + * letters at the end of the word. + * <ul> + * <li> + * A letter group (e.g., aeiou) will match any of the letters in the group. + * <li> + * A letter group prefixed with a period (.) may be matched anywhere + * preceding the match of its subsequent letter group. A letter group + * of this type is referred to as "unanchored." + * <li> + * A group that is to be matched at a specified position is "anchored." + * <li> + * A plus sign (+) in the pattern, in place of a letter group, marks the + * point in the pattern after which the matching letters will be removed + * to form the stem. There should be no unanchored letter groups after + * the plus sign, and there should be at most one plus sign in the pattern + * (otherwise only the leftmost will count). + * <li> + * An ampersand (&) in place of + * a letter group in an ending pattern will match a letter that is the same + * as its preceeding letter in the word. + * <li> + * An ampersand in the list of alternative endings indicates a repeat of + * the letter that ends the stem. + * <li> + * An under bar (_) as an alternative ending indicates that nothing is to + * be added to the stem for that alternative. + * <li> + * An ending beginning with an + * asterisk (*) indicates that the rules are to be reapplied recursively to + * the form obtained from using this ending. + * </ul> + * <p> + * Rule(s) are grouped in blocks and labeled (usually by a common final + * sequence) and are ordered within each group so that after a matching + * rule is found no further rules are to be tried (except when invoked + * explicitly on a new word by a redo (*) operator in an alternative ending). + * + * @author Roger D. Brinkley + * @author Jacek Ambroziak + * @version 1.3 10/30/06 + * + * @see LiteMorph + */ + +public class Rule { + private String[] pattern; + private int killnum=0; + private String[] expansions; + private Vector words; + private LiteMorph morph; + + /** + * Create a Rule + * @param expression A String representing the ending patern described previously. + * @param expansionString A String of space delimeted expansions as described previously. + */ + public Rule(String expression, String expansionString, LiteMorph morph) { + String chars; + boolean passedPlus = false; + + this.morph = morph; + + //set up pattern array: + + if (expression.length() > 0) { + Vector patternBuffer = new Vector(expression.length()); + StringTokenizer temp = new StringTokenizer(expression, " \t\n\r"); + while (temp.hasMoreTokens()) { + if (passedPlus) { + // count number of characters after + + killnum++; + } + chars = temp.nextToken(); + if (chars.equals("+")) { + passedPlus = true; + } else { + patternBuffer.addElement(chars); + } + } + pattern = new String[patternBuffer.size()]; + patternBuffer.copyInto(pattern); + } + else pattern = new String[0]; + + //set up expansions array: + if (expansionString.length() > 0) { + Vector expansionsBuffer = new Vector(expansionString.length()); + StringTokenizer temp = new StringTokenizer(expansionString, ", \t\n\r"); + while (temp.hasMoreTokens()) { + expansionsBuffer.addElement(temp.nextToken()); + } + expansions = new String[expansionsBuffer.size()]; + expansionsBuffer.copyInto(expansions); + } + else { + expansions = new String[0]; + } + } + + /** + * Determines if a word matches the rule + */ + public String [] match(String word, int depth, int skipnum) { + words = new Vector(); + boolean matched = true; + + //skipnum positions have already been + //tested by the dispatch method + int position = word.length()-1-skipnum; + int i = pattern.length-1-skipnum; + while (i > -1) { + debug(" trying "+pattern[i]+" at "+position+ + " for i = "+i); + // There isn't anything left to test + // the match failed + if (position<0) { + matched = false; + break; + } + + //"&" match duplicate of previous letter + if (pattern[i].equals("&")) { + if (position < 1 || word.charAt(position) != word.charAt(position-1)) { + matched = false; + break; + } + else i--; + } + + //"." pattern can match anywhere + else if (pattern[i].startsWith(".")) { + if (pattern[i].indexOf(word.charAt(position), 1) >= 0) { + //it matches here, so go to next pattern element + i--; + } + } else if (pattern[i].indexOf(word.charAt(position))<0) { + // doesn't match here + matched = false; + break; + } else { + i--; + } + position--; + } + + // All done with the compares. If we've got a match then + // build the list words from the expansion list + if (matched) + { + String stem = word.substring(0, word.length() - killnum); + for (i = 0; i < expansions.length; i++) { + makeForm(stem, expansions[i], depth); + } + } + String[] result = new String[words.size()]; + words.copyInto(result); + words = null; + return result; + } + + + private void makeForm(String stem, String expansion, int depth) { + switch (expansion.charAt(0)) { + case '_': + // just use the stem; nothing to add + words.addElement(stem); + break; + + case '&': + // double last letter of stem + words.addElement(stem + stem.charAt(stem.length() - 1) + expansion.substring(1)); + break; + + case '*': + // redo MorphWord on the resulting form + debug(" starting redo: with "+stem+" + "+expansion+ + " from depth "+depth); + if (expansion.charAt(1) == '_') + morph.morphWord(stem, depth + 1); + else + morph.morphWord(stem + expansion.substring(1), depth + 1); + break; + + default: + words.addElement(stem + expansion); + break; + } + } + /** + * For printf debugging. + */ + private static final boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("Rule: " + str); + } + } +} + diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java b/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java new file mode 100644 index 0000000000000000000000000000000000000000..5d259a6d8fbc2e9de79bf8acabaa99265c8f6e66 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java @@ -0,0 +1,194 @@ +/* + * @(#)Schema.java 1.11 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @version 1.5 03/18/98 + * @author Jacek R. Ambroziak + */ + +package com.sun.java.help.search; + +import java.util.Vector; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.net.URL; +import java.net.URLConnection; +import java.io.*; + +public class Schema +{ + private String _dirName; + private URL _hsBase = null; + private boolean _update; + private Vector _lines = new Vector(); + + public static void main(String[] args) + { + try { + Schema sch = new Schema(null, "/files/resources/lexicon/LIF_ONT", false); + debug(sch.parametersAsString("EDGE")); + debug(sch.parametersAsString("TMAP")); + debug(sch.parameters("EDGE").get("rt").toString()); + debug(sch.parameters("EDGE").get("vl").toString()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + public Schema(URL base, String dirName, boolean update) throws Exception + { + _hsBase = base; + _dirName = dirName; + _update = update; + try { + read(); + } + catch (java.io.FileNotFoundException e) { + debug("error creating SCHEMA"); + } + for (int i = 0; i < _lines.size(); i++) + debug(_lines.elementAt(i).toString()); + } + + public void update(String partName, String parameters) + { + for (int i = 0; i < _lines.size(); i++) + if (((String)_lines.elementAt(i)).startsWith(partName)) + _lines.removeElementAt(i); + _lines.addElement(partName + " " + parameters); + } + + public String parametersAsString(String name) + { + for (int i = 0; i < _lines.size(); i++) + if (((String)_lines.elementAt(i)).startsWith(name)) + return ((String)_lines.elementAt(i)).substring(name.length() + 1); + return null; + } + + public Hashtable parameters(String name) + { + for (int i = 0; i < _lines.size(); i++) + if (((String)_lines.elementAt(i)).startsWith(name)) + { + Hashtable result = new Hashtable(); + StringTokenizer tokens = + new StringTokenizer((String)_lines.elementAt(i), " ="); + tokens.nextToken(); // skip name + while (tokens.hasMoreTokens()) + result.put(tokens.nextToken(), tokens.nextToken()); + return result; + } + return null; + } + + public URL getURL(String name) throws Exception + { + URL baseURL=null, url, tmapURL=null; + URLConnection connect; + File file; + + debug("getURL " + name); + debug("dirName=" + _dirName + " hsBase= " + _hsBase); + + if (_hsBase == null) { + file = new File(_dirName); + if (file.exists()) { + // On Win32 we need to convert all "\" to "/" + if (File.separatorChar != '/') { + _dirName = _dirName.replace(File.separatorChar, '/'); + } + // Make sure the last character is a file separator + if (_dirName.lastIndexOf('/') + != _dirName.length() - 1) { + _dirName = _dirName.concat("/"); + } + debug ("file:" + _dirName); + // Use a file protocol + baseURL = new URL("file", "", _dirName); + } else { + // Assume that some protocol was specified and try it + baseURL = new URL(_dirName); + } + } + + // Read the SCHEMA data + if (_hsBase != null) { + return new URL(_hsBase, _dirName + "/" + name); + } else { + return new URL(baseURL, name); + } + } + + public void save() + { + if (_update) { + try { + FileWriter out = new FileWriter(_dirName + "/SCHEMA"); + out.write("JavaSearch 1.0\n"); + for (int i = 0; i < _lines.size(); i++) + { + out.write((String)_lines.elementAt(i)); + out.write('\n'); + } + out.close(); + } + catch (IOException e) { + System.err.println("SCHEMA save failed " + e); + } + } + } + + private void read() throws Exception + { + URL url; + URLConnection connect; + BufferedReader in; + + url = getURL("SCHEMA"); + connect = url.openConnection(); + in = new BufferedReader + (new InputStreamReader(connect.getInputStream())); + + // This needs to be replaced with our XML Parser + String line; + while ((line = in.readLine()) != null) + _lines.addElement(line); + in.close(); + } + + /** + * For printf debugging. + */ + private static boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("Schema: " + str); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Search.java b/jhMaster/JSearch/client/com/sun/java/help/search/Search.java new file mode 100644 index 0000000000000000000000000000000000000000..1389238e1c908dc8c35b48d714a503a73aeac222 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Search.java @@ -0,0 +1,422 @@ +/* + * @(#)Search.java 1.17 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; +import javax.help.search.SearchQuery; + +class Search +{ + private static final int InitNConcepts = 128; + + private SearchEnvironment _env; + private int _max; + private int _nConcepts; + private int _nQueries; + private ConceptGroupGenerator _firstGenerator = new ConceptGroupGenerator(); + private int[] _concepts = new int[DocumentCompressor.NConceptsInGroup]; + private int _free2; + private int _size2; + private int _startingIndex = 0; + private int _limit = 0; + private Query[] _query; + private ConceptData[] _conceptData; + private GeneratorHeap _genHeap = new GeneratorHeap(); + private int _document; + private byte[] _data = null; + private int _base = 0; // index into _data + private NextDocGeneratorHeap _nextDocGenHeap = new NextDocGeneratorHeap(); + private IntegerArray _kTable = new IntegerArray(); + private IntegerArray _offsets = new IntegerArray(); + private IntegerArray _maxConcepts = new IntegerArray(); + + private IntegerArray _docConcepts = new IntegerArray(); + private IntegerArray _queryMasks = new IntegerArray(); + private int _maxHitsToShow = 100; + + public Search(SearchEnvironment se, int nColumns) + { + _env = se; + _nQueries = 1; + _query = new Query[_nQueries]; + + _size2 = InitNConcepts; + _free2 = 0; + _conceptData = new ConceptData[_size2]; + + _query[0] = new Query(se, nColumns, null); + /* + _query[1] = new Query(se, 3, null); + _query[2] = new Query(se, 3, null); + _query[3] = new Query(se, 3, null); + */ + } + + public void addTerm(int col, int concept, double score, int query) + { + if (_env.occursInText(concept)) + { + if (_free2 == _size2) + { + ConceptData[] newArray = new ConceptData[_size2 *= 2]; + System.arraycopy(_conceptData, 0, newArray, 0, _free2); + _conceptData = newArray; + } + _conceptData[_free2++] = + new ConceptData(concept, col, score, query, + _query[query].getNColumns()); + } + } + + public void startSearch(SearchQuery searchQuery) + { + // fprintf(stderr, "startSearch: setup\n"); + int i, j; + // set up ConceptData lists + // order search terms + quicksort(0, _free2 - 1); + // remove duplicates + for (i = 0; i < _free2 - 1; i = j) + for (j = i + 1; j < _free2; j++) + if (_conceptData[i].crqEquals(_conceptData[j])) + _conceptData[j] = null; + else + i = j; + // create lists + for (i = 0; i < _free2 - 1; i = j) + for (j = i + 1; j < _free2; j++) + if (_conceptData[j] != null) + if (_conceptData[i].cEquals(_conceptData[j])) + { + _conceptData[i].addLast(_conceptData[j]); + _conceptData[j] = null; + } + else + i = j; + // densify + for (i = 0; i < _free2 - 1; i++) + if (_conceptData[i] == null) + for (j = i + 1; j < _free2; j++) + if (_conceptData[j] != null) + { + _conceptData[i] = _conceptData[j]; + _conceptData[j] = null; + break; + } + // set up new document generators + _nextDocGenHeap.reset(); + for (i = 0; i < _free2 && _conceptData[i] != null; i++) + { + NextDocGenerator gen = new NextDocGenerator(_conceptData[i], _env); + try { + gen.first(); + if (gen.getDocument() != NonnegativeIntegerGenerator.END) + { + _conceptData[i]. + setConceptLength(_env. + getConceptLength(_conceptData[i].getConcept())); + _nextDocGenHeap.addGenerator(gen); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + _nextDocGenHeap.start(); + searchDocument(); + if (searchQuery == null) { + printResults(_maxHitsToShow); + } else { + _query[0].makeEvent(_maxHitsToShow, searchQuery); + } + } + + private void searchDocument() + { + RoleFiller[] start = new RoleFiller[_nQueries]; + do { + try { + switch (nextDocument(start)) + { + case 0: // multi group + _genHeap.start(start); + while (_genHeap.next(start)) + ; + break; + + case 1: // single group + if (_firstGenerator.next()) + { + _firstGenerator.generateFillers(start); + while (_firstGenerator.next()) + _firstGenerator.generateFillers(start); + } + break; + + case 2: // reached the end + return; + } + } + catch (Exception e) { + e.printStackTrace(System.err); + continue; + } + + for (int i = 0; i < _nQueries; i++) + { + RoleFiller next; + if ((next = start[i]) != null && next != RoleFiller.STOP) + next.scoreList(_query[i], _document); + + } + _genHeap.reset(); + } + while (_nextDocGenHeap.isNonEmpty()); + } + + // will be called for increasing values of c + // searches index interval [_startingIndex, _nConcepts] + // saves state in _startingIndex + private int indexOf(int concept) throws Exception + { + int i = _startingIndex, j = _nConcepts, k; + while (i <= j) + if (_concepts[k = (i + j)/2] < concept) + i = k + 1; + else if (concept < _concepts[k]) + j = k - 1; + else + { + _startingIndex = k + 1; + return k; + } + throw new Exception("indexOf " + concept + " not found"); + } + + private void printResults(int nHits) + { + for (int q = 0; q < _nQueries; q++) + { + System.out.println("query " + q); + if (_query[q] != null) + _query[q].printHits(nHits); + } + } + + private ConceptGroupGenerator makeGenerator(int group) throws Exception + { + int shift, index; + + if (group > 0) + { + index = _base + _offsets.at(group - 1); + shift = _maxConcepts.at(group - 1); + } + else + { + index = _base; + shift = 0; + } + + // initialize generator + ConceptGroupGenerator gen = + new ConceptGroupGenerator(_data, index, _kTable.at(2*group + 1)); + // decode concept table + _nConcepts = gen.decodeConcepts(_kTable.at(2*group), shift, _concepts); + if (group < _limit) + _max = _concepts[_nConcepts] = _maxConcepts.at(group); + else + _max = _concepts[_nConcepts - 1]; + _genHeap.addGenerator(gen); + _startingIndex = 0; // in _concepts; lower search index + return gen; + } + + // returns true if multigroup + private boolean openDocumentIndex(int docID) throws Exception + { + // The data is only the data for this document id. Thus the base is set + // to zero. + _data = _env.getPositions(docID); + _base = 0; + _startingIndex = 0; + int kk = _data[_base] & 0xFF, k2; + switch (kk >> 6) // get type + { + case 0: // single group, no extents + k2 = _data[_base + 1]; + _firstGenerator.init(_data, _base += 2, k2); + // decode concept table + _nConcepts = _firstGenerator.decodeConcepts(kk & 0x3F, 0, _concepts); + return false; + + case 2: // multi group, no extents + _kTable.clear(); + _offsets.clear(); + _maxConcepts.clear(); + ByteArrayDecompressor compr = + new ByteArrayDecompressor(_data, _base + 1); + compr.decode(kk & 0x3F, _kTable); + compr.ascDecode(_kTable.popLast(), _offsets); + compr.ascDecode(_kTable.popLast(), _maxConcepts); + _base += 1 + compr.bytesRead(); + _limit = _maxConcepts.cardinality(); + return true; + + case 1: // single group, extents + case 3: // multi group, extents + throw new Exception("extents not yet implemented\n"); + } + return false; + } + + private int nextDocument(RoleFiller[] start) throws Exception + { + while (_nextDocGenHeap.isNonEmpty()) // still something to do + { + for (int i = 0; i < _nQueries; i++) + if (_query[i] != null) + _query[i].resetForNextDocument(); + + // gather all concepts this document has and store associated conceptData + int index = 0; + _document = _nextDocGenHeap.getDocument(); + _docConcepts.clear(); + _queryMasks.clear(); + do { + _docConcepts.add(_nextDocGenHeap.getConcept()); + _queryMasks.add(_nextDocGenHeap.getQueryMask()); + (_conceptData[index++] = _nextDocGenHeap.getTerms()).runBy(_query); + _nextDocGenHeap.step(); + } + while (_nextDocGenHeap.atDocument(_document)); + + // if there is no saturation model, some query will always vote YES + // and so every document will be opened + // even if this case, however, savings can be achieved by not generating fillers + // for some queries (not scoring, etc) + // and, with more care, creation of some GroupGenerators can be avoided + // saturating queries with lots of good hits will lead to best results + int voteMask = 0; + for (int i = 0; i < _nQueries; i++) + if (_query[i] != null) + if (_query[i].vote()) + { + start[i] = null; // normal reset + voteMask |= 1 << i; + } + else + start[i] = RoleFiller.STOP; // prohibit setting + + // we may eliminate some ConceptGroupGenerators + // those which would be used only by Queries which voted NO + if (voteMask != 0) // need to open up document + { + ConceptGroupGenerator gen; + // !!! don't gather Fillers for disinterested Queries + if (openDocumentIndex(_document)) // multi group + { + // set up all needed generators + int i = 0; + while ((_queryMasks.at(i) & voteMask) == 0) + ++i; + // assert(i < index); + int c = _docConcepts.at(i); + int group = 0; + // find first group + while (c > _maxConcepts.at(group) && ++group < _limit) + ; + gen = makeGenerator(group); + gen.addTerms(indexOf(c), _conceptData[i]); + + for (++i; i < index; i++) + if ((_queryMasks.at(i) & voteMask) > 0) + { + c = _docConcepts.at(i); + if (c > _max) // need to find another group + { + // assert(group < _limit); + while (c > _maxConcepts.at(group) && ++group < _limit) + ; + gen = makeGenerator(group); + } + gen.addTerms(indexOf(c), _conceptData[i]); + } + return 0; + } + else // single group + { + for (int i = 0; i < index; i++) + if ((_queryMasks.at(i) & voteMask) != 0) + _firstGenerator.addTerms(indexOf(_docConcepts.at(i)), + _conceptData[i]); + return 1; + } + } + } + return 2; + } + + // part of quicksearch + private int partition(int p, int r) + { + ConceptData x = _conceptData[p]; + int i = p - 1, j = r + 1; + while (true) + { + while (x.compareWith(_conceptData[--j])) + ; + while (_conceptData[++i].compareWith(x)) + ; + if (i < j) + { + ConceptData t = _conceptData[i]; + _conceptData[i] = _conceptData[j]; + _conceptData[j] = t; + } + else + return j; + } + } + + private void quicksort(int p, int r) + { + if (p < r) + { + int q = partition(p, r); + quicksort(p, q); + quicksort(q + 1, r); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java b/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java new file mode 100644 index 0000000000000000000000000000000000000000..8a35ca450214602f858793b0b4be79f27f751348 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java @@ -0,0 +1,375 @@ +/* + * @(#)SearchEnvironment.java 1.29 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) SearchEnvironment.java 1.11 - last change made 04/19/98 + */ + +package com.sun.java.help.search; + +import javax.help.search.SearchItem; +import java.io.*; +import java.util.Vector; // consider removal +import java.net.URL; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.util.Locale; +import java.awt.datatransfer.DataFlavor; +import java.lang.reflect.Method; + +/** + * This class established a SearchEnvironment for JavaHelp classes + * + * @version 1.11 04/19/98 + * @author Jacek R. Ambroziak + * @author Roger D. Brinkley + */ + +class SearchEnvironment { + private IntegerArray concepts; + private IntegerArray offsets; + private byte[] allLists; + + private IntegerArray concepts3; + private IntegerArray offsets3; + private byte[] allChildren; + + + private IntegerArray documents; + private IntegerArray offsets2; + private IntegerArray titles; + + private RAFFile positionsFile = null; + private byte[] positions; + + private ByteArrayDecompressor compr; + + private BtreeDict tmap; + + private URL base; // the base for all searches + private String indexDir; // the index directory + + + public SearchEnvironment(String indexDir, URL hsBase) throws Exception { + this.base = hsBase; + this.indexDir = indexDir; + + readFromDB(); + compr = new ByteArrayDecompressor(null, 0); + } + + public int fetch(String conceptName) throws Exception { + return tmap.fetch(conceptName); + } + + public String fetch(int conceptID) throws Exception { + return tmap.fetch(conceptID); + } + + public SearchItem makeItem(QueryHit hit) throws Exception + { + Vector concepts = new Vector(); + int[] conceptIDs = hit.getArray(); + for (int i = 0; i < conceptIDs.length; i++) { + if (conceptIDs[i] > 0) { + concepts.addElement(fetch(conceptIDs[i])); + } + } + + int begin = hit.getBegin(); + int end = hit.getEnd(); + return new SearchItem(this.base, + fetch(titles.at(hit.getDocument())), + Locale.getDefault().toString(), + fetch(documents.at(hit.getDocument())), + hit.getScore(), + begin, + end, + concepts); + } + + public String hitToString(QueryHit hit) throws Exception + { + StringBuffer result = new StringBuffer(); + result.append(hit.getScore()); + result.append(" "); + result.append(fetch(documents.at(hit.getDocument()))); + if (false) { + result.append(" "); + result.append(fetch(titles.at(hit.getDocument()))); + } + result.append(" ["); + int begin = hit.getBegin(); + int end = hit.getEnd(); + result.append(begin); + result.append(", "); + result.append(end); + result.append("], {"); + int[] concepts = hit.getArray(); + for (int i = 0; i < concepts.length; i++) + { + if (concepts[i] > 0) + result.append(fetch(concepts[i])); + else + result.append("--"); + if (i < concepts.length - 1) + result.append(", "); + } + result.append("}"); + return result.toString(); + } + + public byte[] getPositions(int docId) throws java.io.IOException + { + // Later on we should do some caching of this + int offset = offsets2.at(docId); + int upto; + if (docId+1 == offsets2.cardinality()) { + upto = (int)positionsFile.length(); + } else { + upto = offsets2.at(docId+1); + } + positions = new byte[upto - offset]; + positionsFile.seek(offset); + positionsFile.read(positions, 0, upto - offset); + return positions; + } + + public int getDocumentIndex(int docId) { + return offsets2.at(docId); + } + + public void close() throws java.io.IOException { + positionsFile.close(); + } + + public boolean occursInText(int concept) { + return concepts.indexOf(concept) >= 0; + } + + public NonnegativeIntegerGenerator getDocumentIterator(int concept) + { + int index = concepts.indexOf(concept); + if (index >= 0) + return new ConceptList(allLists, offsets.at(index)); + else + return null; + } + + public NonnegativeIntegerGenerator getChildIterator(int concept) + { + int index = concepts3.indexOf(concept); + if (index >= 0) + return new ConceptList(allChildren, offsets3.at(index)); + else + return null; + } + + public void getChildren(int concept, IntegerArray array) throws Exception + { + int index = concepts3.indexOf(concept); + if (index >= 0) + { + int where = offsets3.at(index); + compr.initReading(allChildren, where + 1); + compr.ascDecode(allChildren[where], array); + } + } + + public int getConceptLength(int concept) throws Exception { + return tmap.fetch(concept).length(); + } + + // A temporary piece of code + // Should be rearranged as soon as possible + + private URL getURL(String s) throws MalformedURLException { + URL hsBase = this.base; + String dir = this.indexDir; + URL back; + URL baseURL = null; + File file; + + if (hsBase == null) { + file = new File(dir); + if (file.exists()) { + // On Win32 we need to convert all "\" to "/" + if (File.separatorChar != '/') { + dir = dir.replace(File.separatorChar, '/'); + } + // Make sure the last character is a file separator + if (dir.lastIndexOf('/') + != dir.length() - 1) { + dir = dir.concat("/"); + } + debug ("file:" + dir); + // Use a file protocol + baseURL = new URL("file", "", dir); + } else { + // Assume that some protocol was specified and try it + baseURL = new URL(dir); + } + } + + if (hsBase != null) { + back = new URL(hsBase, dir + "/" + s); + } else { + back = new URL(baseURL, s); + } + + return back; + } + + private void readChildrenData() throws Exception { + URL url; + URLConnection connect; + BufferedInputStream in; + + // Read the Children.Tab data + try { + url = getURL("CHILDREN.TAB"); + connect = url.openConnection(); + InputStream ois = connect.getInputStream(); + + if (ois == null) { + concepts3 = new IntegerArray(1); + return; + } + + in = new BufferedInputStream(ois); + + int k1 = in.read(); + concepts3 = new IntegerArray(4096); + StreamDecompressor sddocs = new StreamDecompressor(in); + sddocs.ascDecode(k1, concepts3); + int k2 = in.read(); + offsets3 = new IntegerArray(concepts3.cardinality() + 1); + offsets3.add(0); + StreamDecompressor sdoffsets = new StreamDecompressor(in); + sdoffsets.ascDecode(k2, offsets3); + in.close(); + + // Read the Chilren data + url = getURL("CHILDREN"); + connect = url.openConnection(); + ois = connect.getInputStream(); + + if (ois == null) { + concepts3 = new IntegerArray(1); + return; + } + + in = new BufferedInputStream(ois); + int length = connect.getContentLength(); + allChildren = new byte[length]; + in.read(allChildren); + in.close(); + } catch (MalformedURLException e) { + concepts3 = new IntegerArray(1); + } catch (FileNotFoundException e2) { + concepts3 = new IntegerArray(1); + } catch (IOException e2) { + concepts3 = new IntegerArray(1); + } + } + + private void readFromDB() throws Exception { + URL url; + URLConnection connect; + BufferedInputStream in = null; + + Schema schema = new Schema(base, indexDir, false); + BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP"); + params.readState(); + tmap = new BtreeDict(params); + + readChildrenData(); + + url = getURL("DOCS.TAB"); + connect = url.openConnection(); + in = new BufferedInputStream(connect.getInputStream()); + int k1 = in.read(); + concepts = new IntegerArray(4096); + StreamDecompressor sddocs = new StreamDecompressor(in); + sddocs.ascDecode(k1, concepts); + int k2 = in.read(); + offsets = new IntegerArray(concepts.cardinality() + 1); + offsets.add(0); + StreamDecompressor sdoffsets = new StreamDecompressor(in); + sdoffsets.ascDecode(k2, offsets); + in.close(); + + // Read the Lists data + url = getURL("DOCS"); + connect = url.openConnection(); + in = new BufferedInputStream(connect.getInputStream()); + // Note: I'd rather look a the length in the URLConnection + // and read in all the data at once, but it doesn't work on 1.1 + ByteArrayOutputStream data = new ByteArrayOutputStream(); + byte [] buff = new byte[512]; + int i = 0; + while ((i = in.read(buff)) != -1) { + data.write(buff, 0, i); + } + allLists = data.toByteArray(); + in.close(); + + // Read the positions offset data + url = getURL("OFFSETS"); + connect = url.openConnection(); + in = new BufferedInputStream(connect.getInputStream()); + k1 = in.read(); + documents = new IntegerArray(4096); + sddocs = new StreamDecompressor(in); + sddocs.ascDecode(k1, documents); + k2 = in.read(); + offsets2 = new IntegerArray(documents.cardinality() + 1); + sdoffsets = new StreamDecompressor(in); + sdoffsets.ascDecode(k2, offsets2); + // decompress titles' ids table + int k3 = in.read(); + titles = new IntegerArray(documents.cardinality()); + StreamDecompressor sdtitles = new StreamDecompressor(in); + sdtitles.decode(k3, titles); + in.close(); + + // Read in the Positions data + RAFFileFactory factory = RAFFileFactory.create(); + url = getURL("POSITIONS"); + positionsFile = factory.get(url, false); + } + + /** + * For printf debugging. + */ + private static boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("SearchEnvironment: " + str); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java new file mode 100644 index 0000000000000000000000000000000000000000..b4d39b98cf9e50b3ea478d0b6a37ec17469c4f37 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java @@ -0,0 +1,95 @@ +/* + * @(#)StreamDecompressor.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 1/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; + +class StreamDecompressor extends Decompressor +{ + private InputStream _input; + + public StreamDecompressor(InputStream input) { + initReading(input); + } + + public void initReading(InputStream input) + { + _input = input; + initReading(); + } + + public int getNextByte() throws java.io.IOException { + return _input.read(); + } + + public static void main(String[] args) + { + try { + FileInputStream file = new FileInputStream(args[0]); + try { + int k1 = file.read(); + long start = System.currentTimeMillis(); + System.out.println("k1 = " + k1); + IntegerArray concepts = new IntegerArray(); + StreamDecompressor documents = new StreamDecompressor(file); + try { + documents.ascDecode(k1, concepts); + } + catch (Exception e) { + System.err.println(e); + } + System.out.println("index1 = " + concepts.cardinality()); + int k2 = file.read(); + System.out.println("k2 = " + k2); + IntegerArray offs = new IntegerArray(concepts.cardinality()); + StreamDecompressor offsets = new StreamDecompressor(file); + try { + offsets.decode(k2, offs); + } + catch (Exception e) { + System.err.println(e); + } + System.out.println("index2 = " + offs.cardinality()); + System.out.println((System.currentTimeMillis() - start) + " msec"); + file.close(); + } + catch (IOException e) { + System.err.println(e); + } + } + catch (FileNotFoundException e) { + System.err.println(e); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java new file mode 100644 index 0000000000000000000000000000000000000000..ffce75a4f0ecb5bae6e6f646f5e646cdc9ac89b8 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java @@ -0,0 +1,128 @@ +/* + * @(#)TemporaryRAFFile.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) TemporaryRAFFile.java 1.4 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.IOException; + +/** + * This class can be used to read/write the contents of a RAF type files + * (i.e. DICT (Dictionary) & POSITIONS (Positions)) + * file as part of JavaHelp Search Database. It uses RandamAccessFile for + * quick access to dictionary blocks (DictBlock). + * </p> + * Extension of this class serve include memory resident or unwriteable + * RAFFile. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.4 10/30/06 + */ + +import java.net.URL; +import java.io.RandomAccessFile; +import java.io.File; +import java.io.IOException; +import java.security.Permission; + +final public class TemporaryRAFFile extends RAFFile { + + private RandomAccessFile raf; + private Permission permission; + + // provides only read access. + public TemporaryRAFFile(File file, Permission permission) throws IOException{ + debug("TemporaryRAFFile " + file); + raf = new RandomAccessFile(file, "r"); + this.permission = permission; + } + + public long length() throws IOException { + // check permission + return raf.length(); + } + + public long getFilePointer() throws IOException { + // check permission + return raf.getFilePointer(); + } + + public void close() throws IOException { + // check permission + raf.close(); + } + + public void seek(long pos) throws IOException { + // check permission + raf.seek(pos); + } + + public int readInt() throws IOException { + // check permission + return raf.readInt(); + } + + public int read() throws IOException { + // check permission + return raf.read(); + } + + public void readFully (byte b[]) throws IOException { + // check permission + raf.readFully(b); + } + + public int read(byte[] b, int off, int len) throws IOException { + // check permission + return raf.read(b, off, len); + } + + public void writeInt(int v) throws IOException { + // check permission + raf.writeInt(v); + } + + public void write(byte b[]) throws IOException { + // check permission + raf.write(b); + } + + /** + * Debug code + */ + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("TemporaryRAFFile: "+msg); + } + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java b/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java new file mode 100644 index 0000000000000000000000000000000000000000..f6d58a5878ef25288cd4d78c911804afc77a5b70 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java @@ -0,0 +1,60 @@ +/* + * @(#)Utilities.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * 1.3 10/30/06 + */ + +package com.sun.java.help.search; + +import java.lang.reflect.Method; + +/** + * + * @version 1.3 10/30/06 + * @author Roger D. Brinkley + */ + +class Utilities +{ + public static String URLDecoder (String str) { + String returnStr = str; + try { + Class klass = Class.forName("java.net.URLDecoder"); + Class types[] = {String.class}; + Method m = klass.getMethod("decode", types); + + if (m != null) { + Object args[] = {str}; + returnStr = (String)m.invoke(null, args); + } + } catch (Throwable t) { + t.printStackTrace(); + } + return returnStr; + } +} diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/package.html b/jhMaster/JSearch/client/com/sun/java/help/search/package.html new file mode 100644 index 0000000000000000000000000000000000000000..09fc77ecee0d1da7e3f5ccfb63e160413a0f4b22 --- /dev/null +++ b/jhMaster/JSearch/client/com/sun/java/help/search/package.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.2 10/15/98 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Implementation classes for the default Search client using in the +reference implementation of JavaHelp. + +<p> +<em>Note:</em>We have not yet finalized the location for these classes. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see +<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A> + + </body> +</html> diff --git a/jhMaster/JSearch/indexer/GNUmakefile b/jhMaster/JSearch/indexer/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..503fdd603f230c02c9a2da6d5bb1a964a54c869e --- /dev/null +++ b/jhMaster/JSearch/indexer/GNUmakefile @@ -0,0 +1,47 @@ +# +# @(#)GNUmakefile 1.9 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +SOURCES := $(shell find . -name 'SCCS*' -prune -o -name '*Old*' -prune -o -name '*.java' -print) +CLASSES = $(SOURCES:%.java=classes/%.class) + +RM=/bin/rm + +jar: ../lib/jsearch-indexer.jar + +../lib/jsearch-indexer.jar: $(CLASSES) + cd classes ; \ + jar cf ../../lib/jsearch-indexer.jar com + +classes/%.class: %.java classes + export CLASSPATH ; CLASSPATH=../lib/jsearch-misc.jar:../lib/jsearch-client.jar:. ; \ + javac -d classes $< + +classes: + mkdir classes + +clean: + $(RM) -rf classes diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java new file mode 100644 index 0000000000000000000000000000000000000000..43b658a420505987b837bf7a39731d7ec6f47e67 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java @@ -0,0 +1,267 @@ +/* + * @(#)BtreeDictCompactor.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 5/1/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.net.URL; + +public class BtreeDictCompactor extends FullBtreeDict +{ + private CompactorDictBlock _currentLeaf; + private byte[] _lastKey = new byte[MaxKeyLength]; + private int _lastKeyLength = 0; + private int _limit; + private int _nEntries = 0; + private int _entry = 0; + + private int _counter = 0; + private InternalBlockState _parent = null; + + private final class CompactorDictBlock extends FullDictBlock + { + private int restoreKey1(int entry, byte[] buffer) + { + int howMany = entryKeyLength(entry); + int where = entryCompression(entry); + int from = entryKey(entry); + while (howMany-- > 0) + buffer[where++] = data[from++]; + return where; + } + + protected void doMap1(BtreeDictCompactor owner, BtreeDictCompactor target) + throws Exception + { + byte[] buffer = new byte[MaxKeyLength]; + final int freeSpace = free(); + int entry = firstEntry(); + if (isLeaf) + while (entry < freeSpace) { + target.store(buffer, restoreKey1(entry, buffer), entryID(entry)); + entry = nextEntry(entry); + } + else + { + owner.lock(this); + int entryIndex = 0; + while (entry < freeSpace) { + owner.accessBlock1(getChildIdx(entryIndex)).doMap1(owner,target); + target.store(buffer, restoreKey1(entry, buffer), entryID(entry)); + entry = nextEntry(entry); + ++entryIndex; + } + owner.accessBlock1(getChildIdx(entryIndex)).doMap1(owner, target); + owner.unlock(this); + } + } + } // end of internal class + + private final class InternalBlockState + { + private CompactorDictBlock _block; + private byte[] _lastKey = new byte[MaxKeyLength]; + private int _lastKeyLength; + private int _entry; + private int _nEntries; + private int _limit; + private InternalBlockState _parent; + + public InternalBlockState(int leftChild) + { + debug("NEW ROOT " + _counter); + debug(params.toString()); + params.setRoot(_counter); + _block = new CompactorDictBlock(); + _block.isLeaf = false; + _block.setBlockNumber(_counter++); + init(leftChild); + } + + private void init(int leftChild) + { + _entry = _block.firstEntry(); + _nEntries = 0; + _lastKeyLength = 0; + _limit = 4*(lastPtrIndex - 1); + _block.setChildIndex(0, leftChild); + } + + public void store(byte[] buffer, int keyLen, int id, int newBlock) + { + // System.out.println(new String(buffer, 0, keyLen) + " " + id); + int cpr = 0; + while (cpr < _lastKeyLength && _lastKey[cpr] == buffer[cpr]) + ++cpr; + int needed = ENTHEADERLEN + keyLen - cpr; + if (_entry + needed <= _limit) + { + _block.makeEntry(_entry, buffer, id, keyLen - cpr, cpr); + _entry += needed; + _nEntries++; + _block.setChildIndex(_nEntries, newBlock); + _limit -= 4; + _lastKeyLength = keyLen; + System.arraycopy(buffer, cpr, _lastKey, cpr, keyLen - cpr); + } + else + { + debug("NEW: SPLIT INTERNAL"); + _block.setFree(_entry); + _block.setNumberOfEntries(_nEntries); + if (_parent == null) + _parent = new InternalBlockState(_block.number); + _parent.store(buffer, keyLen, id, newBlock(_block)); + init(newBlock); + } + } + + public void close() throws java.io.IOException + { + _block.setFree(_entry); + _block.setNumberOfEntries(_nEntries); + blockManager.writeBlock(_block); + if (_parent == null) + debug("root: " + _block.number); + else + _parent.close(); + } + } // end of internal class + + public BtreeDictCompactor(BtreeDictParameters params, boolean update) + throws Exception + { + init(params, update, new BlockFactory() { + public Block makeBlock() { return new CompactorDictBlock(); } + }); + _currentLeaf = new CompactorDictBlock(); + _currentLeaf.setBlockNumber(_counter++); + _limit = DATALEN - 2; + _entry = _currentLeaf.firstEntry(); + this.params = params; + } + + protected CompactorDictBlock accessBlock1(int index) throws Exception { + return (CompactorDictBlock)blockManager.accessBlock(index); + } + + public void store(byte[] buffer, int keyLen, int id) + { + // System.out.println(new String(buffer, 0, keyLen)); + if (id > 0) + { + int cpr = 0; + while (cpr < _lastKeyLength && _lastKey[cpr] == buffer[cpr]) + ++cpr; + int needed = ENTHEADERLEN + keyLen - cpr; + if (_entry + needed <= _limit) + { + _currentLeaf.makeEntry(_entry, buffer, id, keyLen - cpr, cpr); + _entry += needed; + _nEntries++; + _lastKeyLength = keyLen; + System.arraycopy(buffer, cpr, _lastKey, cpr, keyLen - cpr); + } + else + { + _currentLeaf.setFree(_entry); + _currentLeaf.setNumberOfEntries(_nEntries); + if (_parent == null) + _parent = new InternalBlockState(_currentLeaf.number); + _parent.store(buffer, keyLen, id, newBlock(_currentLeaf)); + _entry = _currentLeaf.firstEntry(); + _nEntries = 0; + _lastKeyLength = 0; + } + } + } + + private int newBlock(DictBlock block) + { + int number = _counter++; + try { + blockManager.writeBlock(block); // write out full + block.setBlockNumber(number); // recycle + blockManager.writeBlock(block); // reserve space for new + } + catch (java.io.IOException e) { + e.printStackTrace(); + } + return number; + } + + public void close() throws java.io.IOException + { + _currentLeaf.setFree(_entry); + _currentLeaf.setNumberOfEntries(_nEntries); + blockManager.writeBlock(_currentLeaf); + if (_parent == null) + debug("root: " + _currentLeaf.number); + else + _parent.close(); + blockManager.close(); + } + + public void compact(BtreeDictParameters params) throws Exception + { + final BtreeDictCompactor target = new BtreeDictCompactor(params, true); + ((CompactorDictBlock)blockManager.accessBlock(root)).doMap1(this, target); + target.close(); + blockManager.close(); + } + + public static void main(String[] args) + { + try { + Schema schema = new Schema(null, args[0], false); + BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP"); + BtreeDictCompactor source = new BtreeDictCompactor(params, false); + URL url = new URL("file", "", args[1]); + BtreeDictParameters params2 = new BtreeDictParameters(url, 2048, 0, 24); + source.compact(params2); + } + catch (Exception e) { + System.err.println(e); + e.printStackTrace(); + } + } + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("BtreeDictCompactor: "+msg); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java new file mode 100644 index 0000000000000000000000000000000000000000..31ddf166560087310366bca2a943466373bb13f2 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java @@ -0,0 +1,61 @@ +/* + * @(#)ChangedCharSetException.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) ChangedCharSetException.java 1.6 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.IOException; + +/** + * ChangedCharSetException as the name indicates is an exception + * thrown when the charset is changed. + * + * @author Roger Brinkley + * 10/30/06 %V% + */ +public class ChangedCharSetException extends IOException { + + String charSetSpec; + boolean charSetKey; + + public ChangedCharSetException(String charSetSpec, boolean charSetKey) { + this.charSetSpec = charSetSpec; + this.charSetKey = charSetKey; + } + + public String getCharSetSpec() { + return charSetSpec; + } + + public boolean keyEqualsCharSet() { + return charSetKey; + } + +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..04b978c5f965f795797024331d54fffa6d3c47c1 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java @@ -0,0 +1,243 @@ +/* + * @(#)DefaultIndexBuilder.java 1.23 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 3/13/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.net.URL; +import java.io.*; +import java.util.Hashtable; +import java.util.Enumeration; +import javax.help.search.IndexBuilder; + +public class DefaultIndexBuilder extends IndexBuilder +{ + private static int InitSize = 4096; + private FullBtreeDict dict; + protected Hashtable cache = new Hashtable(15000); + private DocumentCompressor compr; + private int free = 0; + private int size = InitSize; + private ConceptLocation[] locations = new ConceptLocation[size]; + private int freeID; + private int currentDocID = 0; + private Schema _schema; + private BtreeDictParameters _tmapParams; + private int _title = 0; + + public DefaultIndexBuilder(String indexDir) throws Exception + { + super (indexDir); + // temporary code to disable incremental updates + removeExistingFiles(indexDir); + _schema = new Schema(null, indexDir, true); + _tmapParams = new BtreeDictParameters(_schema, "TMAP"); + if (_tmapParams.readState() == false) + { + _tmapParams.setBlockSize(2048); + _tmapParams.setRoot(0); + _tmapParams.setFreeID(1); + } + + URL url = new URL("file", "", indexDir); + /* + try { + params = BtreeDictParameters.read(indexDir, null); + } catch (java.io.FileNotFoundException e) { + params = BtreeDictParameters.create(url); + } + */ + dict = new FullBtreeDict(_tmapParams, true); + freeID = _tmapParams.getFreeID(); + compr = new DocumentCompressor(url); + } + + // temporary until Jacek incorporates stop words into IndexBuilder + private Hashtable tmpstopWords = new Hashtable(); + + public void storeStopWords(Enumeration stopWords) { + for (; stopWords.hasMoreElements() ;) { + String word = (String) stopWords.nextElement(); + // temporarily keep the list here until Jacek finishes adding + // stop words to indexes + tmpstopWords.put(word, word); + } + } + + public Enumeration getStopWords() { + // For now the stop words are not stored in the index + // Jacek will change this when he supports stop words in indexes + return null; + } + + // temporary code until Jacek provides support for stop words in indexes + private boolean isStopWord(String word) { + return tmpstopWords.get(word) != null; + } + + public void close() throws Exception + { + dict.close(freeID); + _tmapParams.setFreeID(freeID); + _tmapParams.updateSchema(); + + debug("compacting..."); + BtreeDictCompactor source = new BtreeDictCompactor(_tmapParams, false); + URL url = new URL("file", "", indexDir + "compacted"); + BtreeDictParameters params = + new BtreeDictParameters(url, _tmapParams.getBlockSize(), 0, freeID); + source.compact(params); + URL tmapURL = new URL("file", "", indexDir + "TMAP"); + File tmap = new File(Utilities.URLDecoder(tmapURL.getFile())); + tmap.delete(); + File compacted = new File(Utilities.URLDecoder(url.getFile())); + compacted.renameTo(tmap); + _tmapParams.setRoot(params.getRootPosition()); + _tmapParams.updateSchema(); + + debug("freeID is " + freeID); + compr.close(indexDir + "OFFSETS"); + debug("inverting index"); + DocumentLists.invert(indexDir); + _schema.save(); + } + + public void openDocument(String name) throws Exception + { + if (currentDocID != 0) { + throw new Exception("document already open"); + } + currentDocID = intern(name); + } + + public void closeDocument() throws Exception + { + if (currentDocID == 0) { + throw new Exception("no document open"); + } + compr.compress(currentDocID, _title, locations, free, null, 0); + free = 0; + currentDocID = 0; // state: nothing open + _title = 0; + } + + public void storeLocation(String text, int position) throws Exception + { + // next line is temporary until Jacek provides support for stop words in + // indexes + if (isStopWord(text)) return; + if (free == size) { + ConceptLocation[] newArray = new ConceptLocation[size *= 2]; + System.arraycopy(locations, 0, newArray, 0, free); + locations = newArray; + } + locations[free++] = new ConceptLocation(intern(text), + position, + position + text.length()); + } + + public void storeTitle(String title) throws Exception + { + _title = intern(title); + } + + private int intern(String name) throws Exception + { + Integer cached = (Integer)cache.get(name); + if (cached != null) + return cached.intValue(); + else + { + int id = dict.fetch(name); + if (id == 0) { + dict.store(name, id = freeID++); + } + cache.put(name, new Integer(id)); + return id; + } + } + + /** + * Temporary code to remove existing files + * remove when updates actually works + */ + private void removeExistingFiles(String indexDir) { + File test = new File(indexDir); + try { + if (test.exists()) { + try { + File tmap = new File(test, "TMAP"); + tmap.delete(); + } catch (java.lang.NullPointerException te) { + } + try { + File docs = new File(test, "DOCS"); + docs.delete(); + } catch (java.lang.NullPointerException de) { + } + try { + File docstab = new File(test, "DOCS.TAB"); + docstab.delete(); + } catch (java.lang.NullPointerException dte) { + } + try { + File offsets = new File(test, "OFFSETS"); + offsets.delete(); + } catch (java.lang.NullPointerException oe) { + } + try { + File positions = new File(test, "POSITIONS"); + positions.delete(); + } catch (java.lang.NullPointerException pe) { + } + try { + File schema = new File(test, "SCHEMA"); + schema.delete(); + } catch (java.lang.NullPointerException se) { + } + } + } catch (java.lang.SecurityException e) { + } + + } + + /** + * Debug code + */ + + private boolean debug = false; + private void debug(String msg) { + if (debug) { + System.err.println("DefaultIndexBuilder: "+msg); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java new file mode 100644 index 0000000000000000000000000000000000000000..d5690952f4bdca2677ee25429a3b7632d75782ca --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java @@ -0,0 +1,188 @@ +/* + * @(#)DefaultIndexerKit.java 1.17 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) DefaultIndexerKit.java 1.17 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.util.Locale; +import java.text.*; +import javax.help.search.IndexerKit; +import javax.help.search.IndexBuilder; +import javax.help.search.ConfigFile; + +/** + * This is the set of things needed by an indexing object + * to be a reasonably functioning indexer for some <em>type</em> + * of text document. This implementation provides a default + * implementation which treats text as plain text + * + * @author Roger D. Brinkley + * @version %I %G + */ +public class DefaultIndexerKit extends IndexerKit { + + protected boolean documentStarted; + + + public DefaultIndexerKit() { + locale = Locale.getDefault(); + } + + /** + * Creates a copy of the indexer kit. This + * allows an implementation to serve as a prototype + * for others, so that they can be quickly created. + * + * @return the copy + */ + public Object clone() { + return new DefaultIndexerKit(); + } + + /** + * Gets the MIME type of the data that this + * kit represents support for. The default + * is <code>text/plain</code>. + * + * @return the type + */ + public String getContentType() { + return ""; + } + + /** + * Inserts content from the given stream, which will be + * treated as plain text. + * + * @param in The stream to read from + * @param file The file name being parsed + * @param ignoreCharset Ignore the CharacterSet when parsing + * @param builder The IndexBuilder for the full text insertion. + * @param config The indexer configuration information + * @exception IOException on any I/O error + */ + public void parse(Reader in, String file, boolean ignoreCharset, + IndexBuilder builder, + ConfigFile config) throws IOException + { + debug ("parsing " + file); + // Do nothing in the default implementation + } + + public int parseIntoTokens (String source, int pos) { + BreakIterator boundary; + int start; + String word; + int currentPos = pos; + + try { + boundary = BreakIterator.getWordInstance(locale); + boundary.setText(source); + start = boundary.first(); + for (int end = boundary.next(); + end != BreakIterator.DONE; + start = end, end = boundary.next()) { + word = new String(source.substring(start,end)); + word = word.trim(); + word = word.toLowerCase(locale); + if (word.length() > 1) { + storeToken(word, currentPos + start); + } else if (word.length() == 1) { + int charType = Character.getType(word.charAt(0)); + if ((charType == Character.DECIMAL_DIGIT_NUMBER) || + (charType == Character.LETTER_NUMBER) || + (charType == Character.LOWERCASE_LETTER) || + (charType == Character.OTHER_LETTER) || + (charType == Character.OTHER_NUMBER) || + (charType == Character.TITLECASE_LETTER) || + (charType == Character.UNASSIGNED) || + (charType == Character.UPPERCASE_LETTER)) { + storeToken (word, currentPos + start); + } + } + } + currentPos += source.length(); + } + catch (Exception e) { + e.printStackTrace(); + } + return currentPos; + } + + protected void startStoreDocument (String file) throws Exception { + if ((config == null) || (builder == null)) { + throw new Exception("ConfigFile and/or IndexBuilder not set"); + } + builder.openDocument(config.getURLString(file)); + } + + protected void endStoreDocument () throws Exception { + if ((config == null) || (builder == null)) { + throw new Exception("ConfigFile and/or IndexBuilder not set"); + } + builder.closeDocument(); + } + + protected void storeToken (String token, int pos) throws Exception { + if ((config == null) || (builder == null)) { + throw new Exception("ConfigFile and/or IndexBuilder not set"); + } + if (!documentStarted) { + try { + startStoreDocument(file); + documentStarted = true; + } catch (Exception e) { + if (debugFlag) e.printStackTrace(); + throw new IOException("Can't store Document"); + } + } + builder.storeLocation(token, pos); + } + + protected void storeTitle (String title) throws Exception { + if ((config == null) || (builder == null)) { + throw new Exception("ConfigFile and/or IndexBuilder not set"); + } + builder.storeTitle(title); + } + + + /** + * Debug code + */ + + private boolean debugFlag=false; + private void debug(String msg) { + if (debugFlag) { + System.err.println("DefaultIndexKit: "+msg); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java new file mode 100644 index 0000000000000000000000000000000000000000..69b539fbdbbafb3e05dbb3274de11b1ece4e7a17 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java @@ -0,0 +1,294 @@ +/* + * @(#)DocumentLists.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 3/10/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; + +class DocumentLists +{ + private static final int RANGE = 1024; + private static final int NConcepts = 16; + private static final int K = 3; + + private final IntegerArray[] _arrays = new IntegerArray[RANGE]; + private int _minConcept = 0; + private int _limit = RANGE; + private final IntegerArray _concepts = new IntegerArray(); + private final IntegerArray _offsets = new IntegerArray(); + private final Compressor _compr = new Compressor(); + private final IntegerArray _diffs = new IntegerArray(); + private final ByteArrayDecompressor _decmp = + new ByteArrayDecompressor(null, 0); + private DataOutputStream _mainFile; + // heap + private int _heapSize = 0; + private MicroIndex[] _heap; + + private class MicroIndex + { + private int _currentRange; + private final int _documentNumber; + private int[] _concepts = new int[NConcepts + 1]; + private short _group; + private short _ix; + private IntegerArray _kTable = new IntegerArray(); + private IntegerArray _offsets = new IntegerArray(); + private IntegerArray _maxConcepts = new IntegerArray(); + private byte[] _data; + private int _base; + private int _limit; + private int _nc; + + public MicroIndex(int documentNumber, byte[] positions, int index) + throws Exception + { + _documentNumber = documentNumber; + _data = positions; + _base = index; + openDocumentIndex(); + } + + public boolean smallerThan(MicroIndex other) + { + return _currentRange < other._currentRange || + _currentRange == other._currentRange && + _documentNumber < other._documentNumber; + } + + private boolean next() throws Exception + { + if (_group <= _limit) + { + int shift, index; + if (_group > 0) + { + index = _base + _offsets.at(_group - 1); + shift = _maxConcepts.at(_group - 1); + } + else + { + index = _base; + shift = 0; + } + _decmp.initReading(_data, index); + _nc = _decmp.ascendingDecode(_kTable.at(_group*2), shift, _concepts); + if (_group < _limit) + _concepts[_nc++] = _maxConcepts.at(_group); + _currentRange = _concepts[_ix = 0]/RANGE; + _group++; + return true; + } + else + return false; + } + + private void openDocumentIndex() throws Exception + { + int kk = _data[_base] & 0xFF; + switch (kk >> 6) // get type + { + case 0: // single group, no extents + _decmp.initReading(_data, _base += 2); + _nc = _decmp.ascendingDecode(kk & 0x3F, 0, _concepts); + _currentRange = _concepts[_ix = 0]/RANGE; + _limit = 0; + _group = 1; + break; + + case 2: // multi group, no extents + _decmp.initReading(_data, _base + 1); + _decmp.decode(kk & 0x3F, _kTable); + _decmp.ascDecode(_kTable.popLast(), _offsets); + _decmp.ascDecode(_kTable.popLast(), _maxConcepts); + _base += 1 + _decmp.bytesRead(); + _limit = _maxConcepts.cardinality(); + _group = 0; + next(); + break; + + case 1: // single group, extents + case 3: // multi group, extents + System.err.println("extents not yet implemented\n"); + break; + } + } + + public boolean process(DocumentLists lists) throws Exception + { + boolean firstTime = true; + while (true) + { + short stop = lists.process(_documentNumber, _concepts, _nc, _ix, + firstTime); + if (stop < _nc) + { + _currentRange = _concepts[_ix = stop]/RANGE; + return true; + } + else if (next()) + firstTime = false; + else + return false; + } + } + } + + private DocumentLists(String indexDir) throws Exception + { + for (int i = 0; i < RANGE; i++) + _arrays[i] = new IntegerArray(); + _mainFile = new DataOutputStream + (new BufferedOutputStream + (new FileOutputStream(indexDir + "DOCS"))); + // main work + InputStream file = + new BufferedInputStream(new FileInputStream(indexDir + "OFFSETS")); + int k1 = file.read(); + IntegerArray array = new IntegerArray(4096); + StreamDecompressor documents = new StreamDecompressor(file); + documents.ascDecode(k1, array); + int k2 = file.read(); + IntegerArray offsetArray = new IntegerArray(array.cardinality() + 1); + StreamDecompressor offsets = new StreamDecompressor(file); + offsets.ascDecode(k2, offsetArray); + file.close(); + File listsFile = new File(indexDir + "POSITIONS"); + byte[] positions = new byte[(int)listsFile.length()]; + FileInputStream in = new FileInputStream(listsFile); + in.read(positions); + in.close(); + // build heap + _heap = new MicroIndex[_heapSize = array.cardinality()]; + for (int i = 0; i < array.cardinality(); i++) + _heap[i] = new MicroIndex(i, positions, offsetArray.at(i)); + debug(array.cardinality() + " documents"); + for (int i = _heapSize/2; i >= 0; i--) + heapify(i); + // process till exhausted + while (true) + if (_heap[0].process(this)) + heapify(0); + else if (_heapSize > 1) + { + _heap[0] = _heap[--_heapSize]; + heapify(0); + } + else + break; + // closing + flush(); + _mainFile.close(); + // compress index file + DataOutputStream indexFile = new DataOutputStream + (new BufferedOutputStream + (new FileOutputStream(indexDir + "DOCS.TAB"))); + indexFile.write(_compr.compressAscending(_concepts)); // write k + _compr.write(indexFile); + _compr.clear(); + indexFile.write(_compr.minimize(_offsets, K)); // write k + _compr.write(indexFile); + indexFile.close(); + } + + public short process(int documentNumber, int[] concepts, int n, short start, + boolean firstTime) + throws IOException + { + if (firstTime && concepts[start] >= _limit) + flush(); + concepts[n] = _limit; // sentinel + while (concepts[start] < _limit) + _arrays[concepts[start++] - _minConcept].add(documentNumber); + return start; + } + + private void heapify(int i) + { + int r = (i + 1) << 1, l = r - 1; + int smallest = l < _heapSize && _heap[l].smallerThan(_heap[i]) ? l : i; + if (r < _heapSize && _heap[r].smallerThan(_heap[smallest])) + smallest = r; + if (smallest != i) + { + MicroIndex temp = _heap[smallest]; + _heap[smallest] = _heap[i]; + _heap[i] = temp; + heapify(smallest); + } + } + + private void flush() throws IOException + { + for (int i = 0; i < RANGE; i++) + if (_arrays[i].cardinality() > 0) + { + _arrays[i].toDifferences(_diffs); + _mainFile.write(_compr.minimize(_diffs, K)); // write k + _offsets.add(_compr.byteCount() + 1); + _compr.write(_mainFile); + _concepts.add(_minConcept + i); + _arrays[i].clear(); + _diffs.clear(); + _compr.clear(); + } + _limit += RANGE; + _minConcept += RANGE; + } + + public static void invert(String indexDir) throws Exception { + new DocumentLists(indexDir); + } + + public static void main(String[] args) + { + String indexDir = args[0]; + try { + new DocumentLists(indexDir); + } + catch (Exception e) { + e.printStackTrace(); + } + } + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("DocumentLists: "+msg); + } + } + +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java new file mode 100644 index 0000000000000000000000000000000000000000..15de5da732969248e7936c9587c5bf63c6883275 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java @@ -0,0 +1,475 @@ +/* + * @(#)FullBtreeDict.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @date 2/20/98 + * @author Jacek R. Ambroziak + * @group Sun Microsystems Laboratories + */ + +package com.sun.java.help.search; + +import java.io.*; // debugging in main +import java.util.*; // debugging in main + +public class FullBtreeDict extends BtreeDict +{ + protected BtreeDictParameters params; + private boolean update = false; + + private final class Entry + { + public byte[] key; + public int id; + public int block = -1; + + public Entry(byte[] key, int length, int id) + { + this.key = new byte[length + 1]; + System.arraycopy(key, 0, this.key, 0, length); + this.key[length] = 0; + this.id = id; + } + + public boolean smallerThan(Entry other) + { + for (int i = 0; i < Math.min(key.length, other.key.length); i++) + if (key[i] != other.key[i]) + return (key[i]&0xFF) < (other.key[i]&0xFF); + return false; + } + } + // end of internal class + + protected class FullDictBlock extends DictBlock + { + public void setFree(int free) + { + this.free = free - firstEntry(); + this.data[free] = this.data[free + 1] = 0; // sentinel + } + + public void setNumberOfEntries(int n) { + setIntegerAt(0, n); + } + + protected void setChildIndex(int index, int value) { + setIntegerAt(4*(lastPtrIndex - index + 1), value); + } + + public void setEntryID(int i, int id) { + setIntegerAt(i + 2, id); + } + + // finds the place and context + private boolean insert(Entry entry) + { + byte[] inkey = entry.key; + final int inputKeyLen = inkey.length - 1; + final int freeSpace = free(); + int entryPtr = firstEntry(); + int nCharsEqual = 0; + int prevNCEqual = 0; + int compression = 0; + + for (int entryIndex = 0;;) + { + if (entryPtr == freeSpace) + return insert(entry, entryPtr, nCharsEqual, 0, numberOfEntries()); + else if (compression == nCharsEqual) + { + int keyLen = entryKeyLength(entryPtr); + int keyPtr = entryKey(entryPtr), i; + prevNCEqual = nCharsEqual; + for (i = 0; + i < keyLen && inkey[nCharsEqual] == data[keyPtr + i]; + i++) + ++nCharsEqual; + if (i == keyLen) + { + if (nCharsEqual == inputKeyLen) + { + setEntryID(entryPtr, entry.id); + return true; + } + } + else if ((inkey[nCharsEqual]&0xFF) < (data[keyPtr + i]&0xFF)) + return insert(entry, entryPtr, prevNCEqual, nCharsEqual, + entryIndex); + } + else if (compression < nCharsEqual) // compression dropped + return insert(entry, entryPtr, nCharsEqual, compression, + entryPtr == freeSpace + ? numberOfEntries() : entryIndex); + do { + entryPtr = nextEntry(entryPtr); + ++entryIndex; + } + while (entryCompression(entryPtr) > nCharsEqual); + compression = entryCompression(entryPtr); + } + } + + public void makeEntry(int entry, byte[] key, int id, int length, int compr) + { + data[entry] = (byte) length; + data[entry + 1] = (byte) compr; + setEntryID(entry, id); + System.arraycopy(key, compr, data, entryKey(entry), length); + } + + private boolean insert(Entry ent, final int entryPtr, + final int compr1, final int compr2, + final int index) + { + final byte[] key = ent.key; + final int keyLen = key.length - 1 - compr1; + final int freeSpace = free(); + // calculate how much space is needed to add the new entry + // first, how many bytes are needed for just the new entry + final int demand = ENTHEADERLEN + keyLen; + // adding an entry can increase compression in the following entry + + int increase = 0; + if (entryPtr < freeSpace) + if (entryCompression(entryPtr) < compr2) + increase = compr2 - entryCompression(entryPtr); + /* + System.err.println("key " + key); + System.err.println("entryPtr " + entryPtr); + System.err.println("compr1 " + compr1); + System.err.println("compr2 " + compr2); + System.err.println("index " + index); + System.err.println("demand " + demand); + System.err.println("increase " + increase); + */ + // check if enough space is available + int limit = isLeaf ? DATALEN-2 : 4*(lastPtrIndex-numberOfEntries()-1); + + if (freeSpace + demand - increase <= limit)// 2 for sentinel + { + if (entryPtr < freeSpace) + { + // need to shift extant entries forward + final int toMove = increase > 0 + ? entryPtr + ENTHEADERLEN + increase + : entryPtr; + // move entries + System.arraycopy(data, toMove, + data, toMove + demand - increase, + freeSpace - toMove); + if (increase > 0) + { + // update header + data[entryPtr] -= increase; + data[entryPtr + 1] += increase; + // shift header + System.arraycopy(data, entryPtr, + data, entryPtr + demand, ENTHEADERLEN); + } + } + // now write the new entry in the space made above + makeEntry(entryPtr, key, ent.id, keyLen, compr1); + if (isLeaf == false) + { + int from = 4*(lastPtrIndex - numberOfEntries() + 1); + System.arraycopy(data, from, data, from - 4, + 4*(numberOfEntries() - index)); + setChildIndex(index + 1, ent.block); + } + setFree(freeSpace + demand - increase); + setNumberOfEntries(numberOfEntries() + 1); + + + /* + System.err.println("------------list--------------"); + byte[] buffer = new byte[MaxKeyLength]; + final int freeSpace2 = free(); + int entryPtr2 = firstEntry(); + while (entryPtr2 < freeSpace2) + { + System.err.println(entryPtr2); + System.err.println(entryKeyLength(entryPtr2)); + System.err.println(entryCompression(entryPtr2)); + System.err.println(new String(data, + entryKey(entryPtr2), + entryKeyLength(entryPtr2))); + System.err.println(restoreKey(entryPtr2, buffer)+" "+ + entryID(entryPtr2)); + entryPtr2 = nextEntry(entryPtr2); + } + System.err.println("------------end--------------"); + */ + + + return true; + } + else + return false; + } + + public int insertInternal(Entry entry) + { + byte[] inkey = entry.key; + final int inputKeyLen = inkey.length - 1; + int entryPtr = firstEntry(); + final int freeSpace = free(); + int nCharsEqual = 0; + int compression = 0; + + for (int entryIndex = 0;;) + { + if (entryPtr == freeSpace) + return numberOfEntries(); + else if (compression == nCharsEqual) + { + int i; + int keyLen = entryKeyLength(entryPtr); + int keyPtr = entryKey(entryPtr); + for (i = 0; + i < keyLen && inkey[nCharsEqual] == data[keyPtr + i]; + i++) + ++nCharsEqual; + if (i == keyLen) + { + if (nCharsEqual == inputKeyLen) + { + setEntryID(entryPtr, entry.id); + return -1; + } + } + else if ((inkey[nCharsEqual]&0xFF) < (data[keyPtr + i]&0xFF)) + return entryIndex; + } + else if (compression < nCharsEqual) // compression dropped + return entryPtr >= freeSpace ? numberOfEntries() : entryIndex; + + do { + entryPtr = nextEntry(entryPtr); + ++entryIndex; + } + while (entryCompression(entryPtr) > nCharsEqual); + compression = entryCompression(entryPtr); + } + } + + private Entry split(FullDictBlock newbl) + { + byte[] buffer = new byte[MaxKeyLength]; + int freeSpace = free(); + int half = freeSpace/2; + int index = 0; // of middle entry + newbl.isLeaf = isLeaf; + int ent; + for (ent = firstEntry(); ent < half; ent = nextEntry(ent)) + { + restoreKeyInBuffer(ent, buffer); + ++index; + } + final int entriesToMove = numberOfEntries() - index - 1; + // middle entry + restoreKeyInBuffer(ent, buffer); + int len = entryKeyLength(ent) + entryCompression(ent); + Entry result = new Entry(buffer, len, entryID(ent)); + result.block = newbl.number; + int newFree = ent; + // rest goes to the new block + ent = nextEntry(ent); + restoreKeyInBuffer(ent, buffer); + len = entryKeyLength(ent) + entryCompression(ent); + int nptr = firstEntry(); + newbl.makeEntry(nptr, buffer, entryID(ent), len, 0); + ent = nextEntry(ent); + System.arraycopy(data, ent, + newbl.data, newbl.nextEntry(nptr), freeSpace - ent); + newbl.setNumberOfEntries(entriesToMove); + newbl.setFree(newbl.nextEntry(nptr) + freeSpace - ent); + if (isLeaf == false) // need to split pointers + { + int from = 4*(lastPtrIndex - numberOfEntries() + 1); + System.arraycopy(data, from, + newbl.data, from + 4*(index + 1), + 4*(entriesToMove + 1)); + } + // this entry will end here + setFree(newFree); + setNumberOfEntries(index); + return result; + //!!!remember updating ID -> string association + } + + public void initInternal(int leftBlock, Entry entry) + { + isLeaf = false; + setNumberOfEntries(1); + setChildIndex(0, leftBlock); + setChildIndex(1, entry.block); + final int ent = firstEntry(); + makeEntry(ent, entry.key, entry.id, entry.key.length - 1, 0); + setFree(nextEntry(ent)); + } + } + // end of internal class + + protected FullBtreeDict() {/*empty*/} + + public FullBtreeDict(BtreeDictParameters params, boolean update) + throws Exception + { + init(params, update, new BlockFactory() { + public Block makeBlock() { return new FullDictBlock(); } + }); + blocks = new int[300000]; // !!! + this.params = params; + this.update = update; + } + + public void close(int freeID) throws Exception + { + params.setFreeID(freeID); + if (update) + params.updateSchema(); + super.close(); + } + + public void store(String key, int id) throws Exception + { + // System.err.println("storing "+key+" id "+id); + byte[] bytes = key.getBytes("UTF8"); + Entry entry = insert((FullDictBlock)accessBlock(root), + new Entry(bytes, bytes.length, id)); + if (entry != null) + { + // new root; writing to params needed + FullDictBlock nbl = getNewBlock(); + nbl.initInternal(root, entry); + blocks[entry.id] = root = nbl.number; + params.setRoot(root); + } + } + + private void setModified(Block bl) { + blockManager.setModified(bl.number); + } + + private FullDictBlock getNewBlock() throws Exception + { + FullDictBlock nbl = (FullDictBlock)blockManager.getNewBlock(); + setModified(nbl); + return nbl; + } + + /* + delegation to powerful primitives at the FullDictBlock level lets us + express the insertion algorithm very succintly here + */ + + private Entry insert(FullDictBlock bl, Entry ent) throws Exception + { + if (bl.isLeaf) + return insertHere(bl, ent); + else + { + int index = bl.insertInternal(ent); + if (index != -1) + try { + lock(bl); + ent = insert((FullDictBlock)child(bl, index), ent); + return ent == null ? null : insertHere(bl, ent); + } + finally { + unlock(bl); + } + else + return null; + } + } + + private Entry insertHere(FullDictBlock bl, Entry ent) throws Exception + { + setModified(bl); // to be modified in any case + if (bl.insert(ent)) + return null; + else + { + FullDictBlock nbl = getNewBlock(); + Entry middle = bl.split(nbl); + nbl.setBlockNumbers(blocks); + if ((middle.smallerThan(ent) ? nbl : bl).insert(ent) == false) + throw new Exception("entry didn't fit into a freshly split block"); + return middle; + } + } + + public static void main(String[] args) + { + try { + Schema schema = new Schema(null, args[0], true); + BtreeDictParameters tmapParams = new BtreeDictParameters(schema, "TMAP"); + if (tmapParams.readState() == false) + { + tmapParams.setBlockSize(2048); + tmapParams.setRoot(0); + tmapParams.setFreeID(1); + } + FullBtreeDict dict = new FullBtreeDict(tmapParams, true); + int freeID = tmapParams.getFreeID(); + + LineNumberReader in = new LineNumberReader(new BufferedReader + (new FileReader(args[1]))); + String line; + while ((line = in.readLine()) != null) + { + StringTokenizer tokens = new StringTokenizer(line, " "); + while (tokens.hasMoreTokens()) + { + String token = tokens.nextToken(); + if (token.equals("storing")) + dict.store(tokens.nextToken(), freeID++); + else if (token.equals("fetching")) + dict.fetch(tokens.nextToken()); + } + } + in.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Debug code + */ + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("FullBtreeDict: "+msg); + } + } +} + diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java new file mode 100644 index 0000000000000000000000000000000000000000..a7f05174c5e6ffd220be0d0f7cb56f4f34f7110e --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java @@ -0,0 +1,1211 @@ +/* + * @(#)HTMLIndexerKit.java 1.26 06/10/30 + * + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) HTMLIndexerKit.java 1.26 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import javax.swing.text.*; +import javax.swing.text.html.*; +import java.util.*; +import javax.help.search.IndexerKit; +import javax.help.search.IndexBuilder; +import javax.help.search.ConfigFile; + +/** + * This is the default implementation of html parsing. + * It can be subclasses to use a different parser and + * receiver. + * + * @author Roger D. Brinkley + * @version %I %G + */ +public class HTMLIndexerKit extends DefaultIndexerKit{ + + /** + * Constructs an HTMLEditorKit + */ + public HTMLIndexerKit() { + + } + + /** + * Create a copy of the editor kit. This + * allows an implementation to serve as a prototype + * for others, so that they can be quickly created. + * + * @return the copy + */ + public Object clone() { + return new HTMLIndexerKit(); + } + + /** + * Get the MIME type of the data that this + * kit represents support for. This kit supports + * the type <code>text/html</code>. + * + * @return the type + */ + public String getContentType() { + return "text/html"; + } + + /** + * Create and initialize a model from the given + * stream which is expected to be in a format appropriate + * for this kind of kit. This is implemented to read + * html 3.2 text. + * + * @param in The stream to read from + * @param file The file name being parsed + * @param ignoreCharset Ignore the CharacterSet when parsing + * @param builder The IndexBuilder for the full text insertion. + * @param config The indexer configuration information + * @exception IOException on any I/O error + */ + public void parse(Reader in, String file, boolean ignoreCharset, + IndexBuilder builder, + ConfigFile config) throws IOException{ + + this.builder = builder; + this.config = config; + this.file = file; + documentStarted = false; + + HTMLEditorKit.Parser p = getParser(); + if (p == null) { + throw new IOException("Can't load parser"); + } + if (defaultCallback == null) { + defaultCallback = getParserCallback(this); + } + defaultCallback.initialize(); + try { + p.parse(in, defaultCallback, ignoreCharset); + } catch (javax.swing.text.ChangedCharSetException e4) { + throw new com.sun.java.help.search.ChangedCharSetException + (e4.getCharSetSpec(), + e4.keyEqualsCharSet()); + } + + try { + defaultCallback.flush(); + } catch (BadLocationException e3) { + throw new IOException("Can't flush parser"); + } + + try { + storeTitle(defaultCallback.getTitle()); + endStoreDocument(); + } catch (Exception e2) { + throw new IOException("Can't store title"); + } + + this.builder = null; + this.config = null; + } + + /** + * Fetch the parser to use for reading html streams. + * This can be reimplemented to provide a different + * parser. The default implementation is loaded dynamically + * to avoid the overhead of loading the default parser if + * it's not used. The default parser is the HotJava parser + * using an html 3.2 dtd. + */ + protected HTMLEditorKit.Parser getParser() { + if (defaultParser == null) { + try { + Class c = Class.forName("javax.swing.text.html.parser.ParserDelegator"); + defaultParser = (HTMLEditorKit.Parser) c.newInstance(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return defaultParser; + } + + /** + * Fetch the parser callback to use to parse the + * html. This is implemented to return an instance of + * HTMLEditorKit.HTMLParserCallback. Subclasses can reimplement this + * method to change how the document gets parsed + */ + public HTMLParserCallback getParserCallback(IndexerKit kit) { + return new HTMLParserCallback(kit); + } + // --- variables ------------------------------------------ + + private static HTMLEditorKit.Parser defaultParser = null; + private static HTMLParserCallback defaultCallback = null; + + private static char[] NEWLINE; + + static { + NEWLINE = new char[1]; + NEWLINE[0] = '\n'; + } + + /** + * An html reader to load an html document with an html + * element structure. This is a set of callbacks from + * the parser, implemented to create a set index tokens + */ + public class HTMLParserCallback extends HTMLEditorKit.ParserCallback { + + private IndexerKit kit; + private String title; + private String header; + private boolean firstHeader; + private int currentPos; + private boolean receivedEndHTML; + private boolean insertAfterImplied; + private boolean inParagraph; + private boolean impliedP; + private boolean inPre; + private boolean inTextArea; + private boolean inTitle; + private boolean lastWasNewline; + private boolean emptyAnchor; + private boolean inBody; + private boolean foundInsertTag; + private boolean inHead; + private boolean inStyle; + private boolean inOption; + private boolean inFirstHeader; + private boolean startTagType; + private boolean preservesUnknownTags; + Hashtable tagMap; + int inBlock; + Stack tagStack; + String defaultLang; + String lastLang; + + // LangElement is a simple little internal class to keep + // track of tags and the langs + private class LangElement { + + HTML.Tag tag; + String lang; + + public LangElement (HTML.Tag tag, String lang) { + this.tag = tag; + this.lang = lang; + } + + public HTML.Tag getTag() { + return tag; + } + + public String getLang() { + return lang; + } + } + + + public HTMLParserCallback(IndexerKit kit) { + this.kit = kit; + tagMap = new Hashtable(57); + TagAction na = new TagAction(); + TagAction ba = new BlockAction(); + TagAction pa = new ParagraphAction(); + TagAction ca = new CharacterAction(); + TagAction sa = new SpecialAction(); + TagAction fa = new FormAction(); + TagAction ha = new HiddenAction(); + TagAction conv = new ConvertAction(); + + // register handlers for the well known tags + tagMap.put(HTML.Tag.A, new AnchorAction()); + tagMap.put(HTML.Tag.ADDRESS, ca); + tagMap.put(HTML.Tag.APPLET, ha); + tagMap.put(HTML.Tag.AREA, new AreaAction()); + tagMap.put(HTML.Tag.B, ca); + tagMap.put(HTML.Tag.BASE, new BaseAction()); + tagMap.put(HTML.Tag.BASEFONT, ca); + tagMap.put(HTML.Tag.BIG, ca); + tagMap.put(HTML.Tag.BLOCKQUOTE, ba); + tagMap.put(HTML.Tag.BODY, ba); + tagMap.put(HTML.Tag.BR, sa); + tagMap.put(HTML.Tag.CAPTION, ba); + tagMap.put(HTML.Tag.CENTER, ba); + tagMap.put(HTML.Tag.CITE, ca); + tagMap.put(HTML.Tag.CODE, ca); + tagMap.put(HTML.Tag.DD, ba); + tagMap.put(HTML.Tag.DFN, ca); + tagMap.put(HTML.Tag.DIR, ba); + tagMap.put(HTML.Tag.DIV, ba); + tagMap.put(HTML.Tag.DL, ba); + tagMap.put(HTML.Tag.DT, pa); + tagMap.put(HTML.Tag.EM, ca); + tagMap.put(HTML.Tag.FONT, conv); + tagMap.put(HTML.Tag.FORM, new FormTagAction()); + tagMap.put(HTML.Tag.FRAME, sa); + tagMap.put(HTML.Tag.FRAMESET, ba); + tagMap.put(HTML.Tag.H1, pa); + tagMap.put(HTML.Tag.H2, pa); + tagMap.put(HTML.Tag.H3, pa); + tagMap.put(HTML.Tag.H4, pa); + tagMap.put(HTML.Tag.H5, pa); + tagMap.put(HTML.Tag.H6, pa); + tagMap.put(HTML.Tag.HEAD, new HeadAction()); + tagMap.put(HTML.Tag.HR, sa); + tagMap.put(HTML.Tag.HTML, ba); + tagMap.put(HTML.Tag.I, conv); + tagMap.put(HTML.Tag.IMG, sa); + tagMap.put(HTML.Tag.INPUT, fa); + tagMap.put(HTML.Tag.ISINDEX, new IsindexAction()); + tagMap.put(HTML.Tag.KBD, ca); + tagMap.put(HTML.Tag.LI, ba); + tagMap.put(HTML.Tag.LINK, new LinkAction()); + tagMap.put(HTML.Tag.MAP, new MapAction()); + tagMap.put(HTML.Tag.MENU, ba); + tagMap.put(HTML.Tag.META, new MetaAction()); + // NOBR isn't publicly available so workaround it. + HTML.Tag tag = HTML.getTag("NOBR"); + if (tag != null) { + tagMap.put(tag, ca); + } + tagMap.put(HTML.Tag.NOFRAMES, ba); + tagMap.put(HTML.Tag.OBJECT, sa); + tagMap.put(HTML.Tag.OL, ba); + tagMap.put(HTML.Tag.OPTION, fa); + tagMap.put(HTML.Tag.P, pa); + tagMap.put(HTML.Tag.PARAM, new ObjectAction()); + tagMap.put(HTML.Tag.PRE, new PreAction()); + tagMap.put(HTML.Tag.SAMP, ca); + tagMap.put(HTML.Tag.SCRIPT, ha); + tagMap.put(HTML.Tag.SELECT, fa); + tagMap.put(HTML.Tag.SMALL, ca); + tagMap.put(HTML.Tag.STRIKE, conv); + tagMap.put(HTML.Tag.S, ca); + tagMap.put(HTML.Tag.STRONG, ca); + tagMap.put(HTML.Tag.STYLE, new StyleAction()); + tagMap.put(HTML.Tag.SUB, conv); + tagMap.put(HTML.Tag.SUP, conv); + tagMap.put(HTML.Tag.TABLE, ba); + tagMap.put(HTML.Tag.TD, ba); + tagMap.put(HTML.Tag.TEXTAREA, fa); + tagMap.put(HTML.Tag.TH, ba); + tagMap.put(HTML.Tag.TITLE, new TitleAction()); + tagMap.put(HTML.Tag.TR, ba); + tagMap.put(HTML.Tag.TT, ca); + tagMap.put(HTML.Tag.U, conv); + tagMap.put(HTML.Tag.UL, ba); + tagMap.put(HTML.Tag.VAR, ca); + } + + public void initialize() { + title = null; + header = null; + firstHeader = true; + currentPos = 0; + receivedEndHTML = false; + insertAfterImplied = false; + inParagraph = false; + impliedP = false; + inPre = false; + inTitle = false; + inOption = false; + inFirstHeader = false; + startTagType = false; + emptyAnchor = false; + inBlock = 0; + tagStack = new Stack(); + defaultLang = kit.getLocale().toString(); + lastLang = defaultLang; + inTextArea = false; + lastWasNewline = false; + inBody = false; + foundInsertTag = true; + preservesUnknownTags = true; + inHead = false; + inStyle = false; + } + + public String getTitle() { + if (title == null || title.length() < 1) { + title = header; + if (title == null || title.length() < 1) { + title = "No Title"; + } + } + return title; + } + + // -- ParserCallback methods -------------------- + + /** + * This is the last method called on the reader. It allows + * any pending changes to be flushed into the document. + * Since this is currently loading synchronously, the entire + * set of changes are pushed in at this point. + */ + public void flush() throws BadLocationException { + // Nothing needs to be done here + } + + /** + * Called by the parser to indicate a block of text was + * encountered. + */ + public void handleText(char[] data, int pos) { + if (receivedEndHTML) { + return; + } + if (inTextArea) { + // don't do anything + } else if (inPre) { + preContent(data); + } else if (inTitle) { + titleContent(new String(data)); + } else if (inOption) { + // Nothing to do here + } else if (inStyle) { + // don't do anything + } else if (inBlock > 0) { + // Added test for first header to set the + // header content + if (inFirstHeader) { + headerContent(new String(data)); + } + if (!foundInsertTag && insertAfterImplied) { + // Assume content should be added. + foundInsertTag(false); + foundInsertTag = true; + inParagraph = impliedP = true; + } + if (data.length >= 1) { + addContent(data, 0, data.length); + } + } + } + + /** + * Callback from the parser. Route to the appropriate + * handler for the tag. + * This method differes from HTMLDcoument since there + * is not the possibility of doing a mid insert in the + * document and we don't really need to be concerned with + * the construction of the style sheet. + */ + public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) { + if (receivedEndHTML) { + return; + } + if (!inBody && t == HTML.Tag.BODY) { + inBody = true; + } + TagAction action = (TagAction) tagMap.get(t); + if (action != null) { + action.start(t, a); + } + } + + public void handleComment(char[] data, int pos) { + if (receivedEndHTML) { + // don't do anything here + return; + } + if (inStyle) { + // don't do anything here + } else if (preservesUnknownTags) { + if (inBlock == 0) { + // Comment outside of body, will not be able to show it, + // but can add it as a property on the Document. + // In the indexer we don't care though so + // do nothing. + return; + } + SimpleAttributeSet sas = new SimpleAttributeSet(); + sas.addAttribute(HTML.Attribute.COMMENT, new String(data)); + addSpecialElement(HTML.Tag.COMMENT, sas); + debug ("comment added currentPos=" + currentPos); + } + } + + /** + * Callback from the parser. Route to the appropriate + * handler for the tag. + * + * Ignore the midInsert statements in HTMLDocument + */ + public void handleEndTag(HTML.Tag t, int pos) { + if (receivedEndHTML) { + return; + } + if (t == HTML.Tag.HTML) { + receivedEndHTML = true; + } + if (t == HTML.Tag.BODY) { + inBody = false; + } + TagAction action = (TagAction) tagMap.get(t); + if (action != null) { + action.end(t); + } + } + + /** + * Callback from the parser. Route to the appropriate + * handler for the tag. + * + * Ignore the midInsert and style statements in HTMLDocument + */ + public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) { + if (receivedEndHTML) { + return; + } + + TagAction action = (TagAction) tagMap.get(t); + if (action != null) { + action.start(t, a); + action.end(t); + } else if (preservesUnknownTags) { + addSpecialElement(t, a); + } + } + + // ---- tag handling support ------------------------------ + + /** + * Register a handler for the given tag. By default + * all of the well-known tags will have been registered. + * This can be used to change the handling of a particular + * tag or to add support for custom tags. + */ + protected void registerTag(HTML.Tag t, TagAction a) { + tagMap.put(t, a); + } + + /** + * This is an action to be performed in response + * to parsing a tag. This allows customization + * of how each tag is handled and avoids a large + * switch statement. + */ + public class TagAction { + + /** + * Called when a start tag is seen for the + * type of tag this action was registered + * to. The tag argument indicates the actual + * tag for those actions that are shared across + * many tags. + * + * Different from HTMLDocument it doesn't ignore + * the tag. + */ + public void start(HTML.Tag t, MutableAttributeSet a) { + String lang = (String) a.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + } + + /** + * Called when an end tag is seen for the + * type of tag this action was registered + * to. The tag argument indicates the actual + * tag for those actions that are shared across + * many tags. + * + * Different from HTMLDocument it doesn't ignore + * the tag. + */ + public void end(HTML.Tag t) { + removeTag(t); + } + + } + + public class BlockAction extends TagAction { + + public void start(HTML.Tag t, MutableAttributeSet attr) { + blockOpen(t, attr); + String lang = (String) attr.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + } + + public void end(HTML.Tag t) { + blockClose(t); + removeTag(t); + } + } + + /** + * Action used for the actual element form tag. This is named such + * as there was already a public class named FormAction. + * + * Unlike HTMLDocument there is no need to setup/destroy + * a ButtonGroup + */ + private class FormTagAction extends BlockAction { + public void start(HTML.Tag t, MutableAttributeSet attr) { + super.start(t, attr); + // do nothing else + } + + public void end(HTML.Tag t) { + super.end(t); + // do nothing else + } + } + + + public class ParagraphAction extends BlockAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + // trap the first header as a substitute title if needed + if (firstHeader && + ((t == HTML.Tag.H1) || (t == HTML.Tag.H2) || + (t == HTML.Tag.H3) || (t == HTML.Tag.H4) || + (t == HTML.Tag.H5) || (t == HTML.Tag.H6))) { + inFirstHeader = true; + } + // addTag done in super + super.start(t, a); + inParagraph = true; + } + + public void end(HTML.Tag t) { + // trapped the first header as a substitute title if needed + if (firstHeader && + ((t == HTML.Tag.H1) || (t == HTML.Tag.H2) || + (t == HTML.Tag.H3) || (t == HTML.Tag.H4) || + (t == HTML.Tag.H5) || (t == HTML.Tag.H6))) { + inFirstHeader = false; + firstHeader = false; + } + // removeTag done in super + super.end(t); + inParagraph = false; + } + } + + public class SpecialAction extends TagAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + String lang = (String) a.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + addSpecialElement(t, a); + } + // removeTag is handled in super class + } + + public class IsindexAction extends TagAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet()); + addSpecialElement(t, a); + blockClose(HTML.Tag.IMPLIED); + } + + } + + public class HiddenAction extends TagAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + String lang = (String) a.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + addSpecialElement(t, a); + } + + public void end(HTML.Tag t) { + if (!isEmpty(t)) { + MutableAttributeSet a = new SimpleAttributeSet(); + a.addAttribute(HTML.Attribute.ENDTAG, "true"); + addSpecialElement(t, a); + } + removeTag(t); + } + + private boolean isEmpty(HTML.Tag t) { + if (t == HTML.Tag.APPLET || + t == HTML.Tag.TITLE || + t == HTML.Tag.SCRIPT) { + return false; + } + return true; + } + } + + /** + * Subclass of HiddenAction to set the content type for style sheets, + * and to set the name of the default style sheet. + * + * None of this method is really needed for the Indexer. + * Don't do anything related tot he style sheet and just + * take the actions of HiddenAction to record the position + */ + class MetaAction extends HiddenAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + // ignore all the style sheet setting code + super.start(t, a); + } + + private boolean isEmpty(HTML.Tag t) { + return true; + } + } + + + /** + * End if overridden to create the necessary stylesheets that + * are referenced via the link tag. It is done in this manner + * as the meta tag can be used to specify an alternate style sheet, + * and is not guaranteed to come before the link tags. + * + * For the indexer we don't care much about the style + * sheets. + */ + class HeadAction extends BlockAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + inHead = true; + super.start(t, a); + } + + public void end(HTML.Tag t) { + inHead = inStyle = false; + // ignore the StyleSheet statements + super.end(t); + } + } + + /** + * A subclass to add the AttributeSet to styles if the + * attributes contains an attribute for 'rel' with value + * 'stylesheet' or 'alternate stylesheet'. + * + * For the indexer we don't care about style sheets. + */ + class LinkAction extends HiddenAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + // ignore the style sheet statements + super.start(t, a); + } + } + + /** + * Don't do anything for Maps in Indexer. It just stores + * the information in a property HashTable. + */ + class MapAction extends TagAction { + } + + + /** + * Don't do anthing for an Area action for Indexer. + * It's stored locally in HTMLDocument and doesn't + * require an entry as a tag + */ + class AreaAction extends TagAction { + } + + + /** + * Handle style actions + * + * Ignore the storing the styles as HTMLDocument does + */ + class StyleAction extends TagAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + if (inHead) { + inStyle = true; + } + super.start(t, a); + } + + public void end(HTML.Tag t) { + inStyle = false; + super.end(t); + } + } + + + public class PreAction extends BlockAction { + + public void start(HTML.Tag t, MutableAttributeSet attr) { + inPre = true; + blockOpen(t, attr); + attr.addAttribute(CSS.Attribute.WHITE_SPACE, "pre"); + blockOpen(HTML.Tag.IMPLIED, attr); + String lang = (String) attr.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + } + + public void end(HTML.Tag t) { + blockClose(HTML.Tag.IMPLIED); + // set inPre to false after closing, so that if a newline + // is added it won't generate a blockOpen. + inPre = false; + blockClose(t); + removeTag(t); + } + } + + public class CharacterAction extends TagAction { + + /** + * In the indexer we don't care about character style + * and the foundInsertTag will always be true so there + * really isn't much to do here + * + */ + public void start(HTML.Tag t, MutableAttributeSet a) { + String lang = (String) a.getAttribute(HTML.Attribute.LANG); + if (lang == null) { + lang = lastLang; + } + addTag(t, lang); + } + + public void end(HTML.Tag t) { + removeTag(t); + } + } + + /** + * Provides conversion of HTML tag/attribute + * mappings that have a corresponding StyleConstants + * and CSS mapping. The conversion is to CSS attributes. + * + * For the indexer we really don't care much. We'll keep + * the method here for consistency sake, but it really + * isn't needed. + */ + class ConvertAction extends TagAction { + } + + class AnchorAction extends CharacterAction { + // This class has a dependancy on the "one[0]" character + // used in javax.swing.text.html.HTMLDocument$AnchorAction + // we need to ensure we use the same character value. + private boolean post4207472 = isPost4207472(); + + public void start(HTML.Tag t, MutableAttributeSet attr) { + // set flag to catch empty anchors + emptyAnchor = true; + // addTag done in super + super.start(t, attr); + } + + public void end(HTML.Tag t) { + if (emptyAnchor) { + // if the anchor was empty it was probably a + // named anchor point and we don't want to throw + // it away. + char[] one = new char[1]; + if (post4207472) + one[0] = '\n'; + else + one[0] = ' '; + debug ("emptyAnchor currentPos=" + currentPos); + addContent(one, 0, 1); + } + // remove tag done in super + super.end(t); + } + private boolean isPost4207472() { + try { + String ver = System.getProperty("java.version"); + int major = Integer.parseInt(ver.substring(2,3)); + int minor = 0; + // allow for FCS case - we leave minor as 0 if dealing with FCS + if (ver.length() > 6) + minor = Integer.parseInt(ver.substring(6,8)); + if ((major > 5 ) || (major==5 && minor >= 4)) { + return true; + } else { + return false; + } + } catch (Exception e) { + debug ("Exception in isPost4207472 : " + e); + return true; // assume true if we encounter problem + } + } + } + + class TitleAction extends HiddenAction { + + public void start(HTML.Tag t, MutableAttributeSet attr) { + inTitle = true; + super.start(t, attr); + } + + public void end(HTML.Tag t) { + inTitle = false; + super.end(t); + } + } + + class BaseAction extends TagAction { + + // Nothing here for indexer + } + + + class ObjectAction extends SpecialAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + if (t == HTML.Tag.PARAM) { + // don't do anything if a parameter + } else { + super.start(t, a); + } + } + + public void end(HTML.Tag t) { + if (t != HTML.Tag.PARAM) { + super.end(t); + } + } + + } + + public class FormAction extends SpecialAction { + + /** + * Ignore INPUT and Select. Only be concerned with + * TEXTAREA and OPTION + */ + public void start(HTML.Tag t, MutableAttributeSet attr) { + if (t == HTML.Tag.TEXTAREA) { + inTextArea = true; + } + + // Occupy one space for the element, unless this is an option. + if (t == HTML.Tag.OPTION) { + //options don't take any room. They are internal to selects + } else { + super.start(t, attr); + } + } + + public void end(HTML.Tag t) { + if (t == HTML.Tag.TEXTAREA) { + inTextArea = false; + } + + if (t == HTML.Tag.OPTION) { + // ignore options + } else { + super.end(t); + } + } + + } + + // --- utility methods used by the reader ------------------ + + /** + * Set the title for the doc + */ + protected void titleContent(String s) { + if (title == null) { + title = new String(s); + } else { + title.concat(s); + } + } + + /** + * Set the first header for the doc + */ + protected void headerContent(String s) { + if (header == null) { + header = new String(s); + } else { + header.concat(s); + } + } + + /** + * Add the given content that was encountered in a + * PRE element. This synthesizes lines to hold the + * runs of text, and makes calls to addContent to + * actually add the text. + */ + protected void preContent(char[] data) { + int last = 0; + for (int i = 0; i < data.length; i++) { + if (data[i] == '\n') { + debug ("preContent currentPos=" + currentPos); + addContent(data, last, i - last + 1); + blockClose(HTML.Tag.IMPLIED); + MutableAttributeSet a = new SimpleAttributeSet(); + a.addAttribute(CSS.Attribute.WHITE_SPACE, "pre"); + blockOpen(HTML.Tag.IMPLIED, a); + last = i + 1; + } + } + if (last < data.length) { + debug ("preContent currentPos=" + currentPos); + addContent(data, last, data.length - last); + } + } + + /** + * Add an instruction to the parse buffer to create a + * block element with the given attributes. + */ + protected void blockOpen(HTML.Tag t, MutableAttributeSet attr) { + debug ("blockOpen"); + if (impliedP) { + blockClose(HTML.Tag.IMPLIED); + } + + inBlock++; + if (!canInsertTag(t, attr, true)) { + return; + } + startTagType = true; + lastWasNewline = false; + // parse buffer code not used in indexer + } + + /** + * Add an instruction to the parse buffer to close out + * a block element of the given type. + */ + protected void blockClose(HTML.Tag t) { + debug ("blockClose"); + inBlock --; + + if (!foundInsertTag) { + return; + } + + // Add a new line, if the last character wasn't one. This is + // needed for proper positioning of the cursor. + if(!lastWasNewline) { + debug ("blockClose adding NEWLINE currentPos=" + currentPos); + addContent(NEWLINE, 0, 1, false); + lastWasNewline = true; + } + + if (impliedP) { + impliedP = false; + inParagraph = false; + if (t != HTML.Tag.IMPLIED) { + blockClose(HTML.Tag.IMPLIED); + } + } + + // This is different from HTMLReader. I don't keep parseBuffer + // so I'll use the boolean startTagType instead. + // + // an open/close with no content will be removed, so we + // add a space of content to keep the element being formed. + if (startTagType) { + char[] one = new char[1]; + one[0] = ' '; + debug ("blockclose open/close nocontent currentPos=" + currentPos); + addContent(one, 0, 1); + } + startTagType = false; + } + + /** + * Add some text with the current character attributes. + * + * @param embedded the attributes of an embedded object. + */ + protected void addContent(char[] data, int offs, int length) { + addContent(data, offs, length, true); + } + + /** + * Add some text with the current character attributes. + * + * @param embedded the attributes of an embedded object. + */ + protected void addContent(char[] data, int offs, int length, + boolean generateImpliedPIfNecessary) { + debug ("addContent"); + if (!foundInsertTag) { + return; + } + + if (generateImpliedPIfNecessary && (! inParagraph) && (! inPre)) { + blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet()); + inParagraph = true; + impliedP = true; + } + emptyAnchor = false; + + // This is different from HTMLDocument. The indexer doesn't use + // parseBuffer. Instead pass the strings over to IndexerKit to + // parse the string into tokens. Also set startTagType to false + // to simulate that portion of parseBuffer + debug ("Pre parseIntoTokens String=" + new String(data, offs, length) + " currentPos=" + currentPos); + startTagType = false; + currentPos = kit.parseIntoTokens(new String(data, offs, length), + currentPos); + debug ("Post parseIntoTokens currentPos=" + currentPos); + + // No flushing like HTMLDocument but set the lastWasNewline + // appropriately + if(length > 0) { + lastWasNewline = (data[offs + length - 1] == '\n'); + } + } + + /** + * Add content that is basically specified entirely + * in the attribute set. + */ + protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a) { + if ((t != HTML.Tag.FRAME) && (! inParagraph) && (! inPre)) { + blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet()); + inParagraph = true; + impliedP = true; + } + + if (!canInsertTag(t, a, true)) { + return; + } + emptyAnchor = false; + + // This is different from HTMLDocument. The indexer doesn't use + // parseBuffer. Just increment to currentPos to simulate the + // addition + currentPos += 1; + debug ("addingSpecialElement tag=" + t + " currentPos=" + currentPos); + startTagType = false; + + // Set this to avoid generating a newline for frames, frames + // shouldn't have any content, and shouldn't need a newline. + if (t == HTML.Tag.FRAME) { + lastWasNewline = true; + } + } + + /** + * Returns true if can insert starting at <code>t</code>. This + * will return false if the insert tag is set, and hasn't been found + * yet. + */ + private boolean canInsertTag(HTML.Tag t, AttributeSet attr, + boolean isBlockTag) { + if (!foundInsertTag) { + foundInsertTag(isBlockTag); + return false; + } + return true; + } + + private boolean isInsertTag(HTML.Tag tag) { + return (false); + } + + private void foundInsertTag(boolean isBlockTag) { + foundInsertTag = true; + // The rest of the code is differnt from HTMLDocument since we + // don't need to worry about added to a document we don't care + // about adding a newline or pushing or poping + } + + /** + * addTag keeps track of tags and their lang attributes + */ + protected void addTag(HTML.Tag tag, String lang) { + LangElement el = new LangElement(tag, lang); + tagStack.push(el); + if (lastLang.compareTo(lang) != 0) { + kit.setLocale(lang); + lastLang = lang; + } + } + + /** + * removeTag removes a tag from the tagStack. The tagStack is + * used to keep track of tags and locales + */ + protected void removeTag(HTML.Tag tag) { + LangElement el; + String name = tag.toString(); + String newLang=defaultLang; + + for (;;) { + if (tagStack.empty()) + break; + el = (LangElement) tagStack.pop(); + if (el.getTag().toString().compareTo(name) == 0) { + if (tagStack.empty()) { + newLang = defaultLang; + } else { + el = (LangElement) tagStack.peek(); + newLang = el.getLang(); + } + break; + } + } + if (lastLang.compareTo(newLang) != 0) { + kit.setLocale(newLang); + lastLang = newLang; + } + } + + } + + /** + * Debug code + */ + + private boolean debugFlag=false; + private void debug(String msg) { + if (debugFlag) { + System.err.println("HTMLIndexerKit: "+msg); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java new file mode 100644 index 0000000000000000000000000000000000000000..1bf29848435e12e70e7a3cd83101a2dd05b2e967 --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java @@ -0,0 +1,546 @@ +/* + * @(#)Indexer.java 1.46 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) Indexer.java 1.46 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.text.*; +import java.net.*; +import java.util.Vector; +import java.util.Hashtable; +import java.util.Locale; +import javax.help.search.IndexerKit; +import javax.help.search.ConfigFile; +import com.sun.java.help.impl.HeaderParser; + +/** + * This class provides ... + * + * + * @version 1.46 10/30/06 + * @author Roger D. Brinkley + */ + +public class Indexer { + + /** The database directory name. */ + String dbName = "JavaHelpSearch"; + + /** The stream for printing syntax errors */ + PrintStream verbose=null; + PrintStream logStream=null; + + /** The number of documents correctly parsed and compiled. */ + short docNumber; + + private DefaultIndexBuilder indexBuilder = null; + + private ConfigFile config; + private String title; + private String header; + private boolean firstHeader=false; + String lastPCdata; + int currentPos; + boolean openTagSeen = false; + boolean inPre = false; + boolean inTitle = false; + boolean inFirstHeader = false; + boolean inOption = false; + int inBlock = 0; + String sourcepath; + /** + * Starts the application. + * @param args[] the command line arguments + **/ + + public static void main(String args[]) { + Indexer compiler = new Indexer(); + try { + compiler.compile(args); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Creates an initialised compiler. + **/ + + public Indexer() { + // Make sure the last character is a file separator + if (dbName.lastIndexOf("/") + != dbName.length() - 1) { + dbName = dbName.concat("/"); + } + docNumber = 0; + } + + /** + * Parses the <tt>.html</tt> files, and compiles the search database. + * @param args[] the command line arguments + **/ + + public void compile(String args[]) throws Exception { + long parseTime, compileTime, startTime = System.currentTimeMillis(); + int words; + String configFile = null; + Vector tmpfiles = new Vector(); + Vector files = new Vector(); + String file; + int size; + sourcepath=""; + boolean nostopwords = false; + + for (int i=0; i < args.length ; i++) { + if(args[i].equals("-db")) { + if ((i + 1) < args.length) { + dbName = args[++i]; + // Make sure the last character is a file separator + if (dbName.lastIndexOf("/") + != dbName.length() - 1) { + dbName = dbName.concat("/"); + } + } else { + System.out.println (args[i] + "-db requires argument"); + } + } + else if(args[i].equals("-sourcepath")) { + if ((i + 1) < args.length) { + sourcepath = args[++i]; + } else { + System.out.println (args[i] + "-sourcepath requires argument"); + } + } + else if(args[i].equals("-locale")) { + if ((i + 1) < args.length) { + defaultLang= args[++i]; + } else { + System.out.println (args[i] + "-locale requires argument"); + } + } + else if(args[i].equals("-logfile")) { + if ((i + 1) < args.length) { + String logFile= args[++i]; + try { + logStream = new PrintStream(new FileOutputStream(logFile) + ,true); + System.setErr(logStream); + System.setOut(logStream); + verbose = logStream; + } catch (java.io.FileNotFoundException ex) { + System.out.println("Couldn't create logFile " + logFile); + } + } else { + System.out.println (args[i] + "-logfile requires argument"); + } + } + else if(args[i].equals("-verbose")) verbose = System.out; + else if(args[i].equals("-nostopwords")) nostopwords = true; + else if(args[i].equals("-c")) { + if ((i + 1) < args.length) { + configFile = args[++i]; + } else { + System.out.println (args[i] + "-c requires argument"); + } + } + else if(args[i].startsWith("-")) { + System.out.println("Unknown argument '" + args[i] + "'"); + showUsage(); + return; + } else { + tmpfiles.addElement(args[i]); + } + } + + // read the config file + config = new ConfigFile (configFile, files, nostopwords); + // get the files from the config file + files = config.getFiles(); + + // adjust the passed with config parameters + size = tmpfiles.size(); + for (int i=0; i < size; i++) { + files = loadFiles ((String)tmpfiles.elementAt(i), files); + } + + size = files.size(); + if (size == 0) { + System.out.println("No files specified to index"); + showUsage(); + return; + } + + indexBuilder= new DefaultIndexBuilder(dbName); + // set the stopwords in the indexBuilder + indexBuilder.storeStopWords(config.getStopWords()); + + for (int i=0; i < size; i++) { + file = (String) files.elementAt(i); + URL url = new URL("file", "", sourcepath+file); + InputStream in = url.openStream(); + URLConnection conn = url.openConnection(); + String type = conn.getContentType(); + setContentType(type); + if (kit != null) { + try { + if (verbose != null) { + verbose.println(" File: '" + file + "'"); + verbose.println(" URL: '" + config.getURLString(file) + "'"); + } + parseFile(in, file, false); + in.close(); + } catch (UnsupportedEncodingException e1) { + System.out.println("File: '" + file + "' encoding " + + charSetName + " not supported"); + in.close(); + continue; + } catch (IOException e) { + if (debugFlag) e.printStackTrace(); + System.out.println("I/O exception occurred in file '" + sourcepath+file + "'"); + in.close(); + continue; + } + } + } + parseTime = System.currentTimeMillis() - startTime; + + // show some final statistics + + compileTime = System.currentTimeMillis() - startTime - parseTime; + if (verbose != null) { + verbose.println(" Parse time: " + (float)parseTime / 1000.0 + " s"); + } + indexBuilder.close(); + } + + + + /** + * This method invokes the indexerKit to initiate parsing. In the + * case where a ChangedCharSetException is thrown this exception + * will contain the new CharSet. Therefore the parse() operation + * is then restarted after building a new Reader with the new charset. + * + * @param the inputstream to use. + * @param the document to load. + * + */ + void parseFile(InputStream in, String file, boolean ignoreCharset) throws IOException { + try { + kit.parse(new InputStreamReader(in, charSetName), file, + ignoreCharset, indexBuilder, config); + } catch (com.sun.java.help.search.ChangedCharSetException e1) { + String charSetSpec = e1.getCharSetSpec(); + if (e1.keyEqualsCharSet()) { + charSetName = charSetSpec; + } else { + setCharsetFromContentTypeParameters(charSetSpec); + } + in.close(); + URL url = new URL("file", "", sourcepath+file); + in = url.openStream(); + parseFile(in, file, true); + } + } + + + public Vector loadFiles (String file, Vector files) { + File tstfile = new File (file); + if (tstfile.isDirectory()) { + String list[] = tstfile.list(); + for (int i=0; i < list.length; i++) { + files = loadFiles (tstfile.getPath() + + File.separator + + list[i], files); + } + } else { + files.addElement(file); + } + return files; + } + + /** + * Shows the usage message. + **/ + + public void showUsage() { + System.out.println(" Usage: java JavaHelp.Index options file ..."); + System.out.println(" Options: -c file config file"); + System.out.println(" -db file generated database file name"); + System.out.println(" -verbose verbose documentation"); + System.out.println(" -nostopwords ignore stop words"); + System.out.println(" -locale language_country_variant"); + System.out.println(" -logfile log file name"); + System.out.println("Note: config file composition:"); + System.out.println(" IndexRemove /public_html/JavaHelp/demo"); + System.out.println(" IndexPrepend .."); + System.out.println(" StopWords word1 ... wordN"); + System.out.println(" StopWordsFile stopWordFileName"); + System.out.println(" File /public_html/JavaHelp/demo/first.html"); + System.out.println(" File=/public_html/JavaHelp/demo/second.html"); + System.out.println(" ..."); + } + + /** + * Current content binding of the indexer. + */ + private IndexerKit kit; + + /** + * Table of registered type handlers for this indexer. + */ + private Hashtable typeHandlers; + + private String defaultCharSetName = "ISO8859_1"; + private String charSetName; + private String defaultLang = Locale.getDefault().toString(); + private String lang; + + + /* + * Private AppContext keys for this class's static variables. + */ + private static final Hashtable kitRegistry = new Hashtable(); + private static final Hashtable kitTypeRegistry = new Hashtable(); + private static final Hashtable kitLoaderRegistry = new Hashtable(); + + static { + // set the default bindings + registerIndexerKitForContentType("text/plain", + "com.sun.java.help.search.PlainTextIndexerKit", + null); + registerIndexerKitForContentType("text/html", + "com.sun.java.help.search.HTMLIndexerKit", + null); + + } + + + /** + * Sets the type of content for the current document that this indexer + * handles. This calls <code>getIndexerKitForContentType</code>. + * <p> + * If there is a charset definition specified as a parameter + * of the content type specification, it will be used when + * loading input streams using the associated IndexerKit. + * For example if the type is specified as + * <code>text/html; charset=EUC-JP</code> the content + * will be loaded using the IndexerKit registered for + * <code>text/html</code> and the Reader provided to + * the IndexerKit to load unicode into the document will + * use the <code>EUC-JP</code> charset for translating + * to unicode. + * + * @param type the non-null mime type for the content editing + * support. + */ + public final void setContentType(String type) { + // Set a charSetName to default incase it isn't defined + charSetName = defaultCharSetName; + // Set the lang to default lang incase it isn't defined + lang = defaultLang; + + debug ("type=" + type); + // The type could have optional info is part of it, + // for example some charset info. We need to strip that + // of and save it. + int parm = type.indexOf(";"); + if (parm > -1) { + // Save the paramList. + String paramList = type.substring(parm); + // update the content type string. + type = type.substring(0, parm).trim(); + // Set the charset name from the paramlist + setCharsetFromContentTypeParameters(paramList); + } + if ((kit == null) || (! type.equals(kit.getContentType()))) { + IndexerKit k = getIndexerKitForContentType(type); + if (k != null) { + kit = k; + } + } + kit.setLocale(lang); + } + + /** + * This method get's the charset information specified as part + * of the content type in the http header information. + */ + private void setCharsetFromContentTypeParameters(String paramlist) { + String charset = null; + try { + // paramlist is handed to us with a leading ';', strip it. + int semi = paramlist.indexOf(';'); + if (semi > -1 && semi < paramlist.length()-1) { + paramlist = paramlist.substring(semi + 1); + } + + if (paramlist.length() > 0) { + // parse the paramlist into attr-value pairs & get the + // charset pair's value + HeaderParser hdrParser = new HeaderParser(paramlist); + charset = hdrParser.findValue("charset"); + if (charset != null) { + charSetName = charset; + } + } + } + catch (IndexOutOfBoundsException e) { + // malformed parameter list, use charset we have + } + catch (NullPointerException e) { + // malformed parameter list, use charset we have + } + catch (Exception e) { + // malformed parameter list, use charset we have; but complain + System.err.println("Indexer.getCharsetFromContentTypeParameters failed on: " + paramlist); + e.printStackTrace(); + } + } + + /** + * Fetches the indexer kit to use for the given type + * of content. This is called when a type is requested + * that doesn't match the currently installed type. + * If the component doesn't have an IndexerKit registered + * for the given type, it will try to create an + * IndexerKit from the default IndexerKit registry. + * If that fails, a PlainIndexerKit is used on the + * assumption that all text documents can be represented + * as plain text. + * <p> + * This method can be reimplemented to use some + * other kind of type registry. This can + * be reimplemented to use the Java Activation + * Framework for example. + * + * @param type the non-null content type + * @return the indexer kit + */ + public IndexerKit getIndexerKitForContentType(String type) { + if (typeHandlers == null) { + typeHandlers = new Hashtable(3); + } + IndexerKit k = (IndexerKit) typeHandlers.get(type); + if (k == null) { + k = createIndexerKitForContentType(type); + if (k != null) { + setIndexerKitForContentType(type, k); + } + } + if (k == null) { + k = new DefaultIndexerKit(); + setIndexerKitForContentType(type, k); + } + return k; + } + + /** + * Directly set the indexer kit to use for the given type. + * + * @param type the non-null content type + * @param k the indexer kit to be set + */ + public void setIndexerKitForContentType(String type, IndexerKit k) { + if (typeHandlers == null) { + typeHandlers = new Hashtable(3); + } + typeHandlers.put(type, k); + } + + /** + * Create a handler for the given type from the default registry + * of indexer kits. The registry is created if necessary. An attempt + * is made to dynamically load the prototype of the given kit. If + * successful it is cloned and returned. + * + * @param type the content type + * @return the indexer kit, or null if one cannot be created + */ + public static IndexerKit createIndexerKitForContentType(String type) { + debug ("Getting IndexerKit for " + type); + IndexerKit k = null; + k = (IndexerKit) kitRegistry.get(type); + if (k == null) { + // try to dynamically load the support + String classname = (String) kitTypeRegistry.get(type); + ClassLoader loader = (ClassLoader) kitLoaderRegistry.get(type); + try { + Class c; + if (loader != null) { + c = loader.loadClass(classname); + } else { + c = Class.forName(classname); + } + k = (IndexerKit) c.newInstance(); + kitRegistry.put(type, k); + } catch (Throwable e) { + if (debugFlag) e.printStackTrace(); + k = null; + } + } + + // create a copy of the prototype or null if there + // is no prototype. + if (k != null) { + return (IndexerKit) k.clone(); + } + return null; + } + + /** + * Establishes the default bindings of type to name. + * The class will be dynamically loaded later when actually + * needed, and can be safely changed before attempted uses + * to avoid loading unwanted classes. + * + * @param type the non-null content type + * @param classname the class to load later + */ + public static void registerIndexerKitForContentType(String type, String classname, ClassLoader loader) { + kitTypeRegistry.put(type, classname); + if (loader != null) { + kitLoaderRegistry.put(type, loader); + } + } + + + /** + * For printf debugging. + */ + private static boolean debugFlag = false; + private static void debug(String str) { + if( debugFlag ) { + System.out.println("Indexer: " + str); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java new file mode 100644 index 0000000000000000000000000000000000000000..b2881d4b2d3be57075080fcaf6af94b9b93d51bc --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java @@ -0,0 +1,129 @@ +/* + * @(#)PlainTextIndexerKit.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) PlainTextIndexerKit.java 1.3 - last change made 10/30/06 + */ + +package com.sun.java.help.search; + +import java.io.*; +import java.util.Locale; +import java.text.*; +import javax.help.search.IndexerKit; +import javax.help.search.IndexBuilder; +import javax.help.search.ConfigFile; + +/** + * This is the set of things needed by an indexing object + * to be a reasonably functioning indexer for some <em>type</em> + * of text document. This implementation provides a default + * implementation which treats text as plain text + * + * @author Roger D. Brinkley + * @version %I %G + */ +public class PlainTextIndexerKit extends DefaultIndexerKit { + + public PlainTextIndexerKit() { + locale = Locale.getDefault(); + } + + /** + * Creates a copy of the indexer kit. This + * allows an implementation to serve as a prototype + * for others, so that they can be quickly created. + * + * @return the copy + */ + public Object clone() { + return new PlainTextIndexerKit(); + } + + /** + * Gets the MIME type of the data that this + * kit represents support for. The default + * is <code>text/plain</code>. + * + * @return the type + */ + public String getContentType() { + return "text/plain"; + } + + /** + * Inserts content from the given stream, which will be + * treated as plain text. + * + * @param in The stream to read from + * @param file The file name being parsed + * @param ignoreCharset Ignore the CharacterSet when parsing + * @param builder The IndexBuilder for the full text insertion. + * @param config The indexer configuration information + * @exception IOException on any I/O error + */ + public void parse(Reader in, String file, boolean ignoreCharset, + IndexBuilder builder, + ConfigFile config) throws IOException + { + debug ("parsing " + file); + + this.builder = builder; + this.config = config; + this.file = file; + documentStarted = false; + int currentPos = 1; + + char[] buff = new char[4096]; + int nch; + while ((nch = in.read(buff, 0, buff.length)) != -1) { + currentPos = parseIntoTokens(new String(buff), currentPos); + } + + try { + storeTitle("No Title"); + endStoreDocument(); + } catch (Exception e2) { + throw new IOException("Can't store title"); + } + + this.builder = null; + this.config = null; + } + + + /** + * Debug code + */ + + private boolean debugFlag=false; + private void debug(String msg) { + if (debugFlag) { + System.err.println("PlainTextIndexerKit: "+msg); + } + } +} diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html b/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html new file mode 100644 index 0000000000000000000000000000000000000000..1a412d81375060d24c52b69d47cb8a551f0a4b1d --- /dev/null +++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.1 10/15/98 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Implementation classes for the default Search builder using in the +reference implementation of JavaHelp. + +<p> +<em>Note:</em>We have not yet finalized the location for these classes. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see +<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A> + + </body> +</html> diff --git a/jhMaster/JSearch/jhsearch.bat b/jhMaster/JSearch/jhsearch.bat new file mode 100644 index 0000000000000000000000000000000000000000..59579ada0f1f091467b07feacf26c4598e3afd48 --- /dev/null +++ b/jhMaster/JSearch/jhsearch.bat @@ -0,0 +1,46 @@ +@echo off + +REM +REM @(#)jhsearch.bat 1.5 06/10/30 +REM +REM Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +REM +REM This code is free software; you can redistribute it and/or modify it +REM under the terms of the GNU General Public License version 2 only, as +REM published by the Free Software Foundation. Sun designates this +REM particular file as subject to the "Classpath" exception as provided +REM by Sun in the LICENSE file that accompanied this code. +REM +REM This code is distributed in the hope that it will be useful, but WITHOUT +REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +REM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +REM version 2 for more details (a copy is included in the LICENSE file that +REM accompanied this code). +REM +REM You should have received a copy of the GNU General Public License version +REM 2 along with this work; if not, write to the Free Software Foundation, +REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +REM +REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +REM CA 95054 USA or visit www.sun.com if you need additional information or +REM have any questions. +REM + +rem Run the JHSearch +rem @(#)jhsearch.bat 1.3 07/14/98 + +if ."%JSHOME%".==."". goto nojhhome +goto runnit +:nojhhome +echo The environment variable JSHOME has not been set +goto done +echo +:runnit +@echo on +set CLASSPATH=%JSHOME%\lib\jsearch.jar +java com.sun.java.help.search.QueryEngine %1 +@echo off + +:done + diff --git a/jhMaster/JSearch/misc/GNUmakefile b/jhMaster/JSearch/misc/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..731417a370a1b0a200c93492f08fa844fccc966b --- /dev/null +++ b/jhMaster/JSearch/misc/GNUmakefile @@ -0,0 +1,69 @@ +# +# @(#)GNUmakefile 1.12 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +.SUFFIXES: +.SUFFIXES: .java .class + +JHHOMEWS=../../JavaHelp +VPATH = $(JHHOMEWS)/src/impl:$(JHHOMEWS)/src/new + +SEARCH_SRC=ConfigFile.java \ + IndexBuilder.java \ + IndexerKit.java \ + SearchEngine.java \ + SearchEvent.java \ + SearchItem.java \ + SearchListener.java \ + SearchQuery.java + +SEARCH_CLASSES=$(SEARCH_SRC:%.java=classes/javax/help/search/%.class) + +OTHER_SRC=javax/help/event/EventListenerList.java \ + javax/help/HelpUtilities.java + +OTHER_CLASSES=$(OTHER_SRC:%.java=classes/%.class) + +IMPL_SRC:=com/sun/java/help/impl/HeaderParser.java +IMPL_CLASSES=$(IMPL_SRC:%.java=classes/%.class) + +ALL_CLASSES=$(SEARCH_CLASSES) $(IMPL_CLASSES) $(OTHER_CLASSES) + + +jar: ../lib/jsearch-misc.jar + +../lib/jsearch-misc.jar: classes $(ALL_CLASSES) + cd classes ; \ + jar cf ../../lib/jsearch-misc.jar javax com + +classes/%.class: %.java + javac -d classes -classpath ../../JavaHelp/src/impl:../../JavaHelp/src/new $< + +classes: + mkdir classes + +clean: + $(RM) -rf classes diff --git a/jhMaster/JavaHelp/doc/css/default.css b/jhMaster/JavaHelp/doc/css/default.css new file mode 100644 index 0000000000000000000000000000000000000000..16a11734f93021aeea3da4fdf4eafe0d2a244f51 --- /dev/null +++ b/jhMaster/JavaHelp/doc/css/default.css @@ -0,0 +1,259 @@ +/* + * @(#)default.css 1.37 98/10/17 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +body {font-size: 14pt; + font-family: SansSerif; + margin-left: 0; + margin-right: 0; + color: black} + +p {font-size: medium; + font-weight: normal; + margin-top: 15} + +h1 {font-size: x-large; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +h2 {font-size: large; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +h3 {font-size: medium; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +h4 {font-size: small; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +h5 {font-size: x-small; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +h6 {font-size: xx-small; + font-weight: bold; + margin-top: 10; + margin-bottom: 10} + +li p {margin-top: 0; + margin-bottom: 0} + +menu li p {margin-top: 0; + margin-bottom: 0} + +menu li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +menu {margin-left: 40; + margin-top: 10; + margin-bottom: 10} + +dir li p {margin-top: 0; + margin-bottom: 0} + +dir li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +dir {margin-left: 40; + margin-top: 10; + margin-bottom: 10} + +dd p {margin-left: 40; + margin-top: 0; + margin-bottom: 0} + +dt {margin-top: 0; + margin-bottom: 0} + +dl {margin-left: 10; + margin-top: 10; + margin-bottom: 10} + +ol li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +ol { + margin-top: 10; + margin-bottom: 10; + margin-left: 50; + list-style-type: decimal +} + +ol li p {margin-top: 0; + margin-bottom:0} + +ul li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +ul {margin-top: 10; + margin-bottom: 10; + margin-left: 50; + list-style-type: disc; + -bullet-gap: 10} + +ul li ul li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +ul li ul {list-style-type: circle; + margin-left: 25} + +ul li ul li ul li {margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0} + +ul li ul li ul {list-style-type: square; + margin-left: 25} + +ul li menu {list-style-type: circle; + margin-left: 25} + +ul li p {margin-top: 0; + margin-bottom:0} + +a {color: blue; + text-decoration: underline} + +big {font-size: x-large} + +small {font-size: x-small} + +samp {font-size: small; + font-family: Monospaced} + +cite {font-style: italic} + +code {font-size: small; + font-family: Monospaced} + +dfn {font-style: italic} + +em {font-style: italic} + +i {font-style: italic} + +b {font-weight: bold} + +kbd {font-size: small; + font-family: Monospaced} + +s {text-decoration: line-through} + +strike {text-decoration: line-through} + +strong {font-weight: bold} + +sub {vertical-align: sub} + +sup {vertical-align: sup} + +tt {font-family: Monospaced} + +u {text-decoration: underline} + +var {font-weight: bold; + font-style: italic} + +table { + border-color: Gray; + border-style: outset; + margin-top: 5; + margin-bottom: 5; + margin-left: 5; + margin-right: 5 +} + +td { + border-color: Gray; + border-style: inset; + padding-left: 1; + padding-right: 1; + padding-top: 1; + padding-bottom: 1 +} + +th { + border-color: Gray; + border-style: inset; + padding-left: 1; + padding-right: 1; + padding-top: 1; + padding-bottom: 1 +} + +td p { + margin-top: 0; + padding-top: 2; + padding-bottom: 2; + padding-left: 2; + padding-right: 2 +} + +th p { + margin-top: 0; + font-weight: bold; + padding-top: 2; + padding-bottom: 2; + padding-left: 2; + padding-right: 2 +} + +address { + color: blue; + font-style: italic +} + +blockquote { + margin-top: 5; + margin-bottom: 5; + margin-left: 35; + margin-right: 35 +} + +center {text-align: center} + +pre {margin-top: 5; + margin-bottom: 5; + font-family: Monospaced} + +pre p {margin-top: 0} diff --git a/jhMaster/JavaHelp/doc/jhug/GNUmakefile b/jhMaster/JavaHelp/doc/jhug/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..b501765657d1d9ba961a72fcff37f8e4f929e16a --- /dev/null +++ b/jhMaster/JavaHelp/doc/jhug/GNUmakefile @@ -0,0 +1,116 @@ +# +# @(#)GNUmakefile 1.22 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @(#)GNUmakefile 1.10 97/06/05 +# +# Makefile for use on Solaris using gnumake. +# It assumes JavaHelp has been built previously +# Just builds the search index for the user's guide +# Then build the jhug.pdf file. +# Note: You must set your path correctly for html2ps, perl, and distill +# For building at JavaSoft this means making sure path includes +# /net/suntools.sfbay/export/tools/sparc/bin + +JHHOME = ../../javahelp/ +INDEXER=$(JHHOME)/bin/jhindexer + +JHUG_CONTENT_FILES = jhug.html \ + release/release.html \ + release/contents.html \ + release/requirements.html \ + release/changes.html \ + release/demos.html \ + release/helpsets.html \ + release/libraries.html \ + release/limitations.html \ + release/file_list.html \ + overview/overview.html \ + overview/intro.html \ + overview/features.html \ + overview/scenarios.html \ + overview/invocation.html \ + overview/deploy.html \ + overview/search.html \ + overview/jcomp.html \ + author/author.html \ + author/viewing.html \ + author/accessibility.html \ + author/setup.html \ + author/helpset.html \ + author/map.html \ + author/jar.html \ + author/toc.html \ + author/index.html \ + author/csh.html \ + author/search.html \ + author/searchdb.html \ + author/jhindexer.html \ + author/jhsearch.html \ + author/popup.html \ + author/merge.html \ + dev/dev.html \ + dev/basics.html \ + dev/csh.html \ + dev/dynamicmerge.html \ + dev/embed.html \ + dev/lwcomp.html \ + dev/serverhlp.html \ + locale/loc.html \ + locale/loc_pres.html \ + locale/loc_helpset.html \ + locale/loc_xml.html \ + locale/loc_html.html \ + locale/loc_font.html \ + locale/loc_search.html\ + jhugIndex.html + +JHUG_SEARCH_FILES = \ + JavaHelpSearch/DOCS \ + JavaHelpSearch/DOCS.TAB \ + JavaHelpSearch/OFFSETS \ + JavaHelpSearch/POSITIONS \ + JavaHelpSearch/SCHEMA \ + JavaHelpSearch/TMAP + +JHUG_SOURCE_FILES = \ + $(JHUG_CONTENT_FILES) \ + +all: $(JHUG_SEARCH_FILES) + +clean: + rm -f $(JHUG_SEARCH_FILES) + +$(JHUG_SEARCH_FILES): $(JHUG_CONTENT_FILES) + @rm -f $(JHUG_SEARCH_FILES) + @mkdir -p JavaHelpSearch + ksh $(INDEXER) -verbose $(JHUG_CONTENT_FILES) + +# jhug.pdf: $(JHUG_CONTENT_FILES) +# @rm -f jhug.pdf +# perl5 ../../build/tools/html2ps -u -t -C hb $(JHUG_CONTENT_FILES) > jhug.ps +# distill jhug.ps +# $(RM) jhug.ps diff --git a/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile b/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..b207cb8d3209a041c2833f63d59231da5868a828 --- /dev/null +++ b/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile @@ -0,0 +1,43 @@ +# +# @(#)GNUmakefile 1.3 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# demo.jar is the JAR that defines the application +SPEC = JavaHelp_V2_0_Specification.pdf + +FILES = JavaHelp_V2_0_Specification.fm \ + bookTOC.fm \ + contents.fm \ + cover.fm \ + credits.fm + +all: $(SPEC) + +clean: + rm -rf $(SPEC) + +$(SPEC): $(FILES) + /usr/dist/share/framemaker/bin/fmbatch -v createbook.txt diff --git a/jhMaster/JavaHelp/javahelp/bin/GNUmakefile b/jhMaster/JavaHelp/javahelp/bin/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..ee8f4940e0d080305253a489b078e2dc303140dd --- /dev/null +++ b/jhMaster/JavaHelp/javahelp/bin/GNUmakefile @@ -0,0 +1,50 @@ +# +# @(#)GNUmakefile 1.2 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @(#)GNUmakefile 1.10 97/06/05 +# +# Makefile for use on Solaris using gnumake. + +# apiviewer.jar has launcher code. +JHINDEXER_JAR = jhindexer.jar +JHSEARCH_JAR = jhsearch.jar + +CP=/bin/cp -f + +all: $(JHINDEXER_JAR) $(JHSEARCH_JAR) + +clean: + rm -f -r $(JHINDEXER_JAR) $(JHSEARCH_JAR) + +$(JHINDEXER_JAR): + @rm -f $(JHINDEXER_JAR) + jar cmf manifest_jhindexer $(JHINDEXER_JAR) + +$(JHSEARCH_JAR): + @rm -f $(JHSEARCH_JAR) + jar cmf manifest_jhsearch $(JHSEARCH_JAR) + diff --git a/jhMaster/JavaHelp/javahelp/bin/jhindexer b/jhMaster/JavaHelp/javahelp/bin/jhindexer new file mode 100644 index 0000000000000000000000000000000000000000..e84a1b2de1e412be2cf73f6e779e5ceb95fc35aa --- /dev/null +++ b/jhMaster/JavaHelp/javahelp/bin/jhindexer @@ -0,0 +1,49 @@ +#! /bin/sh +# This builds a search database + +# Cygwin support. $cygwin _must_ be set to either true or false. +case "`uname`" in + CYGWIN*) cygwin=true ;; + *) cygwin=false ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$JAVAHELP_HOME" ] && + JAVAHELP_HOME=`cygpath --unix "$JAVAHELP_HOME"` +fi + +if [ "$JAVAHELP_HOME" = "" ] ; then + # try to find jhindexer + if [ -d /opt/javahelp ] ; then + JAVAHELP_HOME=/opt/javahelp + fi + + if [ -d ${HOME}/opt/jhindexer ] ; then + JAVAHELP_HOME=${HOME}/opt/javahelp + fi + + ## resolve links - $0 may be a link to javahelp's home + PRG=$0 + progname=`basename $0` + + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '.*/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname $PRG`/$link" + fi + done + + JAVAHELP_HOME=`dirname "$PRG"`/../.. + +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + JAVAHELP_HOME=`cygpath --path --windows "$JAVAHELP_HOME"` +fi + +java -jar $JAVAHELP_HOME/javahelp/bin/jhindexer.jar "$@" diff --git a/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat b/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat new file mode 100644 index 0000000000000000000000000000000000000000..454af485d9e476c1329001d945bd7b02128d7cd9 --- /dev/null +++ b/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat @@ -0,0 +1,75 @@ +@echo off + +REM +REM @(#)jhindexer.bat 1.20 06/10/30 +REM +REM Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +REM +REM This code is free software; you can redistribute it and/or modify it +REM under the terms of the GNU General Public License version 2 only, as +REM published by the Free Software Foundation. Sun designates this +REM particular file as subject to the "Classpath" exception as provided +REM by Sun in the LICENSE file that accompanied this code. +REM +REM This code is distributed in the hope that it will be useful, but WITHOUT +REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +REM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +REM version 2 for more details (a copy is included in the LICENSE file that +REM accompanied this code). +REM +REM You should have received a copy of the GNU General Public License version +REM 2 along with this work; if not, write to the Free Software Foundation, +REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +REM +REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +REM CA 95054 USA or visit www.sun.com if you need additional information or +REM have any questions. +REM + + +if not "%OS%"=="Windows_NT" goto win9xStart +:winNTStart +@setlocal + +rem %~dp0 is name of current script under NT +set DEFAULT_JAVAHELP_HOME=%~dp0 + +rem : operator works similar to make : operator +set DEFAULT_JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME:\javahelp\bin\=% + +if %JAVAHELP_HOME%a==a set JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME% +set DEFAULT_JAVAHELP_HOME= +goto doneStart + +:win9xStart +:doneStart +rem This label provides a place for NT handling to skip to. + +rem find JAVAHELP_HOME +if not "%JAVAHELP_HOME%"=="" goto runjhindexer + +rem check for JavaHelp in Program Files on system drive +if not exist "%SystemDrive%\Program Files\jh" goto checkSystemDrive +set JAVAHELP_HOME=%SystemDrive%\Program Files\jh +goto checkJava + +:checkSystemDrive +rem check for JavaHelp in root directory of system drive +if not exist "%SystemDrive%\jh" goto noJavaHelpHome +set JAVA_HOME=%SystemDrive%\jh +goto runjhindexer + +:noJavaHelpHome +echo JAVAHELP_HOME is not set and JavaHelp could not be located. Please set JAVAHELP_HOME. +goto end + +:runjhindexer +java -jar %JAVAHELP_HOME%\javahelp\bin\jhindexer.jar %1 %2 %3 %4 %5 %6 %7 %8 %9 + +if not "%OS%"=="Windows_NT" goto mainEnd +:winNTend +@endlocal + +:mainEnd + diff --git a/jhMaster/JavaHelp/javahelp/bin/jhsearch b/jhMaster/JavaHelp/javahelp/bin/jhsearch new file mode 100644 index 0000000000000000000000000000000000000000..67e050b8c50c5f2db8d27db16c2c0a9696cf1d14 --- /dev/null +++ b/jhMaster/JavaHelp/javahelp/bin/jhsearch @@ -0,0 +1,49 @@ +#! /bin/sh +# This searches a search database. Argument is the database directory + +# Cygwin support. $cygwin _must_ be set to either true or false. +case "`uname`" in + CYGWIN*) cygwin=true ;; + *) cygwin=false ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$JAVAHELP_HOME" ] && + JAVAHELP_HOME=`cygpath --unix "$JAVAHELP_HOME"` +fi + +if [ "$JAVAHELP_HOME" = "" ] ; then + # try to find jhindexer + if [ -d /opt/javahelp ] ; then + JAVAHELP_HOME=/opt/javahelp + fi + + if [ -d ${HOME}/opt/jhindexer ] ; then + JAVAHELP_HOME=${HOME}/opt/javahelp + fi + + ## resolve links - $0 may be a link to javahelp's home + PRG=$0 + progname=`basename $0` + + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '.*/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname $PRG`/$link" + fi + done + + JAVAHELP_HOME=`dirname "$PRG"`/../.. + +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + JAVAHELP_HOME=`cygpath --path --windows "$JAVAHELP_HOME"` +fi + +java -jar $JAVAHELP_HOME/javahelp/bin/jhsearch.jar "$@" diff --git a/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat b/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat new file mode 100644 index 0000000000000000000000000000000000000000..f6ec75d2309a868220769fa60f7be33d271d9378 --- /dev/null +++ b/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat @@ -0,0 +1,77 @@ +@echo off + +REM +REM @(#)jhsearch.bat 1.13 06/10/30 +REM +REM Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +REM +REM This code is free software; you can redistribute it and/or modify it +REM under the terms of the GNU General Public License version 2 only, as +REM published by the Free Software Foundation. Sun designates this +REM particular file as subject to the "Classpath" exception as provided +REM by Sun in the LICENSE file that accompanied this code. +REM +REM This code is distributed in the hope that it will be useful, but WITHOUT +REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +REM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +REM version 2 for more details (a copy is included in the LICENSE file that +REM accompanied this code). +REM +REM You should have received a copy of the GNU General Public License version +REM 2 along with this work; if not, write to the Free Software Foundation, +REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +REM +REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +REM CA 95054 USA or visit www.sun.com if you need additional information or +REM have any questions. +REM + + +if not "%OS%"=="Windows_NT" goto win9xStart +:winNTStart +@setlocal + +rem %~dp0 is name of current script under NT +set DEFAULT_JAVAHELP_HOME=%~dp0 + +rem : operator works similar to make : operator +set DEFAULT_JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME:\javahelp\bin\=% + +if %JAVAHELP_HOME%a==a set JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME% +set DEFAULT_JAVAHELP_HOME= +goto doneStart + +:win9xStart +:doneStart +rem This label provides a place for NT handling to skip to. + +rem find JAVAHELP_HOME +if not "%JAVAHELP_HOME%"=="" goto runjhsearch + +rem check for JavaHelp in Program Files on system drive +if not exist "%SystemDrive%\Program Files\jh" goto checkSystemDrive +set JAVAHELP_HOME=%SystemDrive%\Program Files\jh +goto checkJava + +:checkSystemDrive +rem check for JavaHelp in root directory of system drive +if not exist "%SystemDrive%\jh" goto noJavaHelpHome +set JAVA_HOME=%SystemDrive%\jh +goto runjhsearch + +:noJavaHelpHome +echo JAVAHELP_HOME is not set and JavaHelp could not be located. Please set JAVAHELP_HOME. +goto end + +:runjhsearch +java -jar %JAVAHELP_HOME%\javahelp\bin\jhsearch.jar %1 + +if not "%OS%"=="Windows_NT" goto mainEnd +:winNTend +@endlocal + +:mainEnd + + + diff --git a/jhMaster/JavaHelp/linuxRPM/GNUmakefile b/jhMaster/JavaHelp/linuxRPM/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..cb80ebb20bfd02dda7b32ea6f4eb684825e7d9b2 --- /dev/null +++ b/jhMaster/JavaHelp/linuxRPM/GNUmakefile @@ -0,0 +1,207 @@ +# +# @(#)GNUmakefile 1.7 06/11/01 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @(#)GNUmakefile 1.7 06/11/01 +# Install for JavaHelp. +# This is a linux RPM GNUmakefile + +JH_NAME=javahelp +JH_VERSION=2.0 +TEMP_DIR=/tmp/rpm-$(JH_NAME) +NATIVE_ARCH=i586 +JH_VERSION=2.0 +PKGNAME=SUNWjhrt +J2SE=j2se +OPT=j2se/opt +DJH=j2se/opt/javahelp +INSTALL=$(PKGNAME)/install +RELOC=$(PKGNAME)/reloc +PWD=$(shell pwd) +OWNERGROUP=$(shell id | cut -f2 -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ') +PKGPATH=$(PWD)/$(PKGNAME) + +JD=../$(JH_NAME) +TOP=.. +PKGTOP=. + +CAT=/bin/cat +CD=cd +CHMOD=/bin/chmod +CP=/bin/cp -p -f +ECHO=echo +MKDIR=/bin/mkdir -p +RM=/bin/rm -f +RPM=/usr/bin/rpmbuild +TAR=/bin/tar +FIND=/usr/bin/find +MV=/bin/mv -f +JAR=jar + +all: copy prep-RPM build-RPM + echo DONE with RPM! + +dirs: $(J2SE) $(OPT) $(DJH) + +package: $(PKGPATH) pkginfo proto + +copy: + $(ECHO) ### Removing old javahelp directories + $(RM) -r $(TEMP_DIR) + $(MKDIR) -p $(TEMP_DIR) + pwd + $(ECHO) ### Copying over the jh2.0 image for use with RPM + $(CD) .. ;$(TAR) cf - jh$(JH_VERSION) | ( cd $(TEMP_DIR) ; $(TAR) xfBp -) +### $(MV) $(TEMP_DIR)/jh$(JH_VERSION) $(TEMP_DIR)/$(JH_NAME)$(JH_VERSION) + $(MKDIR) $(TEMP_DIR)/packages + $(MV) $(TEMP_DIR)/jh$(JH_VERSION) $(TEMP_DIR)/packages/javax.help-$(JH_VERSION) + $(FIND) $(TEMP_DIR) -name "*.bat" -print -exec $(RM) {} \; +### $(CD) $(TEMP_DIR) ; $(TAR) cf $(JH_NAME)$(JH_VERSION).tar $(JH_NAME)$(JH_VERSION) + $(CD) $(TEMP_DIR) ; $(TAR) cf $(JH_NAME)$(JH_VERSION).tar packages + + +clobber: + $(RM) -rf j2se + $(RM) -rf $(PKGNAME) + $(RM) -rf prototype + $(RM) -rf pkginfo + + + +prep-RPM: + + @#subtle: override the sourcedir so that we don't have to copy + @# large binaries around. + @# $(ECHO) "%_sourcedir $(ABS_OUTPUTDIR)" >> $(RPM_MACROFILE) + @# $(ECHO) "%_sourcedir $(TEMP_DIR)" >> $(HOME)/.rpmmacros_jh + @# $(ECHO) "%_builddir $(TEMP_DIR)/BUILD" >> $(RPM_MACROFILE) + @# $(ECHO) "%_rpmdir $(TEMP_DIR)" >> $(RPM_MACROFILE) + @# + @# generate the gen-rpm-jh.spec file + @# + $(ECHO) milestone is $(MILESTONE) + $(ECHO) ### generate the gen-rpm-jh.spec file + $(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define _builddir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define _sourcedir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define _rpmdir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define _tmppath $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define jh_prefix /usr/java" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define jh_tarfile javahelp$(VERSION).tar" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define arch i586" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define jh_dir packages/javax.help-$(JH_VERSION)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define jh_name $(JH_NAME)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%define jh_version $(JH_VERSION)" >> $(TEMP_DIR)/gen-rpm-jh.spec + @# $(ECHO) "%define packed_jars \"$(JRE_PACKED_JARS)\"" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Name: sun-$(JH_NAME)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Summary: JavaHelp Runtime/Development Environment" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Version: %{jh_version}" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Release: fcs" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Copyright: 1994-2004 Sun Microsystems, Inc." >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Group: Java Software Engineering" >> $(TEMP_DIR)/gen-rpm-jh.spec + @# $(ECHO) "Provides: jaxp_parser_impl, xml-commons-apis" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Requires: glibc >= 2.1.2-11, sh-utils >= 2.0-1, fileutils >= 4.0-8, gawk >= 3.0.4-1, textutils >= 2.0-2" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "AutoReqProv: no" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Url: http://java.sun.com/products/javahelp" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Vendor: Sun Microsystems, Inc." >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Source: $(JH_NAME)$(JH_VERSION).tar" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Packager: Java Software <http://java.sun.com/docs/forms/javahelp-sendusmail.html>" >> \ + $(TEMP_DIR)/gen-rpm-jh.spec + @###$(ECHO) "Buildroot: $(TEMP_DIR)/rpm-root" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Buildroot: $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "Prefix: %{jre_prefix}" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) "%description" >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) -n "The JavaHelp Runtime/Development Environment consists of JavaHelp " >> $(TEMP_DIR)/gen-rpm-jh.spec + @# $(ECHO) -n "virtual machine, the Java platform core classes, " >> $(TEMP_DIR)/gen-rpm-jh.spec + @# $(ECHO) -n "and supporting files. It is the runtime part of " >> $(TEMP_DIR)/gen-rpm-jh.spec + $(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec + @# + @# add the rest of the template to the spec file... + @# + $(CAT) rpm-jh.spec >> $(TEMP_DIR)/gen-rpm-jh.spec + +build-RPM: + @# + @# rpm wants to put the .rpm file the _rpmdir/{arch} directory. + @# + @######-$(MKDIR) $(TEMP_DIR) + @# on RH8 rpm builds as user 'rpm' + $(CHMOD) 777 $(TEMP_DIR) + @# + @# generate the rpm file... + @# + $(RPM) -bb --buildroot $(TEMP_DIR) --rmsource --target $(NATIVE_ARCH)-Sun-Linux $(TEMP_DIR)/gen-rpm-jh.spec + @# + @# rename the generated .rpm file to the name we want + @# + @# -$(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(TEMP_JRE_RPMFILE_NAME) \ + @# $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm + @# + +zip-RPM: + @# not being zipped right now. + @# + @# zip it up for inclusion in self-extracting zip... + @# + $(RM) $(OUTPUTDIR)/$(NATIVE_ARCH)/temp.rpm $(TEMP_DIR)/temp.bin + $(CD) $(OUTPUTDIR)/$(NATIVE_ARCH) ; \ + $(ZIPEXE) -qryn nothing temp.rpm $(JRE_SHORT_BUNDLE_NAME).rpm + @# + @# combine the self-extractor and .rpm.zip into a single binary... + @# + $(CAT) $(UNZIPSFX) $(OUTPUTDIR)/$(NATIVE_ARCH)/temp.rpm > $(TEMP_DIR)/temp.bin + $(SFX2SH) $(TEMP_DIR)/temp.bin \ + $(JRE_IMAGE_DIR)/LICENSE \ + $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh \ + $(JRE_NODOTVERSION) \ + $(OUTPUTDIR)/$(JRE_TEMPORARY_DIR) \ + "$(JRE_PACKED_JARS)" \ + $(PLATFORM) \ + " " \ + "RPM" + $(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME).rpm + $(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME)-rpm.sh + @# + @# remove the intermediate files... + @# + $(RM) $(TEMP_DIR)/temp.bin + $(RM) -r $(OUTPUTDIR)/$(NATIVE_ARCH) + $(RM) -r $(OUTPUTDIR)/$(JRE_TEMPORARY_DIR) + $(RM) $(OUTPUTDIR)/$(JRE_BUNDLE_NAME).bin $(OUTPUTDIR)/$(JRE_BUNDLE_NAME).zip + +jh-rpm-clobber: + $(RM) $(TEMP_DIR)/gen-rpm-jh.spec $(RPM_MACROFILE) + $(RM) -r $(TEMP_DIR)/BUILD $(TEMP_DIR)/RPMS + $(RM) $(OUTPUTDIR)/$(JRE_RPM_TARFILE) + $(RM) $(OUTPUTDIR)/$(ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm + $(RM) $(OUTPUTDIR)/$(ARCH)/temp.rpm $(TEMP_DIR)/temp.bin + $(RM) $(OUTPUTDIR)/$(ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh + $(RM) $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME).rpm + $(RM) $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME)-rpm.sh + $(RM) -r $(OUTPUTDIR)/$(ARCH) + diff --git a/jhMaster/JavaHelp/solarispkgs/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..e01ce34d8a7e4b12f5447ff9918832cd743dfd68 --- /dev/null +++ b/jhMaster/JavaHelp/solarispkgs/GNUmakefile @@ -0,0 +1,50 @@ +# +# @(#)GNUmakefile 1.2 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# @(#)GNUmakefile 1.2 10/30/06 +# + +SUBDIRS = SUNWjhrt SUNWjhdev SUNWjhdem SUNWjhdoc + +all: + @for dir in $(SUBDIRS) ; do \ + echo "" ; \ + cd $$dir ; \ + $(MAKE) $@ ; \ + cd .. ; \ + done + +clean: clobber + +clobber: + @for dir in $(SUBDIRS) ; do \ + echo "" ; \ + cd $$dir ; \ + $(MAKE) $@ ; \ + cd .. ; \ + done diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..d4ec250bae26d5615f1fca96a556f94aa8a6c680 --- /dev/null +++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile @@ -0,0 +1,219 @@ +# +# @(#)GNUmakefile 1.11 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# Install for JavaHelp. +# This is a Solaris GNUmakefile + +PKGNAME=SUNWjhdem +J2SE=jdk +#OPT=j2se/opt +OPT=$(J2SE)/packages +#DJH=j2se/opt/javahelp +DJH=$(OPT)/javax.help-2.0 +INSTALL=$(PKGNAME)/install +RELOC=$(PKGNAME)/reloc +PWD=$(shell pwd) +OWNERGROUP=$(shell id | cut -f2 -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ') +PKGPATH=$(PWD)/$(PKGNAME) + +Dbin=$(DJH)/bin + +Ddemos=$(DJH)/demos $(DJH)/demos/bin $(DJH)/demos/hsjar \ + $(DJH)/demos/lib $(DJH)/demos/hs \ + $(DJH)/demos/hs/merge $(DJH)/demos/hs/newmerge\ + $(DJH)/demos/browser + +Ddemosrc=$(DJH)/demos/src/sunw/demo/jhdemo \ + $(DJH)/demos/src/sunw/demo/idedemo \ + $(DJH)/demos/src/sunw/demo/classviewer \ + $(DJH)/demos/src/sunw/demo/classviewer/plaf/basic \ + $(DJH)/demos/src/sunw/demo/classviewer/plaf/metal \ + $(DJH)/demos/src/sunw/demo/classviewer/plaf/motif \ + $(DJH)/demos/src/sunw/demo/classviewer/plaf/windows \ + $(DJH)/demos/src/sunw/demo/searchdemo \ + $(DJH)/demos/src/sunw/demo/merge \ + $(DJH)/demos/src/sunw/demo/newmerge \ + $(DJH)/demos/src/sunw/demo/browser + +TOP=../.. +DD=$(TOP)/demos +JD=$(TOP)/javahelp +PKGTOP=.. + +CP=/bin/cp -p -f +RM=/bin/rm -f +TAR=/usr/sbin/tar +MV=/bin/mv -f +JAR=jar + +CPDIR=/bin/cp -pr -f + +all: dirs helpset demo demosrc package + pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD) + +dirs: $(J2SE) $(OPT) $(DJH) + +package: $(PKGPATH) pkginfo proto + +pkginfo: + sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo + +proto: + chmod -R g-s $(J2SE) + chmod -R o+r $(J2SE) + pkgproto $(J2SE) > prototype.tmp + sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build + $(RM) prototype.tmp + if [ -f prototype.base ]; then \ + cat prototype.base prototype.build > prototype; \ + $(RM) prototype.build; \ + else \ + $(MV) prototype.build prototype; \ + fi; \ + + +# +# HelpSets +# + +helpset: $(Ddemos) + $(CP) $(DD)/hsjar/holidays.jar $(DJH)/demos/hsjar/holidays.jar + chmod 644 $(DJH)/demos/hsjar/holidays.jar + $(CP) $(DD)/hsjar/animals.jar $(DJH)/demos/hsjar/animals.jar + chmod 644 $(DJH)/demos/hsjar/animals.jar + $(CP) $(DD)/hsjar/invertebrates.jar $(DJH)/demos/hsjar/invertebrates.jar + chmod 644 $(DJH)/demos/hsjar/invertebrates.jar + $(CP) $(DD)/hsjar/vertebrates.jar $(DJH)/demos/hsjar/vertebrates.jar + chmod 644 $(DJH)/demos/hsjar/vertebrates.jar + $(CP) $(DD)/hsjar/apidoc.jar $(DJH)/demos/hsjar/apidoc.jar + chmod 644 $(DJH)/demos/hsjar/apidoc.jar + $(CP) $(DD)/hsjar/idehelp.jar $(DJH)/demos/hsjar/idehelp.jar + chmod 644 $(DJH)/demos/hsjar/idehelp.jar + $(CP) $(DD)/hsjar/object.jar $(DJH)/demos/hsjar/object.jar + chmod 644 $(DJH)/demos/hsjar/object.jar + $(CP) $(DD)/hsjar/idehelp_de.jar $(DJH)/demos/hsjar/idehelp_de.jar + chmod 644 $(DJH)/demos/hsjar/idehelp_de.jar + $(CP) $(DD)/hsjar/idehelp_en.jar $(DJH)/demos/hsjar/idehelp_en.jar + chmod 644 $(DJH)/demos/hsjar/idehelp_en.jar + $(CP) $(DD)/hsjar/idehelp_ja.jar $(DJH)/demos/hsjar/idehelp_ja.jar + chmod 644 $(DJH)/demos/hsjar/idehelp_ja.jar + mkdir -m 755 -p $(DJH)/demos/hs ; \ + ( cd $(DD)/hs ; echo merge/GNUmakefile > exclude.tmp ) ; \ + ( cd $(DD)/hs ; $(TAR) cFFXf exclude.tmp - merge ) | (cd $(DJH)/demos/hs ; $(TAR) xf - ) ; \ + chmod -R u+w $(DJH)/demos/hs/merge + rm $(DD)/hs/exclude.tmp + ( cd $(DD)/hs ; echo newmerge/GNUmakefile > exclude.tmp ) ; \ + ( cd $(DD)/hs ; $(TAR) cFFXf exclude.tmp - newmerge ) | (cd $(DJH)/demos/hs ; $(TAR) xf - ) ; \ + chmod -R u+w $(DJH)/demos/hs/newmerge + rm $(DD)/hs/exclude.tmp + chmod -R g-w $(DJH)/demos/hs + +# +# Demos +# + +demo: $(Ddemos) + $(CP) $(DD)/idedemo/idedemo.jar $(DJH)/demos/bin/idedemo.jar + chmod 644 $(DJH)/demos/bin/idedemo.jar + + $(CP) $(DD)/merge/merge.jar $(DJH)/demos/bin/merge.jar + chmod 644 $(DJH)/demos/bin/merge.jar + + $(CP) $(DD)/newmerge/newmerge.jar $(DJH)/demos/bin/newmerge.jar + chmod 644 $(DJH)/demos/bin/newmerge.jar + + $(CP) $(DD)/bin/apiviewer.jar $(DJH)/demos/bin/apiviewer.jar + chmod 644 $(DJH)/demos/bin/apiviewer.jar + + $(CP) $(DD)/bin/object.jar $(DJH)/demos/bin/object.jar + chmod 644 $(DJH)/demos/bin/object.jar + + $(CP) $(DD)/bin/hsviewer.jar $(DJH)/demos/bin/hsviewer.jar + chmod 644 $(DJH)/demos/bin/hsviewer.jar + + $(CP) $(DD)/bin/UserGuide.jar $(DJH)/demos/bin/UserGuide.jar + chmod 644 $(DJH)/demos/bin/hsviewer.jar + + $(CP) $(DD)/lib/classviewer.jar $(DJH)/demos/lib/classviewer.jar + chmod 644 $(DJH)/demos/lib/classviewer.jar + $(CP) $(DD)/lib/searchdemo.jar $(DJH)/demos/lib/searchdemo.jar + chmod 644 $(DJH)/demos/lib/searchdemo.jar + $(CP) $(DD)/lib/browserdemo.jar $(DJH)/demos/browser/browserdemo.jar + chmod 644 $(DJH)/demos/browser/browserdemo.jar + $(CP) $(DD)/newbrowser/*.html $(DJH)/demos/browser/ + $(CP) $(DD)/newbrowser/demo_instructions $(DJH)/demos/browser/ + chmod -R u+w $(DJH)/demos/browser + +# +# Demo sources +# + +demosrc: $(Ddemosrc) + $(CP) $(DD)/jhdemo/sunw/demo/jhdemo/JHLauncher.java $(DJH)/demos/src/sunw/demo/jhdemo/ + $(CP) $(DD)/jhdemo/sunw/demo/jhdemo/Runner.java $(DJH)/demos/src/sunw/demo/jhdemo/ + $(CP) $(DD)/jhdemo/sunw/demo/jhdemo/ElementTreePanel.java $(DJH)/demos/src/sunw/demo/jhdemo/ + $(CP) $(DD)/README.install $(DJH)/demos/README + chmod 644 $(DJH)/demos/README + $(CP) $(DD)/idedemo/sunw/demo/idedemo/ApiDemo.java $(DJH)/demos/src/sunw/demo/idedemo/ + $(CP) $(DD)/idedemo/sunw/demo/idedemo/IdeDemo.properties $(DJH)/demos/src/sunw/demo/idedemo/ + here=`pwd` ; \ + cd $(DJH)/demos/src/sunw/demo/idedemo ; \ + $(JAR) -xf $$here/$(DD)/idedemo/images.jar + $(CP) $(DD)/searchdemo/sunw/demo/searchdemo/ClientSearchEngine.java $(DJH)/demos/src/sunw/demo/searchdemo/ + $(CP) $(DD)/searchdemo/sunw/demo/searchdemo/ClientSearchQuery.java $(DJH)/demos/src/sunw/demo/searchdemo/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/ClassViewerView.java $(DJH)/demos/src/sunw/demo/classviewer/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/ClassViewerNavigator.java $(DJH)/demos/src/sunw/demo/classviewer/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/basic/BasicClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/basic/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/metal/MetalClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/metal/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/motif/MotifClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/motif/ + $(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/windows/WindowsClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/windows/ + $(CP) $(DD)/merge/sunw/demo/merge/Merge.java $(DJH)/demos/src/sunw/demo/merge/ + $(CP) $(DD)/newmerge/sunw/demo/newmerge/Merge.java $(DJH)/demos/src/sunw/demo/newmerge/ + $(CP) $(DD)/newmerge/sunw/demo/newmerge/HSFilter.java $(DJH)/demos/src/sunw/demo/newmerge/ + $(CP) $(DD)/newmerge/sunw/demo/newmerge/JarAccessory.java $(DJH)/demos/src/sunw/demo/newmerge/ + $(CP) $(DD)/newbrowser/sunw/demo/browser/HelpButton.java $(DJH)/demos/src/sunw/demo/browser/ + chmod -R u+w $(DJH)/demos/src + chmod -R g-w $(DJH)/demos/src + +# +# Directory creation +# +$(J2SE) $(OPT) $(DJH) $(Ddemos) $(Ddemosrc) $(Dbin) $(PKGPATH): + mkdir -m 755 -p $@ + chmod 755 $@ + +# +# Cleanup +# +clean: clobber + +clobber: + $(RM) -rf $(J2SE) + $(RM) -rf $(PKGNAME) + $(RM) -rf prototype + $(RM) -rf pkginfo + diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..e88d80fdc0b837088e00d6e18927184cec13cfec --- /dev/null +++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile @@ -0,0 +1,148 @@ +# +# @(#)GNUmakefile 1.9 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# Install for JavaHelp. +# This is a Solaris GNUmakefile + +PKGNAME=SUNWjhdev +J2SE=jdk +#OPT=j2se/opt +OPT=$(J2SE)/packages +#DJH=j2se/opt/javahelp +DJH=$(OPT)/javax.help-2.0 +INSTALL=$(PKGNAME)/install +RELOC=$(PKGNAME)/reloc +PWD=$(shell pwd) +OWNERGROUP=$(shell id | cut -f2 -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ') +PKGPATH=$(PWD)/$(PKGNAME) + +Dlib=$(DJH)/lib +Ddtd=$(Dlib)/dtd +Dbin=$(DJH)/bin + +DTDS=\ + $(Ddtd)/helpset_1_0.dtd \ + $(Ddtd)/map_1_0.dtd \ + $(Ddtd)/toc_1_0.dtd \ + $(Ddtd)/index_1_0.dtd + +Dimplsrc=com/sun/java/help/impl/JHSecondaryViewer.java \ + com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java \ + com/sun/java/help/impl/ViewAwareComponent.java + +DSRC=$(DJH)/src + +JD=../../javahelp +TOP=../.. +DOCD=$(TOP)/doc +SRCD=$(TOP)/src +PKGTOP=.. + +CP=/bin/cp -p -f +RM=/bin/rm -f +TAR=/usr/sbin/tar +MV=/bin/mv -f +JAR=jar + +CPDIR=/bin/cp -pr -f + +all: dirs libs bins source package + pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD) + +dirs: $(J2SE) $(OPT) $(DJH) + +package: $(PKGPATH) pkginfo proto + +pkginfo: + sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo + +proto: + chmod -R g-s $(J2SE) + pkgproto $(J2SE) > prototype.tmp + sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build + $(RM) prototype.tmp + if [ -f prototype.base ]; then \ + cat prototype.base prototype.build > prototype; \ + $(RM) prototype.build; \ + else \ + $(MV) prototype.build prototype; \ + fi; \ + + +# +# the JavaHelp libraries +# + +libs: $(Ddtd) $(DTDS) + +$(Ddtd)/%.dtd: $(DOCD)/public-spec/dtd/%.dtd + $(CP) $< $@ + chmod 644 $@ + +# +# predefined commands +# + +bins: $(Dbin) + $(CP) $(JD)/bin/jhindexer_solsparc $(Dbin)/jhindexer + chmod 755 $(Dbin)/jhindexer + $(CP) $(JD)/bin/jhsearch_solsparc $(Dbin)/jhsearch + chmod 755 $(Dbin)/jhsearch + +# +# source +# +source: + mkdir -p $(DSRC) + $(RM) -rf $(DSRC)/* + cd $(SRCD)/new ; \ + $(TAR) cFFf - . | (cd $(PWD)/$(DSRC) ; $(TAR) xf - ) + cd $(SRCD)/impl; \ + $(TAR) cf - $(Dimplsrc) | (cd $(PWD)/$(DSRC) ; $(TAR) xf - ) + cd $(PWD)/$(DSRC); jar -cMvf $(PWD)/$(DJH)/src.jar . + chmod g-w $(DJH)/src.jar + $(RM) -rf $(DSRC); + chmod 755 $(Dlib); + +# +# Directory creation +# +$(J2SE) $(OPT) $(DJH) $(Dlib) $(Ddtd) $(Dbin) $(PKGPATH): + mkdir -m 755 -p $@ + chmod 755 $@ + +# +# Cleanup +# +clean: clobber + +clobber: + $(RM) -rf $(J2SE) + $(RM) -rf $(PKGNAME) + $(RM) -rf prototype + $(RM) -rf pkginfo + diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..a2444e83cc7a23ff340f2f51ca7edb32d5265de2 --- /dev/null +++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile @@ -0,0 +1,141 @@ +# +# @(#)GNUmakefile 1.7 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# Install for JavaHelp. +# This is a Solaris GNUmakefile + +PKGNAME=SUNWjhdoc +J2SE=jdk +#OPT=j2se/opt +OPT=$(J2SE)/packages +#DJH=j2se/opt/javahelp +DJH=$(OPT)/javax.help-2.0 +INSTALL=$(PKGNAME)/install +RELOC=$(PKGNAME)/reloc +PWD=$(shell pwd) +OWNERGROUP=$(shell id | cut -f2 -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ') +PKGPATH=$(PWD)/$(PKGNAME) + +DDOC=$(DJH)/doc + +Ddocs=$(DDOC)/jhug $(DDOC)/jhug/overview $(DDOC)/jhug/author \ + $(DDOC)/jhug/images $(DDOC)/jhug/images/overview $(DDOC)/jhug/dev \ + $(DDOC)/jhug/merge $(DDOC)/jhug/locale $(DDOC)/jhug/release \ + $(DDOC)/jhug/JavaHelpSearch $(DDOC)/api $(DDOC)/css + +Ddocimages=$(DDOC)/images + +Dspecs=$(DDOC)/spec + +TOP=../.. +JD=$(TOP)/javahelp +DOCD=$(TOP)/doc +PKGTOP=.. + +ifeq ($(JHUGDIR),) +JHUGDIR=$(TOP)/doc/jhug +endif +JHUG=jhug.pdf + +CP=/bin/cp -p -f +RM=/bin/rm -f +TAR=/usr/sbin/tar +MV=/bin/mv -f +JAR=jar + +CPDIR=/bin/cp -pr -f + +all: dirs spec docs package + pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD) + +dirs: $(J2SE) $(OPT) $(DJH) $(DDOC) + +package: $(PKGPATH) pkginfo proto + +pkginfo: + sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo + +proto: + chmod -R g-s $(J2SE) + pkgproto $(J2SE) > prototype.tmp + sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build + $(RM) prototype.tmp + if [ -f prototype.base ]; then \ + cat prototype.base prototype.build > prototype; \ + $(RM) prototype.build; \ + else \ + $(MV) prototype.build prototype; \ + fi; \ + + +# +# JavaHelp Specification +# +spec: $(Dspecs) + mkdir -m 755 -p $(DDOC)/spec + cp $(DOCD)/public-spec/V2.0/JavaHelp_V2_0_Specification.pdf $(DDOC)/spec + chmod -R u+w $(DDOC)/spec + +# +# Generic Documentation +# +docs: $(Ddocs) docimages $(JHUGDIR)/$(JHUG) + cd $(DOCD) ; \ + $(TAR) cFFf - jhug | (cd $(PWD)/$(DDOC) ; $(TAR) xf - ) + $(MV) $(DDOC)/jhug/$(JHUG) $(DDOC)/$(JHUG) + chmod u+w $(DDOC)/$(JHUG) + chmod -R u+w $(DDOC)/jhug + chmod g-w $(DDOC)/jhug/JavaHelpSearch/* + $(RM) $(DDOC)/jhug/GNUmakefile $(DDOC)/jhug/createps.sh + $(CPDIR) $(DOCD)/api/* $(DDOC)/api/ + chmod -R g-w $(DDOC)/api + $(CP) $(DOCD)/css/default.css $(DDOC)/css/default.css + chmod u+w $(DDOC)/css/default.css + +docimages: $(Ddocimages) + cd $(DOCD) ; \ + $(TAR) cFFf - images | (cd $(PWD)/$(DDOC) ; $(TAR) xf - ) + chmod -R u+w $(DDOC)/images + +# +# Directory creation +# +$(J2SE) $(OPT) $(DJH) $(DDOC) $(Ddocs) $(Ddocimages) $(Dspecs) $(PKGPATH): + mkdir -m 755 -p $@ + chmod 755 $@ + +# +# Cleanup +# +clean: clobber + +clobber: + $(RM) -rf $(J2SE) + $(RM) -rf $(PKGNAME) + $(RM) -rf prototype + $(RM) -rf pkginfo + diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..40afaccc750909eb7c70a765e4c51682146c14a7 --- /dev/null +++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile @@ -0,0 +1,119 @@ +# +# @(#)GNUmakefile 1.8 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# Install for JavaHelp. +# This is a Solaris GNUmakefile + +PKGNAME=SUNWjhrt +J2SE=jdk +#OPT=j2se/opt +OPT=$(J2SE)/packages +#DJH=j2se/opt/javahelp +DJH=$(OPT)/javax.help-2.0 +INSTALL=$(PKGNAME)/install +RELOC=$(PKGNAME)/reloc +PWD=$(shell pwd) +OWNERGROUP=$(shell id | cut -f2 -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ') +PKGPATH=$(PWD)/$(PKGNAME) + +Dlib=$(DJH)/lib + +LIBS=$(Dlib)/jhall.jar + +JD=../../javahelp +TOP=../.. +PKGTOP=.. + +CP=/bin/cp -p -f +RM=/bin/rm -f +TAR=/usr/sbin/tar +MV=/bin/mv -f +JAR=jar + +CPDIR=/bin/cp -pr -f + +all: dirs misc libs package + echo owner group is $(OWNERGROUP) + pkgmk -f $(PWD)/prototype -d $(PWD) -o -r $(PWD) basedir=$(PWD) + +dirs: $(J2SE) $(OPT) $(DJH) + +package: $(PKGPATH) pkginfo proto + +pkginfo: + sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo + +proto: + chmod -R g-s $(J2SE) + pkgproto $(J2SE) > prototype.tmp + sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build + $(RM) prototype.tmp + if [ -f prototype.base ]; then \ + cat prototype.base prototype.build > prototype; \ + $(RM) prototype.build; \ + else \ + $(MV) prototype.build prototype; \ + fi; \ + + +# +# Miscellaneous information +# +misc: $(DJH) + $(CP) $(TOP)/LICENSE.html $(DJH)/LICENSE.html + chmod 644 $(DJH)/LICENSE.html + + +# +# the JavaHelp libraries +# + +libs: jars + +jars: $(Dlib) $(LIBS) + +$(Dlib)/%.jar: $(JD)/lib/%.jar + $(CP) $< $@ + chmod 644 $@ + +# +# Directory creation +# +$(J2SE) $(OPT) $(DJH) $(Dlib) $(PKGPATH): + mkdir -m 755 -p $@ + chmod 755 $@ +# +# Cleanup +# +clean: clobber + +clobber: + $(RM) -rf $(J2SE) + $(RM) -rf $(PKGNAME) + $(RM) -rf prototype + $(RM) -rf pkginfo + diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java new file mode 100644 index 0000000000000000000000000000000000000000..fa10f0ff8fddf854faeb27dbaa6c1123a2a443d2 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java @@ -0,0 +1,387 @@ +/* + * @(#)CustomKit.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +import java.util.Enumeration; +import java.util.Vector; +import java.awt.*; +import java.net.*; +import java.io.*; +import javax.swing.*; +import javax.swing.text.*; +import java.beans.*; +import java.lang.reflect.*; +import javax.swing.text.html.*; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseEvent; + +/** + * Subclass of HTMLEditorKit from Swing to adds better functionality + * for handing <OBJECT> tags and supports some special classes + * for JavaHelp. + * + * @author Tim Prinzing + * @author Eduardo Pelegri-Llopart + * @version 1.15 10/30/06 + */ + +public class CustomKit extends HTMLEditorKit { + + public CustomKit() { + super(); + } + + /** + * Clone the editorkit + */ + public Object clone() { + return new CustomKit(); + } + + /** + * Called when the kit is being installed into the + * a JEditorPane. + * + * @param c the JEditorPane + */ + public void install(JEditorPane c) { + c.addMouseMotionListener(mouseHandler); + super.install(c); + } + + /** + * Called when the kit is being removed from the + * JEditorPane. This is used to unregister any + * listeners that were attached. + * + * @param c the JEditorPane + */ + public void deinstall(JEditorPane c) { + c.removeMouseMotionListener(mouseHandler); + super.deinstall(c); + } + + public Document createDefaultDocument() { + // normally we would do exactly what HTMLEditor.createDefaultDocument + // does: + // + // StyleSheet styles = getStyleSheet(); + // StyleSheet ss = new StyleSheet(); + // ss.addStyleSheet(styles); + // HTMLDocument doc = new HTMLDocument(ss); + // + // However, since StyleSheet.addStyleSheet is package private, we'll + // have to work around the problem. + HTMLDocument tmpDoc = (HTMLDocument)super.createDefaultDocument(); + + HTMLDocument doc = new CustomDocument(tmpDoc.getStyleSheet()); + doc.putProperty ("__PARSER__", getParser()); + doc.setAsynchronousLoadPriority(4); + doc.setTokenThreshold(100); + debug("fetch custom document"); + return doc; + } + + /** + * Fetch a factory that is suitable for producing + * views of any models that are produced by this + * kit. + * + * @return the factory + */ + public ViewFactory getViewFactory() { + debug("fetched custom factory"); + return new CustomFactory(); + } + + // --- variables ------------------------------------------ + private MouseMotionListener mouseHandler = new MouseHandler(); + + /** + * Class to watch the associated component and change the + * cursor when in a hyperlink + */ + public static class MouseHandler implements MouseMotionListener { + + private Element curElem = null; + private Cursor origCursor; + private Cursor handCursor=null; + + // ignore the drags + public void mouseDragged(MouseEvent e) { + } + + // track the moving of the mouse. + public void mouseMoved(MouseEvent e) { + JEditorPane editor = (JEditorPane) e.getSource(); + + if (!editor.isEditable()) { + Point pt = new Point(e.getX(), e.getY()); + int pos = editor.viewToModel(pt); + if (pos >= 0) { + Document doc = editor.getDocument(); + if (doc instanceof HTMLDocument) { + HTMLDocument hdoc = (HTMLDocument) doc; + Element elem = hdoc.getCharacterElement(pos); + AttributeSet a = elem.getAttributes(); + AttributeSet anchor = (AttributeSet) a.getAttribute(HTML.Tag.A); + String href = (anchor != null) ? + (String) anchor.getAttribute(HTML.Attribute.HREF) + : null; + + if (href != null) { + if (curElem != elem) { + curElem = elem; + if (origCursor == null) { + origCursor = editor.getCursor(); + } + if (handCursor == null) { + handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + } + editor.setCursor(handCursor); + } + } else { + if (curElem != null) { + curElem = null; + editor.setCursor(origCursor); + } + } + } + } + } + } + } + + static class CustomFactory extends HTMLFactory { + + public View create(Element elem) { + Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute); + if (o instanceof HTML.Tag) { + HTML.Tag kind = (HTML.Tag) o; + if (kind == HTML.Tag.OBJECT) { + debug("creating ObjectView1 for: " + elem); + return new ObjectView1(elem); + } + } + return super.create(elem); + } + + } + + static class CustomDocument extends HTMLDocument { + + CustomDocument(StyleSheet s) { + super(s); + } + + public HTMLEditorKit.ParserCallback getReader(int pos) { + Object desc = getProperty(Document.StreamDescriptionProperty); + if (desc instanceof URL) { + setBase((URL)desc); + } + HTMLReader reader = new CustomReader(pos); + return reader; + } + + class CustomReader extends HTMLReader { + + public CustomReader(int offset) { + super(offset); + registerTag(HTML.Tag.PARAM, new ObjectAction1()); + } + + Vector getParseBuffer() { + return parseBuffer; + } + + class ObjectAction1 extends SpecialAction { + + public void start(HTML.Tag t, MutableAttributeSet a) { + if (t == HTML.Tag.PARAM) { + addParameter(a); + } else { + super.start(t, a); + } + } + + public void end(HTML.Tag t) { + if (t != HTML.Tag.PARAM) { + super.end(t); + } + } + + void addParameter(AttributeSet a) { + debug ("addParameter AttributeSet=" + a); + String name = (String) a.getAttribute(HTML.Attribute.NAME); + String value = (String) a.getAttribute(HTML.Attribute.VALUE); + if ((name != null) && (value != null)) { + ElementSpec objSpec = (ElementSpec) getParseBuffer().lastElement(); + MutableAttributeSet objAttr = (MutableAttributeSet) objSpec.getAttributes(); + objAttr.addAttribute(name, value); + } + } + } + } + } + + static class ObjectView1 extends ComponentView { + + /** + * Creates a new ObjectView object. + * + * @param elem the element to decorate + */ + public ObjectView1(Element elem) { + super(elem); + } + + /** + * Create the component. The classid is used + * as a specification of the classname, which + * we try to load. + */ + protected Component createComponent() { + AttributeSet attr = getElement().getAttributes(); + debug("attr: " + attr.copyAttributes()); + String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); + try { + int colon = classname.indexOf(':'); + if (colon != -1) { + String classtype= classname.substring(0, colon).toLowerCase(); + if (classtype.compareTo("java") == 0) { + classname = classname.substring(colon + 1); + Class c = getClass(classname); + Object o = c.newInstance(); + if (o instanceof Component) { + Component comp = (Component) o; + if (o instanceof ViewAwareComponent) { + ((ViewAwareComponent) comp).setViewData(this); + } + setParameters(comp, attr); + return comp; + } + } + } + } catch (Throwable e) { + // couldn't create a component... fall through to the + // couldn't load representation. + } + + return getUnloadableRepresentation(); + } + + /** + * Fetch a component that can be used to represent the + * object if it can't be created. + */ + Component getUnloadableRepresentation() { + // PENDING(prinz) get some artwork and return something + // interesting here. + Component comp = new JLabel("??"); + comp.setForeground(Color.red); + return comp; + } + + /** + * Get a Class object to use for loading the classid. + * + * If possible, the Classloader used to load the associated + * Document is used. This would typically be the same as the ClassLoader + * used to load the EditorKit. + * + * If the documents ClassLoader is null, + * <code>Class.forName</code> is used. + */ + private Class getClass(String classname) throws ClassNotFoundException { + Class klass = null; + + Class docClass = getDocument().getClass(); + ClassLoader loader = docClass.getClassLoader(); + if (loader != null) { + klass = loader.loadClass(classname); + } + if (klass == null) { + klass = Class.forName(classname); + } + return klass; + } + + /** + * Initialize this component according the KEY/VALUEs passed in + * via the <param> elements in the corresponding + * <object> element. + */ + private void setParameters(Component comp, AttributeSet attr) { + Class k = comp.getClass(); + BeanInfo bi; + try { + bi = Introspector.getBeanInfo(k); + } catch (IntrospectionException ex) { + debug("introspector failed, ex: "+ex); + return; // quit for now + } + PropertyDescriptor props[] = bi.getPropertyDescriptors(); + for (int i=0; i < props.length; i++) { + debug("checking on props[i]: "+props[i].getName()); + Object v = attr.getAttribute(props[i].getName()); + if (v instanceof String) { + // found a property parameter + String value = (String) v; + Method writer = props[i].getWriteMethod(); + if (writer == null) { + // read-only property. ignore + return; // for now + } + Class[] params = writer.getParameterTypes(); + if (params.length != 1) { + // zero or more than one argument, ignore + return; // for now + } + String [] args = { value }; + try { + writer.invoke(comp, (java.lang.Object[]) args); + debug("Invocation succeeded"); + } catch (Exception ex) { + debug("Invocation failed"); + // invocation code + } + } + } + } + } + + /** + * For printf debugging. + */ + private final static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("CustomKit: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java new file mode 100644 index 0000000000000000000000000000000000000000..4050a41563d22eced6f7f26f3eeeb40607cc6117 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java @@ -0,0 +1,60 @@ +/* + * @(#)DocPConst.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) DocPConst.java 1.10 - last change made 10/30/06 + * + * This class defines constants used by the Document Parser in the + * java.help + * package. + */ + +package com.sun.java.help.impl; + +public class DocPConst { + public static final char AMPERSAND = '&'; + public static final char COLON = ':'; + public static final char DQUOTE = '"'; + public static final char EQUALS = '='; + public static final char EXCLAIM = '!'; + public static final char HASH = '#'; + public static final char HORIZBAR = '_'; + public static final char LANGLE = '<'; + public static final char MINUS = '-'; + public static final char NEWLINE = '\n'; + public static final char NINE = '9'; + public static final char NULL = '\0'; + public static final char QUESTION = '?'; + public static final char RANGLE = '>'; + public static final char RETURN = '\r'; + public static final char QUOTE = '\''; + public static final char SEMICOLON = ';'; + public static final char SLASH = '/'; + public static final char SPACE = ' '; + public static final char TAB = '\t'; + public static final char ZERO = '0'; +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..d9f7fbfc4ccc3f006437bf5a6cc26d5abaa5a319 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java @@ -0,0 +1,1321 @@ +/* + * @(#)DocumentParser.java 1.19 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) DocumentParser.java 1.19 - last change made 10/30/06 + */ +package com.sun.java.help.impl; + +/** + * This class is designed to be extended for use. You use it in + * this way: + * + * 1. instantiate the object, passing an inputStream to the + * constructor (a string can be passed as well). + * + * 2. call parse() to start it running. Parse will return + * when the eof of file is reached. + * + * 3. during the parse, each of the following calls will + * be made. The extensions should handle the calls as + * necessary: + * + * flush Called for each contiguous block + * of text. + * + * tag Called for each complete tag + * + * pi Called for each PI (non-xml) recognized + * + * doctype Called for a doctype + * + * comment Called for each complete comment + * + * errorString Called for each parse error + * + * 4. As an extension &xxx; macros can be implemented. For + * each unrecognized &xxx; macro, a call to + * documentAttribute is made that will return a string if + * the macro name has a value. + */ + +import java.io.CharConversionException; +import java.io.*; +import java.util.Hashtable; +import java.net.*; + +public abstract class DocumentParser { + static final char EOF = (char)-1; + + protected Reader source; + int readOffset; + ScanBuffer buffer; + ScanBuffer escapeBuffer; + ScanBuffer documentSource; + boolean shouldCacheSource; + + /************************************************************************ + ***** ***** + ***** Public interface ***** + ***** ***** + ************************************************************************/ + + public DocumentParser(InputStream in) { + source = new MyBufferedReader(new InputStreamReader(in)); + init(); + } + + public DocumentParser(Reader src) { + + //.................................................. + // Check if the Reader src is buffered, and make it buffered + // if it's not already + //................................................. + if (src instanceof MyBufferedReader) { + source = src; + } else { + source = new MyBufferedReader(src); + } + init(); + } + + public void setInput(Reader src){ + //source = s; + //.................................................. + // Check if the Reader src is buffered, and make it buffered + // if it's not already + //................................................. + if (src instanceof MyBufferedReader) { + source = src; + } else { + source = new MyBufferedReader(src); + } + } + + //.....YK..... checking for null InputStream + + public void setInput(InputStream i, String encoding) throws UnsupportedEncodingException + { + if(i == null) { + source = null; + return; + } + source = new MyBufferedReader( new InputStreamReader(i, encoding)); + } + + /* + * sets whether to cache document source + */ + public void setShouldCacheSource(boolean state) { + shouldCacheSource = state; + } + + /* + * return String containing the document source (monsanto) + * Bug 4058915: File->HTML Source ... menu item shows edited source. + */ + public String getDocumentSource() { + if (!shouldCacheSource) + return null; + else { + int offset = + (0 == documentSource.length()) ? 0 : documentSource.length() - 1; + return new String(documentSource.buf, 0, offset) +"\n"; + } + } + + // ................................. YK (Inline) + public void parse() throws IOException { + char c = EOF; // YK: checking for null + + buffer.clear(); + if(source != null) { // YK: checking for null + c = readChar(); + } // YK: checking for null + for (;;){ + if (c == EOF) + break; + if (c == DocPConst.AMPERSAND) + c = parseEscape(); + else if (c == DocPConst.LANGLE){ + buffer.flush(this); + c = parseTag(); + } else { + // ................................................. + // Inlining the data access gives BIG performance win + // ................................................. + // buffer.add(c); // YK: inline + if (buffer.buflen >= buffer.buf.length){ + char [] x = new char [buffer.buf.length * buffer.scale]; + System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length); + buffer.buf = x; + } + + // fixes bug 4056036 - cannot open bat-text files + // (monsanto) + if (c != DocPConst.RETURN) + buffer.buf[buffer.buflen++] = c; + + // ................................................. + // Inlining the data access gives BIG performance win + // ................................................. + + //c = readChar(); // YK: inline + if(myCount >= mySize) { + try { + mySize = source.read(cb, 0, defaultCharBufferSize); + if(mySize < 0) { + break; + } + if(mySize == 0) { + System.err.println(" DocumentParser::parse() !!!ERROR !!! source.read(...) == 0"); + break; + } + myCount = 0; + } catch (CharConversionException e) { + throw e; + } catch (IOException e) { + break; + } + } + // ..........REMIND - removed .......// readOffset++; + if (shouldCacheSource) + documentSource.add(cb[myCount]); + c = cb[myCount++]; + } + } + buffer.flush(this); + } + + + + + public void parseText() throws IOException { + char c; + + tag("PRE", null, false, false); + + buffer.clear(); + c = readChar(); + for (;;) { + if (c == EOF) + break; + buffer.add(c); + c = readChar(); + } + buffer.flush(this); + } + + /** + * Invokes flush(). This method is provided so that flush() can + * be protected + */ + protected void callFlush(char [] buf, int offset, int length) + { + flush(buf, offset, length); + } + + /************************************************************************ + ***** ***** + ***** Methods to be overridden by subclasses ***** + ***** ***** + ************************************************************************/ + + /** + * This method creates a block of text for a document. + * + * It should be overridden by the subclass + */ + abstract protected void flush(char [] buf, int offset, int length); + + /** + * This method inserts a comment + * + * It should be overridden by the subclass + */ + abstract protected void comment(String s); + + /** + * This method emits a tag + * + * It should be overridden by the subclass + */ + abstract protected void tag(String name, TagProperties atts, boolean endTag, boolean emptyTag); + + /** + * This method emits a pi + * + * It should be overridden by the subclass + */ + abstract protected void pi(String target, String data); + + /** + * This method emits a doctype. Internal subset information is discarded + * + * It should be overridden by the subclass + */ + abstract protected void doctype(String root, String publicId, String systemId); + + /** + * This method looks up a &xxx; sequence in the document + * properties (this is used for templates). A return of null + * means the proerty is undefined. + * + * It should be overridden by the subclass + */ + abstract protected String documentAttribute(String name); + + /** + * This method inserts a parse error string into the document + * + * It should be overridden by the subclass + */ + abstract protected void errorString(String s); + + /************************************************************************ + ***** ***** + ***** Internal methods ***** + ***** ***** + ************************************************************************/ + + private void init() { + // .........buffer initialization...................... + // bigger buffer size gives some performance win + buffer = new ScanBuffer(8192, 4); // YK + // ......... escapeBuffer initialization............... + // bigger buffer size gives some performance win + escapeBuffer = new ScanBuffer(8192,4); // YK + documentSource = new ScanBuffer(8192,4); // YK + readOffset = 0; + } + + protected void findCloseAngleForComment(char c) throws IOException { + buffer.add(c); + for(;;){ + c = readChar(); + if (c == DocPConst.RANGLE) + break; + buffer.add(c); + } + buffer.add(c); + comment(buffer.extract(0)); + buffer.clear(); + } + + protected char handleCommentOrDoctype(char c) throws IOException { + buffer.add(c); + int offset = buffer.length(); + c = scanIdentifier(c); + String name = buffer.extract(offset); + + if (! name.equals("DOCTYPE")) { + findCloseAngleForComment(c); + return readChar(); + } + + // a DOCTYPE + c = skipWhite(c); + + // The root of the document... + offset = buffer.length(); + c = scanIdentifier(c); + String root = buffer.extract(offset); + + c = skipWhite(c); + + // If no externaID... + if (c == DocPConst.RANGLE) { + + buffer.clear(); + return readChar(); + } + + offset = buffer.length(); + c = scanIdentifier(c); + name = buffer.extract(offset); + + // two forms are valid: + // "SYSTEM sysid" and "PUBLIC pubid sysid" + + String publicId = null; + String systemId = null; + + if (name.equals("SYSTEM")) { + c = skipWhite(c); + + offset = buffer.length(); + c = scanQuotedString(c); + systemId = buffer.extract(offset); + + doctype(root, null, systemId); + + if (c != DocPConst.RANGLE) { + findCloseAngleForComment(c); + } + buffer.clear(); + return readChar(); + } else if (name.equals("PUBLIC")) { + c = skipWhite(c); + + offset = buffer.length(); + c = scanQuotedString(c); + publicId = buffer.extract(offset); + + c = skipWhite(c); + + offset = buffer.length(); + c = scanQuotedString(c); + systemId = buffer.extract(offset); + + doctype(root, publicId, systemId); + + if (c != DocPConst.RANGLE) { + findCloseAngleForComment(c); + } + buffer.clear(); + return readChar(); + } else { + // we ignore this; altough it is likely an internal DTD subset + if (c != DocPConst.RANGLE) { + findCloseAngleForComment(c); + } + findCloseAngleForComment(c); + + doctype(root, null, null); + + buffer.clear(); + return readChar(); + } + } + + + protected void setXmlEntities(TagProperties attr) { + // Don't do anything for now + } + + protected char parseTag() throws IOException { + char c; + String name; + TagProperties attributes; + int offset; + int tagStartOffset; + boolean endTag; + boolean emptyTag; + + /** + * Comments are handled in the following way: + * 1) If the first character is "!" AND NOT followed by "--" + * then everything is a comment till the subsequent closing + * angle bracket. + * 2) If the first character is "!" AND is followed by "--" then + * everything till "--" followed by a closing angle bracket + * is marked as a comment. This can include other closing and + * opening angle brackets. + * + * N.B Netscape follows the above two rules with a caveat to rule + * 2 from above. If it does not find "--" followed by a closing + * angle bracket in the rest of the document, it behaves as rule + * 1 i.e the subsequent closing angle bracket is taken as the + * end of the comment. + * + * Xml entities are handled in the following way: + * 1) If the first character is "?" AND is followed by "xml" + * then everything is a xml entity till the subsequent closing + * "?" followed by an angle bracket. + * + */ + + buffer.clear(); + tagStartOffset = 0; + c = DocPConst.LANGLE; + buffer.add(DocPConst.LANGLE); + c = readChar(); + if (c == DocPConst.EXCLAIM){ // comment follows + int resetPos = 0; + buffer.add(DocPConst.EXCLAIM); + // =-= jd BEGIN HACK + // Taking the check for - out since Netscape just uses <! + // to mark a comment + c = readChar(); + if (c != DocPConst.MINUS){ + // a shorthand comment or a DOCTYPE + return handleCommentOrDoctype(c); + } + buffer.add(c); // =-= jd Added this line + c = readChar(); + if (c != DocPConst.MINUS){ // it's still a "shorthand" comment + findCloseAngleForComment(c); + return readChar(); + } + buffer.add(c); // =-= jd Added this line + // just in case of the NB comment from above, set a fallback pos + resetPos = buffer.length(); + // source.reset() doesn't work at all :( + // without that, we can't do NB on comments. - the + // comment goes to EOF, unless it encounters "-->" + //if (source.markSupported()) { + // resetPos = buffer.length(); + // try { + // source.mark(64); // pass in readAheadLimit + // } catch (IOException e){ + // } + //} + + // handled "shorthand" comments - now need to look for "-->" + int nDash = 0; + for(;;) { + c = readChar(); + if (c == EOF) { + commentEOFError(resetPos); + break; + } + if (c != DocPConst.MINUS) { + buffer.add(c); + continue; + } + while (c == DocPConst.MINUS) { + buffer.add(c); + nDash ++; + c = readChar(); + } + if (c == EOF) { + commentEOFError(resetPos); + break; + } + buffer.add(c); + if ((nDash >= 2) && (c == DocPConst.RANGLE)) { + comment(buffer.extract(0)); + buffer.clear(); + return readChar(); + } + nDash = 0; + } + } + if (c == DocPConst.QUESTION){ // xml & PI declarations follows + int resetPos = 0; + StringBuffer target = new StringBuffer(); + buffer.add(DocPConst.QUESTION); + while (((c = readChar()) != DocPConst.DQUOTE) && + c != DocPConst.SPACE && + c != DocPConst.TAB && + c != DocPConst.NEWLINE && + c != DocPConst.RANGLE) { + buffer.add(c); + target.append(c); + } + + if (! target.toString().equals("xml")) { + // we have a PI ... + buffer.clear(); // reset the buffer + while (true) { + while ((c = readChar()) != DocPConst.QUESTION && + c != EOF) { + buffer.add(c); + } + if (c == EOF) { + eofError(); + return readChar(); + } + c = readChar(); + if (c != DocPConst.RANGLE && + c != EOF) { + buffer.add(DocPConst.QUESTION); + buffer.add(c); + } + if (c == EOF) { + eofError(); + return readChar(); + } else { + pi(target.toString(), buffer.extract(0)); + return readChar(); + } + } + } + // discard that target + target = null; + + // OK so far + // + // try to find the attributes + c = readChar(); + attributes = null; + for (;;){ + c = skipWhite(c); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.QUESTION) + break; + + offset = buffer.length(); + c = scanIdentifier(c); + if (offset == buffer.length()){ + error("Expecting an attribute"); + skipToCloseAngle(c); + return readChar(); + } + String attname = buffer.extract(offset); + c = skipWhite(c); + if (attributes == null) + attributes = new TagProperties(); + String attvalue; + if (c == DocPConst.EQUALS) { // parsing attribute value + buffer.add(c); + c = readChar(); + int voff; + // ignore whitespace between the EQUALS and the attr value + // because netscape does (bug#4045870) + c = skipWhite(c); + // delimit on RANGLE and LANGLE in case of incomplete line + if (c == DocPConst.QUESTION || c == DocPConst.LANGLE ){ + attvalue = ""; + } else if (c == DocPConst.DQUOTE){ + buffer.add(c); + voff = buffer.length(); + for (;;){ + c = readChar(); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.DQUOTE) + break; + // transform & + if (c == DocPConst.AMPERSAND) + c = parseEscape(); + buffer.add(c); + } + attvalue = buffer.extract(voff); + buffer.add(c); + c = readChar(); + } else { + voff = buffer.length(); + buffer.add(c); + for (;;){ + c = readChar(); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.DQUOTE || + c == DocPConst.SPACE || + c == DocPConst.TAB || + c == DocPConst.NEWLINE || + c == DocPConst.QUESTION) + break; + // transform & + if (c == DocPConst.AMPERSAND) + c = parseEscape(); + buffer.add(c); + } + attvalue = buffer.extract(voff); + } + } else { + attvalue = "true"; + } + attributes.put(attname, attvalue); + } + c = readChar(); + if (c == EOF) { + eofError(); + return readChar(); + } + c = skipWhite(c); + buffer.add(c); + if ((c == DocPConst.RANGLE)) { + setXmlEntities(attributes); + buffer.clear(); + return readChar(); + } else { + error ("Expecting ?>"); + skipToCloseAngle(c); + return readChar(); + } + } + c = skipWhite(c); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.SLASH){ + buffer.add(c); + c = skipWhite(readChar()); + endTag = true; + emptyTag = false; + } else { + endTag = false; + emptyTag = false; + } + offset = buffer.length(); + c = scanIdentifier(c); + name = buffer.extract(offset); + attributes = null; + for (;;){ + c = skipWhite(c); + if (c == EOF){ + eofError(); + return c; + } + + if (c == DocPConst.RANGLE) + break; + + if (c == DocPConst.SLASH) { + buffer.add(c); + c = readChar(); + if (c == DocPConst.RANGLE) { + endTag = true; + emptyTag = true; + break; + } else { + error("Expecting />"); + skipToCloseAngle(c); + return readChar(); + } + } + + if (c == DocPConst.LANGLE) { + + // this could be a comment inside a tag e.g. + // <TABLE width=500 <!-- border=5 --> color="e0e0e0" + // right now we will ignore the comment and + // close the tag as Netscape does. + + // OR + + // our learned HTML author has forgotten to + // close the tag. e.g. + // <TABLE width=500 border=5 color="e0e0e0" + // <CAPTION>.... + + tag(name, attributes, endTag, false); + buffer.clear(); + return (DocPConst.LANGLE); + } + + offset = buffer.length(); + c = scanIdentifier(c); + if (offset == buffer.length()){ + error("Expecting an attribute (2)"); + skipToCloseAngle(c); + return readChar(); + } + String attname = buffer.extract(offset); + c = skipWhite(c); + if (attributes == null) + attributes = new TagProperties(); + String attvalue; + if (c == DocPConst.EQUALS) { // parsing attribute value + buffer.add(c); + c = readChar(); + int voff; + // ignore whitespace between the EQUALS and the attr value + // because netscape does (bug#4045870) + c = skipWhite(c); + // delimit on RANGLE and LANGLE in case of incomplete line + if (c == DocPConst.RANGLE || c == DocPConst.LANGLE ){ + attvalue = ""; + } else if (c == DocPConst.DQUOTE){ + buffer.add(c); + voff = buffer.length(); + for (;;){ + c = readChar(); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.DQUOTE) + break; + // transform & + if (c == DocPConst.AMPERSAND) + c = parseEscape(); + buffer.add(c); + } + attvalue = buffer.extract(voff); + buffer.add(c); + c = readChar(); + } else { + voff = buffer.length(); + buffer.add(c); + for (;;){ + c = readChar(); + if (c == EOF){ + eofError(); + return c; + } + if (c == DocPConst.DQUOTE || + c == DocPConst.SPACE || + c == DocPConst.TAB || + c == DocPConst.NEWLINE || + c == DocPConst.RANGLE) + break; + // transform & + if (c == DocPConst.AMPERSAND) + c = parseEscape(); + buffer.add(c); + } + attvalue = buffer.extract(voff); + } + } else { + attvalue = "true"; + } + attributes.put(attname, attvalue); + } + tag(name, attributes, endTag, emptyTag); + buffer.clear(); + return readChar(); + } + + + protected char parseEscape() throws IOException { + char c; + int offset; + + offset = buffer.length(); + buffer.add(DocPConst.AMPERSAND); + c = readChar(); + if (c == EOF){ + generateError(offset); + return c; + } + if (c == DocPConst.HASH){ + int x; + + x = 0; + for (;;){ + c = readChar(); + if (c == EOF){ + generateError(offset); + return c; + } else if (c == DocPConst.SEMICOLON) { + c = DocPConst.NULL; + break; + } else if (!Character.isDigit(c)){ + if (x > 0) { + break; + } else { + error("Expecting a digit"); + generateError(offset); + return c; + } + } + buffer.add(c); + x = x * 10 + Character.digit(c, 10); + } + buffer.reset(offset); + buffer.add((char)x); + } else if (Character.isLowerCase(c) || + Character.isUpperCase(c)){ + if (entities == null) + initEntities(); + + escapeBuffer.clear(); + escapeBuffer.add(c); + for (;;){ + buffer.add(c); + c= readChar(); + if (c == EOF){ + generateError(offset); + return c; + } + if (Character.isLowerCase(c) || + Character.isUpperCase(c)){ + escapeBuffer.add(c); + if (entities.get(escapeBuffer.extract(0)) != null) { + c = readChar(); + if (c == DocPConst.SEMICOLON) + c = DocPConst.NULL; + break; + } + } else if (c == DocPConst.SEMICOLON) { + c = DocPConst.NULL; + break; + } else { + error("Expecting a letter"); + generateError(offset); + return c; + } + } + String s = escapeBuffer.extract(0); + + buffer.reset(offset); + + Character x = (Character)entities.get(s); + + if (x != null){ + return x.charValue(); + } else { + String a = documentAttribute(s); + + if (a != null){ + int i; + + for (i = 0; i < a.length(); i++) + buffer.add(a.charAt(i)); + } + } + } else { + error("Expecting a letter o"); + generateError(offset); + return c; + } + if (c != DocPConst.NULL) + return c; + else + return readChar(); + } + + Hashtable entities; + + protected void initEntities() { + entities = new Hashtable(); + + entities.put("quot", new Character(DocPConst.DQUOTE)); + entities.put("amp", new Character(DocPConst.AMPERSAND)); + entities.put("gt", new Character(DocPConst.RANGLE)); + entities.put("lt", new Character(DocPConst.LANGLE)); + + entities.put("nbsp", new Character((char)160)); + + entities.put("copy", new Character((char)169)); + + entities.put("Agrave", new Character((char)192)); + entities.put("Aacute", new Character((char)193)); + entities.put("Acirc", new Character((char)194)); + entities.put("Atilde", new Character((char)195)); + entities.put("Auml", new Character((char)196)); + entities.put("Aring", new Character((char)197)); + entities.put("AElig", new Character((char)198)); + entities.put("Ccedil", new Character((char)199)); + entities.put("Egrave", new Character((char)200)); + entities.put("Eacute", new Character((char)201)); + entities.put("Ecirc", new Character((char)202)); + entities.put("Euml", new Character((char)203)); + entities.put("Igrave", new Character((char)204)); + entities.put("Iacute", new Character((char)205)); + entities.put("Icirc", new Character((char)206)); + entities.put("Iuml", new Character((char)207)); + + entities.put("Ntilde", new Character((char)209)); + entities.put("Ograve", new Character((char)210)); + entities.put("Oacute", new Character((char)211)); + entities.put("Ocirc", new Character((char)212)); + entities.put("Otilde", new Character((char)213)); + entities.put("Ouml", new Character((char)214)); + + entities.put("Oslash", new Character((char)216)); + entities.put("Ugrave", new Character((char)217)); + entities.put("Uacute", new Character((char)218)); + entities.put("Ucirc", new Character((char)219)); + entities.put("Uuml", new Character((char)220)); + entities.put("Yacute", new Character((char)221)); + entities.put("THORN", new Character((char)222)); + entities.put("szlig", new Character((char)223)); + entities.put("agrave", new Character((char)224)); + entities.put("aacute", new Character((char)225)); + entities.put("acirc", new Character((char)226)); + entities.put("atilde", new Character((char)227)); + entities.put("auml", new Character((char)228)); + entities.put("aring", new Character((char)229)); + entities.put("aelig", new Character((char)230)); + entities.put("ccedil", new Character((char)231)); + entities.put("egrave", new Character((char)232)); + entities.put("eacute", new Character((char)233)); + entities.put("ecirc", new Character((char)234)); + entities.put("euml", new Character((char)235)); + entities.put("igrave", new Character((char)236)); + entities.put("iacute", new Character((char)237)); + entities.put("icirc", new Character((char)238)); + entities.put("iuml", new Character((char)239)); + entities.put("eth", new Character((char)240)); + entities.put("ntilde", new Character((char)241)); + entities.put("ograve", new Character((char)242)); + entities.put("oacute", new Character((char)243)); + entities.put("ocirc", new Character((char)244)); + entities.put("otilde", new Character((char)245)); + entities.put("ouml", new Character((char)246)); + + entities.put("oslash", new Character((char)248)); + entities.put("ugrave", new Character((char)249)); + entities.put("uacute", new Character((char)250)); + entities.put("ucirc", new Character((char)251)); + entities.put("uuml", new Character((char)252)); + entities.put("yacute", new Character((char)253)); + entities.put("thorn", new Character((char)254)); + entities.put("yuml", new Character((char)255)); + } + + // .................................................... + // YK: optimization: Inlining + // .................................................... + + protected char scanIdentifier(char c) throws IOException { + for (;;) { + if (! ( + c == DocPConst.HORIZBAR || + c == DocPConst.COLON || + (c >= DocPConst.ZERO && c <= DocPConst.NINE) || + Character.isLetter(c) + // Used to be Character.isUpperCase(c) + ) + ) { + break; + } + // ............................................ + // Inlining again an again + // ............................................ + // buffer.add(c); // YK: inline + if (buffer.buflen >= buffer.buf.length){ + char [] x = new char [buffer.buf.length * buffer.scale]; + System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length); + buffer.buf = x; + } + + // ............................................ + // Inlining again an again + // ............................................ + buffer.buf[buffer.buflen++] = c; + + //c = readChar(); // YK: inline + if(myCount >= mySize) { + try { + mySize = source.read(cb, 0, defaultCharBufferSize); + if(mySize < 0) { + break; + } + if(mySize == 0) { + System.err.println(" DocumentParser::scanIdentifier() !!!ERROR !!! source.read(...) == 0"); + break; + } + myCount = 0; + } catch (CharConversionException e) { + throw e; + } catch (IOException e) { + break; + } + } + //...........REMIND............removed......// readOffset++; + if (shouldCacheSource) + documentSource.add(cb[myCount]); + c = cb[myCount++]; + } + return c; + } + + + // ...................................................... + // Scan a single or double quoted string + // ...................................................... + protected char scanQuotedString(char c) throws IOException { + c = skipWhite(c); + if (c == DocPConst.DQUOTE) { + for (;;) { + c = readChar(); + if (c == DocPConst.DQUOTE || + c == DocPConst.RANGLE) { + break; + } + buffer.add(c); + } + return readChar(); + } else if (c == DocPConst.QUOTE) { + for (;;) { + c = readChar(); + if (c == DocPConst.QUOTE || + c == DocPConst.RANGLE) { + break; + } + buffer.add(c); + } + return readChar(); + } else { + return c; + } + } + + // ...................................................... + // This whole method is inlined including the data reading + // ................. YK: Inline + protected char skipWhite(char c) throws IOException { + while (c == DocPConst.SPACE || + c == DocPConst.RETURN || + c == DocPConst.TAB || + c == DocPConst.NEWLINE) { + // ............................................ + // Inlining again an again + // ............................................ + // buffer.add(c); // YK: inline + if (buffer.buflen >= buffer.buf.length){ + char [] x = new char [buffer.buf.length * buffer.scale]; + System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length); + buffer.buf = x; + } + buffer.buf[buffer.buflen++] = c; + + //c = readChar(); // YK: inline + // ............................................ + // Inlining again an again + // ............................................ + + if(myCount >= mySize) { + try { + mySize = source.read(cb, 0, defaultCharBufferSize); + if(mySize < 0) { + break; + } + if(mySize == 0) { + System.err.println(" DocumentParser::parse() !!!ERROR !!! source.read(...) == 0"); + break; + } + myCount = 0; + } catch (CharConversionException e) { + throw e; + } catch (IOException e) { + break; + } + } + //...........REMIND............removed......// readOffset++; + if (shouldCacheSource) + documentSource.add(cb[myCount]); + c = cb[myCount++]; + } + return c; + } + + + // ................................................................ + // The readChar method is heavily inlined + // (all the calls to sychronized read() are removed) + // The read() also creates on char array every time !!! - VERY SLOW + // YK + // ................................................................. + int defaultCharBufferSize = 8192; + char cb[] = new char[defaultCharBufferSize]; + int mySize = 0; + int myCount = 0; + protected char readChar() throws IOException { + if(myCount >=mySize) { + try { + mySize = source.read(cb, 0, defaultCharBufferSize); + if(mySize < 0) { + return EOF; + } + if(mySize == 0) { + System.err.println(" DocumentParser::readChar() !!!ERROR !!! source.read(...) == 0"); + return EOF; + } + myCount = 0; + } catch (CharConversionException e) { + throw e; + } catch (IOException e) { + return EOF; + } + } + //...........REMIND............removed......// readOffset++; + if (shouldCacheSource) + documentSource.add(cb[myCount]); + return cb[myCount++]; + } + + /** + * This method is called when parsing a tag and an error is + * encountered. It skips to the closing angle bracket, + * treating the entire tag as error text. The generateError + * call at the end stuffs the full tag into the document + * as an error. + */ + + // YK: Inlining + // ................................................................ + // The skipToCloseAngle method is heavily inlined + // (all the calls to sychronized read() are removed) + // The read() also creates on char array every time !!! - VERY SLOW + // YK + // ................................................................. + + protected void skipToCloseAngle(char c) throws IOException { + for (;;) { + //buffer.add(c); + + + if (buffer.buflen >= buffer.buf.length){ + char [] x = new char [buffer.buf.length * buffer.scale]; + System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length); + buffer.buf = x; + } + buffer.buf[buffer.buflen++] = c; + + if (c == DocPConst.RANGLE) { + break; + } + + + + //c = readChar(); + + + if(myCount >= mySize) { + try { + mySize = source.read(cb, 0, defaultCharBufferSize); + if(mySize < 0) { + break; + } + if(mySize == 0) { + System.err.println(" DocumentParser::skipToCloseAngle() !!!ERROR !!! source.read(...) == 0"); + break; + } + myCount = 0; + } catch (CharConversionException e) { + throw e; + } catch (IOException e) { + break; + } + } + //...........REMIND............removed......// readOffset++; + c = cb[myCount++]; + } + + + generateError(0); + } + + protected void generateError(int offset) { + String s = buffer.extract(offset); + + buffer.reset(offset); + buffer.flush(this); + errorString(s); + } + + protected void commentEOFError(int resetTo) { + /* tried to use source.reset, but didn't work this way... + // for some reason, this isn't resetting the source (BufferedReader) + source.reset(); + buffer.reset(resetTo); + char c = readChar(); + if (c != DocPConst.RANGLE) + findCloseAngleForComment(c); + else { + buffer.add(c); + comment(buffer.extract(0)); + buffer.clear(); + } + } catch (IOException e) { + } + */ + //System.err.println("DocumentParser:: comment went past end of buffer!"); + eofError(); + } + + protected void eofError() { + error("Unexpected end of file"); + generateError(0); + } + + void error(String s) { + System.err.println("DocumentParser Error: "+s); + } +} // class DocumentParser + +class ScanBuffer { + char [] buf; + int buflen; + int scale = 2; + + ScanBuffer() { + buf = new char [ 256 ]; + } + + //........................................................... + // YK -extra constructor with the initial buffer size + //........................................................... + ScanBuffer(int l, int s) { + buf = new char [l]; + scale = s; + } + + protected void clear() { + buflen = 0; + } + + protected void reset(int offset) { + buflen = offset; + } + + protected void flush(DocumentParser owner) { + if (buflen > 0){ + owner.callFlush(buf, 0, buflen); + buflen = 0; + } + } + + protected void add(char c) { + if (buflen >= buf.length){ + char [] x = new char [buf.length * scale]; + System.arraycopy(buf, 0, x, 0, buf.length); + buf = x; + } + buf[buflen++] = c; + } + + protected int length() { + return buflen; + } + + public String toString() { + return "ScanBuffer, buf = " + buf + ", buflen = " + buflen; + } + + //.................................................... + // YK: optimized creating new strings + // without any data copying (big performance win) + // as this method is called allover the place + //.................................................... + + protected String extract(int offset) { + return new String(buf, offset, buflen - offset); + } + +} // class ScanBuffer + + +// YK: This class is created to fix NullPointerException +// in BufferedReader::read(...) having lock == null + +class MyBufferedReader extends BufferedReader { + public MyBufferedReader(Reader in, int sz) { super(in, sz); } + public MyBufferedReader(Reader in) { super(in); } + public int read(char cbuf[], int off, int len) throws IOException { + if(lock == null) { + //System.err.println("read(): -------------------lock == null"); + return -1; + } + //System.err.println("read(): +++++++++++++++++++lock = " + lock); + return super.read(cbuf, off, len); + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java new file mode 100644 index 0000000000000000000000000000000000000000..94ad203d18a1f6b32bf0e9e2339651f9bbf7b249 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java @@ -0,0 +1,182 @@ +/* + * @(#)HeaderParser.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) HeaderParser.java 1.4 - last change made 10/30/06 + */ + +package com.sun.java.help.impl; + +/** + * This class provides is useful for the nightmare of parsing multi-part + * HTTP/RFC822 headers sensibly: + * <p> + * <pre> + * From a String like: 'timeout=15, max=5' + * create an array of Strings: + * { {"timeout", "15"}, + * {"max", "5"} + * } + * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"' + * create one like (no quotes in literal): + * { {"basic", null}, + * {"realm", "FuzzFace"} + * {"foo", "Biz Bar Baz"} + * } + * keys are converted to lower case, vals are left as is.... + * </pre> + * + * @version 1.4 10/30/06 + * @author Dave Brown + * @author Roger D. Brinkley + */ + + +public class HeaderParser { + + /* table of key/val pairs - maxes out at 10!!!!*/ + String raw; + String[][] tab; + + public HeaderParser(String raw) { + this.raw = raw; + tab = new String[10][2]; + parse(); + } + + private void parse() { + + if (raw != null) { + raw = raw.trim(); + char[] ca = raw.toCharArray(); + int beg = 0, end = 0, i = 0; + boolean inKey = true; + boolean inQuote = false; + int len = ca.length; + while (end < len) { + char c = ca[end]; + if (c == '=') { // end of a key + tab[i][0] = new String(ca, beg, end-beg).toLowerCase(); + inKey = false; + end++; + beg = end; + } else if (c == '\"') { + if (inQuote) { + tab[i++][1]= new String(ca, beg, end-beg); + inQuote=false; + do { + end++; + } while (end < len && (ca[end] == ' ' || ca[end] == ',')); + inKey=true; + beg=end; + } else { + inQuote=true; + end++; + beg=end; + } + } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in + if (inQuote) { + end++; + continue; + } else if (inKey) { + tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase(); + } else { + tab[i++][1] = (new String(ca, beg, end-beg)); + } + while (end < len && (ca[end] == ' ' || ca[end] == ',')) { + end++; + } + inKey = true; + beg = end; + } else { + end++; + } + } + // get last key/val, if any + if (--end > beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = (new String(ca, beg, end-beg)); + } else { + tab[i++][1] = (new String(ca, beg, end-beg+1)); + } + } else { + tab[i][0] = (new String(ca, beg, end-beg+1)).toLowerCase(); + } + } else if (end == beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = String.valueOf(ca[end-1]); + } else { + tab[i++][1] = String.valueOf(ca[end]); + } + } else { + tab[i][0] = String.valueOf(ca[end]).toLowerCase(); + } + } + } + + } + + public String findKey(int i) { + if (i < 0 || i > 10) + return null; + return tab[i][0]; + } + + public String findValue(int i) { + if (i < 0 || i > 10) + return null; + return tab[i][1]; + } + + public String findValue(String key) { + return findValue(key, null); + } + + public String findValue(String k, String Default) { + if (k == null) + return Default; + k.toLowerCase(); + for (int i = 0; i < 10; ++i) { + if (tab[i][0] == null) { + return Default; + } else if (k.equals(tab[i][0])) { + return tab[i][1]; + } + } + return Default; + } + + public int findInt(String k, int Default) { + try { + return Integer.parseInt(findValue(k, String.valueOf(Default))); + } catch (Throwable t) { + return Default; + } + } + } diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java new file mode 100644 index 0000000000000000000000000000000000000000..be62cd1d1eb535505d576febff8398145a5d94cc --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java @@ -0,0 +1,948 @@ +/* + * @(#)JHSecondaryViewer.java 1.25 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Rectangle; +import java.awt.Point; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Font; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicButtonUI; +import javax.swing.border.EmptyBorder; +import javax.swing.text.View; +import javax.swing.text.Element; +import javax.swing.text.AttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.Document; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.StyleSheet; +import javax.help.*; +import javax.help.Map.ID; +import java.awt.event.*; +import java.awt.Dimension; +import java.awt.Insets; +import java.net.*; +import java.util.Hashtable; +import java.beans.PropertyChangeEvent; +import java.util.Enumeration; +import java.awt.Cursor; + +/** + * This class is a secondary viewer to be included in HTML content within + * JHContentViewer. The ViewerType can either be a SecondaryWindow or a Popup. + * Activation is done be either a Button or a mouse enabled Label. Both Button + * and Label support Text, Icon, or Text and Icon. + * <p> + * To use this class within HTML content use the <object> tag. Below is an + * example usage: + * <p><pre> + * <object CLASSID="java:com.sun.java.help.impl.JHSecondaryViewer"> + * <param name="content" value="secondary_contents.html"> + * <param name="viewerActivator" value="javax.help.LinkLabel"> + * <param name="viewerStyle" value="javax.help.Popup"> + * <param name="viewerSize" value="300,400"> + * <param name="text" value="Click here"> + * <param name="textFontFamily" value="SansSerif"> + * <param name="textFontSize" value="x-large"> + * <param name="textFontWeight" value="plain"> + * <param name="textFontStyle" value="italic"> + * <param name="textColor" value="red"> + * </object> + * </pre><p> + * Valid parameters are: + * <ul> + * <li>content - a valid url, can be relative to the current viewer + * @see setContent + * <li>id - a valid id from the current HelpSet + * @see setId + * <li>viewerName - the name of the SecondaryWindow to display the content in + * @see setViewerName + * <li>viewerActivator - the activator type for the viewer. + * Either "javax.help.LinkButton" or "javax.help.LinkLabel" + * @see setViewerActivator + * <li>viewerStyle - the style of the viewer. Either "SecondaryWindow" or "Popup" + * @see setViewerStyle + * <li>viewerLocation - the x,y coordinates applied to a secondary window. + * @see setViewerLocation + * <li>viewerSize - the width, height applied to a viewer. + * @see setViewerSize + * <li>iconByName - the url or id of a icon to be displayed in the activator. + * The url is relative to the base address of the document + * @see setIconByName + * <li>text - the text of the activator + * @see setText + * <li>textFontFamily - the font family of the activator text + * @see setTextFontFamily + * <li>textFontSize - the size of the activator text font. Size is specified + * in a css termonolgy. See the setTextFontSize for acceptable syntax + * @see setTextFontSize + * <li>textFontWeight - the activator text font weight + * @see setTextFontWeight + * <li>textFontStyle - the activator text font style + * @see setTextFontStyle + * <li>textColor - the activator text color + * @see setTextColor + * <ul> + * @see JHSecondaryWindowBeanInfo + * + * @author Roger D. Brinkley + * @version 1.25 10/30/06 + */ +public class JHSecondaryViewer extends JButton implements ActionListener, ViewAwareComponent { + + private View myView; + private HelpSet hs; + private SimpleAttributeSet textAttribs; + private URL base; + private HTMLDocument doc; + + static public String POPUP = "javax.help.Popup"; + static public String SECONDARY_WINDOW = "javax.help.SecondaryWindow"; + static public String LINK_BUTTON = "javax.help.LinkButton"; + static public String LINK_LABEL = "javax.help.LinkLabel"; + private final static String buttonPropertyPrefix = "Button" + "."; + private final static String editorPropertyPrefix = "EditorPane" + "."; + private final static Cursor handCursor = + Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + static private Component container; + + private Cursor origCursor; + + /** + * Create a secondaryviewer. By default the viewer creates a button with + * the text of ">" + */ + public JHSecondaryViewer() { + super(); + setText(">"); + setMargin(new Insets(0,0,0,0)); + createLinkButton(); + addActionListener(this); + origCursor = getCursor(); + addMouseListener(new MouseListener() { + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + setCursor(handCursor); + } + + public void mouseExited(MouseEvent e) { + setCursor(origCursor); + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + }); + } + + /** + * Sets data optained from the View + */ + public void setViewData(View v) { + myView = v; + doc = (HTMLDocument) myView.getDocument(); + base = doc.getBase(); + + // Set the current font information in the local text attributes + Font font = getFont(); + textAttribs = new SimpleAttributeSet(); + textAttribs.removeAttribute(StyleConstants.FontSize); + textAttribs.removeAttribute(StyleConstants.Bold); + textAttribs.removeAttribute(StyleConstants.Italic); + textAttribs.addAttribute(StyleConstants.FontFamily, + font.getName()); + textAttribs.addAttribute(StyleConstants.FontSize, + new Integer(font.getSize())); + textAttribs.addAttribute(StyleConstants.Bold, + new Boolean(font.isBold())); + textAttribs.addAttribute(StyleConstants.Italic, + new Boolean(font.isItalic())); + + + // Loop through and find the JHelpContentViewer + Component c = container = (Component) myView.getContainer(); + while (c != null) { + if (c instanceof JHelpContentViewer) { + break; + } + c = c.getParent(); + } + + // Get the helpset if there was JHelpContentViewer + if (c !=null) { + TextHelpModel thm = ((JHelpContentViewer)c).getModel(); + if (thm != null) { + hs = thm.getHelpSet(); + } + } + } + + /** + * properties + */ + private int viewerHeight = 0; + private int viewerWidth = 0; + private int viewerX = 0; + private int viewerY = 0; + private String viewerName = ""; + private int viewerActivator = 0; + private int viewerStyle = 0; + private Icon viewerIcon; + private String content = ""; + private Map.ID ident; + + /** + * Set the content for the secondary viewer + * @param content a valid URL + */ + public void setContent(String content) { + debug ("setContent"); + this.content = content; + ident = null; + } + + /** + * Returns the content of the secondary viewer + */ + public String getContent() { + + // return the URL of the ident if set + if (ident != null) { + Map map = hs.getCombinedMap(); + try { + URL url = map.getURLFromID(ident); + return (url.toExternalForm()); + } catch (Exception ex) { + } + } + + // just return the content even if "" + return content; + } + + /** + * Set the ID for content in the secondary viewer + * @param content a valid URL + */ + public void setId(String id) { + debug ("setID"); + ident = Map.ID.create(id, hs); + content = ""; + } + + /** + * Returns the ID of the secondary viewer + */ + public String getId() { + return ident.id; + } + + /** + * Sets the viewer name to display the content in. + * Viewer is only valid for ViewerStyle "SecondaryWindow" + */ + public void setViewerName(String name) { + debug("setViewerName"); + viewerName = name; + } + + /** + * Returns the viewer name + */ + public String getViewerName() { + return viewerName; + } + + /** + * Sets the viewer activator. + * Valid activators are + * <ul> + * <li>javax.help.LinkButton + * <li>javax.help.LinkLabel + * </ul> + * The new activatory type will be used the next time a view is displayed. + */ + public void setViewerActivator(String activator) { + debug ("setViewerActivator"); + if (activator.compareTo(LINK_BUTTON) == 0 && + viewerActivator != 0) { + viewerActivator = 0; + createLinkButton(); + } else if (activator.compareTo(LINK_LABEL) == 0 && + viewerActivator != 1) { + viewerActivator = 1; + createLinkLabel(); + } + } + + /** + * Returns the viewer activator + */ + public String getViewerActivator() { + switch (viewerActivator) { + case 0: + return LINK_BUTTON; + case 1: + return LINK_LABEL; + } + return "unknownStyle"; + } + + /** + * Creates a link button. This is just a JButton with default settings. + */ + private void createLinkButton() { + LookAndFeel.installBorder(this, buttonPropertyPrefix + "border"); + setBorderPainted(true); + setFocusPainted(true); + setAlignmentY(Container.CENTER_ALIGNMENT); + setContentAreaFilled(true); + setBackground(UIManager.getColor(buttonPropertyPrefix + "background")); + if (textAttribs != null && + textAttribs.isDefined(StyleConstants.Foreground)) { + setForeground((Color)textAttribs.getAttribute(StyleConstants.Foreground)); + } else { + setForeground(UIManager.getColor(buttonPropertyPrefix + "foreground")); + } + invalidate(); + } + + /** + * Creates a link label. A link label is a form of a JButton but without a + * button like appearance. + */ + private void createLinkLabel() { + setBorder(new EmptyBorder(1,1,1,1)); + setBorderPainted(false); + setFocusPainted(false); + setAlignmentY(getPreferredLabelAlignment()); + setContentAreaFilled(false); + setBackground(UIManager.getColor(editorPropertyPrefix + "background")); + if (textAttribs != null && + textAttribs.isDefined(StyleConstants.Foreground)) { + setForeground((Color)textAttribs.getAttribute(StyleConstants.Foreground)); + } else { + setForeground(Color.blue); + } + invalidate(); + } + + /** + * Determine the alignment offset so the text is aligned with other views + * correctly. + */ + private float getPreferredLabelAlignment() { + Icon icon = (Icon)getIcon(); + String text = getText(); + + Font font = getFont(); + FontMetrics fm = getToolkit().getFontMetrics(font); + + Rectangle iconR = new Rectangle(); + Rectangle textR = new Rectangle(); + Rectangle viewR = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE); + + SwingUtilities.layoutCompoundLabel( + this, fm, text, icon, + getVerticalAlignment(), getHorizontalAlignment(), + getVerticalTextPosition(), getHorizontalTextPosition(), + viewR, iconR, textR, + (text == null ? 0 : ((BasicButtonUI)ui).getDefaultTextIconGap(this)) + ); + + /* The preferred size of the button is the size of + * the text and icon rectangles plus the buttons insets. + */ + Rectangle r = iconR.union(textR); + + Insets insets = getInsets(); + r.height += insets.top + insets.bottom; + + /* Ensure that the height of the button is odd, + * to allow for the focus line. + */ + if(r.height % 2 == 0) { + r.height += 1; + } + + float offAmt = fm.getMaxAscent() + insets.top; + return offAmt/(float)r.height; + } + + /** + * Sets the viewer style. There are two valid viewer styles: + * <ul> + * <li>javax.help.SecondaryWindow + * <li>javax.help.Popup + * <ul> + * <p> + * Viewer style is updated the next time the viewer is made visible + * @param style a valid ViewerStyle + */ + public void setViewerStyle(String style) { + debug ("setViewerStyle"); + if (style.compareTo(SECONDARY_WINDOW) == 0) { + viewerStyle = 0; + } else if (style.compareTo(POPUP) == 0) { + viewerStyle = 1; + } + } + + /** + * Returns the current ViewerStyle + */ + public String getViewerStyle() { + switch (viewerStyle) { + case 0: + return SECONDARY_WINDOW; + case 1: + return POPUP; + } + return "unknownStyle"; + } + + /** + * Sets the viewer's location to display the content in. + * Location is relative to the screen or a modal dialog box + * The String must be in the form of "x,y". If no viewer location + * is established the default is 0,0 for secondary windows. Location + * is ignored for popups. + * @see getViewerLocation + */ + public void setViewerLocation(String location) { + debug("setViewerLocation"); + int comma = location.indexOf(","); + if (comma != -1) { + String x = location.substring(0,comma).trim(); + String y = location.substring(comma+1).trim(); + if (x != null && y != null) { + viewerX = Integer.parseInt(x); + viewerY = Integer.parseInt(y); + } + } + } + + /** + * Returns the viewer Location. Location is relative to the screen or + * a modal dialog box. The form of the location is "x,y". + * The default location is 0,0. + * @see setViewerLocation + */ + public String getViewerLocation() { + String retval = Integer.toString(viewerX) + "," + + Integer.toString(viewerY); + + // try to return the acutal viewer locations if it exists + switch (viewerStyle) { + case 0: + SecondaryWindow sw = + SecondaryWindow.getPresentation(viewerName); + if (sw != null) { + Point p = sw.getLocation(); + if (p != null) { + retval = Integer.toString(p.x) + "," + + Integer.toString(p.y); + } + } + break; + case 1: + // ignored in popups + break; + } + return retval; + } + + /** + * Sets the viewer's size to display the content in. + * The String must be in the form of "width,heigt". + * If no size is set the default is 200,200. + * @see getViewerSize + */ + public void setViewerSize(String size) { + debug ("setViewerSize"); + int comma = size.indexOf(","); + if (comma != -1) { + String width = size.substring(0,comma).trim(); + String height = size.substring(comma+1).trim(); + if (width != null && height != null) { + viewerWidth = Integer.parseInt(width); + viewerHeight = Integer.parseInt(height); + } + } + } + + /** + * Returns the viewer's Size. + * The form of the size is "width,height". + * @see setViewerSize + */ + public String getViewerSize() { + + String retval = ""; + if (viewerWidth != 0) { + retval = Integer.toString(viewerWidth) + "," + + Integer.toString(viewerHeight); + } + + // try to return the acutal viewer locations if it exists + switch (viewerStyle) { + case 0: + SecondaryWindow sw = + SecondaryWindow.getPresentation(viewerName); + if (sw != null) { + Dimension size = sw.getSize(); + if (size != null) { + retval = Integer.toString(size.width) + "," + + Integer.toString(size.height); + } + } + break; + case 1: + // nothing for popups + break; + } + return retval; + } + + /** + * Sets the icon in the activator by url or id. The url is relative to the + * base address of the document. + * @see getIcon + */ + public void setIconByName(String name) { + debug ("setIconByName"); + ImageIcon ig = null; + URL url=null; + // try to get it from the base address + try { + url = new URL (base, name); + } catch (java.net.MalformedURLException ex1) { + return; + } + + // Valid URLs try the Icon + ig = new ImageIcon(url); + if (ig != null) { + setIcon(ig); + // if the text is the default text then make it blank + String text = getText(); + if (text.compareTo(">") == 0) { + setText(""); + } + } + } + + /** + * Sets the icon in the activator by id. + * @see getIcon + */ + public void setIconByID(String name) { + debug ("setIconByID"); + ImageIcon ig = null; + URL url=null; + + Map map = hs.getCombinedMap(); + try { + url = map.getURLFromID(ID.create(name, hs)); + } catch (java.net.MalformedURLException e2) { + return; + } + + // Valid URLs try the Icon + ig = new ImageIcon(url); + if (ig != null) { + setIcon(ig); + // if the text is the default text then make it blank + String text = getText(); + if (text.compareTo(">") == 0) { + setText(""); + } + } + } + + /** + * Sets the text Font family for the activator text. + * For JDK 1.1 this must a family name of Dialog, DialogInput, Monospaced, + * Serif, SansSerif, or Symbol. + */ + public void setTextFontFamily(String family) { + textAttribs.removeAttribute(StyleConstants.FontFamily); + textAttribs.addAttribute(StyleConstants.FontFamily, family); + setFont(getAttributeSetFont(textAttribs)); + Font font = getFont(); + } + + /** + * Returns the text Font family name of the activator text + */ + public String getTextFontFamily() { + return StyleConstants.getFontFamily(textAttribs); + } + + /** + * Sets the text size for the activator text. + * The String size is a valid Cascading Style Sheet value for + * text size. Acceptable values are as follows: + * <ul> + * <li>xx-small + * <li>x-small + * <li>small + * <li>medium + * <li>large + * <li>x-large + * <li>xx-large + * <li>bigger - increase the current base font size by 1 + * <li>smaller - decrease the current base font size by 1 + * <li>xxpt - set the font size to a specific pt value of "xx" + * <li>+x - increase the current base font size by a value of "x" + * <li>-x - decrease the current base font size by a value of "x" + * <li>x - set the font size to the point size associated with + * the index "x" + * </ul> + */ + public void setTextFontSize(String size) { + int newsize, tmp; + StyleSheet css = doc.getStyleSheet(); + try { + if (size.equals("xx-small")) { + newsize = (int)css.getPointSize(0); + } else if (size.equals("x-small")) { + newsize = (int)css.getPointSize(1); + } else if (size.equals("small")) { + newsize = (int)css.getPointSize(2); + } else if (size.equals("medium")) { + newsize = (int)css.getPointSize(3); + } else if (size.equals("large")) { + newsize = (int)css.getPointSize(4); + } else if (size.equals("x-large")) { + newsize = (int)css.getPointSize(5); + } else if (size.equals("xx-large")) { + newsize = (int)css.getPointSize(6); + } else if (size.equals("bigger")) { + newsize = (int)css.getPointSize("+1"); + } else if (size.equals("smaller")) { + newsize = (int)css.getPointSize("-1"); + } else if (size.endsWith("pt")) { + String sz = size.substring(0, size.length() - 2); + newsize = Integer.parseInt(sz); + } else { + newsize = (int) css.getPointSize(size); + } + } catch (NumberFormatException nfe) { + return; + } + if (newsize == 0) { + return; + } + textAttribs.removeAttribute(StyleConstants.FontSize); + textAttribs.addAttribute(StyleConstants.FontSize, + new Integer(newsize)); + setFont(getAttributeSetFont(textAttribs)); + Font font = getFont(); + } + + /** + * Returns the text Font family name of the activator text + */ + public String getTextFontSize() { + return Integer.toString(StyleConstants.getFontSize(textAttribs)); + } + + /** + * Sets the text Font Weigth for the activator text. + * Valid weights are + * <ul> + * <li>plain + * <li>bold + * </ul> + */ + public void setTextFontWeight(String weight) { + boolean isBold=false; + if (weight.compareTo("bold") == 0) { + isBold = true; + } else { + isBold = false; + } + textAttribs.removeAttribute(StyleConstants.Bold); + textAttribs.addAttribute(StyleConstants.Bold, new Boolean(isBold)); + setFont(getAttributeSetFont(textAttribs)); + Font font = getFont(); + } + + /** + * Returns the text Font weight of the activator text + */ + public String getTextFontWeight() { + if (StyleConstants.isBold(textAttribs)) { + return "bold"; + } + return "plain"; + } + + /** + * Sets the text Font Style for the activator text. + * Valid font styles are + * <ul> + * <li>plain + * <li>italic + * </ul> + */ + public void setTextFontStyle(String style) { + boolean isItalic=false; + if (style.compareTo("italic") == 0) { + isItalic = true; + } else { + isItalic = false; + } + textAttribs.removeAttribute(StyleConstants.Italic); + textAttribs.addAttribute(StyleConstants.Italic, new Boolean(isItalic)); + setFont(getAttributeSetFont(textAttribs)); + Font font = getFont(); + } + + /** + * Returns the text Font style of the activator text + */ + public String getTextFontStyle() { + if (StyleConstants.isItalic(textAttribs)) { + return "italic"; + } + return "plain"; + } + + /** + * Sets the text Color for the activator text. + * The following is a list of supported Color names + * <ul> + * <li>black + * <li>blue + * <li>cyan + * <li>darkGray + * <li>gray + * <li>green + * <li>lightGray + * <li>magenta + * <li>orange + * <li>pink + * <li>red + * <li>white + * <li>yellow + * </ul> + */ + public void setTextColor(String name) { + Color color=null; + if (name.compareTo("black") == 0) { + color = Color.black; + } else if (name.compareTo("blue") == 0) { + color = Color.blue; + } else if (name.compareTo("cyan") == 0) { + color = Color.cyan; + } else if (name.compareTo("darkGray") == 0) { + color = Color.darkGray; + } else if (name.compareTo("gray") == 0) { + color = Color.gray; + } else if (name.compareTo("green") == 0) { + color = Color.green; + } else if (name.compareTo("lightGray") == 0) { + color = Color.lightGray; + } else if (name.compareTo("magenta") == 0) { + color = Color.magenta; + } else if (name.compareTo("orange") == 0) { + color = Color.orange; + } else if (name.compareTo("pink") == 0) { + color = Color.pink; + } else if (name.compareTo("red") == 0) { + color = Color.red; + } else if (name.compareTo("white") == 0) { + color = Color.white; + } else if (name.compareTo("yellow") == 0) { + color = Color.yellow; + } + + if (color == null) { + return; + } + textAttribs.removeAttribute(StyleConstants.Foreground); + textAttribs.addAttribute(StyleConstants.Foreground, color); + setForeground(color); + } + + /** + * Returns the text Color of the activator text + */ + public String getTextColor() { + Color color = getForeground(); + return color.toString(); + } + + /** + * Gets the font from an attribute set. This is + * implemented to try and fetch a cached font + * for the given AttributeSet, and if that fails + * the font features are resolved and the + * font is fetched from the low-level font cache. + * Font's are cached in the StyleSheet of a document + * + * @param attr the attribute set + * @return the font + */ + private Font getAttributeSetFont(AttributeSet attr) { + // PENDING(prinz) add cache behavior + int style = Font.PLAIN; + if (StyleConstants.isBold(attr)) { + style |= Font.BOLD; + } + if (StyleConstants.isItalic(attr)) { + style |= Font.ITALIC; + } + String family = StyleConstants.getFontFamily(attr); + int size = StyleConstants.getFontSize(attr); + + /** + * if either superscript or subscript is + * is set, we need to reduce the font size + * by 2. + */ + if (StyleConstants.isSuperscript(attr) || + StyleConstants.isSubscript(attr)) { + size -= 2; + } + + // fonts are cached in the StyleSheet so use that + return doc.getStyleSheet().getFont(family, style, size); + } + + /** + * Displays the viewer according to the viewerType + */ + public void actionPerformed(ActionEvent e) { + debug ("actionPerformed"); + + // System.err.println("clicked on me..."); + switch (viewerStyle) { + case 0: + if (hs != null) { + SecondaryWindow sw = (SecondaryWindow) + SecondaryWindow.getPresentation(hs, viewerName); + + // set the topic to be displayed + if (ident != null) { + debug ("ident=" + ident); + try { + sw.setCurrentID(ident); + } catch (Exception ex) { + debug ("error setting CurrentID"); + // do nothing + } + } else if (content != null) { + debug ("content=" + content); + try { + URL url = new URL(base, content); + sw.setCurrentURL(url); + } catch (Exception ex) { + debug ("error setting URL"); + } + } + + // set the location if defined + if (viewerX != -1) { + sw.setLocation(new Point(viewerX, viewerY)); + } + + // set the size if desired + if (viewerWidth != 0) { + sw.setSize(new Dimension(viewerWidth, viewerHeight)); + } + + // make sure the secondary window is displayed + sw.setDisplayed(true); + + } + break; + case 1: + if (hs != null) { + Popup popup = (Popup) Popup.getPresentation(hs, viewerName); + + // set the topic to be displayed + if (ident != null) { + debug ("ident=" + ident); + try { + popup.setCurrentID(ident); + } catch (Exception ex) { + debug ("error setting CurrentID"); + // do nothing + } + } else if (content != null) { + debug ("content=" + content); + try { + URL url = new URL(base, content); + popup.setCurrentURL(url); + } catch (Exception ex) { + debug ("error setting URL"); + } + } + + // set the size if desired + if (viewerWidth != 0) { + popup.setSize(new Dimension(viewerWidth, viewerHeight)); + } + + popup.setInvoker(this); + + // make sure the popup is displayed + popup.setDisplayed(true); + } + break; + default: + System.out.println ("Unknown viewerStyle"); + } + } + + /** + * For printf debugging. + */ + private final static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("JHSecondaryWindow: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..634c549981ed1a28dc07db22c3f67240ce6a3963 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java @@ -0,0 +1,67 @@ +/* + * @(#)JHSecondaryViewerBeanInfo.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; +import java.beans.*; + +/** + * This class provides information about getter/setter methods within + * JHSecondaryWindow. It is usefull for reflection. + * @see JHSecondaryViewer + * + * @author Roger D. Brinkley + * @version 1.7 10/30/06 + */ +public class JHSecondaryViewerBeanInfo extends SimpleBeanInfo { + + public JHSecondaryViewerBeanInfo() { + } + + public PropertyDescriptor[] getPropertyDescriptors() { + PropertyDescriptor back[] = new PropertyDescriptor[15]; + try { + back[0] = new PropertyDescriptor("content", JHSecondaryViewer.class); + back[1] = new PropertyDescriptor("id", JHSecondaryViewer.class); + back[2] = new PropertyDescriptor("viewerName", JHSecondaryViewer.class); + back[3] = new PropertyDescriptor("viewerActivator", JHSecondaryViewer.class); + back[4] = new PropertyDescriptor("viewerStyle", JHSecondaryViewer.class); + back[5] = new PropertyDescriptor("viewerLocation", JHSecondaryViewer.class); + back[6] = new PropertyDescriptor("viewerSize", JHSecondaryViewer.class); + back[7] = new PropertyDescriptor("iconByName", JHSecondaryViewer.class); + back[8] = new PropertyDescriptor("iconByID", JHSecondaryViewer.class); + back[9] = new PropertyDescriptor("text", JHSecondaryViewer.class); + back[10] = new PropertyDescriptor("textFontFamily", JHSecondaryViewer.class); + back[11] = new PropertyDescriptor("textFontSize", JHSecondaryViewer.class); + back[12] = new PropertyDescriptor("textFontWeight", JHSecondaryViewer.class); + back[13] = new PropertyDescriptor("textFontStyle", JHSecondaryViewer.class); + back[14] = new PropertyDescriptor("textColor", JHSecondaryViewer.class); + return back; + } catch (Exception ex) { + return null; + } + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..788eb1df0dce6129e44d66cc39bf0db76c396fa2 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java @@ -0,0 +1,1058 @@ +/* + * @(#)JHelpPrintHandler.java 1.30 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +import javax.help.*; +import javax.help.event.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.net.URL; +import java.net.MalformedURLException; +import java.util.Vector; +import java.util.WeakHashMap; + +/** + * Print handler for JavaHelp. Because JDK1.1 is not supported since JavaHelp + * version 2.0 this class contains all printing code. + * + * @author Roger D. Brinkley + * @author Stepan Marek + * @version 1.30 10/30/06 + */ +public class JHelpPrintHandler implements ActionListener { + + public static final String PRINT_BUTTON_NAME = "PrintButton"; + public static final String PAGE_SETUP_BUTTON_NAME = "PageSetupButton"; + public static final String PRINT_LATER_BUTTON_NAME = "PrintLaterButton"; + + /** + * Specifies whether action is enabled; the default is true. + */ + private boolean enabled = true; + private PrinterJob printerJob; + private PageFormat pageFormat; + private JHelp help; + private HelpModel helpModel; + // private DefaultListModel listModel = new DefaultListModel(); + private URL documentURL; + private String documentTitle; + + + + public JHelpPrintHandler(JHelp help) { + this.help = help; + } + + private static WeakHashMap handlers; + + public static JHelpPrintHandler getJHelpPrintHandler(JHelp help) { + JHelpPrintHandler handler = null; + if (handlers == null) { + handlers = new WeakHashMap(); + } else { + handler = (JHelpPrintHandler)handlers.get(help); + } + if (handler == null) { + handler = new JHelpPrintHandler(help); + handlers.put(help, handler); + } + return handler; + } + + /** + * If any <code>PropertyChangeListeners</code> have been registered, the + * <code>changeSupport</code> field describes them. + */ + protected SwingPropertyChangeSupport changeSupport; + + /** + * Supports reporting bound property changes. This method can be called + * when a bound property has changed and it will send the appropriate + * <code>PropertyChangeEvent</code> to any registered + * <code>PropertyChangeListeners</code>. + */ + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (changeSupport == null) { + return; + } + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + + /** + * Adds a <code>PropertyChangeListener</code> to the listener list. + * The listener is registered for all properties. + * <p> + * A <code>PropertyChangeEvent</code> will get fired in response to setting + * a bound property, e.g. <code>setFont</code>, <code>setBackground</code>, + * or <code>setForeground</code>. + * Note that if the current component is inheriting its foreground, + * background, or font from its container, then no event will be + * fired in response to a change in the inherited property. + * + * @param listener The <code>PropertyChangeListener</code> to be added + * + * @see Action#addPropertyChangeListener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + if (changeSupport == null) { + changeSupport = new SwingPropertyChangeSupport(this); + } + changeSupport.addPropertyChangeListener(listener); + } + + + /** + * Removes a <code>PropertyChangeListener</code> from the listener list. + * This removes a <code>PropertyChangeListener</code> that was registered + * for all properties. + * + * @param listener the <code>PropertyChangeListener</code> to be removed + * + * @see Action#removePropertyChangeListener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + if (changeSupport == null) { + return; + } + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + * @see Action#isEnabled + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Enables or disables the action. + * + * @param newValue true to enable the action, false to + * disable it + * @see Action#setEnabled + */ + public void setEnabled(boolean newValue) { + boolean oldValue = this.enabled; + this.enabled = newValue; + firePropertyChange("enabled", new Boolean(oldValue), new Boolean(newValue)); + } + + /** + * ActionListener to perform printing. The current implementation of Swing + * requires that this go through an ActionListener as it must be in the + * EventDispatchThread. + */ + public void actionPerformed(ActionEvent e) { + + String name = null; + Object source = e.getSource(); + if (source instanceof MenuComponent) { + name = ((MenuComponent)source).getName(); + } if (source instanceof Component) { + name = ((Component)source).getName(); + } + + if (isEnabled()) { + if (name != null && name.equals(JHelpPrintHandler.PAGE_SETUP_BUTTON_NAME)) { + printSetup(); + } else { + if (getHelp() != null) { + print(getURLs()); + } else if (getHelpModel() != null) { + print(getHelpModel().getCurrentURL()); + } + } + } + } + + + public void printSetup() { + if (isEnabled()) { + new PageSetupThread().start(); + } + } + + public void print(URL url) { + if (isEnabled()) { + new PrintThread(url).start(); + } + } + + public void print(URL[] urls) { + if (isEnabled()) { + new PrintThread(urls).start(); + } + } + + private JHelp getHelp() { + return help; + } + + private URL[] getURLs() { + URL[] urls = null; + if (getHelp() != null) { + TreeItem[] items = getHelp().getSelectedItems(); + if (items != null) { + debug("pages to print: "+items.length); + urls = new URL[items.length]; + for (int i = 0; i < items.length; i++) { + debug(" "+items[i].getName()+": "+items[i].getURL()); + urls[i] = items[i].getURL(); + } + } + } + return urls; + } + + /** Getter for property pageFormat. + * @return Value of property pageFormat. + */ + public PageFormat getPageFormat() { + if ((pageFormat == null) && (getPrinterJob() != null)) { + pageFormat = getPrinterJob().defaultPage(); + } + return pageFormat; + } + + /** + * @deprecated As of JavaHelp version 2.0, + * replaced by <code>getPageFormat()</code>. + */ + public PageFormat getPF() { + return getPageFormat(); + } + + /** Setter for property pageFormat. + * @param pageFormat New value of property pageFormat. + */ + public void setPageFormat(PageFormat pageFormat) { + if (this.pageFormat == pageFormat) return; + PageFormat oldPageFormat = this.pageFormat; + this.pageFormat = pageFormat; + firePropertyChange("pageFormat", oldPageFormat, pageFormat); + } + + /** + * @deprecated As of JDK version 2.0, + * replaced by <code>setPageFormat(pageFormat)</code>. + */ + public void setPF(PageFormat pf) { + setPageFormat(pf); + } + + public PrinterJob getPrinterJob() { + if (printerJob == null) { + try { + printerJob = PrinterJob.getPrinterJob(); + } catch (SecurityException se) { + setEnabled(false); + processException(se); + } + } + return printerJob; + } + + /** + * Sets the PrintHandler to handle pageSetup as a separate action from + * printing. PageSetup is only in 1.2 but we put in the 1.1 code to make + * it easier. On 1.1 this will essential do nothing. On 1.2 this sets up + * the button so we know if we're printing or just doing a page setup. + */ + public void handlePageSetup(Component psComp) { + psComp.setName(JHelpPrintHandler.PAGE_SETUP_BUTTON_NAME); + } + + public void setHelpModel(HelpModel helpModel) { + HelpModel oldModel = this.helpModel; + this.helpModel = helpModel; + firePropertyChange("helpModel", oldModel, helpModel); + } + + /** Getter for property model. + * @return Value of property model. + */ + public HelpModel getHelpModel() { + return helpModel; + } + + /** + * Returns the specified component's toplevel <code>Frame</code> or + * <code>Dialog</code>. + * + * @param comp the <code>Component</code> or <code>MenuComponent</code> to + * check for a <code>Frame</code> or <code>Dialog</code> + * @return the <code>Frame</code> or <code>Dialog</code> that + * contains the <code>Component</code> or <code>MenuComponent</code>, + * or <code>null</code>, if there is not a valid + * <code>Frame</code> or <code>Dialog</code> parent + */ + static Window getWindowForObject(Object comp) { + if (comp == null || comp instanceof Frame || comp instanceof Dialog) { + return (Window)comp; + } + Object parent = null; + if (comp instanceof MenuComponent) { + parent = ((MenuComponent)comp).getParent(); + } else if (comp instanceof Component) { + parent = ((Component)comp).getParent(); + } + return getWindowForObject(parent); + } + + static Insets getInsetsForContainer(Container c) { + Insets i = c.getInsets(); + for (c = c.getParent(); c != null; c = c.getParent()) { + Insets ii = c.getInsets(); + i.bottom += ii.bottom; + i.left += ii.left; + i.right += ii.right; + i.top += ii.top; + if (c instanceof Window) { + break; + } + } + return i; + } + + /** + * Create a handler for the given type from HelpSet or from the + * default registry of editor kits. + * + * @param type the content type + * @return the editor kit, or null if there is nothing + * registered for the given type. + */ + EditorKit createEditorKitForContentType(String type) { + + HelpModel model = null; + JHelp help = getHelp(); + + if (help != null) { + model = help.getModel(); + } else { + model = getHelpModel(); + } + + if (model == null) { + return null; + } + + HelpSet hs = model.getHelpSet(); + if (hs == null) { + return null; + } + + // try to dynamically load the support + String classname = (String) hs.getKeyData(HelpSet.kitTypeRegistry, type); + // I don't know of a class for this type + if (classname == null) { + return null; + } + + ClassLoader loader = (ClassLoader) hs.getKeyData(HelpSet.kitLoaderRegistry, type); + if (loader == null) { + loader = hs.getLoader(); + } + + EditorKit k = null; + try { + Class c; + if (loader != null) { + c = loader.loadClass(classname); + } else { + c = Class.forName(classname); + } + k = (EditorKit) c.newInstance(); + // kitRegistry.put(type, k); + } catch (Throwable e) { + System.err.println(e); + k = null; + } + + // create a copy of the prototype or null if there + // is no prototype. + if (k != null) { + return (EditorKit) k.clone(); + } + return k; + } + + class PageSetupThread extends Thread { + + PrinterJob job; + + PageSetupThread() { + setDaemon(true); + } + + public void run() { + PrinterJob job = getPrinterJob(); + if (job != null) { + synchronized (job) { + try { + setPageFormat(job.pageDialog(getPageFormat())); + } catch (Exception e) { + processException(e); + } + } + } + } + } + + class PrintThread extends Thread { + + private URL[] urls; + private int index = 0; + + PrintThread(URL url) { + this(new URL[] {url}); + } + + PrintThread(URL[] urls) { + this.urls = urls; + setDaemon(true); + } + + public void run() { + PrinterJob job = getPrinterJob(); + if (job != null) { + synchronized (job) { + JEditorPane editor = new JHEditorPane(); + + JFrame frame = new JHFrame(); + frame.setContentPane(editor); + + try { + job.setPageable(new JHPageable(editor, urls, + (PageFormat)JHelpPrintHandler.this.getPageFormat().clone())); + } catch (Exception e) { + processException(e); + } + + if (job.printDialog()) { + try { + job.print(); + } catch (Exception e) { + processException(e); + } + } + frame.dispose(); + } + } + } + } + + class PageTransform extends AffineTransform { + + /** Holds value of property height. */ + private double height; + + /** Getter for property height. + * @return Value of property height. + */ + public double getHeight() { + return height; + } + + /** Setter for property height. + * @param height New value of property height. + * + * @throws PropertyVetoException + */ + public void setHeight(double height) { + this.height = height; + } + + } + + class JHPrintable implements Printable, PropertyChangeListener { + + JEditorPane editor; + URL url; + PageFormat pf; + int firstPage; + boolean scaleToFit; + Vector transforms; + + public JHPrintable(JEditorPane editor, URL url, PageFormat pf, int firstPage, boolean scaleToFit) { + this.editor = editor; + this.url = url; + this.pf = pf; + this.firstPage = firstPage; + this.scaleToFit = scaleToFit; + } + + private synchronized void loadPage() { + debug("JHPrintable.loadPage(): "+url); + URL currentURL = editor.getPage(); + if (currentURL != null && currentURL.equals(url)) { + // If the editors have the same url return otherwise + // you'll just wait forever since a set page with + // the same URL doesn't send a property change notice + return; + } + editor.addPropertyChangeListener("page", this); + try { + editor.setPage(url); + wait(); + } catch (Exception e) { + processException(e); + } + editor.removePropertyChangeListener("page", this); + } + + public int getNumberOfPages() { + if (transforms == null) { + loadPage(); + transforms = createTransforms(); + } + return transforms.size(); + } + + public synchronized void propertyChange(PropertyChangeEvent evt) { + notifyAll(); + } + + public Vector createTransforms() { + + int page = 0; + Vector transforms = new Vector(); + + double curHeight = 0.0, height = 0.0; + double yval = 0.0; + double scale = 1.0; + + Component root = SwingUtilities.windowForComponent(editor); + if (root == null) { + root = editor; + } + + root.addNotify(); + + View rootview = editor.getUI().getRootView(editor); + Rectangle viewRec = JHelpPrintHandler.getViewRec(rootview, (float)pf.getImageableWidth(), (float)pf.getImageableHeight()); + debug("viewRec=" + viewRec); + + Insets i = JHelpPrintHandler.getInsetsForContainer(editor); + root.setBounds(0, 0, viewRec.width + i.left + i.right, viewRec.height + i.top + i.bottom); + root.setVisible(true); + + // Do any scaling that is necessary + if (scaleToFit) { + if (viewRec.getWidth() > pf.getImageableWidth()) { + scale = pf.getImageableWidth() / viewRec.getWidth(); + } + debug("scale=" + scale + + " ImageableWidth=" + pf.getImageableWidth() + + " width=" + viewRec.getWidth()); + } + + // Determine the print Rectangle size + Rectangle2D.Double printRec = + new Rectangle2D.Double(0.0, 0.0, pf.getImageableWidth(), pf.getImageableHeight() / scale); + debug("printRec=" + printRec); + Position.Bias[] bias = new Position.Bias[1]; + + while (true) { + debug("preparing page=" + page + " curHeight=" + curHeight); + + double maxHeight = printRec.getHeight() + curHeight; + + // Find the point that corresponds to the end of the current + // page that we are printing. + int point = rootview.viewToModel(0, (float) maxHeight, viewRec, bias); + debug("point=" + point); + try { + // Get the Rectangle around that point + Shape s = rootview.modelToView(point, viewRec, bias[0]); + Rectangle2D pointRec = s.getBounds2D(); + debug("pointRec=" + pointRec); + + // Create a proper offset on the printed page + yval = curHeight; + + // Create the proper height to print. + // Be carefull not chop anything off. + // All print the full view if it will fit, otherwise + // print the point above. + height = pointRec.getY() - 1.0; + debug("Starting height=" + height); + if (maxHeight >= pointRec.getY() + pointRec.getHeight()) { + height = pointRec.getY() + pointRec.getHeight() - 1.0; + debug("Adjusted height=" + height); + } + + // Make sure there isn't any other object that would be slightly + // lower. + double baseY = pointRec.getY(); + double baseHeight = pointRec.getY() + pointRec.getHeight() - 1.0; + // move over 20 pixels. We'd user pointRec.getWidth() but it's 0 + double nextX = pointRec.getX() + 20.0; + double testY = 0.0, testHeight = 0.0; + Rectangle2D testRec = pointRec; + while (true) { + // don't look past max width. + if (nextX > (pf.getImageableWidth() * scale)) { + break; + } + int point2 = + rootview.viewToModel((float) nextX, + (float) maxHeight, + viewRec, bias); + Shape s2 = rootview.modelToView(point2, viewRec, bias[0]); + Rectangle2D pointRec2 = s2.getBounds2D(); + // if this is same Rectangle then try 20 pixels over + if (testRec.equals(pointRec2) || pointRec2.getX() < nextX) { + nextX += 20.0; + continue; + } + debug("pointRec2=" + pointRec2); + testY = pointRec2.getY(); + testHeight = pointRec2.getY() + pointRec2.getHeight() - 1.0; + + // if test height is less than base y then don't bother + // testing. Just pass through + if (testHeight > baseY) { + + // if the testHeight is greater than the baseHeight + // we might want to use the test height values + if (testHeight > baseHeight) { + // if the test height is less than the max height + // use that height instead + if (testHeight < maxHeight) { + height = testHeight; + baseHeight = testHeight; + if (testY < baseY) { + baseY = testY; + } + debug("Adjust height to testheight " + height); + } else { + // the test height is greater than the max + // height. + if (testY > baseHeight) { + // test Y is greater than the base height + // move the base height to just above + // test Y + height = testY - 1.0; + baseHeight = testHeight; + baseY = testY; + debug("new base component " + height); + } else { + // test Y is less than base height. + // if the test Y is less than the base y + // use it + if (testY < baseY) { + height = testY - 1.0; + baseY = testY; + baseHeight = testHeight; + debug("test height > maxheight. Adjust height testY - 1 " + height); + } else { + // otherwise use the base y + height = baseY - 1.0; + baseHeight = testHeight; + debug("test height > maxheight. Adjust height baseY - 1 " + height); + } + } + } + } else { + // the base height is greater than the test + // height use the base height values + if (baseHeight < maxHeight) { + // this value has already been set to this + // height but I'm doing this for consistency + // The baseHeight is valid so use it. + height = baseHeight; + if (testY < baseY) { + baseY = testY; + } + debug("baseHeight ok " + height); + } else { + // the base height is greater than the max height + // if the base Y is less than the test y use it + if (baseY <= testY) { + height = baseY - 1.0; + debug("baseHeight too long - height ok" + height); + } else { + // otherwise use the test Y + height = testY - 1.0; + baseY = testY; + debug("baseHeight too long - use testY - 1 " + height); + } + } + } + } + testRec = pointRec2; + // move over 20 pixels. pointRec.width is 0 + nextX = testRec.getX() + 20.0; + } + + // Create new transform for each page to be printed + PageTransform t = new PageTransform(); + + // Set the translation values so we print the + // correct part of editor componenet. + t.translate(pf.getImageableX(), pf.getImageableY()); + debug("t.translate="+t); + t.translate(- (double) i.left * scale, - ((double) i.top + yval) * scale); + debug("t.translate="+t); + + // Scaling will advirsely affect the yval. Multiple yval to scale + // to correct the future scaling. + t.scale(scale, scale); + debug("t.scale="+t); + + // Store height + t.setHeight(height + (double) i.top); + + // bug fix for JDK1.4 which caused repeated pages to be printed + if (curHeight == height + 1.0) { + break; + } + + // Strore transform + transforms.add(page, t); + + // Set the current Height for the next page. + curHeight = height + 1.0; + debug("Setting curHeight=" + curHeight); + + // increment the page counter + page++; + + // If the current Height is greater than the viewRec height + // then we are done. + debug ("curHeight="+curHeight+" viewRec.getHeight()="+ viewRec.getHeight()); + if (curHeight >= viewRec.getHeight()) { + break; + } + + } catch (BadLocationException ble) { + break; + } + } + return transforms; + } + + private void printHeader(Graphics2D g2d, int pi) { + + g2d.setClip(new Rectangle2D.Double(0.0, 0.0, pf.getWidth(), pf.getHeight())); + g2d.setFont(new Font("Serif", Font.ITALIC, 10)); + + String s = (String)editor.getDocument().getProperty(Document.TitleProperty) + + " " + (pi + 1) + "/" +transforms.size(); + + Rectangle2D rec = g2d.getFontMetrics().getStringBounds(s, g2d); + g2d.drawString(s, (float)(pf.getWidth() - rec.getX() - rec.getWidth() - 36.0), (float)36.0); + g2d.setClip(new Rectangle2D.Double( + pf.getImageableX(), + pf.getImageableY(), + pf.getImageableWidth(), + pf.getImageableHeight() + )); + } + + public int print(Graphics pg, PageFormat pageFormat, int pi) { + + debug("Printing document page=" + pi); + pi -= firstPage; + debug("Printing page=" + pi); + + if (pi >= getNumberOfPages()) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2d = (Graphics2D) pg; + + printHeader(g2d, pi); + + // Apply transformation for current page + g2d.transform((AffineTransform) transforms.get(pi)); + debug("Graphics tansform=" + g2d.getTransform()); + debug("Graphics clip=" + g2d.getClip()); + + // Get the Rectangle of the adjusted print graphics. This helps in + // printing the correct height. Indirectly gotten through + // the shape to perserve the coordinates (prevent rounding) + Rectangle2D g2dRec = g2d.getClip().getBounds2D(); + + // See if any adjustments to the height are necessary + // If so create a new Rectangle and apply it to the g2d + double height = ((PageTransform)transforms.get(pi)).getHeight(); + double adjheight = g2dRec.getY() + g2dRec.getHeight() - 1.0 - height; + if (adjheight > 0.0) { + debug("Graphics adjusted height=" + adjheight); + g2d.clip(new Rectangle2D.Double( + g2dRec.getX(), + g2dRec.getY(), + g2dRec.getWidth(), + g2dRec.getHeight() - adjheight + )); + g2dRec = g2d.getClip().getBounds2D(); + debug("Graphics tansform=" + g2d.getTransform()); + debug("Graphics clip=" + g2d.getClip()); + } + + // Just print editor + if (g2dRec.getY() < height) { + // using editor.printAll(g2d) here should be better for jdk1.3 + // but there are bugs in jdk1.2 + editor.paint(g2d); + } else { + return Printable.NO_SUCH_PAGE; + } + + return Printable.PAGE_EXISTS; + } + } + + class EmptyPrintable implements Printable { + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { + return Printable.NO_SUCH_PAGE; + } + } + + public class JHPageable implements Pageable { + + private JEditorPane editor; + private URL[] urls; + private PageFormat pf; + private int lastIndex = -1; + private int lastPage = 0; + private Printable printable = new EmptyPrintable(); + private int numPages = 0; + + public JHPageable(JEditorPane editor, URL[] urls, PageFormat pf) { + this.editor = editor; + this.urls = urls; + this.pf = pf; + } + + /** + * Returns the <code>PageFormat</code> of the page specified by + * <code>pageIndex</code>. + * @param pageIndex the zero based index of the page whose + * <code>PageFormat</code> is being requested + * @return the <code>PageFormat</code> describing the size and + * orientation. + * @exception <code>IndexOutOfBoundsException</code> + * the <code>Pageable</code> does not contain the requested + * page. + */ + public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException { + return pf; + } + + /** + * Returns the number of pages in the set. + * To enable advanced printing features, + * it is recommended that <code>Pageable</code> + * implementations return the true number of pages + * rather than the + * UNKNOWN_NUMBER_OF_PAGES constant. + * @return the number of pages in this <code>Pageable</code>. + */ + public int getNumberOfPages() { + if (numPages != 0) { + // only do this once ??? + return numPages; + } + if (urls != null) { + for (int i=0; i < urls.length; i++) { + JHPrintable printable = new JHPrintable(editor, urls[i], + pf, 0, true); + numPages += printable.getNumberOfPages(); + } + } + return numPages; + } + + /** + * Returns the <code>Printable</code> instance responsible for + * rendering the page specified by <code>pageIndex</code>. + * @param pageIndex the zero based index of the page whose + * <code>Printable</code> is being requested + * @return the <code>Printable</code> that renders the page. + * @exception <code>IndexOutOfBoundsException</code> + * the <code>Pageable</code> does not contain the requested + * page. + */ + public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException { + + debug("JHPageable.getPrintable("+pageIndex+"): lastIndex="+lastIndex+", lastPage"+lastPage); + + if (pageIndex < 0) { + throw new IndexOutOfBoundsException(pageIndex + " < 0"); + } + + if (urls != null) { + while ((pageIndex >= lastPage) && ((lastIndex + 1) < urls.length)) { + if (urls[++lastIndex] != null) { + printable = new JHPrintable(editor, urls[lastIndex], + pf, lastPage, true); + lastPage += ((JHPrintable)printable).getNumberOfPages(); + } else { + printable = new EmptyPrintable(); + } + } + } + + if (pageIndex > lastPage) { + throw new IndexOutOfBoundsException(pageIndex + " > " + lastPage); + } + + return printable; + } + + } + + /** + * Setups size of editor and return its optimal width. + */ + static protected Rectangle getViewRec(View rootview, float width, float height) { + Rectangle r = new Rectangle(); + rootview.setSize(width, height); + r.width = (int) Math.max((long)Math.ceil(rootview.getMinimumSpan(View.X_AXIS)), (long) width); + r.height = (int) Math.min((long)Math.ceil(rootview.getPreferredSpan(View.Y_AXIS)), (long) Integer.MAX_VALUE); + rootview.setSize(r.width, r.height); + if (rootview.getView(0) instanceof BoxView) { + BoxView box = (BoxView) rootview.getView(0); + r.width = box.getWidth(); + r.height = box.getHeight(); + } else { + r.height = (int) Math.min((long)Math.ceil(rootview.getPreferredSpan(View.Y_AXIS)), (long) Integer.MAX_VALUE); + } + return r; + } + + /** + * Private implementation of invisible Frame which is used + * as a parent for JHEditorPane. This Frame has no peer so it cannot + * be displayed on screen and visibility is just predended. + */ + class JHFrame extends JFrame { + + public void addNotify() { + getRootPane().addNotify(); + } + + public void validate() { + validateTree(); + } + + // The editor has to have a graphics set for it. + // This is bug in jdk1.2.2. The Graphics is not necessery + // for jdk1.1 and jdk1.3. + public Graphics getGraphics() { + return JHelpPrintHandler.this.getHelp().getGraphics(); + } + + } + + /** + * Implementation of JEditorPane which support EditorKit created from + * current HelpSet. Listeners are not necessery for printing and they are + * skiped as workaround of bug in Component.addNotify() method in jdk1.1. + */ + class JHEditorPane extends JEditorPane { + + public JHEditorPane() { + setDoubleBuffered(false); + setEditable(false); + + // turn of DnD support + // necessary for jdk1.4 + setDropTarget(null); + } + + public EditorKit getEditorKitForContentType(String type) { + EditorKit k = JHelpPrintHandler.this.createEditorKitForContentType(type); + if (k == null) { + k = super.getEditorKitForContentType(type); + } + return k; + } + + // This methods enable to keep references to listeners null. It is + // workaround for bug in Component.addNotify() method in jdk1.1 + // and jdk1.2. Moreover it can save resources. + public void addMouseListener(MouseListener l) { + } + + public void removeMouseListener(MouseListener l) { + } + + public void addMouseMotionListener(MouseMotionListener l) { + } + + public void removeMouseMotionListener(MouseMotionListener l) { + } + + public void addFocusListener(FocusListener l) { + } + + public void removeFocusListener(FocusListener l) { + } + + public void addKeyListener(KeyListener l) { + } + + public void removeKeyListener(KeyListener l) { + } + + } + + protected static void processException(Exception e) { + if (debug) { + e.printStackTrace(); + } else { + System.err.println(e); + } + } + + /** + * For printf debugging. + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.err.println("JHelpPrintHandler: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java new file mode 100644 index 0000000000000000000000000000000000000000..fa205a141768b47bec9fa1c1ff4e9581b8de04a4 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java @@ -0,0 +1,68 @@ +/* + * @(#)JHelpPrintHandler1_2.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +import javax.help.JHelp; +import javax.help.HelpModel; +import java.awt.Component; + +/** + * Print handler for JavaHelp. Handles all printer requests for printing + * in JDK1.2 and above. Because JDK1.1 is not supported since JavaHelp version 2.0 + * all code was moved into JHelpPrintHandler. This class is preserved for backward + * compatibility. + * + * @author Roger D. Brinkley + * @author Stepan Marek + * @version 1.12 10/30/06 + */ + +public class JHelpPrintHandler1_2 extends JHelpPrintHandler { + + public JHelpPrintHandler1_2(JHelp help) { + super(help); + } + + /* + public JHelpPrintHandler1_2(HelpModel model) { + super(model); + } + */ + + /** + * JHelpPrintHandler constructor. Creates a JHelpPrintHandler with a null + * Document. + * @param model The HelpModel to derive URLs from. + * @param comp The component from which the Frame can be optained for 1.1 printing + */ + /* + public JHelpPrintHandler1_2(HelpModel model, Component comp) { + super (model, comp); + } + */ +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java new file mode 100644 index 0000000000000000000000000000000000000000..e7146cf23ffb58d40c5235863aa81d95919685e0 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java @@ -0,0 +1,60 @@ +/* + * @(#)LangElement.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) LangElement.java 1.5 - last change made 10/30/06 + */ +package com.sun.java.help.impl; + +import java.util.Locale; + +/** + * LangElement is a simple little internal class to keep + * track of tags and the langs + * + * @author Roger D. Brinkley + * @version 1.5 10/30/06 + */ + +public class LangElement { + + Tag tag; + Locale locale; + + public LangElement (Tag tag, Locale locale) { + this.tag = tag; + this.locale = locale; + } + + public Tag getTag() { + return tag; + } + + public Locale getLocale() { + return locale; + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java new file mode 100644 index 0000000000000000000000000000000000000000..5866b614debc225d68871d28aac3076feee1c850 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java @@ -0,0 +1,171 @@ +/* + * @(#)Parser.java 1.13 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) Parser.java 1.13 - last change made 10/30/06 + */ + +package com.sun.java.help.impl; + +/** + * This class parses an HTML or XML document. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.13 10/30/06 + */ +import java.util.Vector; +import java.io.Reader; +import java.io.InputStream; +import java.util.EventListener; + +public class Parser extends DocumentParser { + protected ParserListener listenerList; + + public Parser(Reader src) { + super(src); + } + + public Parser(InputStream in) { + super(in); + } + + protected void tag(String name, TagProperties atts, boolean endTag, boolean emptyTag) { + Tag tag = new Tag(name, atts, endTag, emptyTag); + listenerList.tagFound(new ParserEvent(this, tag)); + } + + protected void pi(String target, String data) { + listenerList.piFound(new ParserEvent(this, target, data)); + } + + protected void doctype(String root, String publicId, String systemId) { + listenerList.doctypeFound(new ParserEvent(this, root, publicId, systemId)); + } + + + protected void flush(char [] buf, int offset, int length) { + if (length == 1 &&((buf[offset] == DocPConst.NEWLINE) || + (buf[offset] == DocPConst.RETURN))) { + return; + } + String text = new String(buf, offset, length); + listenerList.textFound(new ParserEvent(this, text)); + } + + protected void comment(String s) { + listenerList.commentFound(new ParserEvent(this, s)); + } + + protected void errorString(String s) { + listenerList.errorFound(new ParserEvent(this, s)); + } + + // Not need for our version of Parser + protected String documentAttribute(String name) {return null;} + + public void addParserListener(ParserListener l) { + listenerList = ParserMulticaster.add(listenerList, l); + } + + public void removeParserListener(ParserListener l) { + listenerList = ParserMulticaster.remove(listenerList, l); + } + + static protected class ParserMulticaster implements ParserListener { + protected final EventListener a, b; + + protected ParserMulticaster(EventListener newA, EventListener newB) { + this.a = newA; this.b = newB; + } + + protected EventListener remove(EventListener oldl) { + if (oldl == a) return b; + if (oldl == b) return a; + EventListener a2 = removeInternal(a, oldl); + EventListener b2 = removeInternal(b, oldl); + if (a2 == a && b2 == b) { + return this; // it's not here + } + return addInternal(a2, b2); + } + + protected static EventListener addInternal(EventListener a, EventListener b) { + if (a == null) return b; + if (b == null) return a; + return new ParserMulticaster(a, b); + } + + protected static EventListener removeInternal(EventListener l, EventListener oldl) { + if (l == oldl || l == null) { + return null; + } else if (l instanceof ParserMulticaster) { + return ((ParserMulticaster)l).remove(oldl); + } else { + return l; // it's not here + } + } + + public void tagFound(ParserEvent e) { + ((ParserListener)a).tagFound(e); + ((ParserListener)b).tagFound(e); + } + + public void piFound(ParserEvent e) { + ((ParserListener)a).piFound(e); + ((ParserListener)b).piFound(e); + } + + public void doctypeFound(ParserEvent e) { + ((ParserListener)a).doctypeFound(e); + ((ParserListener)b).doctypeFound(e); + } + + public void textFound(ParserEvent e) { + ((ParserListener)a).textFound(e); + ((ParserListener)b).textFound(e); + } + + public void commentFound(ParserEvent e) { + ((ParserListener)a).commentFound(e); + ((ParserListener)b).commentFound(e); + } + + public void errorFound(ParserEvent e) { + ((ParserListener)a).errorFound(e); + ((ParserListener)b).errorFound(e); + } + + public static ParserListener add(ParserListener a, ParserListener b) { + return (ParserListener)addInternal(a, b); + } + + public static ParserListener remove(ParserListener l, ParserListener oldl) { + return (ParserListener)removeInternal(l, oldl); + } + } // End of class Parser.ParserMulticaster +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..7319fd119afe38e19201fd4e528650d967844762 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java @@ -0,0 +1,152 @@ +/* + * @(#)ParserEvent.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +/** + * An event in the HTML/XML Parser + * + * @author Roger D. Brinkley + * @version 1.12 10/30/06 + */ + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; + +public class ParserEvent extends java.util.EventObject { + private Tag tag; + private String text; + private String target; + private String data; + private String root; + private String publicId; + private String systemId; + + /** + * Represents a parsed Tag in the Parser + * @see java.help.basic.Parser + * + * @param source The Parser this came from + * @param tag The parsed Tag. + */ + public ParserEvent(Object source, Tag tag) { + super (source); + this.tag = tag; + } + + /** + * Represents a parsed continous block of text, a comment, or an error. + * @see java.help.basic.Parser + * + * @param source The Parser this came from + * @param String The text, comment, or error + */ + public ParserEvent(Object source, String text) { + super (source); + this.text = text; + } + + /** + * Represents a PI (processing instruction) + * @see java.help.basic.Parser + * + * @param source The Parser this came from + * @param target The PI target + * @param data The rest of the PI + */ + public ParserEvent(Object source, String target, String data) { + super (source); + this.target = target; + this.data = data; + } + + /** + * Represents a DOCTYPE + * @see java.help.basic.Parser + * + * @param source The Parser this came from + * @param root The root + * @param publicId The publicID (may be null) + * @param systemID The systemID (may be null) + */ + public ParserEvent(Object source, String root, String publicId, String systemId) { + super (source); + this.root = root; + this.publicId = publicId; + this.systemId = systemId; + } + + /** + * @return the Tag + */ + public Tag getTag() { + return tag; + } + + /** + * @return the text + */ + public String getText() { + return text; + } + + /** + * @return the target + */ + public String getTarget() { + return target; + } + + /** + * @return the data + */ + public String getData() { + return data; + } + + /** + * @return the root + */ + public String getRoot() { + return root; + } + + /** + * @return the publicId + */ + public String getPublicId() { + return publicId; + } + + /** + * @return the systemId + */ + public String getSystemId() { + return systemId; + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java new file mode 100644 index 0000000000000000000000000000000000000000..1acec3081cacb71eb03501107fc4bf3828b53e0e --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java @@ -0,0 +1,81 @@ +/* + * @(#)ParserListener.java 1.11 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +/** + * ParserListener defines the interface for an object that listens to + * parsing events in a Parser. + * + * @author Roger D. Brinkley + * @version 1.11 10/30/06 + */ + +public interface ParserListener extends java.util.EventListener { + /** + * This tells the listener that a Tag was parsed + * + * @param e The event + */ + public void tagFound(ParserEvent e); + + /** + * This tells the listener that a PI was parsed + * + * @param e The event + */ + public void piFound(ParserEvent e); + + /** + * This tells the listener that a DOCTYPE was parsed + * + * @param e The event + */ + public void doctypeFound(ParserEvent e); + + /** + * This tells the listener that a continous block of text was parsed + * + * @param e The event + */ + public void textFound(ParserEvent e); + + /** + * This tells the listener that a comment was parsed + * + * @param e The event + */ + public void commentFound(ParserEvent e); + + /** + * This tells the listener that a error was parsed + * + * @param e The event + */ + public void errorFound(ParserEvent e); + +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java new file mode 100644 index 0000000000000000000000000000000000000000..1b924f077b341d654d16f241c2a4892bfbcf14c7 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java @@ -0,0 +1,172 @@ +/* + * @(#)SwingWorker.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) SwingWorker.java 1.3 - last change made 10/30/06 + */ + +package com.sun.java.help.impl; + +import javax.swing.SwingUtilities; + +/** + * This is the 3rd version of SwingWorker (also known as + * SwingWorker 3), an abstract class that you subclass to + * perform GUI-related work in a dedicated thread. For + * instructions on and examples of using this class, see: + * + * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html + * + * Note that the API changed slightly in the 3rd version: + * You must now invoke start() on the SwingWorker after + * creating it. + */ + +public abstract class SwingWorker { + private Object value; // see getValue(), setValue() + + /** + * Class to maintain reference to current worker thread + * under separate synchronization control. + */ + private static class ThreadVar { + private Thread thread; + ThreadVar(Thread t) { thread = t; } + synchronized Thread get() { return thread; } + synchronized void clear() { thread = null; } + } + + private ThreadVar threadVar; + + /** + * Get the value produced by the worker thread, or null if it + * hasn't been constructed yet. + */ + protected synchronized Object getValue() { + return value; + } + + /** + * Set the value produced by worker thread + */ + private synchronized void setValue(Object x) { + value = x; + } + + /** + * Compute the value to be returned by the <code>get</code> method. + */ + public abstract Object construct(); + + /** + * Called on the event dispatching thread (not on the worker thread) + * after the <code>construct</code> method has returned. + */ + public void finished() { + } + + /** + * A new method that interrupts the worker thread. Call this method + * to force the worker to stop what it's doing. + */ + public void interrupt() { + Thread t = threadVar.get(); + if (t != null) { + t.interrupt(); + } + threadVar.clear(); + } + + /** + * Return the value created by the <code>construct</code> method. + * Returns null if either the constructing thread or the current + * thread was interrupted before a value was produced. + * + * @return the value created by the <code>construct</code> method + */ + public Object get() { + while (true) { + Thread t = threadVar.get(); + if (t == null) { + return getValue(); + } + try { + t.join(); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); // propagate + return null; + } + } + } + + + /** + * Start a thread that will call the <code>construct</code> method + * and then exit. + */ + public SwingWorker() { + final Runnable doFinished = new Runnable() { + public void run() { finished(); } + }; + + Runnable doConstruct = new Runnable() { + public void run() { + try { + setValue(construct()); + } + finally { + threadVar.clear(); + } + + SwingUtilities.invokeLater(doFinished); + } + }; + + Thread t = new Thread(doConstruct); + threadVar = new ThreadVar(t); + } + + /** + * Start the worker thread. + */ + public void start() { + start(Thread.NORM_PRIORITY); + } + + /** + * Start the worker thread. + */ + public void start(int priority) { + Thread t = threadVar.get(); + if (t != null) { + if (priority < Thread.MAX_PRIORITY && priority > Thread.MIN_PRIORITY) { + t.setPriority(priority); + } + t.start(); + } + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java new file mode 100644 index 0000000000000000000000000000000000000000..6cfa48369587f7df0b10df40703b97d6c2562c9e --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java @@ -0,0 +1,77 @@ +/* + * @(#)Tag.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) Tag.java 1.8 - last change made 10/30/06 + */ + +package com.sun.java.help.impl; + +/** + * This class contains a reference to a tag in a parsed document, the type of + * tag, and the tag's attributes. + * + * @author Roger D. Brinkley + * @version 1.8 10/30/06 + * + * @see Parser + * @see HTMLParser + */ + + +public class Tag { + + /** The name of the tag */ + public String name; + + /** The type of tag, false if an opening tag or true if a closing tag. */ + public boolean isEnd; + + /** The type of tag, true if an empty tag. */ + public boolean isEmpty; + + /** The tag attributes, in identifier, value pairs. */ + public TagProperties atts; + + + /** + * Sets the tag, position, and type. + * @param tag the tag descriptor + * @param pos the position in the text + * @param isEnd true if a </tag> or <tag/> tag + * @param isEmpty true if a <tag/> tag + * @see Tag + **/ + + public Tag(String name, TagProperties atts, boolean isEnd, boolean isEmpty) { + this.name = name; + this.atts = atts; + this.isEnd = isEnd; + this.isEmpty = isEmpty; + } + +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..1f79a4c69b5cff803f0324967b861dc8b0cb22e3 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java @@ -0,0 +1,293 @@ +/* + * @(#)TagProperties.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) TagProperties.java 1.8 - last change made 10/30/06 + */ +package com.sun.java.help.impl; + +/** + * The <code>TagProperties</code> class represents a persistent set of + * properties. Each key and its corresponding value in + * the property list is a string. + * + * @see java.help.Tag + */ + +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.Hashtable; + +public class TagProperties implements Cloneable { + + protected Hashtable hashtable; + protected int initialSize; + +static int count1 = 0, count2 = 0; + + /** + * Creates an empty property list with no default values. + * + * @since JDK1.0 + */ + public TagProperties() { + this(7); // Prime number + } + + public TagProperties(int initialSize) { + this.initialSize = initialSize; + } + + + /** + * Searches for the property with the specified key in this property list. + * The method returns + * <code>null</code> if the property is not found. + * + * @param key the property key. + * @return the value in this property list with the specified key value. + * @since JDK1.0 + */ + public String getProperty(String key) { + return (String)get(key); + } + + /** + * Searches for the property with the specified key in this property list. + * The method returns the + * default value argument if the property is not found. + * + * @param key the hashtable key. + * @param defaultValue a default value. + * + * @return the value in this property list with the specified key value. + * @since JDK1.0 + */ + public String getProperty(String key, String defaultValue) { + String val = getProperty(key); + return (val == null) ? defaultValue : val; + } + + /** + * Returns an enumeration of all the keys in this property list + * + * @return an enumeration of all the keys in this property list + * @see java.util.Enumeration + * @since JDK1.0 + */ + public Enumeration propertyNames() { + Hashtable h = new Hashtable(11); + enumerate(h); + return h.keys(); + } + + /** + * Prints this property list out to the specified output stream. + * This method is useful for debugging. + * + * @param out an output stream. + * @since JDK1.0 + */ + public void list(PrintStream out) { + out.println("-- listing properties --"); + Hashtable h = new Hashtable(11); + enumerate(h); + for (Enumeration e = h.keys() ; e.hasMoreElements() ;) { + String key = (String)e.nextElement(); + String val = (String)h.get(key); + if (val.length() > 40) { + val = val.substring(0, 37) + "..."; + } + out.println(key + "=" + val); + } + } + + /** + * Prints this property list out to the specified output stream. + * This method is useful for debugging. + * + * @param out an output stream. + * @since JDK1.1 + */ + /* + * Rather than use an anonymous inner class to share common code, this + * method is duplicated in order to ensure that a non-1.1 compiler can + * compile this file. + */ + public void list(PrintWriter out) { + out.println("-- listing properties --"); + Hashtable h = new Hashtable(11); + enumerate(h); + for (Enumeration e = h.keys() ; e.hasMoreElements() ;) { + String key = (String)e.nextElement(); + String val = (String)h.get(key); + if (val.length() > 40) { + val = val.substring(0, 37) + "..."; + } + out.println(key + "=" + val); + } + } + + /** + * Enumerates all key/value pairs in the specified hastable. + * @param h the hashtable + */ + private synchronized void enumerate(Hashtable h) { + for (Enumeration e = keys() ; e.hasMoreElements() ;) { + String key = (String)e.nextElement(); + h.put(key, get(key)); + } + } + + /***** Implementation of a deferred hashtable *****/ + + public int size() { + if (hashtable != null) { + return hashtable.size(); + } else { + return 0; + } + } + + public boolean isEmpty() { + if (hashtable != null) { + return hashtable.isEmpty(); + } else { + return true; + } + } + + public synchronized Enumeration keys() { + if (hashtable != null) { + return hashtable.keys(); + } else { + return new EmptyEnumerator(); + } + } + + public synchronized Enumeration elements() { + if (hashtable != null) { + return hashtable.elements(); + } else { + return new EmptyEnumerator(); + } + } + + public synchronized boolean contains(Object value) { + if (hashtable != null) { + return hashtable.contains(value); + } else { + return false; + } + } + + public synchronized boolean containsKey(Object key) { + if (hashtable != null) { + return hashtable.containsKey(key); + } else { + return false; + } + } + + public synchronized Object get(Object key) { + if (hashtable != null) { + return hashtable.get(key); + } else { + return null; + } + } + + public synchronized Object put(Object key, Object value) { + if (hashtable == null) { + hashtable = new Hashtable(initialSize); + } + return hashtable.put(key, value); + } + + public synchronized Object remove(Object key) { + if (hashtable != null) { + return hashtable.remove(key); + } else { + return null; + } + } + + public synchronized void clear() { + if (hashtable != null) { + hashtable.clear(); + } + } + + protected void setHashtable(Hashtable t) { + hashtable = t; + } + + /** + * HERE - we probably should use plain Hashtable instead of TagProperties + */ + public Hashtable getHashtable() { + return hashtable; + } + + public synchronized Object clone() { + try { + TagProperties tp = (TagProperties)super.clone(); + if (hashtable != null) { + tp.setHashtable((Hashtable)hashtable.clone()); + } + return tp; + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + public synchronized String toString() { + if (hashtable != null) { + return hashtable.toString(); + } else { + return "{ }"; + } + } + + class EmptyEnumerator implements Enumeration { + + public boolean hasMoreElements() { + return false; + } + + public Object nextElement() { + throw new java.util.NoSuchElementException("EmptyEnumerator"); + } + } + +} + diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..6f9204a4c0e72bdf8442316de198e12eae2a2eae --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java @@ -0,0 +1,53 @@ +/* + * @(#)ViewAwareComponent.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.help.impl; + +import javax.swing.text.*; + +/** + * Interface that a Component should support if it wants to play in the View + * hierachy. + * + * WARNING!! This is an experimental feature of the JavaHelp reference + * implemenation and may change in future versions of the implementation. + * + * @author Eduardo Pelegri-Llopart + * @version 1.5 10/30/06 */ + + +public interface ViewAwareComponent { + /** + * Set the View that corresponds to this object + * This gives access to a wealth of information. + */ + public void setViewData(View v); + + /** + * May need something to react to changes (in my view?) + */ +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java new file mode 100644 index 0000000000000000000000000000000000000000..23a75168e26b4a7840ed897ba911fedcd47a7322 --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java @@ -0,0 +1,803 @@ +/* + * @(#)XmlReader.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) XmlReader.java 1.5 - last change made 10/30/06 + */ + +package com.sun.java.help.impl; + +import java.io.*; +import java.net.URLConnection; + +/** + * This handles several XML-related tasks that normal java.io Readers + * don't support, inluding use of IETF standard encoding names and + * automatic detection of most XML encodings. The former is needed + * for interoperability; the latter is needed to conform with the XML + * spec. This class also optimizes reading some common encodings by + * providing low-overhead unsynchronized Reader support. + * + * <P> Note that the autodetection facility should be used only on + * data streams which have an unknown character encoding. For example, + * it should never be used on MIME text/xml entities. + * + * <P> Note that XML processors are only required to support UTF-8 and + * UTF-16 character encodings. Autodetection permits the underlying Java + * implementation to provide support for many other encodings, such as + * ISO-8859-5, Shift_JIS, EUC-JP, and ISO-2022-JP. + * + * @author David Brownell + * @author Roger D. Brinkley + * @version 1.24 + */ + +final public class XmlReader extends Reader +{ + private boolean closed; + private InputStreamReader in; + + // + // This class either handles reading itself, in common encodings + // (US-ASCII, ISO-Latin-1, UTF-8) or delegates to another Reader. + // + // Autodetection requires reading/buffering part of the XML declaration, + // then potentially switching _after entire characters are read_ to + // delegate further operations to such a Reader. The reader will get + // no header (e.g. no UTF-16 Byte Order Mark). This can work since, + // XML declarations contain only ASCII characters, which are a subset + // of many encodings (Shift_JIS, ISO-8859-*, EUC-*, ISO-2022-*, more). + // + // It's got do this efficiently: character I/O is solidly on the + // critical path. Synchronization isn't needed, and buffering must + // as always be done only with care. (So keep buffer length over + // 2 Kbytes to avoid excess buffering, since most URL handlers stuff + // a BufferedInputStream between here and the real data source. That + // class tries to be smart enough not to try buffering if you ask for + // more data than it could buffer for you.) + // + private InputStream raw; + private byte buffer []; + private boolean isASCII, isLatin1; + private int offset, length; + + // 2nd half of UTF-8 surrogate pair + private char nextChar; + + private int switchover; + private String encodingAssigned; + + /** + * Constructs the reader from a URLConnection. Uses the encoding + * specified in the HTTP header or autodetects + * the encoding to use according to the heuristic specified + * in the XML 1.0 recommendation. + * + * @param uc the URLConnection from which the reader is constructed + * @exception IOException on error + * @exception UnsupportedEncodingException when the input stream + * is not in an encoding which is supported; this is a fatal XML + * error. + */ + public static Reader createReader (URLConnection uc) throws IOException + { + String encoding = getEncodingFromContentType(uc.getContentType()); + if (encoding == null) { + return createReader (uc.getInputStream()); + } + return createReader (uc.getInputStream(), encoding); + } + + /** + * Gets the encoding from the content type string. + * If there is a charset definition specified as a parameter + * of the content type specification, it will be used when + * loading input streams using the associated XmlReader. + * For example if the type is specified as + * <code>text/xml; charset=EUC-JP</code> the Reader will + * use the <code>EUC-JP</code> charset for translating + * to unicode. + * + * @param type the non-null mime type for the content editing + * support. + */ + private static String getEncodingFromContentType(String type) { + + debug ("type=" + type); + // The type could have optional info is part of it, + // for example some charset info. We need to strip that + // of and save it. + if (type == null) { + return null; + } + int parm = type.indexOf(";"); + if (parm > -1) { + // Save the paramList. + String paramList = type.substring(parm); + // update the content type string. + type = type.substring(0, parm).trim(); + if (type.compareTo("text/xml") == 0) { + // Set the charset name from the paramlist + return getCharsetFromContentTypeParameters(paramList); + } + } + return null; + } + + /** + * This method get's the charset information specified as part + * of the content type in the http header information. + */ + private static String getCharsetFromContentTypeParameters(String paramlist) { + String charset = null; + try { + // paramlist is handed to us with a leading ';', strip it. + int semi = paramlist.indexOf(';'); + if (semi > -1 && semi < paramlist.length()-1) { + paramlist = paramlist.substring(semi + 1); + } + + if (paramlist.length() > 0) { + // parse the paramlist into attr-value pairs & get the + // charset pair's value + HeaderParser hdrParser = new HeaderParser(paramlist); + charset = hdrParser.findValue("charset"); + return charset; + } + } + catch (IndexOutOfBoundsException e) { + // malformed parameter list, use charset we have + } + catch (NullPointerException e) { + // malformed parameter list, use charset we have + } + catch (Exception e) { + // malformed parameter list, use charset we have; but complain + System.err.println("Indexer.getCharsetFromContentTypeParameters failed on: " + paramlist); + e.printStackTrace(); + } + return charset; + } + + /** + * Constructs the reader from an input stream, autodetecting + * the encoding to use according to the heuristic specified + * in the XML 1.0 recommendation. + * + * @param in the input stream from which the reader is constructed + * @exception IOException on error + * @exception UnsupportedEncodingException when the input stream + * is not in an encoding which is supported; this is a fatal XML + * error. + */ + public static Reader createReader (InputStream in) throws IOException + { + return new XmlReader (in); + } + + /** + * Creates a reader supporting the given encoding, mapping + * from standard encoding names to ones that understood by + * Java where necessary. + * + * @param in the input stream from which the reader is constructed + * @param encoding the IETF standard name of the encoding to use; + * if null, autodetection is used. + * @exception IOException on error + * @exception UnsupportedEncodingException when the input stream + * is not in an encoding which is supported; this is a fatal XML + * error. + */ + public static Reader createReader (InputStream in, String encoding) + throws IOException + { + if (encoding == null) + return new XmlReader (in); + + // UTF-16 == ISO-10646-UCS-2 plus surrogates. + // The sun.io "Unicode" encoders/decoders don't check + // for correctly paired surrogates, so they accept UTF-16. + + if ("UTF-16".equalsIgnoreCase (encoding) + || "ISO-106460-UCS-2".equalsIgnoreCase (encoding)) + encoding = "Unicode"; + else if ("UTF-8".equalsIgnoreCase (encoding)) + return new XmlReader (in, "UTF-8"); + else if ("EUC-JP".equalsIgnoreCase (encoding)) + encoding = "EUCJIS"; // works on JDK 1.1 and 1.2 + else if (isAsciiName (encoding)) + return new XmlReader (in, "US-ASCII"); + else if (isLatinName (encoding)) + return new XmlReader (in, "ISO-8859-1"); + + // XXX we should provide provide better "unsupported encoding" + // diagnostics than this produces... + return new InputStreamReader (in, encoding); + } + + private XmlReader (InputStream in, String encoding) + throws IOException + { + buffer = new byte [8 * 1024]; + length = 0; + raw = in; + if ("US-ASCII".equals (encoding)) + setASCII (); + else if ("ISO-8859-1".equals (encoding)) + setLatin1 (); + else if (!"UTF-8".equals (encoding)) + throw new UnsupportedEncodingException (encoding); + else + setUTF8 (); + } + + private static boolean isAsciiName (String encoding) + { + return "US-ASCII".equalsIgnoreCase (encoding) + || "ASCII".equalsIgnoreCase (encoding); + } + + private static boolean isLatinName (String encoding) + { + return "ISO-8859-1".equalsIgnoreCase (encoding) + || "Latin1".equalsIgnoreCase (encoding) + || "8859_1".equalsIgnoreCase (encoding); + } + + private void setASCII () + { + encodingAssigned = "US-ASCII"; + isASCII = true; + isLatin1 = false; + offset = 0; + } + + private void setLatin1 () + { + encodingAssigned = "ISO-8859-1"; + isASCII = false; + isLatin1 = true; + offset = 0; + } + + private void setUTF8 () + { + encodingAssigned = "UTF-8"; + isASCII = false; + isLatin1 = false; + offset = 0; + } + + /** Returns the (non)standard name of the encoding in use */ + public String getEncoding () + { + return encodingAssigned; + } + + private XmlReader (InputStream in) throws IOException + { + int c; + + // + // Set up buffering ... we buffer at least the XML text + // declaration (if it's there), and for some encodings we + // manage bulk character I/O. We can reset within this + // buffer so long as we've not assigned the encoding. + // + raw = in; + switchover = -1; + buffer = new byte [8 * 1024]; + offset = length = 0; + isLatin1 = true; + + // + // See if we can figure out the character encoding used + // in this file by peeking at the first few bytes. If not, + // we may be able to look at the whole XML declaration. + // + switch ((c = read ())) { + case 0: + // 00 3c 00 3f == illegal UTF-16 big-endian + if ((c = read ()) == 0x3c + && (c = read ()) == 0x00 + && (c = read ()) == 0x3f) { + setSwitchover ("UnicodeBig"); + // no BOM to ignore + return; + } + + // 00 00 00 3c == UCS-4 big endian + // 00 00 3c 00 == UCS-4 unusual "2143" order + // 00 3c 00 00 == UCS-4 unusual "3412" order + // ... or something else! note that only some parts + // of UCS-4 work with UNICODE based systems. + throw new UnsupportedEncodingException ("UCS-4 (?)"); + + case '<': // 0x3c: the most common cases! + switch ((c = read ())) { + // First character is '<'; could be XML without + // an XML directive such as "<hello>", "<!-- ...", + // and so on. Default intelligently; the byte we + // just read could be _part_ of a UTF-8 character! + default: + break; + + // 3c 00 3f 00 == illegal UTF-16 little endian + // 3c 00 00 00 == UCS-4 little endian + case 0x00: + if (read () == 0x3f && read () == 0x00) { + setSwitchover ("UnicodeLittle"); + // no BOM to ignore + return; + } + throw new UnsupportedEncodingException ("UCS-4"); + + // 3c 3f 78 6d == ASCII and supersets '<?xm' + case '?': + if (read () != 'x' || read () != 'm' + || read () != 'l' || read () != ' ') + break; + // + // One of several encodings could be used: + // Shift-JIS, ASCII, UTF-8, ISO-8859-*, etc + // + guessEncoding (); + return; + } + break; + + // UTF-16 big-endian + case 0xfe: + if ((c = read ()) != 0xff) + break; + setSwitchover ("UnicodeBig"); + offset = 2; // skip BOM + return; + + // UTF-16 little-endian + case 0xff: + if ((c = read ()) != 0xfe) + break; + setSwitchover ("UnicodeLittle"); + offset = 2; // skip BOM + return; + + // EOF + case -1: + return; + + // default ... no XML declaration + default: + break; + } + + // + // If all else fails, assume XML without a declaration, and + // using UTF-8 encoding. We must be prepared to re-interpret + // bytes we've already read as parts of UTF-8 characters, so + // we can't use the "switchover" technique (which works only + // "between" characters). + // + setUTF8 (); + } + + // When the buffered input is done, switch to a reader + // that can decode data in that encoding. Only call this + // routine after entire characters have been scanned. + private void setSwitchover (String encoding) throws IOException + { + switchover = offset; + encodingAssigned = encoding; + offset = 0; + } + + // we've consumed our buffer, now switch over to a reader + // which will decode the rest of the (non-ASCII) input + private void doSwitchover () throws IOException + { + if (offset != switchover) + throw new InternalError (); + in = new InputStreamReader (raw, encodingAssigned); + buffer = null; + switchover = -1; + } + + + /* + * Used for ASCII supersets ... including the default UTF-8 encoding. + */ + private void guessEncoding () throws IOException + { + // + // We know that "<?xml " has been seen; so we'll skip any + // S? version="..." [or single quotes] + // bit and get the + // S? encoding="..." [or single quotes] + // parts. We place an arbitrary limit on the amount of text we + // expect to find in the XML declarations; excessive whitespace + // will cause this to guess "UTF-8". + // + int c; + StringBuffer buf = new StringBuffer (); + StringBuffer keyBuf = null; + String key = null; + boolean sawEq = false; + char quoteChar = 0; + boolean sawQuestion = false; + + XmlDecl: + for (int i = 0; i < 100; ++i) { + if ((c = read ()) == -1) { + setASCII (); + return; + } + + // ignore whitespace before/between "key = 'value'" + if (Character.isWhitespace ((char) c)) + continue; + + // terminate the loop ASAP + if (c == '?') + sawQuestion = true; + else if (sawQuestion) { + if (c == '>') + break; + sawQuestion = false; + } + + // did we get the "key =" bit yet? + if (key == null || !sawEq) { + if (keyBuf == null) { + if (Character.isWhitespace ((char) c)) + continue; + keyBuf = buf; + buf.setLength (0); + buf.append ((char)c); + sawEq = false; + } else if (Character.isWhitespace ((char) c)) { + key = keyBuf.toString (); + } else if (c == '=') { + if (key == null) + key = keyBuf.toString (); + sawEq = true; + keyBuf = null; + quoteChar = 0; + } else + keyBuf.append ((char)c); + continue; + } + + // space before quoted value + if (Character.isWhitespace ((char) c)) + continue; + if (c == '"' || c == '\'') { + if (quoteChar == 0) { + quoteChar = (char) c; + buf.setLength (0); + continue; + } else if (c == quoteChar) { + if ("encoding".equals (key)) { + String encoding = buf.toString (); + + // [81] Encname ::= [A-Za-z] ([A-Za-z0-9._]|'-')* + for (i = 0; i < encoding.length(); i++) { + c = encoding.charAt (i); + if ((c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')) + continue; + if (i > 0 && (c == '-' + || (c >= '0' && c <= '9') + || c == '.' || c == '_')) + continue; + // map errors to UTF-8 default + break XmlDecl; + } + + // we handle ASCII directly + if (isAsciiName (encoding)) { + setASCII (); + return; + } + + // ditto ISO 8859/1 + if (isLatinName (encoding)) { + setLatin1 (); + return; + } + + // and UTF-8 + if ("UTF-8".equalsIgnoreCase (encoding) + || "UTF8".equalsIgnoreCase (encoding) + ) + break XmlDecl; + + // JDK uses nonstandard names internally + if ("EUC-JP".equalsIgnoreCase (encoding)) + encoding = "EUCJIS"; + + // other encodings ... use a reader. + setSwitchover (encoding); + return; + } else { + key = null; + continue; + } + } + } + buf.append ((char) c); + } + + setUTF8 (); + } + + /* + * Converts a UTF-8 character from the input buffer, optionally + * restricting to the US-ASCII subset of UTF-8. + */ + private char utf8char () throws IOException + { + char retval; + int character; + + // return second half of a surrogate pair + if (nextChar != 0) { + retval = nextChar; + nextChar = 0; + return retval; + } + + // + // Excerpted from RFC 2279: + // + // UCS-4 range (hex.) UTF-8 octet sequence (binary) + // 0000 0000-0000 007F 0xxxxxxx + // 0000 0080-0000 07FF 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + // 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx + // + // The last two encodings (5 and 6 bytes per char) aren't allowed + // in XML documents since the characters are out of range. + // + retval = (char) buffer [offset]; + if ((retval & 0x80) == 0x00) { // 1 byte + offset++; + return retval; + } + if (isASCII) + throw new CharConversionException ("Not US-ASCII: 0x" + + Integer.toHexString (retval & 0xff)); + + // + // Multibyte sequences -- check offsets optimistically, + // ditto the "10xx xxxx" format for non-initial bytes + // + int off = offset; + + try { + if ((buffer [off] & 0x0E0) == 0x0C0) { // 2 bytes + character = (buffer [off++] & 0x1f) << 6; + character += buffer [off++] & 0x3f; + retval = (char) character; + character = 0; + } else if ((buffer [off] & 0x0F0) == 0x0E0) { // 3 bytes + character = (buffer [off++] & 0x0f) << 12; + character += (buffer [off++] & 0x3f) << 6; + character += buffer [off++] & 0x3f; + retval = (char) character; + character = 0; + } else if ((buffer [off] & 0x0f8) == 0x0F0) { // 4 bytes + character = (buffer [off++] & 0x07) << 18; + character += (buffer [off++] & 0x3f) << 12; + character += (buffer [off++] & 0x3f) << 6; + character += buffer [off++] & 0x3f; + // Convert UCS-4 char to a Unicode surrogate pair + character -= 0x10000; + retval = (char) (0xD800 + (character >> 10)); + character = 0xDC00 + (character & 0x03ff); + } else + // XXX actually a WF error ... + throw new CharConversionException ("Illegal XML character" + + " 0x" + Integer.toHexString (buffer [offset] & 0xff) + ); + + } catch (ArrayIndexOutOfBoundsException e) { + // that is, off > length && length >= buffer.length + retval = (char) 0; + character = 0; + } + + // + // if the buffer held only a partial character, compact it + // and try to read the rest of the character. worst case + // involves three single-byte reads. + // + if (off > length) { + System.arraycopy (buffer, offset, buffer, 0, length - offset); + length -= offset; + offset = 0; + off = raw.read (buffer, length, buffer.length - length); + if (off < 0) + throw new CharConversionException ("Partial UTF-8 char"); + length += off; + return utf8char (); + } + + // + // check the format of the non-initial bytes, and return + // + for (offset++; offset < off; offset++) + if ((buffer [offset] & 0xC0) != 0x80) + throw new CharConversionException ("Malformed UTF-8 char"); + nextChar = (char) character; + return retval; + } + + /** + * Reads the number of characters read into the buffer, or -1 on EOF. + */ + public int read (char buf [], int off, int len) throws IOException + { + int i; + + if (closed) + return -1; + if (switchover > 0 && offset == switchover) + doSwitchover (); + if (in != null) + return in.read (buf, off, len); + + if (offset >= length) { + offset = 0; + length = raw.read (buffer, 0, buffer.length); + } + if (length <= 0) + return -1; + if (encodingAssigned == null || isLatin1) + for (i = 0; i < len && offset < length; i++) + buf [off++] = (char) (buffer [offset++] & 0xff); + else + for (i = 0; i < len && offset < length; i++) + buf [off++] = utf8char (); + return i; + } + + /** + * Reads a single character. + */ + public int read () throws IOException + { + if (closed) + return -1; + if (switchover > 0 && offset == switchover) + doSwitchover (); + if (in != null) + return in.read (); + + if (offset >= length) { + if (encodingAssigned == null) { + // minimize readahead we might regret... + if (length == buffer.length) + throw new InternalError ("too much peekahead"); + int len = raw.read (buffer, offset, 1); + if (len <= 0) + return -1; + length += len; + } else { + offset = 0; + length = raw.read (buffer, 0, buffer.length); + if (length <= 0) + return -1; + } + } + + if (isLatin1 || encodingAssigned == null) + return buffer [offset++] & 0x0ff; + else + return utf8char (); + } + + /** + * Returns true iff the reader supports mark/reset. + */ + public boolean markSupported () + { + return in != null && in.markSupported (); + } + + /** + * Sets a mark allowing a limited number of characters to + * be "peeked", by reading and then resetting. + * @param value how many characters may be "peeked". + */ + public void mark (int value) throws IOException + { + if (in != null) + in.mark (value); + } + + /** + * Resets the current position to the last marked position. + */ + public void reset () throws IOException + { + if (in != null) + in.reset (); + } + + /** + * Skips a specified number of characters. + */ + public long skip (long value) throws IOException + { + if (value < 0) + return 0; + if (in != null) + return in.skip (value); + long avail = length - offset; + if (avail >= value) { + offset += (int) value; + return value; + } + offset += avail; + return avail + raw.skip (value - avail); + } + + /** + * Returns true iff input characters are known to be ready. + */ + public boolean ready () throws IOException + { + if (in != null) + return in.ready (); + return (length > offset) || raw.available () != 0; + } + + /** + * Closes the reader. + */ + public void close () throws IOException + { + if (closed) + return; + if (in != null) + in.close (); + else + raw.close (); + closed = true; + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("XmlReader: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html new file mode 100644 index 0000000000000000000000000000000000000000..42320a02191dd6efa178e9b8ceb2e0c849de84ab --- /dev/null +++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.1 10/15/98 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Implementation classes for JavaHelp. +This classes are private and are not intented to be used by programmers +and can change without any notice. + +<p> +<em>Note:</em>We have not yet finalized the location for these classes. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see +<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A> + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java b/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java new file mode 100644 index 0000000000000000000000000000000000000000..18d9e30a824f010b146e157f3a35c05444e1a265 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java @@ -0,0 +1,148 @@ +/* + * @(#)AbstractHelpAction.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Hashtable; + +/** + * + * @author Stepan Marek + * @version 1.2 10/30/06 + */ +public abstract class AbstractHelpAction implements HelpAction { + + AbstractHelpAction(Object control, String name) { + this.control = control; + putValue("name", name); + } + + /** Holds value of property enabled. */ + private boolean enabled = true; + + /** Holds value of property control. */ + private Object control; + + private Hashtable table; + + /** Utility field used by bound properties. */ + private PropertyChangeSupport propertyChangeSupport;; + + /** Add a PropertyChangeListener to the listener list. + * @param l The listener to add. + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener l) { + if (propertyChangeSupport == null) { + propertyChangeSupport = new PropertyChangeSupport(this); + } + propertyChangeSupport.addPropertyChangeListener(l); + } + + /** Removes a PropertyChangeListener from the listener list. + * @param l The listener to remove. + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener l) { + if (propertyChangeSupport == null) { + propertyChangeSupport = new PropertyChangeSupport(this); + } + propertyChangeSupport.removePropertyChangeListener(l); + } + + /** + * Supports reporting bound property changes. This method can be called + * when a bound property has changed and it will send the appropriate + * <code>PropertyChangeEvent</code> to any registered + * <code>PropertyChangeListeners</code>. + */ + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (propertyChangeSupport == null) { + return; + } + propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** Getter for property enabled. + * @return Value of property enabled. + */ + public boolean isEnabled() { + return enabled; + } + + /** Setter for property enabled. + * @param enabled New value of property enabled. + */ + public void setEnabled(boolean enabled) { + boolean oldEnabled = this.enabled; + this.enabled = enabled; + firePropertyChange("enabled", new Boolean(oldEnabled), new Boolean(enabled)); + } + + /** Getter for property control. + * @return Value of property control. + */ + public Object getControl() { + return control; + } + + /** + * Gets the <code>Object</code> associated with the specified key. + * + * @param key a string containing the specified <code>key</code> + * @return the binding <code>Object</code> stored with this key; if there + * are no keys, it will return <code>null</code> + * @see Action#getValue + */ + public Object getValue(String key) { + if (table == null) { + return null; + } + return table.get(key); + } + + /** + * Sets the <code>Value</code> associated with the specified key. + * + * @param key the <code>String</code> that identifies the stored object + * @param newValue the <code>Object</code> to store using this key + * @see Action#putValue + */ + public void putValue(String key, Object newValue) { + if (table == null) { + table = new Hashtable(); + } + Object oldValue; + if (newValue == null) { + oldValue = table.remove(key); + } else { + oldValue = table.put(key, newValue); + } + firePropertyChange(key, oldValue, newValue); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java b/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java new file mode 100644 index 0000000000000000000000000000000000000000..032d859b6a08559ae28b77e779ab2ee9c98c0237 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java @@ -0,0 +1,116 @@ +/* + * @(#)AppendMerge.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.*; +import java.util.*; +import java.text.*; + +/** + * Append merge type + * + * @author Richard Gregor + * @version 1.4 10/30/06 + */ +public class AppendMerge extends Merge{ + + /** + * Constructs AppendMerge + * + * @param master The master NavigatorView + * @param slave The slave NavigatorView + */ + public AppendMerge(NavigatorView master, NavigatorView slave){ + super(master,slave); + + } + + /** + * Processes append merge + * + * @param node The master node + * @return Merged master node + */ + public TreeNode processMerge(TreeNode node){ + debug("start merge"); + + mergeNodes(node, slaveTopNode); + return node; + } + + + /** + * Merge Nodes. Merge two nodes according to the Append merging rules + * + * @param masterNode The master node to merge with + * @param slaveNode The node to merge into the master + */ + public static void mergeNodes(TreeNode master, TreeNode slave) { + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master; + DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave; + debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode) + + " slave=" + MergeHelpUtilities.getNodeName(slaveNode)); + while (slaveNode.getChildCount() > 0) { + DefaultMutableTreeNode slaveNodeChild = + (DefaultMutableTreeNode)slaveNode.getFirstChild(); + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.AppendMerge", + slaveNodeChild); + } + } + + /** + * Merge Node Children. Merge the children of a node according to the + * Append merging. + * + * @param node The parent node from which the children are merged + */ + public static void mergeNodeChildren(TreeNode node) { + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node; + debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode)); + + // The rules are there are no rules. Nothing else needs to be done + // except for merging through the children + for (int i=0; i < masterNode.getChildCount(); i++) { + DefaultMutableTreeNode child = + (DefaultMutableTreeNode)masterNode.getChildAt(i); + if (!child.isLeaf()) { + MergeHelpUtilities.mergeNodeChildren("javax.help.AppendMerge", + child); + } + } + } + + private static boolean debug = false; + private static void debug(String msg){ + if (debug) { + System.out.println("AppendMerge :"+msg); + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/BackAction.java b/jhMaster/JavaHelp/src/new/javax/help/BackAction.java new file mode 100644 index 0000000000000000000000000000000000000000..63c79465ebb52c1cafde8ba2d4052da5f4bd4ad5 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/BackAction.java @@ -0,0 +1,188 @@ +/* + * @(#)BackAction.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.*; +import java.awt.event.*; +import javax.help.*; +import javax.help.event.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Stack; +import javax.swing.*; + +/** + * + * @author Stepan Marek + * @version 1.4 10/30/06 + */ +public class BackAction extends AbstractHelpAction implements MouseListener, HelpHistoryModelListener { + + private static final String NAME = "BackAction"; + + private static final int DELAY = 500; + private Timer timer; + private HelpHistoryModel historyModel; + + /** Creates new BackAction */ + public BackAction(Object control) { + super(control, NAME); + if (control instanceof JHelp) { + JHelp help = (JHelp)control; + historyModel = help.getHistoryModel(); + historyModel.addHelpHistoryModelListener(this); + + setEnabled(historyModel.getIndex() > 0); + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + } + } + + /** + * Invoked when the mouse exits a component. + */ + public void mouseExited(MouseEvent e) { + } + + /** + * Invoked when a mouse button has been released on a component. + */ + public void mouseReleased(MouseEvent e) { + if (timer != null) { + timer.stop(); + } + } + + /** + * Invoked when a mouse button has been pressed on a component. + */ + public void mousePressed(MouseEvent e) { + timer = new Timer(DELAY, new TimeListener(e)); + timer.start(); + } + + /** + * Invoked when the mouse has been clicked on a component. + */ + public void mouseClicked(MouseEvent e) { + if ((historyModel != null) && isEnabled()) { + historyModel.goBack(); + } + } + + /** + * Invoked when the mouse enters a component. + */ + public void mouseEntered(MouseEvent e) { + } + + private class TimeListener implements ActionListener { + + private MouseEvent e; + + public TimeListener(MouseEvent e) { + this.e = e; + } + + public void actionPerformed(ActionEvent evt) { + timer.stop(); + if (BackAction.this.isEnabled()) { + BackAction.this.showBackwardHistory(e); + } + } + } + + private class HistoryActionListener implements ActionListener { + + private int index; + + public HistoryActionListener(int index) { + this.index = index; + } + + public void actionPerformed(java.awt.event.ActionEvent event) { + if(historyModel != null) { + historyModel.setHistoryEntry(index); + } + } + } + + private void showBackwardHistory(MouseEvent e) { + + JPopupMenu backwardMenu = new JPopupMenu("Backward History"); + + if (historyModel == null) { + return; + } + + Stack menuStack = new Stack(); + Locale locale = ((JHelp)getControl()).getModel().getHelpSet().getLocale(); + Enumeration items = historyModel.getBackwardHistory().elements(); + JMenuItem mi = null; + //while(items.hasMoreElements()) { + for (int i = 0; items.hasMoreElements(); i++) { + HelpModelEvent item = (HelpModelEvent)items.nextElement(); + if (item != null) { + String title = item.getHistoryName(); + if (title == null) { + title = HelpUtilities.getString(locale, "history.unknownTitle"); + } + mi = new JMenuItem(title); + //mi.setToolTipText(item.getURL().getPath()); + mi.addActionListener(new HistoryActionListener(i)); + menuStack.push(mi); + } + } + int size = menuStack.size(); + for(int j = 0; j < size; j++) { + backwardMenu.add((JMenuItem)menuStack.pop()); + } + // if(e.isPopupTrigger()) + backwardMenu.show(e.getComponent(),e.getX(),e.getY()); + } + + /** + * Tells the listener that the history has changed. + * Will enable/disable the Action depending on the events previous flag + * + * @param e The HelpHistoryModelEvent + */ + public void historyChanged(HelpHistoryModelEvent e) { + setEnabled(e.isPrevious()); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java b/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java new file mode 100644 index 0000000000000000000000000000000000000000..c9083494904972810de5a760234be9210c770ff6 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java @@ -0,0 +1,79 @@ +/* + * @(#)BadIDException.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +/** + * An ID was attempted to be created with incorrect arguments + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.15 10/30/06 + */ + +public class BadIDException extends IllegalArgumentException { + private Map map; + private String id; + private HelpSet hs; + + /** + * Create the exception. Null values are allowed for each parameter. + * + * @param map The Map in which the ID wasn't found + * @param msg A generic message + * @param id The ID in Map that wasn't found + * @see javax.help.Map + */ + public BadIDException(String msg, Map map, String id, HelpSet hs) { + super(msg); + this.map = map; + this.id = id; + this.hs = hs; + } + + /** + * The HelpSet in which the ID wasn't found + */ + public Map getMap() { + return map; + } + + /** + * The ID that wasn't found in the Map + */ + public String getID() { + return id; + } + + /** + * The HelpSet that wasn't found in the Map + */ + public HelpSet getHelpSet() { + return hs; + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/CSH.java b/jhMaster/JavaHelp/src/new/javax/help/CSH.java new file mode 100644 index 0000000000000000000000000000000000000000..07f50b693765b1dec3e97dd54b74abd717ca1ae7 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/CSH.java @@ -0,0 +1,1729 @@ +/* + * @(#)CSH.java 1.50 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.lang.reflect.*; +import javax.help.Map.ID; +import java.awt.ActiveEvent; +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.MenuComponent; +import java.awt.MenuItem; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRootPane; +import javax.swing.JTable; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.tree.TreePath; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import java.applet.Applet; +import java.net.URL; +import java.util.Stack; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; +import java.util.WeakHashMap; +import java.lang.ref.WeakReference; + +/** + * A convenience class that provides simple + * access to context-senstive help functionality. It creates a default JavaHelp + * viewer as well as ActionListeners for "Help" keys, on-item help, and + * help buttons. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version 1.50 10/30/06 + * + */ +public class CSH { + + static private java.util.Map comps; + static private java.util.Map parents; + static private java.util.Vector managers = new Vector(); + + /** + * Registers the specified manager to maintain dynamic CSH. + * @param m the CSH manager + * @since 2.0 + */ + public static void addManager(Manager m) { + managers.add(m); + } + + /** + * Registers the specified manager to maintain dynamic CSH at the specified + * position in list of managers. + * @param i index at which specified manager is to be inserted. + * @param m the CSH manager + * @exception ArrayIndexOutOfBoundsException index out of range + * (i < 0 || i >= CSH.getManagerCount()). + * @since 2.0 + */ + public static void addManager(int i, Manager m) { + managers.add(i, m); + } + + /** + * Removes the first occurrence of the specified manager in manager list. + * @param m manager to be removed from the list, if present. + * @return <code>true</code> if the list contained the specified manager. + * @since 2.0 + */ + public static boolean removeManager(Manager m) { + return managers.remove(m); + } + + /** + * Removes the manager at the specified position in manager list. + * @param i the index of the manager to removed. + * @exception ArrayIndexOutOfBoundsException index out of range + * (i < 0 || i >= CHS.getManagerCount()). + * @since 2.0 + */ + public static void removeManager(int i) { + managers.remove(i); + } + + /** + * Removes all managers from manager list. + * @since 2.0 + */ + public static void removeAllManagers() { + managers.clear(); + } + + /** + * Returns the manager at the specified position in manager list. + * @param i index of manager to return. + * @exception ArrayIndexOutOfBoundsException index is out of range + * (i < 0 || i >= CSH.getManagerCount()). + * @since 2.0 + */ + public static Manager getManager(int i) { + return (Manager)managers.get(i); + } + + /** + * Returns array of managers registered to maintain dynamic CSH. + * + * @return an array containing the managers. + * @exception ArrayStoreException the runtime type of a manager is not a + * <code>CSH.Manager</code> + * @since 2.0 + */ + public static Manager[] getManagers() { + return (Manager[])managers.toArray(new Manager[0]); + } + + /** + * Returns the number of managers registered to maintain dynamic CSH. + * + * @return the number of managers. + * @since 2.0 + */ + public static int getManagerCount() { + return managers.size(); + } + + /** + * Store HelpID String for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static void _setHelpIDString(Object comp, String helpID) { + + if (comp instanceof JComponent) { + + // For JComponents just use client property + ((JComponent)comp).putClientProperty("HelpID", helpID); + + } else if ((comp instanceof Component) || (comp instanceof MenuItem)) { + // For MenuItems and Components we have an internal Hashtable of + // components and their properties. + + // Initialize as necessary + if (comps == null) { + comps = new WeakHashMap(5); + } + + // See if this component has already set some client properties + // If so update. + // If not then create the client props (as needed) and add to + // the internal Hashtable of components and properties + Hashtable clientProps = (Hashtable) comps.get(comp); + if (clientProps != null) { + if (helpID != null) { + clientProps.put("HelpID", helpID); + } else { + clientProps.remove("HelpID"); + if (clientProps.isEmpty()) { + comps.remove(comp); + } + } + } else { + // Only create properties if there is a valid helpID + if (helpID != null) { + clientProps = new Hashtable(2); + clientProps.put("HelpID", helpID); + comps.put(comp, clientProps); + } + } + + } else { + throw new IllegalArgumentException("Invalid Component"); + } + } + + /** + * Returns the static HelpID for given object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static String _getHelpIDString(Object comp) { + String helpID = null; + if (comp != null) { + if (comp instanceof JComponent) { + helpID = (String) ((JComponent)comp).getClientProperty("HelpID"); + } else if ((comp instanceof Component) || (comp instanceof MenuItem)) { + if (comps != null) { + Hashtable clientProps = (Hashtable)comps.get(comp); + if (clientProps !=null) { + helpID = (String) clientProps.get("HelpID"); + } + } + } else { + throw new IllegalArgumentException("Invalid Component"); + } + } + return helpID; + } + + + /** + * Returns the dynamic HelpID for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static String _getHelpIDString(Object comp, AWTEvent evt) { + String helpID = null; + if (comp != null) { + Manager managers[] = getManagers(); + for (int i = 0; i < managers.length; i++) { + helpID = managers[i].getHelpIDString(comp, evt); + if (helpID != null) { + return helpID; + } + } + } + return null; + } + + /** + * Returns ancestor for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static Object getParent(Object comp) { + + if (comp == null) { + return null; + } + + Object parent = null; + if (comp instanceof MenuComponent) { + parent = ((MenuComponent)comp).getParent(); + } else if (comp instanceof JPopupMenu) { + parent = ((JPopupMenu)comp).getInvoker(); + } else if (comp instanceof Component) { + parent = ((Component)comp).getParent(); + } else { + throw new IllegalArgumentException("Invalid Component"); + } + + if (parent == null && parents != null) { + parent = parents.get(comp); + } + + return parent; + } + + + /** + * Sets the helpID for a Component. + * If helpID is null this method removes the helpID from the component. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + */ + public static void setHelpIDString(Component comp, String helpID) { + _setHelpIDString(comp, helpID); + } + + /** + * Sets the helpID for a MenuItem. + * If helpID is null, this method removes the helpID from the component. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + */ + public static void setHelpIDString(MenuItem comp, String helpID) { + _setHelpIDString(comp, helpID); + } + + /** + * Returns the dynamic HelpID for a object. The method passes the arguments + * into all registered CSH manageres to obtain dynamic HelpID. If no manager + * provides HelpID for the object, the static HelpID is returned or traverse + * to the component's ancestors for help. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + * @since 2.0 + */ + public static String getHelpIDString(Object comp, AWTEvent evt) { + + if (comp == null) { + return null; + } + + String helpID = _getHelpIDString(comp, evt); + + if (helpID == null) { + helpID = _getHelpIDString(comp); + } + + if (helpID == null) { + helpID = getHelpIDString(getParent(comp), evt); + } + + return helpID; + } + + /** + * Returns the static helpID for a component. + * If the component doesn't have associated help, traverse the + * component's ancestors for help.<p> + * + * This method calls <code>CSH.getHelpIDString(comp, null)</code>. + * + * @see #setHelpIDString(Component, String) + */ + public static String getHelpIDString(Component comp) { + return getHelpIDString(comp, null); + + /* + if (comp == null) { + return null; + } + + String helpID = _getHelpIDString(comp); + + // return the helpID if it exists + if (helpID != null) { + return helpID; + } + + // loop through the parents to try to find a valid helpID + Component parent = null; + if (comp instanceof JPopupMenu) { + parent = ((JPopupMenu)comp).getInvoker(); + } else { + parent = comp.getParent(); + } + + if (parent == null && parents != null) { + parent = (Component)parents.get(comp); + } + + if (parent != null) { + return getHelpIDString(parent); + } else { + return null; + } + */ + } + + /** + * Returns the static helpID for a MenuItem. + * If the component doesn't have associated help, traverse the + * component's ancestors for help.<p> + * + * This method calls <code>CSH.getHelpIDString(comp, null)</code>. + * + * @see #setHelpIDString(MenuItem, String) + */ + public static String getHelpIDString(MenuItem comp) { + return getHelpIDString(comp, null); + + /* + String helpID = _getHelpIDString(comp); + // return the helpID if it exists + if (helpID != null) { + return helpID; + } + + // loop through the parents to try to find a valid helpID + MenuContainer parent = comp.getParent(); + if (parent instanceof MenuItem) { + return getHelpIDString((MenuItem)parent); + } else { + return null; + } + */ + } + + + /** + * Store HelpSet for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static void _setHelpSet(Object comp, HelpSet hs) { + + if (comp instanceof JComponent) { + + // For JComponents just use client property + ((JComponent)comp).putClientProperty("HelpSet", hs); + + } else if ((comp instanceof Component) || (comp instanceof MenuItem)) { + + // For MenuItem and Components we have an internal Hashtable of + // components and their properties. + + // Initialize as necessary + if (comps == null) { + comps = new WeakHashMap(5); + } + + // See if this component has already set some client properties + // If so update. + // If not then create the client props (as needed) and add to + // the internal Hashtable of components and properties + Hashtable clientProps = (Hashtable) comps.get(comp); + if (clientProps != null) { + if (hs != null) { + clientProps.put("HelpSet", hs); + } else { + clientProps.remove("HelpSet"); + if (clientProps.isEmpty()) { + comps.remove(comp); + } + } + } else { + // Only create properties if there is a valid helpID + if (hs != null) { + clientProps = new Hashtable(2); + clientProps.put("HelpSet", hs); + comps.put(comp, clientProps); + } + } + } else { + throw new IllegalArgumentException("Invalid Component"); + } + } + + /** + * Returns the static HelpSet for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static HelpSet _getHelpSet(Object comp) { + HelpSet hs = null; + if (comp != null) { + if (comp instanceof JComponent) { + hs = (HelpSet) ((JComponent)comp).getClientProperty("HelpSet"); + } else if ((comp instanceof Component) || (comp instanceof MenuItem)) { + if (comps != null) { + Hashtable clientProps = (Hashtable)comps.get(comp); + if (clientProps !=null) { + hs = (HelpSet) clientProps.get("HelpSet"); + } + } + } else { + throw new IllegalArgumentException("Invalid Component"); + } + } + return hs; + } + + /** + * Returns the dynamic HelpSet for an object. + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + */ + private static HelpSet _getHelpSet(Object comp, AWTEvent evt) { + HelpSet hs = null; + if (comp != null) { + Manager[] managers = getManagers(); + for (int i = 0; i < managers.length; i++) { + hs = managers[i].getHelpSet(comp, evt); + if (hs != null) { + return hs; + } + } + } + return hs; + } + + /** + * Sets the static HelpSet for a Component. + * If HelpSet is null, this method removes the HelpSet + * from the component. + */ + public static void setHelpSet(Component comp, HelpSet hs) { + _setHelpSet(comp, hs); + } + + /** + * Sets the static HelpSet for a MenuItem. + * If HelpSet is null, this method removes the HelpSet + * from the component. + */ + public static void setHelpSet(MenuItem comp, HelpSet hs) { + _setHelpSet(comp, hs); + } + + /** + * Returns the dynamic HelpSet for an object. + * HelpSets are stored in conjunction with helpIDs. It is possible for a + * object to have a helpID without a HelpSet, but a object cannot have a HelpSet + * without a helpID. + * If the component doesn't have an associated helpID, traverse the + * component's ancestors for a helpID. If the componet has a helpID but + * doesn't have a HelpSet, return null. + * + * @exception IllegalArgumentException comp is neither <code>Component</code> nor + * <code>MenuItem</code>. + * + * @see getHelpID + */ + public static HelpSet getHelpSet(Object comp, AWTEvent evt) { + + if (comp == null) { + return null; + } + + String helpID = _getHelpIDString(comp, evt); + if (helpID == null) { + helpID = _getHelpIDString(comp); + } + + if (helpID != null) { + HelpSet hs = _getHelpSet(comp, evt); + if (hs == null) { + hs = _getHelpSet(comp); + } + return hs; + } + + return (getHelpSet(getParent(comp), evt)); + } + + /** + * Returns the static HelpSet for a Component. + * HelpSets are stored in conjunction with helpIDs. It is possible for a + * Component to have + * a helpID without a HelpSet, but a Component cannot have a HelpSet + * without a helpID. + * If the component doesn't have an associated helpID, traverse the + * component's ancestors for a helpID. If the componet has a helpID but + * doesn't have a HelpSet, return null.<p> + * + * This method calls <code>CSH.getHelpSet(comp, null)</code>. + * + * @see getHelpID + * @exception IllegalArgumentException comp is not <code>Component</code + */ + public static HelpSet getHelpSet(Component comp) { + return getHelpSet(comp, null); + + /* + if (comp == null) { + return null; + } + + String helpID = _getHelpIDString(comp); + + if (helpID != null) { + HelpSet hs = _getHelpSet(comp); + if (hs != null) { + return hs; + } + } + + Component parent = null; + if (comp instanceof JPopupMenu) { + parent = ((JPopupMenu)comp).getInvoker(); + } else { + parent = comp.getParent(); + } + + if (parent == null && parents != null) { + parent = (Component)parents.get(comp); + } + + if (parent != null) { + return getHelpSet(parent); + } else { + return null; + } + */ + } + + + /** + * Returns the static HelpSet for a MenuItem. + * HelpSets are stored in conjunction with helpIDs. It is possible for a + * MenuItem to have a helpID without a HelpSet, but a MenuItem + * cannot have a HelpSet without a helpID. + * If the component doesn't have an associated helpID, traverse the + * component's ancestors for a helpID. If the componet has a helpID, but + * doesn't have a HelpSet return null. + * + * This method calls <code>CSH.getHelpIDString(comp, null)</code>. + * @exception IllegalArgumentException comp is not <code>MenuItem</code> + * + * @see getHelpID + */ + public static HelpSet getHelpSet(MenuItem comp) { + return getHelpSet(comp, null); + + /* + if (comp == null) { + return null; + } + + String helpID = _getHelpIDString(comp); + + if (helpID != null) { + HelpSet hs = _getHelpSet(comp); + if (hs != null) { + return hs; + } + } + + MenuContainer parent = comp.getParent(); + if (parent instanceof MenuItem) { + return getHelpSet((MenuItem)parent); + } else { + return null; + } + */ + } + + /** + * Context Sensitive Event Tracking + * + * Creates a new EventDispatchThread from which to dispatch events. This + * method returns when stopModal is invoked. + * + * @return Object The object on which the event occurred. Null if + * cancelled on an undetermined object. + */ + public static Object trackCSEvents() { + MouseEvent e = getMouseEvent(); + if (e != null) { + return getDeepestObjectAt(e.getSource(), e.getX(), e.getY()); + } else { + return null; + } + } + + /* + * Generic displayHelp for all CSH.Display* subclasses + * + * @param hb The HelpBroker to display in. Can be null but hs and + * and presentation must be supplies + * @param hs The HelpSet to display in. Can be null if hb != null + * @param presentation The Presentation class to display the content in + * @param presentationName The named presentation to modify the + * Presentation class with. In some Presenations this is also + * a "named" Presentation. + * @param obj The object for which the help is displayed for + * @param source The Window for focusOwner purposes + * @param event The event that caused this action. + */ + private static void displayHelp(HelpBroker hb, HelpSet hs, + String presentation, + String presentationName, Object obj, + Object source, AWTEvent event) { + + Presentation pres=null; + + if (hb != null) { + // Start by setting the ownerWindow in the HelpBroker + if (hb instanceof DefaultHelpBroker) { + ((DefaultHelpBroker)hb).setActivationObject(source); + } + } else { + // using a Presentation + // Get a Presentation + ClassLoader loader; + Class klass; + Class types[] = { HelpSet.class, + String.class}; + Object args[] = { hs, + presentationName}; + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + Method m = klass.getMethod("getPresentation", types); + pres = (Presentation)m.invoke(null, args); + } catch (Exception ex) { + throw new RuntimeException("error invoking presentation" ); + } + + if (pres == null) { + return; + } + + if (pres instanceof WindowPresentation) { + ((WindowPresentation)pres).setActivationObject(source); + } + if (pres instanceof Popup && obj instanceof Component) { + ((Popup)pres).setInvoker((Component)obj); + } + } + + + // OK now do the CSH stuff + String helpID = null; + HelpSet objHS = null; + helpID = CSH.getHelpIDString(obj, event); + objHS = CSH.getHelpSet(obj, event); + if (objHS == null) { + if (hb != null) { + objHS = hb.getHelpSet(); + } else { + objHS = hs; + } + } + try { + ID id = ID.create(helpID, objHS); + if (id == null) { + id = objHS.getHomeID(); + } + if (hb != null) { + hb.setCurrentID(id); + hb.setDisplayed(true); + } else { + pres.setCurrentID(id); + pres.setDisplayed(true); + } + } catch (Exception e2) { + e2.printStackTrace(); + } + } + + /** + * Context Sensitive Event Tracking + * + * Creates a new EventDispatchThread from which to dispatch events. This + * method returns when stopModal is invoked. + * + * @return MouseEvent The mouse event occurred. Null if + * cancelled on an undetermined object. + */ + private static MouseEvent getMouseEvent() { + // Should the cursor change to a quesiton mark here or + // require the user to change the cursor externally to this method? + // The problem is that each component can have it's own cursor. + // For that reason it might be better to have the user change the + // cusor rather than us. + + // To track context-sensitive events get the event queue and process + // the events the same way EventDispatchThread does. Filter out + // ContextSensitiveEvents SelectObject & Cancel (MouseDown & ???). + // Note: This code only handles mouse events. Accessiblity might + // require additional functionality or event trapping + + // If the eventQueue can't be retrieved, the thread gets interrupted, + // or the thread isn't a instanceof EventDispatchThread then return + // a null as we won't be able to trap events. + try { + if (EventQueue.isDispatchThread()) { + EventQueue eq = null; + + // Find the eventQueue. If we can't get to it then just return + // null since we won't be able to trap any events. + + try { + eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + } catch (Exception ee) { + debug(ee); + } + + // Safe guard + if (eq == null) { + return null; + } + + int eventNumber = -1; + + // Process the events until an object has been selected or + // the context-sensitive search has been canceled. + while (true) { + // This is essentially the body of EventDispatchThread + // modified to trap context-senstive events and act + // appropriately + eventNumber++; + AWTEvent event = eq.getNextEvent(); + Object src = event.getSource(); + // can't call eq.dispatchEvent + // so I pasted it's body here + + // debug(event); + + // Not sure if I should suppress ActiveEvents or not + // Modal dialogs do. For now we will not suppress the + // ActiveEvent events + + if (event instanceof ActiveEvent) { + ((ActiveEvent)event).dispatch(); + continue; + } + + if (src instanceof Component) { + // Trap the context-sensitive events here + if (event instanceof KeyEvent) { + KeyEvent e = (KeyEvent) event; + // if this is the cancel key then exit + // otherwise pass all other keys up + if (e.getKeyCode() == KeyEvent.VK_CANCEL || + e.getKeyCode() == KeyEvent.VK_ESCAPE) { + e.consume(); + return null; + } else { + e.consume(); + // dispatchEvent(event); + } + } else if (event instanceof MouseEvent) { + MouseEvent e = (MouseEvent) event; + int eID = e.getID(); + if ((eID == MouseEvent.MOUSE_CLICKED || + eID == MouseEvent.MOUSE_PRESSED || + eID == MouseEvent.MOUSE_RELEASED) && + SwingUtilities.isLeftMouseButton(e)) { + if (eID == MouseEvent.MOUSE_CLICKED) { + if (eventNumber == 0) { + dispatchEvent(event); + continue; + } + } + e.consume(); + return e; + } else { + e.consume(); + } + } else { + dispatchEvent(event); + } + } else if (src instanceof MenuComponent) { + if (event instanceof InputEvent) { + ((InputEvent)event).consume(); + } + } else { + System.err.println("unable to dispatch event: " + event); + } + } + } + } catch(InterruptedException e) { + debug(e); + } + debug("Fall Through code"); + return null; + } + + private static void dispatchEvent(AWTEvent event) { + Object src = event.getSource(); + if (event instanceof ActiveEvent) { + // This could become the sole method of dispatching in time. + ((ActiveEvent)event).dispatch(); + } else if (src instanceof Component) { + ((Component)src).dispatchEvent(event); + } else if (src instanceof MenuComponent) { + ((MenuComponent)src).dispatchEvent(event); + } else { + System.err.println("unable to dispatch event: " + event); + } + } + + /** + * Gets the higest visible component in a ancestor hierarchy at + * specific x,y coordinates + */ + private static Object getDeepestObjectAt(Object parent, int x, int y) { + if (parent instanceof Container) { + Container cont = (Container)parent; + // use a copy of 1.3 Container.findComponentAt + Component child = findComponentAt(cont, cont.getWidth(), cont.getHeight(), x, y); + if (child != null && child != cont) { + if (child instanceof JRootPane) { + JLayeredPane lp = ((JRootPane)child).getLayeredPane(); + Rectangle b = lp.getBounds(); + child = (Component)getDeepestObjectAt(lp, x - b.x, y - b.y); + } + if (child != null) { + return child; + } + } + } + // if the parent is not a Container then it might be a MenuItem. + // But even if it isn't a MenuItem just return the parent because + // that's a close as we can come. + return parent; + } + + private static Component findComponentAt(Container cont, int width, int height, int x, int y) { + synchronized (cont.getTreeLock()) { + + if (!((x >= 0) && (x < width) && (y >= 0) && (y < height) && cont.isVisible() && cont.isEnabled())) { + return null; + } + + Component[] component = cont.getComponents(); + int ncomponents = cont.getComponentCount(); + + // Two passes: see comment in sun.awt.SunGraphicsCallback + for (int i = 0 ; i < ncomponents ; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp instanceof CellRendererPane) { + Component c = getComponentAt((CellRendererPane)comp, x, y); + if (c != null) { + rect = getRectangleAt((CellRendererPane)comp, x, y); + comp = c; + } + } + + if (comp != null && !comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof Container) { + comp = findComponentAt((Container)comp, rect.width, rect.height, x - rect.x, y - rect.y); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + + for (int i = 0 ; i < ncomponents ; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp instanceof CellRendererPane) { + Component c = getComponentAt((CellRendererPane)comp, x, y); + if (c != null) { + rect = getRectangleAt((CellRendererPane)comp, x, y); + comp = c; + } + } + + if (comp != null && comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof Container) { + comp = findComponentAt((Container)comp, rect.width, rect.height, x - rect.x, y - rect.y); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + return cont; + } + } + + /** + * Returns the Rectangle enclosing component part that the component + * provided by renderer will be draw into. + */ + private static Rectangle getRectangleAt(CellRendererPane cont, int x, int y) { + Rectangle rect = null; + Container c = cont.getParent(); + // I can process only this four components at present time + if (c instanceof JTable) { + rect = getRectangleAt((JTable)c, x, y); + } else if (c instanceof JTableHeader) { + rect = getRectangleAt((JTableHeader)c, x, y); + } else if (c instanceof JTree) { + rect = getRectangleAt((JTree)c, x, y); + } else if (c instanceof JList) { + rect = getRectangleAt((JList)c, x, y); + } + return rect; + } + + /** + * Returns the Component provided by Renderer at x, y coordinates. + */ + private static Component getComponentAt(CellRendererPane cont, int x, int y) { + Component comp = null; + Container c = cont.getParent(); + // I can process only this four components at present time + if (c instanceof JTable) { + comp = getComponentAt((JTable)c, x, y); + } else if (c instanceof JTableHeader) { + comp = getComponentAt((JTableHeader)c, x, y); + } else if (c instanceof JTree) { + comp = getComponentAt((JTree)c, x, y); + } else if (c instanceof JList) { + comp = getComponentAt((JList)c, x, y); + } + + // store reference from comp to CellRendererPane + // It is needed for backtrack searching of HelpSet and HelpID + // in getHelpSet() and getHelpIDString(). + if (comp != null) { + if (parents == null) { + // WeakHashMap of WeakReferences + parents = new WeakHashMap(4) { + public Object put(Object key, Object value) { + return super.put(key, new WeakReference(value)); + } + public Object get(Object key) { + WeakReference wr = (WeakReference)super.get(key); + if (wr != null) { + return wr.get(); + } else { + return null; + } + } + }; + } + parents.put(comp, cont); + } + return comp; + } + + private static Rectangle getRectangleAt(JTableHeader header, int x, int y) { + Rectangle rect = null; + try { + int column = header.columnAtPoint(new Point(x, y)); + rect = header.getHeaderRect(column); + } catch (Exception e) { + } + return rect; + } + + private static Component getComponentAt(JTableHeader header, int x, int y) { + try { + + if (!(header.contains(x, y) && header.isVisible() && header.isEnabled())) { + return null; + } + + TableColumnModel columnModel = header.getColumnModel(); + int columnIndex = columnModel.getColumnIndexAtX(x); + TableColumn column = columnModel.getColumn(columnIndex); + + TableCellRenderer renderer = column.getHeaderRenderer(); + if (renderer == null) { + renderer = header.getDefaultRenderer(); + } + + return renderer.getTableCellRendererComponent( + header.getTable(), column.getHeaderValue(), false, false, -1, columnIndex); + + } catch (Exception e) { + // NullPointerException in case of (header == null) or (columnModel == null) + // ArrayIndexOutOfBoundsException from getColumn(columnIndex) + } + return null; + } + + private static Rectangle getRectangleAt(JTable table, int x, int y) { + Rectangle rect = null; + try { + Point point = new Point(x, y); + int row = table.rowAtPoint(point); + int column = table.columnAtPoint(point); + rect = table.getCellRect(row, column, true); + } catch (Exception e) { + } + return rect; + } + + private static Component getComponentAt(JTable table, int x, int y) { + try { + + if (!(table.contains(x, y) && table.isVisible() && table.isEnabled())) { + return null; + } + + Point point = new Point(x, y); + int row = table.rowAtPoint(point); + int column = table.columnAtPoint(point); + + if (table.isEditing() && table.getEditingRow() == row && table.getEditingColumn() == column) { + // Pointed component is provided by TableCellEditor. Editor + // component is part of component hierarchy so it is checked + // directly in loop in findComponentAt() + // comp = table.getEditorComponent(); + return null; + } + + TableCellRenderer renderer = table.getCellRenderer(row, column); + return table.prepareRenderer(renderer, row, column); + + } catch (Exception e) { + } + return null; + } + + private static Rectangle getRectangleAt(JTree tree, int x, int y) { + Rectangle rect = null; + try { + TreePath path = tree.getPathForLocation(x, y); + rect = tree.getPathBounds(path); + } catch (Exception e) { + } + return rect; + } + + private static Component getComponentAt(JTree tree, int x, int y) { + try { + + TreePath path = tree.getPathForLocation(x, y); + + if (tree.isEditing() && tree.getSelectionPath() == path) { + return null; + } + + int row = tree.getRowForPath(path); + Object value = path.getLastPathComponent(); + boolean isSelected = tree.isRowSelected(row); + boolean isExpanded = tree.isExpanded(path); + boolean isLeaf = tree.getModel().isLeaf(value); + boolean hasFocus= tree.hasFocus() && tree.getLeadSelectionRow() == row; + + return tree.getCellRenderer().getTreeCellRendererComponent( + tree, value, isSelected, isExpanded, isLeaf, row, hasFocus); + + } catch (Exception e) { + return null; + } + } + + private static Rectangle getRectangleAt(JList list, int x, int y) { + Rectangle rect = null; + try { + int index = list.locationToIndex(new Point(x, y)); + rect = list.getCellBounds(index, index); + } catch (Exception e) { + } + return rect; + } + + private static Component getComponentAt(JList list, int x, int y) { + try { + + int index = list.locationToIndex(new Point(x, y)); + Object value = list.getModel().getElementAt(index); + boolean isSelected = list.isSelectedIndex(index); + boolean hasFocus = list.hasFocus() && list.getLeadSelectionIndex() == index; + + return list.getCellRenderer().getListCellRendererComponent( + list, value, index, isSelected, hasFocus); + } catch (Exception e) { + return null; + } + } + + /* + private static Rectangle getRectangleAt(JComboBox combo, int x, int y) { + return combo.getBounds(); + } + + private static Component getComponentAt(JComboBox combo, int x, int y) { + try{ + if (combo.isEditable()) { + return null; + } + + Object value = combo.getSelectedItem(); + boolean hasFocus = combo.hasFocus() && !combo.isPopupVisible(); + + // How to get JList for getListCellRendererComponent()? + // That's the question... + JList list = new JList(); + return combo.getRenderer().getListCellRendererComponent( + list, value, -1, hasFocus, false); + } catch (Exception e) { + return null; + } + } + */ + + /** + * An ActionListener that displays the help of the + * object that currently has focus. This method is used + * to enable HelpKey action listening for components other than + * the RootPane. This listener determines if the + * object with the current focus has a helpID. If it does, the helpID + * is displayed, + * otherwise the helpID on the action's source is displayed (if one exists). + * + * @see HelpBroker.enableHelpKey + */ + public static class DisplayHelpFromFocus implements ActionListener { + + private HelpBroker hb = null; + private HelpSet hs = null; + private String presentation = null; + private String presentationName = null; + + public DisplayHelpFromFocus(HelpBroker hb) { + if (hb == null) { + throw new NullPointerException("hb"); + } + this.hb = hb; + } + + /** + * Create a DisplayHelpFromFocus actionListener for a given + * HelpSet. Display the results in specific Presentation of given + * PresentationName. + * + * @param hs A valid HelpSet. + * @param presention A valid javax.help.Presentation class. Throws + * an IllegalArgumentException if the presentation class cannot + * instantiated. + * @param name The name of the presentation. This will retrieve the + * presentation details from the HelpSet hs if one exists. For + * some Presentation this name will also indicate the "named" + * Presentation to display the information in. + * @throws NullPointerException if hs is Null. + * @throws IllegalArgumentException if presentation is not valid. + */ + public DisplayHelpFromFocus(HelpSet hs, + String presentation, + String presentationName) { + if (hs == null) { + throw new NullPointerException("hs"); + } + + ClassLoader loader; + Class klass; + + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + } catch (Exception ex) { + throw new IllegalArgumentException(presentation + "presentation invalid"); + } + + this.presentation = presentation; + this.presentationName = presentationName; + this.hs = hs; + } + + + public void actionPerformed(ActionEvent e) { + + Component src = (Component) e.getSource(); + // Start by setting the ownerWindow in the HelpBroker + if (hb instanceof DefaultHelpBroker) { + ((DefaultHelpBroker)hb).setActivationObject(src); + } + + Component comp = CSH.findFocusOwner(src); + + debug("focusOwner:"+comp); + + if (comp == null) { + comp = src; + } + + displayHelp(hb, hs, presentation, presentationName, comp, comp, e); + } + } + + + /** + * Returns the popup menu which is at the root of the menu system + * for this popup menu. + * + * @return the topmost grandparent <code>JPopupMenu</code> + */ + private static JPopupMenu getRootPopupMenu(JPopupMenu popup) { + while((popup != null) && + (popup.getInvoker() instanceof JMenu) && + (popup.getInvoker().getParent() instanceof JPopupMenu) + ) { + popup = (JPopupMenu) popup.getInvoker().getParent(); + } + return popup; + } + + /** + * Returns the deepest focused Component or the deepest JPopupMenu + * or the deepest armed MenuItem from JPopupMenu hierarchy. + */ + private static Component findFocusOwner(JPopupMenu popup) { + if (popup == null) { + return null; + } + synchronized (popup.getTreeLock()) { + if (!popup.isVisible()) { + return null; + } + Component comp = null; + for (int i = 0, n = popup.getComponentCount(); i < n; i++) { + Component c = popup.getComponent(i); + if (c.hasFocus()) { + comp = c; + break; + } + if (c instanceof JMenu && ((JMenu)c).isPopupMenuVisible()) { + comp = c; + } + if (c instanceof JMenuItem && ((JMenuItem)c).isArmed()) { + comp = c; + } + } + if (comp instanceof JMenu) { + comp = findFocusOwner(((JMenu)comp).getPopupMenu()); + } + if (comp != null) { + return comp; + } + } + return popup; + } + + /** + * Returns the child component which has focus with respects + * of PopupMenu visibility. + */ + private static Component findFocusOwner(Component c) { + synchronized (c.getTreeLock()) { + + if (c instanceof JPopupMenu) { + return findFocusOwner(getRootPopupMenu((JPopupMenu)c)); + } + + if (c.hasFocus()) { + return c; + } + + if (c instanceof Container) { + for (int i = 0, n = ((Container)c).getComponentCount(); i < n; i++) { + Component focusOwner = findFocusOwner(((Container)c).getComponent(i)); + if (focusOwner != null) { + return focusOwner; + } + } + } + return null; // Component doesn't have hasFocus(). + } + } + + /** + * An ActionListener that displays help on a + * selected object after tracking context-sensitive events. + * It is normally activated + * from a button. It uses CSH.trackingCSEvents to track context-sensitive + * events and when an object is selected it gets + * the helpID for the object and displays the helpID in the help viewer. + */ + public static class DisplayHelpAfterTracking implements ActionListener { + + private HelpBroker hb = null; + private HelpSet hs = null; + private String presentation = null; + private String presentationName = null; + + public DisplayHelpAfterTracking(HelpBroker hb) { + if (hb == null) { + throw new NullPointerException("hb"); + } + this.hb = hb; + } + + /** + * Create a DisplayHelpAfterTracking actionListener for a given + * HelpSet. Display the results in specific Presentation of given + * PresentationName. + * + * @param hs A valid HelpSet. + * @param presention A valid javax.help.Presentation class. Throws + * an IllegalArgumentException if the presentation class cannot + * instantiated. + * @param name The name of the presentation. This will retrieve the + * presentation details from the HelpSet hs if one exists. For + * some Presentation this name will also indicate the "named" + * Presentation to display the information in. + * @throws NullPointerException if hs is Null. + * @throws IllegalArgumentException if presentation is not valid. + */ + public DisplayHelpAfterTracking(HelpSet hs, + String presentation, + String presentationName) { + if (hs == null) { + throw new NullPointerException("hs"); + } + + ClassLoader loader; + Class klass; + + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + } catch (Exception ex) { + throw new IllegalArgumentException(presentation + "presentation invalid"); + } + + this.presentation = presentation; + this.presentationName = presentationName; + this.hs = hs; + } + + public void actionPerformed(ActionEvent e) { + Cursor onItemCursor, oldCursor; + + // Make sure that LAF is installed. + // It is necessery for UIManager.get("HelpOnItemCursor"); + SwingHelpUtilities.installUIDefaults(); + + // Get the onItemCursor + onItemCursor = (Cursor) UIManager.get("HelpOnItemCursor"); + if (onItemCursor == null) { + return; + } + + // change all the cursors on all windows + Vector topComponents = null; + cursors = null; + + if (onItemCursor != null) { + cursors = new Hashtable(); + topComponents = getTopContainers(e.getSource()); + Enumeration enum1 = topComponents.elements(); + while (enum1.hasMoreElements()) { + setAndStoreCursors((Container)enum1.nextElement(), onItemCursor); + } + } + + MouseEvent event = CSH.getMouseEvent(); + debug("CSH.getMouseEvent() >>> "+event); + + if (event != null) { + + Object obj = CSH.getDeepestObjectAt(event.getSource(), event.getX(), event.getY()); + debug("CSH.getDeepestObjectAt() >>> "+obj); + + if (obj != null) { + + displayHelp(hb, hs, presentation, presentationName, + obj, e.getSource(), event); + } + } + + // restore the old cursors + if (topComponents != null) { + Enumeration containers = topComponents.elements(); + while (containers.hasMoreElements()) { + resetAndRestoreCursors((Container)containers.nextElement()); + } + } + cursors = null; + } + + private Hashtable cursors; + + /* + * Get all top level containers to change it's cursors + */ + private static Vector getTopContainers(Object source) { + // This method is used to obtain all top level components of application + // for which the changing of cursor to question mark is wanted. + // Method Frame.getFrames() is used to get list of Frames and + // Frame.getOwnedWindows() method on elements of the list + // returns all Windows, Dialogs etc. It works correctly in application. + // Problem is in applets. There is no way how to get reference to applets + // from elsewhere than applet itself. So, if request for CSH (this means + // pressing help button or select help menu item) does't come from component + // in a Applet, cursor for applets is not changed to question mark. Only for + // Frames, Windows and Dialogs is cursor changed properly. + + Vector containers = new Vector(); + Component topComponent = null; + topComponent = getRoot(source); + if (topComponent instanceof Applet) { + try { + Enumeration applets = ((Applet)topComponent).getAppletContext().getApplets(); + while (applets.hasMoreElements()) { + containers.add(applets.nextElement()); + } + } catch (NullPointerException npe) { + containers.add(topComponent); + } + } + Frame frames[] = Frame.getFrames(); + for (int i = 0; i < frames.length; i++) { + Window[] windows = frames[i].getOwnedWindows(); + for (int j = 0; j < windows.length; j++) { + containers.add(windows[j]); + } + if (!containers.contains(frames[i])) { + containers.add(frames[i]); + } + } + return containers; + } + + + private static Component getRoot(Object comp) { + Object parent = comp; + while (parent != null) { + comp = parent; + if (comp instanceof MenuComponent) { + parent = ((MenuComponent)comp).getParent(); + } else if (comp instanceof Component) { + if (comp instanceof Window) { + break; + } + if (comp instanceof Applet) { + break; + } + parent = ((Component)comp).getParent(); + } else { + break; + } + } + if (comp instanceof Component) { + return ((Component)comp); + } + return null; + } + + + /* + * Set the cursor for a component and its children. + * Store the old cursors for future resetting + */ + private void setAndStoreCursors(Component comp, Cursor cursor) { + if (comp == null) { + return; + } + Cursor compCursor = comp.getCursor(); + if (compCursor != cursor) { + cursors.put(comp, compCursor); + debug("set cursor on " + comp); + comp.setCursor(cursor); + } + if (comp instanceof Container) { + Component component[] = ((Container)comp).getComponents(); + for (int i = 0 ; i < component.length; i++) { + setAndStoreCursors(component[i], cursor); + } + } + } + + /* + * Actually restore the cursor for a component and its children + */ + private void resetAndRestoreCursors(Component comp) { + if (comp == null) { + return; + } + Cursor oldCursor = (Cursor) cursors.get(comp); + if (oldCursor != null) { + debug("restored cursor " + oldCursor + " on " + comp); + comp.setCursor(oldCursor); + } + if (comp instanceof Container) { + Component component[] = ((Container)comp).getComponents(); + for (int i = 0 ; i < component.length; i++) { + resetAndRestoreCursors(component[i]); + } + } + } + } + + /** + * An ActionListener that + * gets the helpID for the action source and displays the helpID in the + * help viewer. + * + * @see HelpBroker.enableHelp + */ + public static class DisplayHelpFromSource implements ActionListener { + + private HelpBroker hb; + private HelpSet hs = null; + private String presentation = null; + private String presentationName = null; + + public DisplayHelpFromSource(HelpBroker hb) { + if (hb == null) { + throw new NullPointerException("hb"); + } + this.hb = hb; + } + + /** + * Create a DisplayHelpFromSource actionListener for a given + * HelpSet. Display the results in specific Presentation of given + * PresentationName. + * + * @param hs A valid HelpSet. + * @param presention A valid javax.help.Presentation class. Throws + * an IllegalArgumentException if the presentation class cannot + * instantiated. + * @param name The name of the presentation. This will retrieve the + * presentation details from the HelpSet hs if one exists. For + * some Presentation this name will also indicate the "named" + * Presentation to display the information in. + * @throws NullPointerException if hs is Null. + * @throws IllegalArgumentException if presentation is not valid. + */ + public DisplayHelpFromSource(HelpSet hs, + String presentation, + String presentationName) { + if (hs == null) { + throw new NullPointerException("hs"); + } + + ClassLoader loader; + Class klass; + + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + } catch (Exception ex) { + throw new IllegalArgumentException(presentation + "presentation invalid"); + } + + this.presentation = presentation; + this.presentationName = presentationName; + this.hs = hs; + } + + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + displayHelp(hb, hs, presentation, presentationName, + source, source, e); + + } + } + + /** + * CSH Manager Interface to support dynamic <code>HelpSet</code> and <code>ID</code> + * for object. CSH is allowed only for <code>Component</code> and <code>MenuItem</code>. + * + * @since 2.0 + */ + public interface Manager { + /** + * Returns HelpSet of the object depending on the event. + * @param comp The object to get <code>HelpSet</code> for it. Only <code>Component</code> + * and <code>MenuItem</code> is allowed. + * @param e The event by which dynamic CSH was invoked. It can be <code>MouseEvent</code> + * in case of window level CSH, <code>ActionEvent</code> in case of field level CSH or + * <code>null</code> otherwise. + * @return A HelpSet for given object or null if no HelpSet is assigned to object + * @see CSH.DisplayHelpAfterTracking + * @see CSH.DisplayHelpFromFocus + * @see CSH.DisplayHelpFromSource + */ + public HelpSet getHelpSet(Object comp, AWTEvent e); + + /** + * Returns String represent Map.ID of the object depending on the event. + * @param comp The object to get <code>Map.ID</code> for it. Only <code>Component</code> + * and <code>MenuItem</code> is allowed. + * @param e The event by which dynamic CSH was invoked. It can be <code>MouseEvent</code> + * in case of window level CSH, <code>ActionEvent</code> in case of field level CSH or + * <code>null</code> otherwise. + * @return A Map.ID string for given object or null if no Map.ID is assigned to object + * @see CSH.DisplayHelpAfterTracking + * @see CSH.DisplayHelpFromFocus + * @see CSH.DisplayHelpFromSource + */ + public String getHelpIDString(Object comp, AWTEvent e); + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("CSH: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java new file mode 100644 index 0000000000000000000000000000000000000000..4bc43d4134cbee6cff431993d5a3475167a61ad3 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java @@ -0,0 +1,779 @@ +/* + * @(#)DefaultHelpBroker.java 1.69 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.*; +import javax.help.*; +import java.util.Enumeration; +import java.util.Hashtable; +import java.net.URL; +import java.awt.*; +import java.awt.event.*; +import javax.help.Map.ID; +import java.util.Locale; +import java.awt.Font; +import java.awt.Dimension; +import java.lang.reflect.*; + +/** + * An implmentation of the HelpBroker interface + * + * @author Roger Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.33 01/25/99 + */ + +public class DefaultHelpBroker implements HelpBroker, KeyListener { + + private MainWindow mw = null; + private HelpSet helpKeyHS = null; + private String helpKeyPresentation = null; + private String helpKeyPresentationName = null; + + /** + * Constructor + */ + + public DefaultHelpBroker(HelpSet hs) { + mw = (MainWindow) MainWindow.getPresentation(hs, null); + } + + /** + * Zero-argument constructor. + * It should be followed by a setHelpSet() invocation. + */ + + public DefaultHelpBroker() { + mw = (MainWindow) MainWindow.getPresentation(null, null); + } + + + /** + * Get the WindowPresentation for this HelpBroker + * @returns the window presentation for this object + */ + public WindowPresentation getWindowPresentation() { + return mw; + } + + /** + * Returns the default HelpSet + */ + public HelpSet getHelpSet() { + return mw.getHelpSet(); + } + + /** + * Changes the HelpSet for this broker. + * @param hs The HelpSet to set for this broker. + * A null hs is valid parameter. + */ + public void setHelpSet(HelpSet hs) { + debug ("setHelpSet"); + mw.setHelpSet(hs); + } + + /** + * Set the presentation attributes from a HelpSet.Presentation. + * The HelpSet.Presentation must be in the current HelpSet. + * + * @param hsPres The HelpSet.Presentation + * @since 2.0 + */ + public void setHelpSetPresentation(HelpSet.Presentation hsPres) { + debug ("setHelpSetPresentation"); + mw.setHelpSetPresentation(hsPres); + } + + /** + * Gets the locale of this component. + * @return This component's locale. If this component does not + * have a locale, the defaultLocale is returned. + * @see #setLocale + */ + public Locale getLocale() { + return mw.getLocale(); + } + + /** + * Sets the locale of this HelpBroker. The locale is propagated to + * the presentation. + * @param l The locale to become this component's locale. A null locale + * is the same as the defaultLocale. + * @see #getLocale + */ + public void setLocale(Locale l) { + mw.setLocale(l); + } + + /** + * Gets the font for this HelpBroker. + */ + public Font getFont () { + return mw.getFont(); + } + + /** + * Sets the font for this this HelpBroker. + * @param f The font. + */ + public void setFont (Font f) { + mw.setFont(f); + } + + /** + * Set the currentView to the navigator with the same + * name as the <tt>name</tt> parameter. + * + * @param name The name of the navigator to set as the + * current view. If nav is null or not a valid Navigator + * in this HelpBroker then an + * IllegalArgumentException is thrown. + * @throws IllegalArgumentException if nav is null or not a valid Navigator. + */ + public void setCurrentView(String name) { + mw.setCurrentView(name); + } + + /** + * Determines the current navigator. + */ + public String getCurrentView() { + return mw.getCurrentView(); + } + + + /** + * Initializes the presentation. + * This method allows the presentation to be initialized but not displayed. + * Typically this would be done in a separate thread to reduce the + * intialization time. + */ + public void initPresentation() { + mw.createHelpWindow(); + } + + /** + * Displays the presentation to the user. + */ + public void setDisplayed(boolean b) { + debug("setDisplayed"); + mw.setDisplayed(b); + } + + /** + * Determines if the presentation is displayed. + */ + public boolean isDisplayed() { + return mw.isDisplayed(); + } + + /** + * Requests the presentation be located at a given position. + */ + public void setLocation(Point p) { + mw.setLocation(p); + } + + /** + * Requests the location of the presentation. + * @returns Point the location of the presentation. + */ + public Point getLocation() { + return mw.getLocation(); + } + + /** + * Requests the presentation be set to a given size. + */ + public void setSize(Dimension d) { + mw.setSize(d); + } + + /** + * Requests the size of the presentation. + * @returns Point the location of the presentation. + */ + public Dimension getSize() throws UnsupportedOperationException { + return mw.getSize(); + } + + /** + * Requests the presentation be set to a given screen. + */ + public void setScreen(int screen) { + mw.setScreen(screen); + } + + /** + * Requests the screen of the presentation. + * @returns int the screen of the presentation. + */ + public int getScreen() throws UnsupportedOperationException { + return mw.getScreen(); + } + + /** + * Hides/Shows view. + */ + public void setViewDisplayed(boolean displayed) { + mw.setViewDisplayed(displayed); + } + + /** + * Determines if the current view is visible. + */ + public boolean isViewDisplayed() { + return mw.isViewDisplayed(); + } + + /** + * Shows this ID. + * + * @param id A string that identifies the topic to show for the loaded (top) HelpSet + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * @exception BadIDException The ID is not valid for the HelpSet + * @exception IllegalArgumentException if presentation is not valid + * @see Presentation + */ + public void showID(String id, String presentation, + String presentationName) throws BadIDException { + debug("showID - string"); + Presentation pres = getPresentation(presentation, presentationName); + if (pres != null) { + pres.setCurrentID(id); + pres.setDisplayed(true); + } + } + + /** + * Show this ID. + * + * @param id a Map.ID indicating the URL to display + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * @exception InvalidHelpSetContextException if the current helpset does not contain + * id.helpset + * @see Presentation + */ + public void showID(ID id, String presentation, String presentationName) + throws InvalidHelpSetContextException { + debug("showID - ID"); + Presentation pres = getPresentation(presentation, presentationName); + if (pres != null) { + pres.setCurrentID(id); + pres.setDisplayed(true); + } + } + + private Presentation getPresentation(String presentation, + String presentationName) { + Presentation pres; + + HelpSet hs = mw.getHelpSet(); + // should never happen, but... + if (hs == null) { + return null; + } + ClassLoader loader; + Class klass; + Class types[] = { HelpSet.class, + String.class}; + Object args[] = { hs, + presentationName}; + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + Method m = klass.getMethod("getPresentation", types); + pres = (Presentation)m.invoke(null, args); + } catch (ClassNotFoundException cnfex) { + throw new IllegalArgumentException(presentation + "presentation invalid"); + } catch (Exception ex) { + throw new RuntimeException("error invoking presentation" ); + } + + if (pres == null) { + return null; + } + + // It is not possible to call this method for Popup + if (pres instanceof Popup) { + return null; + } + + return pres; + } + + /** + * Shows this ID as content relative to the (top) HelpSet for the HelpBroker + * instance--HelpVisitListeners are notified. + * + * @param id A string that identifies the topic to show for the loaded (top) HelpSet + * @exception BadIDException The ID is not valid for the HelpSet + */ + public void setCurrentID(String id) throws BadIDException { + debug("setCurrentID - string"); + mw.setCurrentID(id); + } + + /** + * Displays this ID--HelpVisitListeners are notified. + * + * @param id a Map.ID indicating the URL to display + * @exception InvalidHelpSetContextException if the current helpset does not contain + * id.helpset + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException { + debug("setCurrentID - ID"); + mw.setCurrentID(id); + } + + /** + * Determines which ID is displayed (if any). + */ + public ID getCurrentID() { + return mw.getCurrentID(); + } + + /** + * Displays this URL. + * HelpVisitListeners are notified. + * The currentID changes if there is a mathing ID for this URL + * @param url The url to display. A null URL is a valid url. + */ + public void setCurrentURL(URL url) { + debug ("setCurrentURL"); + mw.setCurrentURL(url); + } + + /** + * Determines which URL is displayed. + */ + public URL getCurrentURL() { + return mw.getCurrentURL(); + } + + + // Context-Senstive methods + /** + * Enables the Help key on a Component. This method works best when + * the component is the + * rootPane of a JFrame in Swing implementations, or a java.awt.Window + * (or subclass thereof) in AWT implementations. + * This method sets the default + * helpID and HelpSet for the Component and registers keyboard actions + * to trap the "Help" keypress. When the "Help" key is pressed, if the + * object with the current focus has a helpID, the helpID is displayed. + * otherwise the default helpID is displayed. + * + * @param comp the Component to enable the keyboard actions on. + * @param id the default HelpID to be displayed + * @param hs the default HelpSet to be displayed. If hs is null the default HelpSet + * will be assumed. + * + * @see getHelpKeyActionListener + * @see enableHelpKey(Component, String, HelpSet, String, String); + */ + public void enableHelpKey(Component comp, String id, HelpSet hs) { + enableHelpKey(comp, id, hs, null, null); + } + + /** + * Enables the Help key on a Component. This method works best when + * the component is the + * rootPane of a JFrame in Swing implementations, or a java.awt.Window + * (or subclass thereof) in AWT implementations. + * This method sets the default + * helpID and HelpSet for the Component and registers keyboard actions + * to trap the "Help" keypress. When the "Help" key is pressed, if the + * object with the current focus has a helpID, the helpID is displayed. + * otherwise the default helpID is displayed. + * + * @param comp the Component to enable the keyboard actions on. + * @param id the default HelpID to be displayed + * @param hs the default HelpSet to be displayed. If hs is null the + * default HelpSet from the HelpBroker is assummed. null is not + * valid if presenation is not null. + * @param presentation The Presentation class to display the content in. + * If presentation is null the HelpBroker is used to display the + * content. + * @param presentationName The name of a Presentation section to control + * the display of the content. Also for some Presenations this + * will be used to "name" the Presentation. + * + * @see getHelpKeyActionListener + * @see enableHelpKey(Component, String, HelpSet); + * @throws IllegalArgumentException if presentation != null and hs == null + */ + public void enableHelpKey(Component comp, String id, HelpSet hs, + String presentation, String presentationName) { + if (id == null) { + throw new NullPointerException("id"); + } + if (presentation != null && hs == null) { + throw new IllegalArgumentException("hs"); + } + CSH.setHelpIDString(comp, id); + if (hs !=null) { + CSH.setHelpSet(comp, hs); + } + if (comp instanceof JComponent) { + JComponent root = (JComponent) comp; + ActionListener al = null; + if (presentation == null) { + al = getDisplayHelpFromFocus(); + } else { + al = new CSH.DisplayHelpFromFocus(hs, presentation, + presentationName); + } + root.registerKeyboardAction(al, + KeyStroke.getKeyStroke(KeyEvent.VK_HELP, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + root.registerKeyboardAction(al, + KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } else { + helpKeyHS = hs; + helpKeyPresentation = presentation; + helpKeyPresentationName = presentationName; + comp.addKeyListener(this); + } + } + + /** + * Invoked when a key is typed. This event occurs when a + * key press is followed by a key release. Not intended to be overridden or extended. + */ + public void keyTyped(KeyEvent e) { + //ignore + } + + /** + * Invoked when a key is pressed. Not intended to be overridden or extended. + */ + public void keyPressed(KeyEvent e) { + //ingore + } + + + + /** + * Invoked when a key is released. Not intended to be overridden or extended. + */ + public void keyReleased(KeyEvent e) { + // simulate what is done in JComponents registerKeyboardActions. + int code = e.getKeyCode(); + if (code == KeyEvent.VK_F1 || code == KeyEvent.VK_HELP) { + ActionListener al = null; + if (helpKeyHS != null) { + al = new CSH.DisplayHelpFromFocus(helpKeyHS, + helpKeyPresentation, + helpKeyPresentationName); + } else { + al = getDisplayHelpFromFocus(); + } + al.actionPerformed(new ActionEvent(e.getComponent(), + ActionEvent.ACTION_PERFORMED, + null)); + } + + } + + /** + * Enables help for a Component. This method sets a + * component's helpID and HelpSet. + * + * @param comp the Component to set the id and hs on. + * @param id the String value of an Map.ID. + * @param hs the HelpSet the id is in. If hs is null the default HelpSet + * will be assumed. + * @see CSH.setHelpID + * @see CSH.setHelpSet + */ + public void enableHelp(Component comp, String id, HelpSet hs) + { + if (id == null) { + throw new NullPointerException("id"); + } + CSH.setHelpIDString(comp, id); + if (hs != null) { + CSH.setHelpSet(comp, hs); + } + } + + /** + * Enables help for a MenuItem. This method sets a + * component's helpID and HelpSet. + * + * @param comp the MenuItem to set the id and hs on. + * @param id the String value of an Map.ID. + * @param hs the HelpSet the id is in. If hs is null the default HelpSet + * will be assumed. + * @see CSH.setHelpID + * @see CSH.setHelpSet + */ + public void enableHelp(MenuItem comp, String id, HelpSet hs) + { + if (id == null) { + throw new NullPointerException("id"); + } + CSH.setHelpIDString(comp, id); + if (hs != null) { + CSH.setHelpSet(comp, hs); + } + } + + /** + * Enables help for a Component. This method sets a + * Component's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the Component's helpID and HelpSet in the default viewer. + * + * @param comp the Component to set the id and hs on. If the Component is not + * a javax.swing.AbstractButton or a + * java.awt.Button an IllegalArgumentException is thrown. + * @param id the String value of an Map.ID. + * @param hs the HelpSet the id is in. If hs is null the default HelpSet + * will be assumed. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see javax.swing.AbstractButton + * @see java.awt.Button + * @throws IllegalArgumentException if comp is null. + */ + public void enableHelpOnButton(Component comp, String id, HelpSet hs) + { + if (!(comp instanceof AbstractButton) && !(comp instanceof Button)) { + throw new IllegalArgumentException("Invalid Component"); + } + if (id == null) { + throw new NullPointerException("id"); + } + CSH.setHelpIDString(comp, id); + if (hs != null) { + CSH.setHelpSet(comp, hs); + } + if (comp instanceof AbstractButton) { + AbstractButton button = (AbstractButton) comp; + button.addActionListener(getDisplayHelpFromSource()); + } else if (comp instanceof Button) { + Button button = (Button) comp; + button.addActionListener(getDisplayHelpFromSource()); + } + } + + /** + * Enables help for a MenuItem. This method sets a + * Component's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the Component's helpID and HelpSet in the default viewer. + * + * @param comp the MenuItem to set the id and hs on. If comp is null + * an IllegalAgrumentException is thrown. + * @param id the String value of an Map.ID. + * @param hs the HelpSet the id is in. If hs is null the default HelpSet + * will be assumed. + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see java.awt.MenuItem + * @throws IllegalArgumentException if comp is null. + */ + public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs) + { + if (comp == null) { + throw new IllegalArgumentException("Invalid Component"); + } + if (id == null) { + throw new NullPointerException("id"); + } + CSH.setHelpIDString(comp, id); + if (hs != null) { + CSH.setHelpSet(comp, hs); + } + comp.addActionListener(getDisplayHelpFromSource()); + } + + /** + * Enables help for a Component. This method sets a + * Component's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the Component's helpID and HelpSet in the default viewer. + * + * @param comp the Component to set the id and hs on. If the Component is not + * a javax.swing.AbstractButton or a + * java.awt.Button an IllegalArgumentException is thrown. + * @param id the String value of an Map.ID. + * @param hs the HelpSet the id is in. If hs is null the default HelpSet + * will be assumed. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see javax.swing.AbstractButton + * @see java.awt.Button + * @throws IllegalArgumentException if comp is null. + */ + public void enableHelpOnButton(Object obj, String id, HelpSet hs, + String presentation, + String presentationName) + { + if (!(obj instanceof AbstractButton) && !(obj instanceof Button) && + !(obj instanceof MenuItem)) { + throw new IllegalArgumentException("Invalid Object"); + } + if (id == null) { + throw new NullPointerException("id"); + } + + if (obj instanceof AbstractButton || obj instanceof Button) { + CSH.setHelpIDString((Component)obj, id); + if (hs != null) { + CSH.setHelpSet((Component)obj, hs); + } + } else { + CSH.setHelpIDString((MenuItem)obj, id); + if (hs != null) { + CSH.setHelpSet((MenuItem)obj, hs); + } + } + + if (presentation == null) { + if (obj instanceof AbstractButton) { + AbstractButton button = (AbstractButton) obj; + button.addActionListener(getDisplayHelpFromSource()); + } else if (obj instanceof Button) { + Button button = (Button) obj; + button.addActionListener(getDisplayHelpFromSource()); + } else if (obj instanceof MenuItem) { + MenuItem item = (MenuItem) obj; + item.addActionListener(getDisplayHelpFromSource()); + } + } else { + if (obj instanceof AbstractButton) { + AbstractButton button = (AbstractButton) obj; + button.addActionListener(new CSH.DisplayHelpFromSource(hs, + presentation, + presentationName)); + } else if (obj instanceof Button) { + Button button = (Button) obj; + button.addActionListener(new CSH.DisplayHelpFromSource(hs, + presentation, + presentationName)); + } else if (obj instanceof MenuItem) { + MenuItem item = (MenuItem) obj; + item.addActionListener(new CSH.DisplayHelpFromSource(hs, + presentation, + presentationName)); + } + } + + } + + /** + * Returns the default DisplayHelpFromFocus listener. + * + * @see enableHelpKey + */ + protected ActionListener getDisplayHelpFromFocus() { + if (displayHelpFromFocus == null) { + displayHelpFromFocus = new CSH.DisplayHelpFromFocus(this); + } + return displayHelpFromFocus; + } + + /** + * Returns the default DisplayHelpFromSource listener. + * + * @see enableHelp + */ + protected ActionListener getDisplayHelpFromSource() { + if (displayHelpFromSource==null) { + displayHelpFromSource = new CSH.DisplayHelpFromSource(this); + } + return displayHelpFromSource; + } + + /** + * Set the activation window from given Component or MenuItem. It find Window component + * in the component tree from given Component or MenuItem end call + * <pre>setActivationWindow</pre>. + * @parem comp the activation Component or MenuItem + * @since 1.1 + * + * @see setActivationWindow + */ + public void setActivationObject(Object comp) { + mw.setActivationObject(comp); + } + + /** + * Set the activation window. If the window is an instance of a + * Dialog and the is modal, modallyActivated help is set to true and + * ownerDialog is set to the window. In all other instances + * modallyActivated is set to false and ownerDialog is set to null. + * @param window the activating window + * @since 1.1 + */ + public void setActivationWindow(Window window) { + mw.setActivationWindow(window); + } + + + // the listeners. + protected ActionListener displayHelpFromFocus; + protected ActionListener displayHelpFromSource; + + /* + * Make sure the Look and Feel will be set + */ + static { + SwingHelpUtilities.installLookAndFeelDefaults(); + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("DefaultHelpBroker: "+msg); + } + } + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java new file mode 100644 index 0000000000000000000000000000000000000000..3078e19c910a7a181b028597529cfd3cbea27270 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java @@ -0,0 +1,393 @@ +/* + * @(#)DefaultHelpHistoryModel.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package javax.help; + +import java.beans.*; +import java.util.Vector; +import javax.help.event.*; +import javax.help.Map.ID; +import java.util.Enumeration; +import java.net.URL; +import java.util.Stack; +/** + * DefaultHelpHistoryModel is default implementation of HelpHistoryModel interface + * + * @author Richard Gregor + * @version 1.4 10/30/06 + */ + +public class DefaultHelpHistoryModel implements HelpHistoryModel{ + + protected Vector history = new Vector(); + protected int historyIndex = -1; + protected HelpModel helpModel; + protected EventListenerList listenerList = new EventListenerList(); + protected JHelp help; + + /** + * Creates new DefaultHelpHistoryModel for given JHelp + * + * @param help The JHelp + */ + public DefaultHelpHistoryModel(JHelp help) { + this.help = help; + if (help != null){ + setHelpModel(help.getModel()); + } + } + + /** + * Sets a new HelpModel + * + * @param model The new HelpModel + */ + public void setHelpModel(HelpModel model){ + if(model == helpModel) + return; + else + discard(); + if(helpModel != null) + helpModel.removeHelpModelListener(this); + if(model != null) + model.addHelpModelListener(this); + helpModel = model; + } + + + /** + * Removes a listener previously added with <tt>addHelpHistoryModelListener</tt> + * + * @param l The listener to remove. + * @see javax.help.HelpHistoryModel#addHelpHistoryModelListener + */ + public void removeHelpHistoryModelListener(HelpHistoryModelListener l) { + listenerList.remove(HelpHistoryModelListener.class, l); + } + + /** + * Adds a listener for the HelpHistoryModelEvent posted after the model has + * changed. + * + * @param l The listener to add. + * @see javax.help.HelpHistoryModel#removeHelpHistoryModelListener + */ + public void addHelpHistoryModelListener(HelpHistoryModelListener l) { + listenerList.add(HelpHistoryModelListener.class, l); + } + + /** + * Discards a history + */ + public void discard() { + history.setSize(0); + historyIndex = -1; + fireHistoryChanged(this,false,false); + } + + /** + * Returns a history + * + * @return The vector of history entries + */ + public Vector getHistory(){ + return history; + } + + /** + * Removes the last history entry + * + */ + public void removeLastEntry(){ + int size = history.size(); + if(size > 0) + history.removeElementAt(history.size() -1); + } + /** + * Returns a current history position + * + * @return The history index + */ + public int getIndex(){ + return historyIndex; + } + + /** + * Sets the next history entry + */ + public void goForward(){ + setHistoryEntry(historyIndex+1); + } + + /** + * Sets the previous histroy entry + */ + public void goBack(){ + setHistoryEntry(historyIndex-1); + } + + /** + * Returns a forward history vector + * + * @return The vector of forward history entries + */ + public Vector getForwardHistory() { + Vector historyCopy = (Vector)history.clone(); + Vector forwardHistory = new Vector(); + int size = historyCopy.size(); + debug(" forward size : "+size); + for(int i = historyIndex + 1 ; i < size; i++){ + forwardHistory.addElement(historyCopy.elementAt(i)); + } + return forwardHistory; + } + + /** + * Returns a backward history vector + * + * @return The vector of backward history entries + */ + public Vector getBackwardHistory() { + Vector backwardHistory = new Vector(); + Vector historyCopy = (Vector)history.clone(); + debug(" backward size : "+historyCopy.size()); + debug(" backward index : "+historyIndex); + if(historyCopy != null){ + for(int i = 0 ; i < historyIndex; i++){ + backwardHistory.addElement(historyCopy.elementAt(i)); + } + } + + return backwardHistory; + } + + /** + * Sets the current history entry + * + * @param index The index of history entry + */ + public void setHistoryEntry(int index) { + debug("setHistoryEntry("+index+")"); + + + if (helpModel == null) { + return; + } + + if (index < 0 || index >= history.size()) { + // invalid index + discard(); + return; + } + + HelpModelEvent e = (HelpModelEvent) history.elementAt(index); + // set the historyIndex so it is ready to take the next event... + historyIndex = index-1; + ID id = e.getID(); + URL url = e.getURL(); + JHelpNavigator navigator = e.getNavigator(); + if (id != null) { + // try to set the ID + try { + debug(" setCurrentID"+id); + helpModel.setCurrentID(id, e.getHistoryName(),e.getNavigator()); + if(navigator != null) + help.setCurrentNavigator(navigator); + return; + } catch (Exception ex) { + // fall through + } + } + if (url != null) { + // try to set the URL + try { + debug(" setCurrentURL"+url); + helpModel.setCurrentURL(url,e.getHistoryName(),e.getNavigator()); + if(navigator != null) + help.setCurrentNavigator(navigator); + return; + } catch (Exception ex) { + // fall through + } + } + + // this really should not happen but... + discard(); + } + /** + * Fires the history change + */ + protected void fireHistoryChanged(Object source, boolean previous, boolean next) { + Object[] listeners = listenerList.getListenerList(); + HelpHistoryModelEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == HelpHistoryModelListener.class) { + if (e == null) { + e = new HelpHistoryModelEvent(source, previous, next); + } + debug("fireHistoryChanged: "); + debug(" "+listeners[i+1]); + debug(" previous="+e.isPrevious() + " next="+e.isNext()); + ((HelpHistoryModelListener)listeners[i+1]).historyChanged(e); + } + } + } + + + /** + * Tells the listener that the current ID in the HelpModel has + * changed. + * All highlights from the previous location change at this point. + * + * @param e The event + */ + public void idChanged(HelpModelEvent e) { + debug("idChanged("+e+")"); + debug(" historyIndex=="+historyIndex); + debug(" history.size=="+history.size()); + + if (historyIndex == history.size()-1) { + // we are at the end + // (this covers the initial case of historyIndex == -1 + history.addElement(e); + historyIndex += 1; + fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1)); + return; + } + + if (historyIndex >= -1 && + historyIndex < history.size()-1) { + // check the next slot where to record + + historyIndex += 1; // advance + HelpModelEvent h + = (HelpModelEvent) history.elementAt(historyIndex); + + if (h == null) { + // this really should not happen + discard(); + return; + } + + // compare ID's first + if (h.getID() != null && e.getID() != null && + h.getID().equals(e.getID())) { + // we are were we wanted to be, just return + fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1)); + return; + } + + // compare URL's now + if (h.getURL() != null && e.getURL() != null && + h.getURL().sameFile(e.getURL())) { + // we are were we wanted to be, just return + fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1)); + return; + } + + // new location is different, so throw away object and the rest + history.setSize(historyIndex); + // add the new element + history.addElement(e); + fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1)); + } + } + + /** + * Removes entries related to removed HelpSet from history + * + * @param hs The removed HelpSet + */ + public void removeHelpSet(HelpSet hs){ + Enumeration e = history.elements(); + debug(" size before " +history.size()); + + if(debug){ + System.err.println("before : "); + for(int j = 0; j < history.size(); j++){ + System.err.println(((HelpModelEvent)history.elementAt(j)).getID()); + } + } + int size = history.size(); + Vector newHistory = new Vector(); + int index = historyIndex; + + for(int i = 0; i < size; i++){ + HelpModelEvent evt = (HelpModelEvent)history.elementAt(i); + ID id = evt.getID(); + debug(" update id "+id); + URL url = evt.getURL(); + debug(" update url " +url); + if ((id != null) && (id.hs != hs)) { + debug(" remain - "+id); + newHistory.addElement(history.elementAt(i)); + } + else if (url != null) { + //find out if there is a matching ID for this URL + ID idcan = hs.getCombinedMap().getIDFromURL(url); + if(idcan == null){ + debug(" remain > "+idcan); + newHistory.addElement(history.elementAt(i)); + } + } + } + + history = newHistory; + historyIndex = history.size() -1; + + debug(" size after " + history.size()); + if(debug){ + System.err.println("after : "); + for(int j = 0; j < history.size(); j++){ + System.err.println(((HelpModelEvent)history.elementAt(j)).getID()); + } + } + setHistoryEntry(historyIndex); + //computeHistoryButtons(); + + } + + /** + * Returns HelpModel + * + * @return The HelpModel + */ + protected HelpModel getModel(){ + return helpModel; + } + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicHelpUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java new file mode 100644 index 0000000000000000000000000000000000000000..14cd059dd7db6c0120b6a198afbea382568effd8 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java @@ -0,0 +1,510 @@ +/* + * @(#)DefaultHelpModel.java 1.49 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; +import java.io.Serializable; +import javax.help.event.EventListenerList; +import javax.help.event.*; +import javax.help.Map.ID; +import javax.help.TextHelpModel.Highlight; +import java.beans.*; + +/** + * This class implements the javax.help.HelpModel API and + * notifies the JHelpModel listeners when changes occur. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @@version 1.49 10/30/06 + */ + +public class DefaultHelpModel implements TextHelpModel, Serializable { + private HelpSet helpset; // the loaded, aka "the top", HelpSet + private ID currentID; + private URL currentURL; + private String navID; // the label to the "current" navigator + private Vector highlights = new Vector(); + + private String title; // title of the document - if appropriate + + protected EventListenerList listenerList = new EventListenerList(); + protected EventListenerList textListenerList = new EventListenerList(); protected PropertyChangeSupport changes = new PropertyChangeSupport(this); + + /** + * Constructs a HelpModel from a HelpSet + * + * @see javax.help.HelpSet + * @param hs The HelpSet from which to build this model. A null hs is valid + * creating a DefaultHelpModel without a HelpSet. + */ + public DefaultHelpModel(HelpSet hs) { + this.helpset = hs; + } + + /** + * Sets the HelpSet for this HelpModel. A null hs is valid. + */ + public void setHelpSet(HelpSet hs) { + HelpSet old = this.helpset; + this.helpset = hs; + changes.firePropertyChange("helpSet", old, hs); + } + + /** + * Gets the backing HelpSet. + * + * @return the helpset. A null hs is valid. + */ + public HelpSet getHelpSet() { + return helpset; + } + + /** + * Sets the current ID. + * HelpModelListeners and HelpVisitListeners are notified. + * If the parameter ident is null, the homeID of the current HelpSet is + * used unless it is also null in which case the method returns without + * setting the currentID. + * + * @param ident The ID to set. + * If ident is null set the currentID to the HelpSet's HomeID. + * If the HomeID doesn't exist the currentID is set to null. + * @exception InvalidHelpSetContextException The ID is not valid for the HelpSet + */ + public void setCurrentID(ID ident) throws InvalidHelpSetContextException { + setCurrentID(ident,(String)null, (JHelpNavigator) null); + + } + /** + * Sets the current ID relative to some HelpSet + * HelpModelListeners and HelpVisitListeners are notified + * + * @param id the ID used to set + * @param historyName the name for history storage + * @param navigator the name of the navigator for history + * @exception InvalidHelpSetContextException The HelpSet of the ID is not + * valid for the HelpSet currently loaded in the model + */ + public void setCurrentID(ID ident, String historyName, JHelpNavigator navigator) throws InvalidHelpSetContextException{ + if (ident == null) { + ident = helpset.getHomeID(); + } + if (ident == null || ident.equals(currentID)) { + // quick return if already set + return; + } + + String id = ident.id; + HelpSet hs = ident.hs; + + if (! helpset.contains(hs)) { + // invalid context + throw new InvalidHelpSetContextException("Wrong context", + helpset, + hs); + } + + Map map = helpset.getCombinedMap(); + currentID = ident; + try { + ID tmpID = ident; + URL url; + if (hs == helpset) { + url = map.getURLFromID(ident); + } else { + Map hsmap = hs.getLocalMap(); + url = hsmap.getURLFromID(ident); + } + if (currentURL != null && + currentURL.equals(url)) { + // workaround bug in 1.1.x doesn't compare anchors correctly + String currentRef = currentURL.getRef(); + String urlRef = url.getRef(); + // if both are null then they are the same + if (currentRef == null && urlRef == null) { + return; // avoid loops, don't propagate the ID change! + } + // if both have some value and have the same content they are + // the same + if (currentRef != null && urlRef != null && + currentRef.compareTo(urlRef) == 0) { + return; // avoid loops, don't propagate the ID change! + } + } + currentURL = url; + } catch (Exception ex) { + currentURL = null; + } + + // remove the highlights, but no need to fire an event because it is + // implicit in the next fireIDChanged() event + highlights.setSize(0); + fireIDChanged(this, currentID, currentURL, historyName, navigator); + } + + + /** + * Gets the current ID. + * + * @return the current ID. A null ID is a valid id. If no ID has been set + * a null ID is returned. + */ + public ID getCurrentID() { + return currentID; + } + + /** + * Sets the current URL. + * The current ID changes if there is a matching ID for this URL + * and HelpModelListners are notified. + * + * @param url The url to set the model to. A null URL is a valid url. + */ + public void setCurrentURL(URL url) { + setCurrentURL(url, (String)null, (JHelpNavigator)null); + } + + /** + * Sets the current URL and the name wich will appear in history list. + * HelpModelListeners are notified. + * The current ID changes if there is a matching id for this URL + * + * @param url The URL to set. + * @param historyName The name to set for history + * @param navigator The name of the navigator for history + */ + public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator){ + + boolean fire = false; + + // Setup CurrentURL + if (currentURL == null) { + if (currentURL != url) { + currentURL = url; + fire = true; + } + } else { + if (!currentURL.equals(url)) { + currentURL = url; + fire = true; + } + } + + // Setup CurrentID + if (currentURL == null) { + if (currentID != null) { + currentID = null; + fire = true; + } + } else { + ID id = helpset.getCombinedMap().getIDFromURL(currentURL); + if (currentID == null) { + if (currentID != id) { + currentID = id; + fire = true; + } + } else { + if (!currentID.equals(id)) { + currentID = id; + fire = true; + } + } + } + + // Fire only if CurrentURL or CurrentID was changed + if (fire) { + // remove the highlights, but no need to fire an event because it is + // implicit in the next fireIDChanged() event + highlights.setSize(0); + fireIDChanged(this, currentID, currentURL, historyName, navigator); + } + } + + + /** + * Returns the current URL + * + * @return The current URL. A null URL is a valid URL. If no URL has been + * previously set a null URL will be returned. + */ + public URL getCurrentURL() { + return currentURL; + } + + /** + * Highlights a range of positions in a document. + * + * @param pos0 start position + * @param pos1 end position + */ + public void addHighlight(int pos0, int pos1) { + debug("addHighlight("+pos0+", "+pos1+")"); + highlights.addElement(new DefaultHighlight(pos0, pos1)); + fireHighlightsChanged(this); + } + + /** + * Removes highlights. + */ + public void removeAllHighlights() { + debug("removeAllHighlights"); + highlights.setSize(0); + fireHighlightsChanged(this); + } + + /** + * Set highlights. Clear the current Hightlights and set new Highlights + * + * @param h An array of Hightlights. If h is null it is the same as setting + * no highlights + */ + public void setHighlights(Highlight[] h) { + highlights.setSize(0); + if (h == null) { + return; + } + for (int i=0; i<h.length; i++) { + highlights.addElement(new DefaultHighlight(h[i].getStartOffset(), + h[i].getEndOffset())); + } + if (highlights.size() > 0) { + fireHighlightsChanged(this); + } + } + + /** + * Geta all the highlights currently active. + * + * @return An array of highlights + */ + public Highlight[] getHighlights() { + Highlight back[] = new DefaultHighlight[highlights.size()]; + highlights.copyInto(back); + return back; + } + + + /** + * Adds a listener for the HelpModelEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.HelpModel#removeHelpModelListener + * @throws IllegalArgumentException if l is null. + */ + public void addHelpModelListener(HelpModelListener l) { + debug("addHelpModelListener: "); + debug(" l:"+l); + if (debug) { + try { + throw new Exception(""); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + listenerList.add(HelpModelListener.class, l); + } + + /** + * Removes a listener previously added with <b>addHelpListener</b> + * + * @param l - The listener to remove. If l is not in the list of listeners + * it is ignored. + * @see javax.help.HelpModel#addHelpModelListener + * @throws IllegalArgumentException if l is null. + */ + public void removeHelpModelListener(HelpModelListener l) { + listenerList.remove(HelpModelListener.class, l); + } + + /** + * Adds a listener for the TextHelpModelEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.HelpModel#removeHelpModelListener + * @throws IllegalArgumentException if l is null. + */ + public void addTextHelpModelListener(TextHelpModelListener l) { + debug("addTextHelpModelListener: "); + debug(" l:"+l); + // HERE + if (debug) { + try { + throw new Exception(""); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + textListenerList.add(TextHelpModelListener.class, l); + } + + /** + * Removes a listener previously added with <b>addHelpListener</b> + * + * @param l - The listener to remove. If l is not on the list of listeners + * it is ignored. + * @see javax.help.HelpModel#addHelpModelListener + * @throws IllegalArgumentException if l is null. + */ + public void removeTextHelpModelListener(TextHelpModelListener l) { + textListenerList.remove(TextHelpModelListener.class, l); + } + + /** + * Adds a listener to changes to the properties in this model. + * + * @param l the listener to add + */ + public void addPropertyChangeListener(PropertyChangeListener l) { + changes.addPropertyChangeListener(l); + } + + /** + * Removes a listener to changes to the properties in this model. + * + * @param l the listener to remove. If l is not on the list of listeners + * it is ignored. + */ + public void removePropertyChangeListener(PropertyChangeListener l) { + changes.removePropertyChangeListener(l); + } + + /** + * Assigns the document title. + * + * @param title the Title for the document currently being shown. A null + * title is valid. + */ + public void setDocumentTitle(String title) { + String oldTitle = this.title; + this.title = title; + changes.firePropertyChange("documentTitle", oldTitle, title); + } + + /** + * Gets the document title. + * + * @return The title for the current document. A null title is valid. If + * the title has not be previously set it will be null. + */ + public String getDocumentTitle() { + return title; + } + + protected void fireIDChanged(Object source, ID id, URL url, String historyName, JHelpNavigator navigator) { + Object[] listeners = listenerList.getListenerList(); + HelpModelEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == HelpModelListener.class) { + if (e == null) { + e = new HelpModelEvent(source, id, url, historyName, navigator); + } + debug("fireIDChanged: "); + debug(" "+listeners[i+1]); + debug(" id="+e.getID() + " url="+e.getURL()); + ((HelpModelListener)listeners[i+1]).idChanged(e); + } + } + } + + protected void fireIDChanged(Object source, ID id, URL url){ + fireIDChanged(source, id, url, (String)null, (JHelpNavigator)null); + } + + protected void fireHighlightsChanged(Object source) { + Object[] listeners = textListenerList.getListenerList(); + TextHelpModelEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == TextHelpModelListener.class) { + if (e == null) { + e = new TextHelpModelEvent(source); + } + debug("fireHighlightsChanged: "); + debug(" "+listeners[i+1]); + debug(" "+e); + ((TextHelpModelListener)listeners[i+1]).highlightsChanged(e); + } + } + } + + /** + * A default implementation of TextHelpModel.Highlight + */ + + public static class DefaultHighlight implements Highlight { + public int start, end; // start, end offsets. >=0 + + /** + * Constructor + */ + public DefaultHighlight(int start, int end) { + if (start < 0) { + throw new IllegalArgumentException("start"); + } + if (end < 0) { + throw new IllegalArgumentException("end"); + } + this.start = start; + this.end = end; + } + + /** + * Start offset + * + * @returns start offset (>=0) + */ + public int getStartOffset() { + return start; + } + + /** + * End offset + * + * @returns end offset (>=0) + */ + public int getEndOffset() { + return end; + } + } + + /** + * For printf debugging... + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.err.println("DefaultHelpModel: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java new file mode 100644 index 0000000000000000000000000000000000000000..c32ad8ce3ada6dd083e7f8720b433c7702c97635 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java @@ -0,0 +1,80 @@ +/* + * @(#)FavoritesAction.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.event.ActionListener; +import java.util.Enumeration; +import java.util.Locale; +import javax.swing.UIManager; + +/** + * + * @author Roger Brinkley + * @version 1.3 10/30/06 + */ +public class FavoritesAction extends AbstractHelpAction implements ActionListener { + + private static final String NAME = "FavoritesAction"; + private JHelpFavoritesNavigator favorites=null; + private ActionListener favoritesActionListener=null; + + /** Creates new FavoritesAction */ + public FavoritesAction(Object control) { + super(control, NAME); + if (control instanceof JHelp) { + JHelp help = (JHelp)control; + for (Enumeration e = help.getHelpNavigators(); e.hasMoreElements();) { + JHelpNavigator nav = (JHelpNavigator)e.nextElement(); + if(nav instanceof JHelpFavoritesNavigator) { + favorites = (JHelpFavoritesNavigator)nav; + favoritesActionListener = favorites.getAddAction(); + } + } + + setEnabled(favoritesActionListener != null); + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + } + } + + public void actionPerformed(java.awt.event.ActionEvent event) { + if (favoritesActionListener != null) { + favoritesActionListener.actionPerformed(event); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java new file mode 100644 index 0000000000000000000000000000000000000000..f4804ac6df24cc051660e67036ea50f21989e407 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java @@ -0,0 +1,250 @@ +/* + * @(#)FavoritesItem.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Vector; +import java.util.Locale; +import javax.help.Map.ID; +import java.awt.datatransfer.*; +import java.io.IOException; +import java.io.Serializable; +import java.net.URL; +import java.net.MalformedURLException; + +/** + * A class for individual favorites items. + * + * @author Richard Gregor + * @version 1.6 10/30/06 + */ + +public class FavoritesItem extends TreeItem implements Transferable, Serializable{ + private boolean isFolder = false; + + final public static DataFlavor FAVORITES_FLAVOR = + new DataFlavor(FavoritesItem.class, "Favorites Item"); + + static DataFlavor flavors[] = {FAVORITES_FLAVOR }; + + private FavoritesItem parent = null; + private Vector children = new Vector(); + private String url= null; + private String target = null; + private String title = null; + //determines wheter item was initialized as empty or not + private boolean emptyInitState = true; + private boolean visible = true; + + /** + * Creates item with name + * + * @param name The name of item + */ + public FavoritesItem(String name){ + setName(name); + } + + /** + * Creates empty item + */ + public FavoritesItem(){ + this(null); + } + /** + * Creates FavoritesItem. + * + * @param name The name of item + * @param target The target of item + * @param url The external representation of url + * @param title The title of the HelpSet + * @param locale The Locale of this item + */ + public FavoritesItem(String name, String target, String url, String title, Locale locale){ + this(name); + this.target = target; + this.url = url; + this.locale = locale; + this.title = title; + } + + public void setVisible(boolean visible){ + this.visible = visible; + } + + public boolean isVisible(){ + return visible; + } + + /** + * Returns the id for this item. + */ + public String getTarget() { + return target; + } + + /** + *Returns the external representation of url for this item. + */ + public String getURLSpec(){ + return url; + } + + /** + * Return the URL for this item + */ + public URL getURL () { + try { + return new URL(url); + } catch (MalformedURLException e) { + } + return null; + } + + /** + * Returns the title of HelpSet + */ + public String getHelpSetTitle(){ + return title; + } + + /** + * Sets this item as folder. + */ + public void setAsFolder(){ + isFolder = true; + } + + /** + * Returns wheter item allows children or not + */ + public boolean allowsChildren(){ + return isFolder(); + } + + /** + * Returns whether or not this item is leaf + */ + public boolean isLeaf(){ + return(!isFolder()); + } + /** + * Returns whether or not this item is folder. + */ + public boolean isFolder(){ + return isFolder; + } + + /** + * Adds FavoritesItem as a child. + * + * @param item The FavoritesItem. + */ + public void add(FavoritesItem item) { + item.setParent(this); + children.add(item); + emptyInitState = false; + isFolder = true; + } + + /** + * Returns true if item was initialized as empty + */ + public boolean emptyInitState(){ + return emptyInitState; + } + + /** + * Removes FavoritesItem from vector of children. + * + * @param item The FavoritesItem to remove. + */ + public void remove(FavoritesItem item) { + item.setParent(null); + children.remove(item); + } + + /** + * Returns parent of FavoritesItem. + */ + public FavoritesItem getParent() { + return parent; + } + + /** + * Sets the parent of this item. + * + * @param parent The FavoritesItem. + */ + public void setParent(FavoritesItem parent) { + this.parent = parent; + } + + /** + * Returns children of this FavoritesItem. + */ + public Vector getChildren() { + return children; + } + + public Object clone(){ + FavoritesItem item = new FavoritesItem(getName(), target, url, + title, locale); + return item; + } + + public String toString(){ + return getName(); + } + + /** + * Returns an object which represents the data to be transferred. + */ + public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException { + if (df.equals(FAVORITES_FLAVOR)) { + return this; + } + else throw new UnsupportedFlavorException(df); + } + + /** + * Returns an array of DataFlavor objects indicating the flavors the data can be provided in. + */ + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + /** + * Returns whether or not the specified data flavor is supported for this object. + */ + public boolean isDataFlavorSupported(DataFlavor df) { + return df.equals(FAVORITES_FLAVOR); + } + +} + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java new file mode 100644 index 0000000000000000000000000000000000000000..56302c6c1735cbf9b45359d0b014e188e30b4f44 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java @@ -0,0 +1,280 @@ +/* + * @(#)FavoritesNode.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.*; +import java.beans.*; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.IOException; +import java.util.Enumeration; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * A class for Favorites node. This class forces none-folders to have children. + * + * @author Richard Gregor + * @version 1.5 10/30/06 + */ + +public class FavoritesNode extends DefaultMutableTreeNode { + /** + * Header part of xml file + */ + public static final String HEADER="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+ + "<!DOCTYPE favorites\n PUBLIC \""+FavoritesView.publicIDString+ + "\"\n \"http://java.sun.com/products/javahelp/favorites_2_0.dtd\">\n"+ + "\n<favorites version=\"2.0\">\n"; + + /** + * XML element name + */ + public static final String ELEMENT="favoriteitem"; + /** + * Footer of xml document + */ + public static final String FOOTER="</favorites>"; + /** + * FavoritesItem userObject of this node + */ + private FavoritesItem item; + /** + * Creates a FavoritesNode for FavoritesItem. + * + * @param item The FavoritesItem + */ + public FavoritesNode(FavoritesItem item) { + super(item); + this.item = item; + } + + /** + * Returns wheter node is allowed to have children or not. + */ + public boolean getAllowsChildren() { + return ((FavoritesItem) getUserObject()).isFolder(); + } + + /** + * Adds the child node. + * + * @param child The DefaultMutableTreeNode with FavoritesItem as UserObject. + */ + public void add(DefaultMutableTreeNode child) { + super.add(child); + FavoritesItem childItem = (FavoritesItem) child.getUserObject(); + FavoritesItem oldParent = childItem.getParent(); + FavoritesItem newParent = (FavoritesItem) getUserObject(); + newParent.add(childItem); + } + + /** + * Removes the child node. + * + * @param child Node to remove. + */ + public void remove(DefaultMutableTreeNode child) { + super.remove(child); + FavoritesItem childItem = (FavoritesItem) ((FavoritesNode) child).getUserObject(); + FavoritesItem ParentItem = (FavoritesItem) getUserObject(); + if (parent != null) + ParentItem.remove(childItem); + } + /** + * Returns the number of visible children + * + */ + public int getVisibleChildCount(){ + int count = 0; + if( item == null) + return 0; + + for(Enumeration en = item.getChildren().elements(); en.hasMoreElements();){ + FavoritesItem nItem =(FavoritesItem)en.nextElement(); + if(nItem.isVisible()) + count++; + } + return count; + } + /** + * Returns the string representation of offset. + */ + public String getOffset(){ + String parentOffset = null; + String offset = null; + + FavoritesNode parent = (FavoritesNode)getParent(); + if(parent != null){ + parentOffset = parent.getOffset(); + offset = parentOffset + " "; + }else + offset = " "; + + return offset; + } + /** + * Exports nodes descendants to the OutputStream + * + * @param out The OutputStream + */ + public void export(OutputStream out) throws IOException{ + OutputStreamWriter writer = new OutputStreamWriter(out); + writer = exportHeader(out); + //exportNode(writer); + Enumeration chldn = children(); + if(!(chldn.equals(DefaultMutableTreeNode.EMPTY_ENUMERATION))){ + while(chldn.hasMoreElements()){ + FavoritesNode node = (FavoritesNode)chldn.nextElement(); + node.exportNode(writer); + } + } + writer.write(FOOTER); + //out.close(); + writer.close(); + } + + /** + * Exports node and its descendants to the xml file according favorites.dtd. + * + * @param out The OutputStream + */ + public void exportNode(OutputStreamWriter writer) throws IOException{ + TreeNode paren = getParent(); + FavoritesItem item = (FavoritesItem)getUserObject(); + writer.write(getOffset()+"<"+getXMLElement()+ " text=\""+item.getName()+"\" "); + String target = item.getTarget(); + if(target != null) + writer.write("target=\""+target+"\" "); + String url = item.getURLSpec(); + if(url != null) + writer.write("url=\""+url+"\""); + String hstitle = item.getHelpSetTitle(); + if(hstitle != null) + writer.write(" hstitle=\""+hstitle+"\""); + Enumeration chldn = children(); + if(chldn.equals(DefaultMutableTreeNode.EMPTY_ENUMERATION)) + writer.write("/>\n"); + else{ + writer.write(">\n"); + Enumeration offspring = children.elements(); + while(offspring.hasMoreElements()){ + FavoritesNode off = (FavoritesNode)offspring.nextElement(); + debug("offspring: "+off); + off.exportNode(writer); + } + writer.write(getOffset()+"</"+ELEMENT+">\n"); + } + + + } + + /** + * Exports header defined for this type of node to the OutputStream. + * + * @param out The OutputStream. + */ + public OutputStreamWriter exportHeader(OutputStream out) throws IOException{ + //OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8") + + OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8"); + writer.write(HEADER); + return writer; + } + + /** + * Returns the XML header string + */ + public String getXMLHeader(){ + return HEADER; + } + /** + * Returns the XML element string + */ + public String getXMLElement(){ + return ELEMENT; + } + + /** + * Returns the deep copy of node + */ + public FavoritesNode getDeepCopy(){ + + return new FavoritesNode((FavoritesItem)item.clone()); + /* + FavoritesNode copy = null; + ObjectOutputStream out = null; + ObjectInputStream in = null; + + try{ + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + out = new ObjectOutputStream(bOut); + out.writeObject(this); + out.flush(); + + in = new ObjectInputStream(new ByteArrayInputStream(bOut.toByteArray())); + copy =(FavoritesNode) in.readObject(); + + out.close(); + in.close(); + }catch(Exception e){ + System.err.println(e); + } + + return copy; + */ + + } + + /** + * Returns wheter node is visible or not + */ + public boolean isVisible(){ + return item.isVisible(); + } + + /** + * Sets visibility of node + */ + public void setVisible(boolean vis){ + item.setVisible(vis); + } + + /** + * Debugging code + */ + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("FavoritesNode: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java new file mode 100644 index 0000000000000000000000000000000000000000..98dc9f3beae4092b2c5946fee2feb8b74c48839c --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java @@ -0,0 +1,604 @@ +/* + * @(#)FavoritesView.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.Component; +import java.net.*; +import java.io.*; +import java.util.Hashtable; +import java.util.HashMap; +import java.util.Locale; +import java.util.Vector; +import java.util.Stack; +import java.util.Enumeration; +import javax.help.Map.ID; +import javax.swing.tree.TreeNode; +import javax.swing.tree.DefaultMutableTreeNode; +import com.sun.java.help.impl.*; + + +/** + * Navigational View information for the Favorites + * + * @author Richard Gregor + * @version 1.2 08/29/01 + */ +public class FavoritesView extends NavigatorView{ + /** + * PublicID (known to this XML processor) to the DTD for version 2.0 of the Index + */ + public static final String publicIDString = + "-//Sun Microsystems Inc.//DTD JavaHelp Favorites Version 2.0//EN"; + + // turn this on if you want messages on failures + private static boolean warningOfFailures = false; + /** + * The HelpSet + */ + private HelpSet hs; + /** + * Determines wheter save action of favorites file is enabled or not + */ + private boolean enabledSave = true; + + /** + * Construct an FavoritesView with some given data. Locale defaults to that + * of the HelpSet. + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param params A hashtable providing different key/values for this type. + * A null for params is valid. + */ + public FavoritesView(HelpSet hs, + String name, + String label, + Hashtable params) { + super(hs, name, label, hs.getLocale(), params); + } + + /** + * Constructs an FavoritesView with some given data. + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param locale The default locale to interpret the data in this TOC. A + * null for locale will be interpreted as the defaultLocale. + * @param params A Hashtable providing different key/values for this type + * A null for params is valid. + */ + public FavoritesView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) { + super(hs, name, label, locale, params); + } + + /** + * create a navigator for a given model. + * @param model The HelpModel to create this navigator with. A null model + * is valid. + * @return The appropriate Component for this view. + */ + public Component createNavigator(HelpModel model) { + return new JHelpFavoritesNavigator(this, model); + } + + /** + * Get the Index navigators mergeType. Overrides getMergeType in NavigatorView + */ + public String getMergeType() { + String mergeType = super.getMergeType(); + if (mergeType == null) { + return "javax.help.NoMerge"; + } + return mergeType; + } + + /** + * Gets a DefaultMutableTreeNode representing the + * information in this view instance. + * + * The default implementation parses the data in the URL, but a subclass may + * override this method and provide a different implemenation. For example, + * it may create the tree programatically. + */ + public FavoritesNode getDataAsTree() { + HelpSet hs = getHelpSet(); + debug("helpSet in "+this+hs.toString()); + + return (FavoritesNode)parse(hs, hs.getLocale(), + new DefaultFavoritesFactory()); + } + + /** + * Public method for parsing the Favorites in a URL. + * It returns a DefaultMutableTreeNode and its children + * that correspond to the favoritesItems in the Favorites. The factory is invoked to create + * the TreeItems that are included in the DefaultMutableTreeNode as user + * data. + * + * @param url Location of the Favorites. If null, causes null value to be returned. + * @param hs The HelpSet context for this Favorites. Null hs is ignored. + * @param locale The default locale to interpret the data in this Favorites. Null + * locale is treated as the default locale. + * @param factory A factory instance that is used to create the FavoritesItems + * @return a TreeNode that represents the Favorites. Returns null if parsing errors + * were encountered. + */ + public FavoritesNode parse(HelpSet hs, Locale locale, TreeItemFactory factory) { + Reader src; + DefaultMutableTreeNode node = null; + URL url= null; + try { + String user_dir = System.getProperty("user.home"); + File file = new File(user_dir+File.separator+".JavaHelp"+File.separator+"Favorites.xml"); + if(!file.exists()) + return new FavoritesNode(new FavoritesItem("Favorites")); + try{ + url = file.toURL(); + }catch(MalformedURLException e){ + System.err.println(e); + } + + URLConnection uc = url.openConnection(); + src = XmlReader.createReader(uc); + factory.parsingStarted(url); + node = (new FavoritesParser(factory)).parse(src, hs, locale); + src.close(); + } catch (Exception e) { + factory.reportMessage("Exception caught while parsing "+url+ + e.toString(), + false); + } + return (FavoritesNode)factory.parsingEnded(node); + } + + + /** + * Saves favorites file + * + * @param node The FavoritesNode + */ + + public void saveFavorites(FavoritesNode node){ + if(!enabledSave) + return; + try{ + FileOutputStream out; + String user_dir = System.getProperty("user.home"); + File file = new File(user_dir+File.separator+".JavaHelp"); + file.mkdirs(); + String userFile = file.getPath()+File.separator+"Favorites.xml"; + debug("new file:"+userFile); + node.export(out = new FileOutputStream(userFile)); + out.close(); + }catch(SecurityException se){ + enabledSave = false; + se.printStackTrace(); + }catch(Exception excp){ + excp.printStackTrace(); + } + } + /** + * A default TreeItemFactory that can be used to parse Favorites items as used + * by this navigator. + */ + public static class DefaultFavoritesFactory implements TreeItemFactory{ + private Vector messages = new Vector(); + private URL source; + private boolean validParse = true; + + /** + * Parsing has started + */ + public void parsingStarted(URL source) { + if (source == null) { + throw new NullPointerException("source"); + } + this.source = source; + } + + /** + * Process a DOCTYPE + */ + public void processDOCTYPE(String root, + String publicID, + String systemID) { + if (publicID == null || + !publicID.equals(publicIDString)) { + reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat", publicID), false); + } + } + + /** + * We have found a PI; ignore it + */ + public void processPI(HelpSet hs, String target, String data) { + } + + /** + * Creates an FavoritesItem with the given data. + * @param tagName The favorites type to create. + * Valid types are "favoriteitem". Null or invalid types throw an + * IllegalArgumentException. + * @param atts Attributes of the Item. Valid attributes are "target" + * and "text". A null <tt>atts</tt> is valid and means no attributes. + * @param hs The HelpSet this item was created under. + * @param locale Locale of this item. A null locale is valid. + * @returns A fully constructed TreeItem. + * @throws IllegalArgumentException if tagname is null or invalid. + */ + public TreeItem createItem(String tagName, + Hashtable atts, + HelpSet hs, + Locale locale) { + if (tagName == null || !tagName.equals("favoriteitem")) { + throw new IllegalArgumentException("tagName"); + } + FavoritesItem item = null; + String target = null; + String name = null; + String mergeType = null; + String url = null; + String hstitle = null; + + if (atts != null ) { + target = (String) atts.get("target"); + debug("target:"+target); + name = (String) atts.get("text"); + url = (String) atts.get("url"); + hstitle = (String) atts.get("hstitle"); + item = new FavoritesItem(name,target,url,hstitle,locale); + if((item.getTarget() == null) &&(item.getURLSpec() == null)) + item.setAsFolder(); + }else + item = new FavoritesItem(); + + + + return item; + } + + /** + * Creates a default FavoritesItem. + */ + public TreeItem createItem() { + debug("empty item created"); + return new FavoritesItem(); + } + + /** + * Reports an error message. + */ + public void reportMessage(String msg, boolean validParse) { + messages.addElement(msg); + this.validParse = this.validParse && validParse; + } + + /** + * Lists all the error messages. + */ + public Enumeration listMessages() { + return messages.elements(); + } + + /** + * Parsing has ended. The last chance to do something + * to the node + * @param node The DefaultMutableTreeNode that has been built during the + * the parsing. If <tt>node</tt> is null or there were parsing errors a null + * is returned. + * @returns A valid DefaultMutableTreeNode if the parsing succeded or null + * if it failed + */ + public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) { + DefaultMutableTreeNode back = node; + if (! validParse) { + // A parse with problems... + back = null; + System.err.println("Parsing failed for "+source); + for (Enumeration e = messages.elements(); + e.hasMoreElements();) { + String msg = (String) e.nextElement(); + // need to think about this one... + System.err.println(msg); + } + } + return back; + } + + } + + + /** + * Inner class for parsing an Favorites stream. + * + * WARNING!! This class is an interim solution until JH moves to a + * real XML parser. This is not a public class. Clients should only use + * the parse method in the enclosing class. + */ + + private static class FavoritesParser implements ParserListener { + private HelpSet currentParseHS; // HelpSet we are parsing into + private Stack nodeStack; // to track the parsing + private Stack itemStack; + private Stack tagStack; + private Locale defaultLocale; + private Locale lastLocale; + private boolean startedfavorites; + private TreeItemFactory factory; + + /** + * Creates an Favorites Parser using a factory instance to create the item nodes. + * + * @param factory The ItemTreeFactory instance to use when a node + * has been recognized. + */ + + FavoritesParser(TreeItemFactory factory) { + this.factory = factory; + } + + /** + * Parse a reader into a DefaultMutableTreeNode. + * Only one of these at a time. + */ + synchronized FavoritesNode parse(Reader src, + HelpSet context, + Locale locale) + throws IOException { + nodeStack = new Stack(); + itemStack = new Stack(); + tagStack = new Stack(); + + if (locale == null) { + defaultLocale = Locale.getDefault(); + } else { + defaultLocale = locale; + } + lastLocale = defaultLocale; + + FavoritesNode node = new FavoritesNode(new FavoritesItem("Favorites")); + nodeStack.push(node); + + currentParseHS = context; + + Parser parser = new Parser(src); // the XML parser instance + parser.addParserListener(this); + parser.parse(); + return node; + } + + /** + * A Tag was parsed. This method is not intended to be of general use. + */ + public void tagFound(ParserEvent e) { + Locale locale = null; + Tag tag = e.getTag(); + TagProperties attr = tag.atts; + + if (attr != null) { + String lang = attr.getProperty("xml:lang"); + locale = HelpUtilities.localeFromLang(lang); + } + if (locale == null) { + locale = lastLocale; + } + + if (tag.name.equals("favoriteitem")) { + if (!startedfavorites) { + factory.reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat"), + false); + } + if (tag.isEnd && ! tag.isEmpty) { + nodeStack.pop(); + itemStack.pop(); + removeTag(tag); + return; + } + + TreeItem item = null; + try { + Hashtable t = null; + if (attr != null) { + t = attr.getHashtable(); + } + item = factory.createItem("favoriteitem", + t, + currentParseHS, + locale); + } catch (Exception ex) { + if (warningOfFailures) { + String id=null; + if (attr != null) { + id = attr.getProperty("target"); + } + System.err.println("Failure in FavoritesItem Creation; "); + System.err.println(" id: "+id); + System.err.println(" hs: "+currentParseHS); + ex.printStackTrace(); + } + debug("empty item !"); + item = factory.createItem(); + } + + FavoritesNode node = new FavoritesNode((FavoritesItem)item); + FavoritesNode parent = + (FavoritesNode) nodeStack.peek(); + parent.add(node); + if (! tag.isEmpty) { + itemStack.push(item); + nodeStack.push(node); + addTag(tag, locale); + } + } else if (tag.name.equals("favorites")) { + if (!tag.isEnd) { + if (attr != null) { + String version = attr.getProperty("version"); + if (version != null && + version.compareTo("2.0") != 0) { + factory.reportMessage(HelpUtilities.getText("favorites.unknownVersion", version), false); + } + } + if (startedfavorites) { + factory.reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat"), + false); + } + startedfavorites = true; + addTag(tag, locale); + } else { + if (startedfavorites) { + startedfavorites = false; + } + removeTag(tag); + } + return; + } + } + + /** + * A PI was parsed. This method is not intended to be of general use. + */ + public void piFound(ParserEvent e) { + // ignore + } + + /** + * A DOCTYPE was parsed. This method is not intended to be of general use. + */ + public void doctypeFound(ParserEvent e) { + // ignore for now + factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId()); + } + + /** + * A continous block of text was parsed. + */ + public void textFound(ParserEvent e) { + if (tagStack.empty()) { + return; // ignore + } + LangElement le = (LangElement) tagStack.peek(); + Tag tag = (Tag) le.getTag(); + if (tag.name.equals("favoriteitem")) { + FavoritesItem item = (FavoritesItem) itemStack.peek(); + String oldName = item.getName(); + if (oldName == null) { + item.setName(e.getText().trim()); + } else { + item.setName(oldName.concat(e.getText()).trim()); + } + } + } + + // The remaing events from Parser are ignored + public void commentFound(ParserEvent e) {} + + public void errorFound(ParserEvent e){ + factory.reportMessage(e.getText(), false); + } + + /** + * Keeps track of tags and their locale attributes. + */ + protected void addTag(Tag tag, Locale locale) { + LangElement el = new LangElement(tag, locale); + tagStack.push(el); + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It is impossible for locale to be null + if (lastLocale == null) { + lastLocale = locale; + return; + } + if (locale == null) { + lastLocale = locale; + return; + } + if (! lastLocale.equals(locale)) { + lastLocale = locale; + } + } + + /** + * Removes a tag from the tagStack. The tagStack is + * used to keep track of tags and locales. + */ + protected void removeTag(Tag tag) { + LangElement el; + String name = tag.name; + Locale newLocale=null; + + for (;;) { + if (tagStack.empty()) + break; + el = (LangElement) tagStack.pop(); + if (! el.getTag().name.equals(name)) { + if (tagStack.empty()) { + newLocale = defaultLocale; + } else { + el = (LangElement) tagStack.peek(); + newLocale = el.getLocale(); + } + break; + } + } + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It also possible for locale to be null so if lastLocale is set + // then reset lastLocale to null; + // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale + if (lastLocale == null) { + lastLocale = newLocale; + return; + } + if (newLocale == null) { + lastLocale = newLocale; + return; + } + if (! lastLocale.equals(newLocale)) { + lastLocale = newLocale; + } + } + + } + + /** + * Debugging code + */ + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("FavoritesView: "+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java b/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java new file mode 100644 index 0000000000000000000000000000000000000000..b3fb909de77a46c76a841b09bd85c7fb1f96294b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java @@ -0,0 +1,480 @@ +/* + * @(#)FlatMap.java 1.36 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.util.*; +import java.io.*; +import java.beans.*; +import javax.help.event.*; +import javax.help.Map.ID; +import com.sun.java.help.impl.*; + +/** + * A FlatMap is a simple implementation of a Map. It is used to represent a + * Map for a single file. + * + * @author Eduardo Pelegri-Llopart + * @version 1.18 01/22/99 + */ +public class FlatMap implements Map, Serializable { + private URL base; // URL to this map + private ResourceBundle resource; // the resource + private HelpSet helpset; // the top HelpSet + + /** + * PublicID (known to this XML processor) to the DTD for version 1.0 of the Map + */ + public static final String publicIDString = + "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN"; + + /** + * PublicID (known to this XML processor) to the DTD for version 1.0 of the Map + */ + public static final String publicIDString_V2 = + "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 2.0//EN"; + + /** + * Create a FlatMap from a given URL. + * + * @param source The URL that is the source for all references in this Map. + * @param hs The HelpSet providing "context" for this Map. + * @throws IllegalArgumentException if hs doesn't have nested HelpSets. + */ + public FlatMap(URL base, HelpSet hs) throws IOException { + debug("Creating FlatMap for: "+base); + + // Verify that this helpset indeed does not have nested HelpSets. + for (Enumeration e = hs.getHelpSets(); + e.hasMoreElements(); ) { + throw new IllegalArgumentException + ("Cannot create - HelpSet is not flat"); + } + + // InputStream is = base.openStream(); + // resource = new MapResourceBundle(is); + resource = new FlatMapResourceBundle(base); + this.base = base; + this.helpset = hs; + } + + /** + * The HelpSet for this Map. + */ + public HelpSet getHelpSet() { + return helpset; + } + + /** + * Determines whether the given ID is valid. If hs is null + * it is ignored. + * + * @param id The String ID. + * @param hs The HelpSet against which to resolve the string. + * @return True if id is valid, false if not valid. + */ + + public boolean isValidID(String id, HelpSet hs) { + debug("isValidID "+id); + + try { + String tmp = resource.getString(id); + } catch (MissingResourceException e) { + return false; + } + return true; + } + + /** + * Gets an enumeration of all the IDs in a Map. + * + * @return An enumeration of all the IDs in a Map. + */ + public Enumeration getAllIDs() { + return new FlatEnumeration(resource.getKeys(), helpset); + } + + /** + * Gets the URL that corresponds to a given ID in the map. + * + * @param iden The iden to get the URL for. If iden is null it is + * treated as an unresolved ID and will return null. + * @return URL The matching URL. Null if this map cannot solve the ID + * @exception MalformedURLException if the URLspecification found is malformed + */ + public URL getURLFromID(ID iden) throws MalformedURLException { + debug("getURLFromID("+iden+")"); + + String id = iden.id; + HelpSet hs = iden.hs; + if (id == null) { + return null; + } + String tmp = null; + try { + tmp = resource.getString(id); + URL back = new URL(base, tmp); + return back; + } catch (MissingResourceException e) { + return null; + } + } + + /** + * Determines if the URL corresponds to an ID in the Map. + * + * @param url The URL to check on. + * @return true If this is an ID, otherwise false. + */ + public boolean isID(URL url) { + URL tmp; + for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) { + try { + String key = (String) e.nextElement(); + tmp = new URL(base, (String) resource.getObject(key)); + // sameFile() ignores the anchor! - epll + if (url.sameFile(tmp) == true) { + return true; + } + } catch (Exception ex) { + } + } + return false; + } + + + /** + * Gets the ID for this URL. + * + * @param url The URL to get the ID for. + * @return The id (Map.ID) or null if URL is not an ID. + */ + public ID getIDFromURL(URL url) { + String tmp; + URL tmpURL; + if (url == null) return null; + String urlString = url.toExternalForm(); + for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) { + String key = (String) e.nextElement(); + try { + tmp = resource.getString(key); + tmpURL = new URL(base, tmp); + + // Sometimes tmp will be null because not all keys are ids + if (tmpURL == null) continue; + String tmpString = tmpURL.toExternalForm(); + if (urlString.compareTo(tmpString) == 0) { + return ID.create(key, helpset); + } + } catch (Exception ex) { + } + } + return null; + } + + /** + * Determines the ID that is "closest" to this URL (with a given anchor). + * + * The definition of this is up to the implementation of Map. In particular, + * it may be the same as getIDFromURL(). + * + * @param url A URL + * @return The closest ID in this map to the given URL + */ + public ID getClosestID(URL url) { + return getIDFromURL(url); + } + + + /** + * Determines the IDs related to this URL. + * + * @param URL The URL to compare the Map IDs to. + * @return Enumeration of Map.IDs + */ + public Enumeration getIDs(URL url) { + String tmp=null; + URL tmpURL=null; + Vector ids = new Vector(); + for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) { + String key = (String) e.nextElement(); + try { + tmp = resource.getString(key); + tmpURL = new URL(base, tmp); + if (url.sameFile(tmpURL) == true) { + ids.addElement(key); + } + } catch (Exception ex) { + } + } + return new FlatEnumeration(ids.elements(), helpset); + } + + private static class FlatEnumeration implements Enumeration { + private Enumeration e; + private HelpSet hs; + + public FlatEnumeration(Enumeration e, HelpSet hs) { + this.e = e; + this.hs = hs; + } + + public boolean hasMoreElements() { + return e.hasMoreElements(); + } + + public Object nextElement() { + Object back = null; + try { + back = ID.create((String) e.nextElement(), hs); + } catch (Exception ex) { + } + return back; + } + } + + + /** + * FlatMapResourceBundle is a ResourceBundle but unlike most + * ResourceBundles it is not locale-based and is loaded via the + * constructor, not getBundle. + */ + protected class FlatMapResourceBundle extends ResourceBundle + implements ParserListener, Serializable + { + + private Hashtable lookup = null; + private boolean startedmap; + private URL source; + + /** + * Creates the FlatMap from the data. + */ + public FlatMapResourceBundle(URL url) { + source = url; + Reader src; + try { + URLConnection uc = url.openConnection(); + src = XmlReader.createReader(uc); + parse(src); + src.close(); + } catch (Exception e) { + reportMessage("Exception caught while parsing "+url+" "+ + e.toString(), false); + } + parsingEnded(); + for (Enumeration e = lookup.keys() ; e.hasMoreElements() ;) { + String key1 = (String) e.nextElement(); + String url1 = (String) lookup.get(key1); + } + } + + /** + * Overrides ResourceBundle, same semantics. + */ + public final Object handleGetObject(String key) { + return lookup.get(key); // this class ignores locales + } + + /** + * Implements ResourceBundle.getKeys. + */ + public Enumeration getKeys() { + return lookup.keys(); + } + + /** + * Parses a reader into a MutableTreeNode + * Only one of these at a time. + */ + synchronized void parse(Reader src) + throws IOException + { + lookup = new Hashtable(10); + + Parser parser = new Parser(src); // the XML parser instance + parser.addParserListener(this); + parser.parse(); + } + + /** + * A tag was parsed. + */ + public void tagFound(ParserEvent e) { + Locale locale = null; + Tag tag = e.getTag(); + FlatMap.debug("TagFound: "+tag.name); + TagProperties attr = tag.atts; + + // Nothing tricky about mapID it doesn't have any hierarchy to it. + if (tag.name.equals("mapID")) { + if (!startedmap) { + parsingError("map.invalidMapFormat"); + } + + String target = null; + String url = null; + if (attr != null) { + target = attr.getProperty("target"); + url = attr.getProperty("url"); + } + if (target == null || url == null) { + reportMessage("Failure in mapID Creation;", true); + reportMessage(" target: "+ target, true); + reportMessage(" url: "+ url, true); + return; + } + lookup.put(target, url); + return; + } else if (tag.name.equals("map")) { + if (!tag.isEnd) { + if (attr != null) { + String version = attr.getProperty("version"); + if (version != null && + (version.compareTo("1.0") != 0 && + version.compareTo("2.0") != 0)) { + parsingError("map.unknownVersion", version); + } + } + if (startedmap) { + parsingError("map.invalidMapFormat"); + } + startedmap = true; + } else { + if (startedmap) { + startedmap = false; + } + } + return; + } + } + + /** + * A PI was parsed. This method is not intended to be of general use. + */ + public void piFound(ParserEvent e) { + // ignore + } + + /** + * A DOCTYPE was parsed. This method is not intended to be of general use. + */ + public void doctypeFound(ParserEvent e) { + String publicID = e.getPublicId(); + if (publicID == null || + (publicID.compareTo(publicIDString) != 0 && + publicID.compareTo(publicIDString_V2) != 0)) { + parsingError("map.wrongPublicID", publicID); + } + } + + /** + * A continous block of text was parsed. + */ + public void textFound(ParserEvent e) { + // At the current time I don't care about text. All the text is + // within the attributes in the tag + } + + // The remaing events from Parser are ignored + public void commentFound(ParserEvent e) {} + + public void errorFound(ParserEvent e){ + reportMessage(e.getText(), false); + } + + + private Vector messages = new Vector(); + private boolean validParse = true; + + /** + * Reports an error message. + */ + public void reportMessage(String msg, boolean validParse) { + messages.addElement(msg); + this.validParse = this.validParse && validParse; + } + + /** + * Enumerates all the error messages. + */ + public Enumeration listMessages() { + return messages.elements(); + } + + /** + * Parsing has ended. We are given a last chance to do something + * to the HelpSet + */ + private void parsingEnded() { + if (! validParse) { + if (lookup != null) { + lookup.clear(); + } + + // A parse with problems... + FlatMap.debug("Parsing failed for "+source); + + for (Enumeration e = messages.elements(); + e.hasMoreElements();) { + String msg = (String) e.nextElement(); + + FlatMap.debug(msg); + } + } else { + // little memory clean up + source = null; + } + } + + // Convenience methods + private void parsingError(String key) { + String s = HelpUtilities.getText(key); + reportMessage(s, false); // tree will be wrong + } + + private void parsingError(String key, String s) { + String msg = HelpUtilities.getText(key, s); + reportMessage(msg, false); // tree will be wrong + } + + } + + /** + * For printf debugging... + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("FlatMap: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java b/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java new file mode 100644 index 0000000000000000000000000000000000000000..0e9da663df41e3175d244aa56a51f064ed5f1a15 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java @@ -0,0 +1,188 @@ +/* + * @(#)ForwardAction.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.*; +import java.awt.event.*; +import javax.help.*; +import javax.help.event.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Stack; +import javax.swing.*; + +/** + * + * @author Stepan Marek + * @version 1.4 10/30/06 + */ +public class ForwardAction extends AbstractHelpAction implements MouseListener, HelpHistoryModelListener { + + private static final String NAME = "ForwardAction"; + + private static final int DELAY = 500; + private Timer timer; + private HelpHistoryModel historyModel; + + /** Creates new ForwardAction */ + public ForwardAction(Object control) { + super(control, NAME); + if (control instanceof JHelp) { + JHelp help = (JHelp)control; + historyModel = help.getHistoryModel(); + historyModel.addHelpHistoryModelListener(this); + + setEnabled(historyModel.getIndex() > 0); + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + } + } + + /** + * Invoked when the mouse exits a component. + */ + public void mouseExited(MouseEvent e) { + } + + /** + * Invoked when a mouse button has been released on a component. + */ + public void mouseReleased(MouseEvent e) { + if (timer != null) { + timer.stop(); + } + } + + /** + * Invoked when a mouse button has been pressed on a component. + */ + public void mousePressed(MouseEvent e) { + timer = new Timer(DELAY, new TimeListener(e)); + timer.start(); + } + + /** + * Invoked when the mouse has been clicked on a component. + */ + public void mouseClicked(MouseEvent e) { + if ((historyModel != null) && isEnabled()) { + historyModel.goForward(); + } + } + + /** + * Invoked when the mouse enters a component. + */ + public void mouseEntered(MouseEvent e) { + } + + private class TimeListener implements ActionListener { + + private MouseEvent e; + + public TimeListener(MouseEvent e) { + this.e = e; + } + + public void actionPerformed(ActionEvent evt){ + timer.stop(); + if (ForwardAction.this.isEnabled()) { + ForwardAction.this.showForwardHistory(e); + } + } + } + + private class HistoryActionListener implements ActionListener { + + private int index; + + public HistoryActionListener(int index) { + this.index = index; + } + + public void actionPerformed(java.awt.event.ActionEvent event) { + if(historyModel != null) { + historyModel.setHistoryEntry(index); + } + } + } + + /** + * Shows popup with forward history entries + */ + private void showForwardHistory(MouseEvent e) { + + JPopupMenu forwardMenu = new JPopupMenu("Forward History"); + + if (historyModel == null) { + return; + } + + Locale locale = ((JHelp)getControl()).getModel().getHelpSet().getLocale(); + Enumeration items = historyModel.getForwardHistory().elements(); + JMenuItem mi = null; + int index = historyModel.getIndex() + 1; + //while(items.hasMoreElements()){ + for(int i = 0; items.hasMoreElements(); i++) { + HelpModelEvent item = (HelpModelEvent) items.nextElement(); + if(item != null) { + String title = item.getHistoryName(); + if (title == null) { + title = HelpUtilities.getString(locale, "history.unknownTitle"); + } + mi = new JMenuItem(title); + //mi.setToolTipText(item.getURL().getPath()); + mi.addActionListener(new HistoryActionListener(i + index)); + forwardMenu.add(mi); + } + } + // if(e.isPopupTrigger()) + forwardMenu.show(e.getComponent(),e.getX(),e.getY()); + + } + + /** + * Tells the listener that the history has changed. + * Will enable/disable the Action depending on the events previous flag + * + * @param e The HelpHistoryModelEvent + */ + public void historyChanged(HelpHistoryModelEvent e) { + setEnabled(e.isNext()); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java b/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java new file mode 100644 index 0000000000000000000000000000000000000000..ae3abafdb695ddaf04e68ae56dbcb845bc892814 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java @@ -0,0 +1,88 @@ +/* + * @(#)GlossaryView.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.Component; +import java.util.Hashtable; +import java.util.Locale; +import javax.help.HelpSet; +import javax.help.HelpModel; +import javax.help.IndexView; + +/** + * View information for a Glossary Navigator + * + * @author Roger Brinkley + * @version 1.2 10/30/06 + */ + +public class GlossaryView extends IndexView { + /** + * Construct a GlossaryView with some given data. Locale defaults + * to that of the HelpSet + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param params A Hashtable providing different key/values for this type + */ + public GlossaryView(HelpSet hs, + String name, + String label, + Hashtable params) { + super(hs, name, label, hs.getLocale(), params); + } + + /** + * Construct a GlossaryViewer VIew with some given data. + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param locale The default locale to interpret data in this View + * @param params A Hashtable providing different key/values for this type + */ + public GlossaryView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) { + super(hs, name, label, locale, params); + } + + /** + * create a navigator for a given model + */ + public Component createNavigator(HelpModel model) { + return new JHelpGlossaryNavigator(this, model); + } +} + + + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java b/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java new file mode 100644 index 0000000000000000000000000000000000000000..719e8d80818a56346c30e8e604e459ca93c85498 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java @@ -0,0 +1,89 @@ +/* + * @(#)HelpAction.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.beans.PropertyChangeListener; +/** + * @author Stepan Marek + * @version 1.2 10/30/06 + */ +public interface HelpAction { + + /** Getter for property enabled. + * @return Value of property enabled. + */ + public boolean isEnabled(); + + /** Setter for property enabled. + * @param enabled New value of property enabled. + */ + public void setEnabled(boolean enabled); + + /** Getter for property control. + * @return Value of property control. + */ + public Object getControl(); + + /** + * Gets one of this object's properties + * using the associated key. + * @see #putValue + */ + public Object getValue(String key); + + /** + * Sets one of this object's properties + * using the associated key. If the value has + * changed, a <code>PropertyChangeEvent</code> is sent + * to listeners. + * + * @param key a <code>String</code> containing the key + * @param value an <code>Object</code> value + */ + public void putValue(String key, Object value); + + /** + * Adds a <code>PropertyChange</code> listener. Containers and attached + * components use these methods to register interest in this + * <code>Action</code> object. When its enabled state or other property + * changes, the registered listeners are informed of the change. + * + * @param listener a <code>PropertyChangeListener</code> object + */ + public void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Removes a <code>PropertyChange</code> listener. + * + * @param listener a <code>PropertyChangeListener</code> object + * @see #addPropertyChangeListener + */ + public void removePropertyChangeListener(PropertyChangeListener listener); + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java new file mode 100644 index 0000000000000000000000000000000000000000..dbae3aa0f1f68a91c9cb7c6f9784c0fecb8bc7d2 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java @@ -0,0 +1,386 @@ +/* + * @(#)HelpBroker.java 1.31 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Enumeration; +import java.net.URL; +import java.awt.Component; +import java.awt.MenuItem; +import java.awt.event.ActionListener; +import java.awt.Point; +import java.awt.Font; +import java.awt.Dimension; +import javax.help.Map.ID; +import java.util.Locale; + +/** + * The HelpBroker is the default presentation of a HelpSet. + * + * A HelpBroker is an abstraction of the presentation for a HelpSet; + * a straight-forward implementation is a JHelp() on the HelpSet. + * + * A HelpBroker can be asked to show a given Navigational View, + * and can display a given ID (help topic). + * + * @author Eduardo Pelegri-Llopart + * @author Roger D.Brinkley + * @version 1.31 10/30/06 + * + * @see javax.help.HelpSet + * @see javax.help.JHelpNavigator + * @see javax.help.HelpVisitListener + */ + +public interface HelpBroker { + /** + * Sets the current HelpSet for this HelpBroker. + * + * @param hs The HelpSet this JavaHelp is presenting. + */ + public void setHelpSet(HelpSet hs); + + /** + * Gets the current HelpSet for this JavaHelp object. + * + * @return The HelpSet this JavaHelp is presenting. + */ + public HelpSet getHelpSet(); + + /** + * Sets the presentation attributes from a HelpSet.Presentation. + * The HelpSet.Presentation must be in the current HelpSet. + * + * @param hsPres The HelpSet.Presentation + * @since 2.0 + */ + public void setHelpSetPresentation(HelpSet.Presentation hsPres); + + /** + * Returns the locale of this object. + * + * @return The locale of this object. + */ + public Locale getLocale(); + + /** + * Sets the locale of this HelpBroker. + * @param l The locale to become this component's locale. + * @see #getLocale + */ + public void setLocale(Locale l); + + /** + * Gets the font for this HelpBroker. + */ + public Font getFont(); + + /** + * Sets the font for this HelpBroker. + * + */ + public void setFont(Font f); + + /** + * Activates the Navigator view with a given name. + * + * @exception IllegalArgumentException if the name is not valid. + */ + public void setCurrentView(String name); + + /** + * Gets name of the current navigational view. + * + * @return The name of the current navigational view. + */ + public String getCurrentView(); + + /** + * Initializes the presentation. + * This method allows the presentation to be initialized but not displayed. + * Typically this is done in a separate thread to reduce the + * intialization time. + */ + public void initPresentation(); + + /** + * Displays the presentation to the user. + * + * @param displayed Makes the presentation visible or not. + * @exception HelpBroker.UnsupportedOperationException If the operation is not supported. + */ + public void setDisplayed(boolean displayed) throws UnsupportedOperationException; + + /** + * Determines if the presentation is visible. + * + * @return Whether the presentation is currently visible. + */ + public boolean isDisplayed(); + + /** + * Sets the position of the presentation. + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public void setLocation(Point p) throws UnsupportedOperationException; + + /** + * Gets the location of the presentation. + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public Point getLocation() throws UnsupportedOperationException; + + /** + * Sets the size of the presentation. + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public void setSize(Dimension d) throws UnsupportedOperationException; + + /** + * Gets the size of the presentation. + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public Dimension getSize() throws UnsupportedOperationException; + + /** + * Set the screen the presentation is to be displayed on + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public void setScreen(int screen) throws UnsupportedOperationException; + + /** + * Get ths the screen the presentation is displayed on + * This operation may throw an UnsupportedOperationException if the + * underlying implementation does not allow this. + */ + public int getScreen() throws UnsupportedOperationException; + + /** + * Hides/Shows Navigational Views. + * + * @param displayed Make the navigational views visible or not. + */ + public void setViewDisplayed(boolean displayed); + + /** + * Determines if the Navigational View is visible. + * + * @return Whether the navigational views are visible. + */ + public boolean isViewDisplayed(); + + + /** + * Displays this ID in a given presentation + * + * @param id An ID that identifies the topic to display. + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * @exception InvalidHelpSetContextException If id.hs is not contanied in the current + * HelpSet of this broker. + * @see Presentation + */ + public void showID(ID id, String presentation, String presentationName) + throws InvalidHelpSetContextException; + + /** + * Displays this ID in a particular presentation + * + * @param id A String identifying the topic to show relative to getHelpSet() + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * @exception BadIDException if the ID is not valid in the map. + * @see Presentation + */ + public void showID(String id, String presentation, String presentationName) + throws BadIDException; + + /** + * Displays this ID. + * + * @param id An ID that identifies the topic to display. + * @exception InvalidHelpSetContextException If id.hs is not contanied in the current + * HelpSet of this broker. + * @see HelpModel#setCurrentID + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException; + + /** + * Displays this ID. + * HelpVisitListeners are notified. + * + * @param id A String identifying the topic to show relative to getHelpSet() + * @exception BadIDException if the ID is not valid in the map. + */ + public void setCurrentID(String id) throws BadIDException; + + /** + * Determines The currently displayed ID (if any). + * + * @return The ID being shown. + */ + public ID getCurrentID(); + + /** + * Displays this ID. + * HelpVisitListeners are notified. + * The currentID changes if there is a matching ID for this URL. + * + * @param url The URL to show + */ + public void setCurrentURL(URL url); + + /** + * Determines the currently displayed ID. + * + * @return The URL being shown. + */ + public URL getCurrentURL(); + + /** + * Enables the Help key on a component. This method works best when + * the component is the + * rootPane of a JFrame in Swing implementations, or a java.awt.Window + * (or subclass thereof) in AWT implementations. + * This method sets the default + * helpID and HelpSet for the component and registers keyboard actions + * to trap the "Help" keypress. When the "Help" key is pressed, if the + * object with the current focus has a helpID, the helpID is displayed, + * otherwise the default helpID is displayed. + * + * @param comp The component to enable the keyboard actions on. + * @param id The default HelpID to be displayed. + * @param hs The default HelpSet to be displayed. + */ + public void enableHelpKey(Component comp, String id, HelpSet hs); + /** + * Enables the Help key on a component. This method works best when + * the component is the + * rootPane of a JFrame in Swing implementations, or a java.awt.Window + * (or subclass thereof) in AWT implementations. + * This method sets the default + * helpID and HelpSet for the component and registers keyboard actions + * to trap the "Help" keypress. When the "Help" key is pressed, if the + * object with the current focus has a helpID, the helpID is displayed, + * otherwise the default helpID is displayed. + * + * @param comp The component to enable the keyboard actions on. + * @param id The default HelpID to be displayed. + * @param hs The default HelpSet to be displayed. + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * @see Presentation + */ + public void enableHelpKey(Component comp, String id, HelpSet hs, + String presentation, String presentationName); + + /** + * Enables help for a component. This method sets a + * component's helpID and HelpSet. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + */ + public void enableHelp(Component comp, String id, HelpSet hs); + + /** + * Enables help for a MenuItem. This method sets a + * component's helpID and HelpSet. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + */ + public void enableHelp(MenuItem comp, String id, HelpSet hs); + + /** + * Enables help for a component. This method sets a + * component's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the component's helpID and HelpSet in the default viewer. + * If the component is not a javax.swing.AbstractButton or a + * java.awt.Button an IllegalArgumentException is thrown. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see javax.swing.AbstractButton + * @see java.awt.Button + */ + public void enableHelpOnButton(Component comp, String id, HelpSet hs) + throws IllegalArgumentException; + + /** + * Enables help for a MenuItem. This method sets a + * component's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the component's helpID and HelpSet in the default viewer. + * + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see java.awt.MenuItem + */ + public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs); + + /** + * Enables help for an object. This method sets a + * object's helpID and HelpSet and adds an ActionListener. + * When an action is performed + * it displays the component's helpID and HelpSet in the default viewer + * or the presenation if defined. + * If the component is not a javax.swing.AbstractButton or a + * java.awt.Button an IllegalArgumentException is thrown. + * + * @param comp The component to enable the keyboard actions on. + * @param id The default HelpID to be displayed. + * @param hs The default HelpSet to be displayed. + * @param presentation The Presentation class to display the Help in. + * @param presentationName The name of a Presentation section from a + * HelpSet to use. For some Presentations this will also be + * the name to apply to the Presentation. + * + * @see Presentation + * @see CSH.setHelpID + * @see CSH.setHelpSet + * @see javax.swing.AbstractButton + * @see java.awt.Button + */ + public void enableHelpOnButton(Object obj, String id, HelpSet hs, + String presentation, + String presentationName) + throws IllegalArgumentException; + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java b/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java new file mode 100644 index 0000000000000000000000000000000000000000..189f83c683493feff52c9ed499333e6b3832669d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java @@ -0,0 +1,125 @@ +/* + * @(#)HelpHistoryModel.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +/** + * History Model for HelpModel + * + * @author Richard Gregor + * @version 1.3 10/30/06 + */ + +import java.awt.event.ActionListener; +import javax.help.event.*; +import java.io.Serializable; +import java.beans.*; +import java.util.Vector; +import javax.help.Map.ID; +import java.util.Enumeration; + +/** + * The interface to the history model. + */ +public interface HelpHistoryModel extends HelpModelListener, Serializable{ + /** + * Adds a listener for the HelpHistoryModelEvent posted after the model has + * changed. + * + * @param l The listener to add. + * @see javax.help.HelpHistoryModel#removeHelpHistoryModelListener + */ + public void addHelpHistoryModelListener(HelpHistoryModelListener l); + + /** + * Removes a listener previously added with <tt>addHelpHistoryModelListener</tt> + * + * @param l The listener to remove. + * @see javax.help.HelpHistoryModel#addHelpHistoryModelListener + */ + public void removeHelpHistoryModelListener(HelpHistoryModelListener l); + + /** + * Discards a history + */ + public void discard(); + /** + * Sets a next history entry + */ + public void goForward(); + + /** + * Sets a previous history entry + */ + public void goBack(); + + /** + * Returns a backward history list + */ + public Vector getBackwardHistory(); + + /** + * Returns a forward history list + */ + public Vector getForwardHistory(); + + /** + * Sets the current history entry + * + * @param index The index of history entry + */ + public void setHistoryEntry(int index); + + /** + * Removes entries related to removed HelpSet from history + * + * @param hs The removed HelpSet + */ + public void removeHelpSet(HelpSet hs); + + /** + * Returns a history + */ + public Vector getHistory(); + + /** + * Returns a current history position + * + * @return The history index + */ + public int getIndex(); + + /** + * Sets the HelpModel + * + * @param model The HeplModel + */ + public void setHelpModel(HelpModel model); + + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java new file mode 100644 index 0000000000000000000000000000000000000000..6b49da0bfa51a3101e6bc92a123fc5f85039c7f9 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java @@ -0,0 +1,146 @@ +/* + * @(#)HelpModel.java 1.27 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; +import javax.help.event.*; +import javax.help.Map.ID; +import java.beans.*; + +/** + * The interface to the model of a JHelp that represents the + * HelpSet being presented to the user. + * + * Note that a HelpSet can contain nested HelpSets within it; IDs + * include both a String and the HelpSet to which the String applies. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Richard Gregor + * @version 1.27 10/30/06 + */ +public interface HelpModel { + /** + * Sets the loaded (aka "top") HelpSet for this model. + */ + public void setHelpSet(HelpSet hs); + + /** + * Gets the loaded (aka "top") HelpSet for this model. + */ + public HelpSet getHelpSet(); + + /** + * Sets the current ID relative to some HelpSet + * HelpModelListeners and HelpVisitListeners are notified + * + * @param id the ID used to set + * @exception InvalidHelpSetContextException The HelpSet of the ID is not + * valid for the HelpSet currently loaded in the model + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException; + + /** + * Sets the current ID relative to some HelpSet + * HelpModelListeners and HelpVisitListeners are notified + * + * @param id the ID used to set + * @param historyName The name for history storage + * @param navigator The JHelpNavigator + * @exception InvalidHelpSetContextException The HelpSet of the ID is not + * valid for the HelpSet currently loaded in the model + */ + public void setCurrentID(ID id, String historyName, JHelpNavigator navigator) throws InvalidHelpSetContextException; + + /** + * Gets the current ID. + * + * @return The current ID. + */ + public ID getCurrentID(); + + /** + * Sets the current URL. + * HelpModelListeners are notified. + * The current ID changes if there is a matching id for this URL + * + * @param The URL to set. + */ + public void setCurrentURL(URL url); + + /** + * Sets the current URL and the name wich will appear in history list. + * HelpModelListeners are notified. + * The current ID changes if there is a matching id for this URL + * + * @param url The URL to set. + * @param historyName The name to set for history + * @param navigator The JHelpNavigator + */ + public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator); + + /** + * Returns The current URL. + * + * @return The current URL. + */ + public URL getCurrentURL(); + + /** + * Adds a listener for the HelpModelEvent posted after the model has + * changed. + * + * @param l The listener to add. + * @see javax.help.HelpModel#removeHelpModelListener + */ + public void addHelpModelListener(HelpModelListener l); + + /** + * Removes a listener previously added with <tt>addHelpModelListener</tt> + * + * @param l The listener to remove. + * @see javax.help.HelpModel#addHelpModelListener + */ + public void removeHelpModelListener(HelpModelListener l); + + /** + * Adds a listener to monitor changes to the properties in this model + * + * @param l The listener to add. + */ + public void addPropertyChangeListener(PropertyChangeListener l); + + /** + * Removes a listener monitoring changes to the properties in this model + * + * @param l The listener to remove. + */ + public void removePropertyChangeListener(PropertyChangeListener l); +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java new file mode 100644 index 0000000000000000000000000000000000000000..ee551031b9908337f676d75b262d22dbadd5ebed --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java @@ -0,0 +1,1917 @@ +/* + * @(#)HelpSet.java 1.108 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.util.*; +import java.io.*; +import java.awt.Dimension; +import java.awt.Point; +import javax.help.event.EventListenerList; +import javax.help.DefaultHelpBroker; +import javax.help.event.HelpSetListener; +import javax.help.event.HelpSetEvent; +import javax.help.Map.ID; + +// implementation-specific +import com.sun.java.help.impl.Parser; +import com.sun.java.help.impl.ParserListener; +import com.sun.java.help.impl.ParserEvent; +import com.sun.java.help.impl.Tag; +import com.sun.java.help.impl.TagProperties; +import com.sun.java.help.impl.XmlReader; +import com.sun.java.help.impl.LangElement; +import javax.help.Map.ID; +import java.beans.PropertyChangeSupport; +import java.lang.reflect.Constructor; +/** + * A HelpSet is a collection of help information consisting of a HelpSet + * file, table of contents (TOC), index, topic files, and Map file. + * The HelpSet file is the portal to the HelpSet. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version 1.108 10/30/06 + */ + +public class HelpSet implements Serializable{ + private static String errorMsg = null; + /* + * Event listeners for adding to the HelpSet + */ + + protected EventListenerList listenerList = new EventListenerList(); + + /** + * PublicID (known to this XML processor) to the DTD for version 1.0 of the HelpSet + */ + public static final String publicIDString = + "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN"; + + /** + * PublicID (known to this XML processor) to the DTD for version 2.0 of the HelpSet + */ + public static final String publicIDString_V2 = + "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN"; + + /** + * Information for implementation customization. + * + * helpBroker/class is used to locate the class for a HelpBroker. + * helpBroker/loader is used to determine the ClassLoader to use. + */ + + public static final Object implRegistry = + new StringBuffer("HelpSet.implRegistry"); + public static final String helpBrokerClass = "helpBroker/class"; + public static final String helpBrokerLoader = "helpBroker/loader"; + + /** + * HelpSet context information. + * + * A HelpSet can map between keys (String) and values (Strings). + * There is a per-HelpSet value and a default value. + * The per-HelpSet value is specified in the appropriate section of the + * HelpSet file. + * The default value is global and only specified at class initialization time. + */ + + public static final Object kitTypeRegistry = + new StringBuffer("JHelpViewer.kitTypeRegistry"); + public static final Object kitLoaderRegistry = + new StringBuffer("JHelpViewer.kitLoaderRegistry"); + + /** + * Creates an empty HelpSet that one can parse into. + * @param loader The ClassLoader to use. If loader is null, the default + * ClassLoader is used. + */ + public HelpSet(ClassLoader loader) { + this.helpsets = new Vector(); + this.loader = loader; + } + + /** + * Creates an empty HelpSet. Uses the default ClassLoader + */ + public HelpSet() { + this.helpsets = new Vector(); + this.loader = null; + } + + /** + * Creates a HelpSet. The locale for the data is either that indicated in + * the <tt>lang</tt> attribute of the <tt>helpset</tt> tag, or + * <tt>Locale.getDefault()</tt> if the <tt>lang</tt> attribute is not present. + * + * @param loader The class loader to use to locate any classes + * required by the navigators in the Helpset + * If loader is null, the default ClassLoader is used. + * @param helpset The URL to the HelpSet "file" + * + * @exception HelpSetException if there are problems parsing the helpset + */ + public HelpSet(ClassLoader loader, URL helpset) throws HelpSetException { + this(loader); + this.helpset = helpset; // so it can be used in parseInto() + + HelpSetFactory factory = new DefaultHelpSetFactory(); + + parseInto(helpset, factory); + HelpSet x = factory.parsingEnded(this); // use the error reporting + + if (x == null) { + // We had trouble parsing + // May need to revisit this... + throw new HelpSetException("Could not parse\n"+errorMsg); + } + } + + + /** + * Locates a HelpSet file and return its URL. + * Applies localization conventions. + * + * @param cl The classloader to use when searching for the resource + * with the appropriate name. If cl is null the default + * ClassLoader is used. + * @param shortName The shortname of the resource. + * @param extension The extension of the resource. + * @param locale The desired Locale + * @see javax.help.HelpUtilities + */ + + public static URL findHelpSet(ClassLoader cl, + String shortName, + String extension, + Locale locale) { + // Test for whether URL can be opened! - workaround Browser bugs + return HelpUtilities.getLocalizedResource(cl, + shortName, + extension, + locale, + true); + } + + /** + * Locates a HelpSet file and return its URL. + * + * If the name does not end with the ".hs" extension, the + * ".hs" extension is appended and localization rules + * are applied to it. + * + * @param cl The classloader to use. If cl is null the default + * ClassLoader is used. + * @param name The name of the resource. + * @param locale The desired locale. + */ + public static URL findHelpSet(ClassLoader cl, + String name, + Locale locale) { + String shortName; + String extension; + if (name.endsWith(".hs")) { + shortName = name.substring(0, name.length()-3); + extension = ".hs"; + } else { + shortName = name; + extension = ".hs"; + } + return findHelpSet(cl, shortName, extension, locale); + } + + /** + * As above but default on locale to Locale.getDefault() + * + * @param cl The ClassLoader to use. If cl is null the default + * ClassLoader is used. + * @param name The name of the resource. + * @return Null if not found. + */ + public static URL findHelpSet(ClassLoader cl, + String name) { + return findHelpSet(cl, name, Locale.getDefault()); + } + + + /** + * Creates a presentation object for this HelpSet. + * Consults the <tt>implRegistry</tt> of <tt>KeyData</tt> for + * the class name (as helpBrokerClass) and for the ClassLoader + * instance (as helpBrokerLoader) and then tries to instantiate + * that class. It then invokes <tt>setHelpSet()</tt> with + * this instance of HelpSet as the argument. The resulting object is + * returned. + * @see createHelpBroker(String) + */ + public HelpBroker createHelpBroker() { + return createHelpBroker(null); + } + + /** + * Creates a presentation object for this HelpSet. + * Consults the <tt>implRegistry</tt> of <tt>KeyData</tt> for + * the class name (as helpBrokerClass) and for the ClassLoader + * instance (as helpBrokerLoader) and then tries to instantiate + * that class. It then invokes <tt>setHelpSet()</tt> with + * this instance of HelpSet as the argument. The resulting object is + * returned. + * @param presenationName A presentation name defined in the HelpSet + * that will dictate the presentation. + * @return HelpBroker The created HelpBroker + * @since 2.0 + * @see createHelpBroker() + */ + public HelpBroker createHelpBroker(String presentationName) { + HelpBroker back = null; + + String classname = + (String) getKeyData(implRegistry, helpBrokerClass); + ClassLoader loader = + (ClassLoader) getKeyData(implRegistry, helpBrokerLoader); + + if (loader == null) { + loader = getLoader(); + } + try { + Class c; + if (loader != null) { + c = loader.loadClass(classname); + } else { + c = Class.forName(classname); + } + back = (HelpBroker) c.newInstance(); + } catch (Throwable e) { + back = null; + } + + if (back != null) { + back.setHelpSet(this); + HelpSet.Presentation hsPres = null; + // If there is a presentation name find it otherwise get the + // default if one exists. + if (presentationName != null) { + hsPres = getPresentation(presentationName); + } else { + hsPres = getDefaultPresentation(); + } + if (hsPres != null) { + back.setHelpSetPresentation(hsPres); + } + } + return back; + } + + /** + * Adds a HelpSet, HelpSetEvents are generated. + * Adding a composed HelpSet to another is equivalent to + * adding all the HelpSets individually. + * + * @param hs The HelpSet to add. + */ + public void add(HelpSet hs) { + debug("add("+hs+")"); + helpsets.addElement(hs); + fireHelpSetAdded(this, hs); + combinedMap = null; // invalidate the map + } + + /** + * Removes a HelpSet from this HelpSet; HelpSetEvents are generated + * Return True if it is found, otherwise false. + * + * @param hs The HelpSet to remove. + * @return False if the hs is null or was not in this HelpSet + */ + public boolean remove(HelpSet hs) { + if (helpsets.removeElement(hs)) { + fireHelpSetRemoved(this, hs); + combinedMap = null; // HERE - invalidate it - epll + return true; + } else { + return false; + } + } + + /** + * Enumerates all the HelpSets that have been added to this one. + * + * @return An enumeration of the HelpSets that have been added to + * this HelpSet. + */ + public Enumeration getHelpSets() { + return helpsets.elements(); + } + + /** + * Determines if a HelpSet is a sub-HelpSet of this object. + * + * @param hs The HelpSet to check + * @return true If <tt>hs</tt> is contained in this HelpSet or in one of its children. + */ + public boolean contains(HelpSet hs) { + if (hs == this) { + return true; + } + for (Enumeration e = helpsets.elements(); + e.hasMoreElements();) { + HelpSet child = (HelpSet) e.nextElement(); + if (child.contains(hs)) { + return true; + } + } + return false; + } + + /** + * Adds a listener for the HelpSetEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.HelpSet#removeHelpSetListener. + * @throws IllegalArgumentException if l is null. + */ + public void addHelpSetListener(HelpSetListener l) { + debug("addHelpSetListener("+l+")"); + listenerList.add(HelpSetListener.class, l); + } + + /** + * Removes a listener previously added with <tt>addHelpSetListener</tt> + * + * @param l - The listener to remove. + * @see javax.help.HelpSet#addHelpSetListener. + * @throws IllegalArgumentException if l is null. + */ + public void removeHelpSetListener(HelpSetListener l) { + listenerList.remove(HelpSetListener.class, l); + } + + /** + * Fires a helpSetAdded event. + */ + protected void fireHelpSetAdded(Object source, HelpSet helpset){ + Object[] listeners = listenerList.getListenerList(); + HelpSetEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == HelpSetListener.class) { + if (e == null) { + e = new HelpSetEvent(this, helpset, + HelpSetEvent.HELPSET_ADDED); + } + ((HelpSetListener)listeners[i+1]).helpSetAdded(e); + } + } + } + + /** + * Fires a helpSetRemoved event. + */ + protected void fireHelpSetRemoved(Object source, HelpSet helpset){ + Object[] listeners = listenerList.getListenerList(); + HelpSetEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == HelpSetListener.class) { + if (e == null) { + e = new HelpSetEvent(this, helpset, + HelpSetEvent.HELPSET_REMOVED); + } + ((HelpSetListener)listeners[i+1]).helpSetRemoved(e); + } + } + } + + // ======= Labels, etc ======= + /** + * Gets the title of this HelpSet. + * + * @return the title + */ + public String getTitle() { + if (title == null) { + return ""; + } else { + return title; + } + } + + /** + * Sest the title for this HelpSet. This is a bound property. + * + * @param title The title to set. + */ + + public void setTitle(String title) { + String oldTitle = this.title; + this.title = title; + changes.firePropertyChange("title", oldTitle, title); + } + + /** + * Gets the locale for this HelpSet. + * + * @return The locale. + */ + public Locale getLocale() { + return locale; + } + + /** + * Sets the locale for this HelpSet. + * Strictly a private routine but the read-only property is bound. + * + * @param locale The locale to set. + */ + private void setLocale(Locale l) { + Locale oldLocale = locale; + locale = l; + changes.firePropertyChange("locale", oldLocale, locale); + } + + /** + * Returns + * the ID to visit when the user makes a "go home" gesture. + * This can be identified in the project file, but may also be changed + * programmatically or (possibly) via the UI. + * + * @return The ID of home. A null is returned if homeID is null + * or if an ID cannot be created for the homeID. + */ + public ID getHomeID() { + if (homeID == null) { + return null; + } else { + try { + return ID.create(homeID, this); + } catch (Exception ex) { + return null; + } + } + } + + /** + * Sets the Home ID for a HelpSet. This is a bound property. + * + * @param The ID (in the Map) that identifies the default topic for this HelpSet. Null is valid homeID. + */ + public void setHomeID(String homeID) { + String oldID = homeID; + this.homeID = homeID; + changes.firePropertyChange("homeID", oldID, homeID); + } + + // WARNING/HERE: In this implementation, the Map is not updated automatically + // so you need to come get a new one - epll + + // Warning. This is not handling recursive aggregation + + /** + * The map for this HelpSet. This map involves the closure of + * this HelpSet's children HelpSets. + * + * @return The map + */ + public Map getCombinedMap() { + if (combinedMap == null) { + combinedMap = new TryMap(); + if (map != null) { + combinedMap.add(map); // the local map + } + for (Enumeration e = helpsets.elements(); + e.hasMoreElements(); ) { + HelpSet hs = (HelpSet) e.nextElement(); + combinedMap.add(hs.getCombinedMap()); + } + } + return combinedMap; + } + + /** + * Get the local (i.e.<!-- --> non-recursive) Map for this HelpSet. + * This Map does not include the Maps for its children. + * + * @return The Map object that associates ID->URL. A null map is valid. + */ + public Map getLocalMap() { + return this.map; + } + + /** + * Set the Map for this HelpSet. This Map object is not recursive; for example, + * it does not include the Maps for its children. + * + * @param The Map object that associates ID->URL. A null map is a valid. + */ + public void setLocalMap(Map map) { + this.map = map; + } + + /** + * The URL that is the base for this HelpSet. + * + * @return The URL that is base to this HelpSet. + */ + public URL getHelpSetURL() { + return helpset; + } + + /** + * A classloader to use when locating classes. + * + * @return The ClassLoader to use when locating classes mentioned + * in this HelpSet. + */ + + public ClassLoader getLoader() { + return loader; + } + + /** + * NavigatorView describes the navigator views that are requested + * by this HelpSet. + * + * @return The array of NavigatorView. + */ + + public NavigatorView[] getNavigatorViews() { + NavigatorView back[] = new NavigatorView[views.size()]; + views.copyInto(back); + return back; + } + + /** + * Gets the NavigatorView with a specific name. + * + * @param The name of the desired navigator view. + */ + public NavigatorView getNavigatorView(String name) { + debug("getNavigatorView("+name+")"); + for (int i=0; i<views.size(); i++) { + NavigatorView view = (NavigatorView) views.elementAt(i); + if (view.getName().equals(name)) { + debug(" = "+view); + return view; + } + } + debug(" = null"); + return null; + } + + /** + * HelpSet.Presentation describes the presentations that are defined + * by this HelpSet. + * + * @return The array of HelpSet.Presentations. + */ + + public HelpSet.Presentation [] getPresentations() { + HelpSet.Presentation back[] = new HelpSet.Presentation[presentations.size()]; + presentations.copyInto(back); + return back; + } + + /** + * Gets the HelpSet.Presentation with a specific name. + * + * @param The name of the desired HelpSet.Presentation. + */ + public HelpSet.Presentation getPresentation(String name) { + debug("getPresentation("+name+")"); + for (int i=0; i<presentations.size(); i++) { + HelpSet.Presentation pres = (HelpSet.Presentation) presentations.elementAt(i); + if (pres.getName().equals(name)) { + debug(" = "+pres); + return pres; + } + } + debug(" = null"); + return null; + } + + public HelpSet.Presentation getDefaultPresentation() { + return defaultPresentation; + } + + /** + * Prints Name for this HelpSet. + */ + public String toString() { + return getTitle(); + } + + // ===== Public interfaces to parsing + + /** + * Parsed a HelpSet file. + */ + public static HelpSet parse(URL url, + ClassLoader loader, + HelpSetFactory factory) { + HelpSet hs = new HelpSet(loader); // an empty HelpSet + hs.helpset = url; + hs.parseInto(url, factory); + return factory.parsingEnded(hs); + } + + /** + * Parses into this HelpSet. + */ + public void parseInto(URL url, + HelpSetFactory factory) { + Reader src; + try { + URLConnection uc = url.openConnection(); + src = XmlReader.createReader(uc); + factory.parsingStarted(url); + (new HelpSetParser(factory)).parseInto(src, this); + src.close(); + } catch (Exception ex) { + factory.reportMessage("Got an IOException ("+ + ex.getMessage()+ + ")", false); + if(debug) + ex.printStackTrace(); + } + + // Now add any subhelpsets + for (int i=0; i<subHelpSets.size(); i++) { + HelpSet subHS = (HelpSet) subHelpSets.elementAt(i); + add(subHS); + } + } + + /** + * The default HelpSetFactory that processes HelpSets. + */ + + public static class DefaultHelpSetFactory implements HelpSetFactory { + private Vector messages = new Vector(); + private URL source; + private boolean validParse = true; + + /** + * Parsing starts. + */ + public void parsingStarted(URL source) { + if (source == null) { + throw new NullPointerException("source"); + } + this.source = source; + } + + /** + * Process a DOCTYPE + * @param publicID the document. If null or is not valid a parsingError + * will be generated. + */ + public void processDOCTYPE(String root, + String publicID, + String systemID) { + if (publicID == null || + (publicID.compareTo(publicIDString) != 0 && + publicID.compareTo(publicIDString_V2) != 0)) { + parsingError("helpset.wrongPublicID", publicID); + } + } + + /** + * Processes a PI + */ + public void processPI(HelpSet hs, + String target, + String data) { + // ignore for now + } + + /** + * A title is found + */ + public void processTitle(HelpSet hs, + String value) { + String title = hs.getTitle(); + if ((title != null) && !title.equals("")) { + parsingWarning("helpset.wrongTitle", value, title); + } + hs.setTitle(value); + } + + /** + * A HomeID is found. + */ + + public void processHomeID(HelpSet hs, + String value) { + ID homeID = hs.getHomeID(); + if ((homeID == null) || homeID.equals("")) { + //parsingError("helpset.wrongHomeID", value, homeID.id); + hs.setHomeID(value); + }else{ + parsingError("helpset.wrongHomeID", value, homeID.id); + } + + } + + /** + * process a <mapref> + * + * @param Spec to the URL + * @param Attributes for the tag + */ + public void processMapRef(HelpSet hs, + Hashtable attributes) { + String spec = (String) attributes.get("location"); + URL hsURL = hs.getHelpSetURL(); + try { + Map map = new FlatMap(new URL(hsURL, spec), hs); + Map omap = hs.getLocalMap(); + if (omap == null) { + debug("map is null"); + hs.setLocalMap(map); + } else { + // to implement multiple Maps add this code: + // + if (omap instanceof TryMap) { + debug("map is TryMap"); + ((TryMap)omap).add(map); + /// + ///what about hs.setLocalMap//// + /// + hs.setLocalMap(omap); + } else { + debug("map is not TryMap"); + TryMap tmap = new TryMap(); + tmap.add(omap); + tmap.add(map); + hs.setLocalMap(tmap); + } + + } + } catch (MalformedURLException ee) { + parsingError("helpset.malformedURL", spec); + } catch (IOException ee) { + parsingError("helpset.incorrectURL", spec); + } catch (Exception ex) { + // parsing error... + } + } + + /* + * Called per <view> + */ + public void processView(HelpSet hs, + String name, + String label, + String type, + Hashtable viewAttributes, + String data, + Hashtable dataAttributes, + Locale locale) { + + try { + NavigatorView view; + if (data != null) { + if (dataAttributes == null) { + dataAttributes = new Hashtable(); + } + dataAttributes.put("data", data); + + } + + view = NavigatorView.create(hs, + name, label, + locale, + type, + dataAttributes); + + if (view == null) { + // ignore ?? + } else { + + hs.addView(view); + } + } catch (Exception ex) { + // ignore this view... + } + } + + /* + * Called per <presentation> + */ + public void processPresentation(HelpSet hs, + String name, + boolean defaultPresentation, + boolean displayViews, + boolean displayViewImages, + Dimension size, + Point location, + String title, + String imageID, + boolean toolbar, + Vector helpActions) { + + Map.ID imageMapID = null; + try { + imageMapID = ID.create(imageID, hs); + } catch (BadIDException bex2) { + } + try { + HelpSet.Presentation presentation = + new HelpSet.Presentation(name, displayViews, + displayViewImages, size, + location, title, imageMapID, + toolbar, helpActions); + + if (presentation == null) { + // ignore ?? + } else { + hs.addPresentation(presentation, defaultPresentation); + } + } catch (Exception ex) { + // ignore this presentation... + } + } + + /** + * Called when a sub-HelpSet is found. + */ + public void processSubHelpSet(HelpSet hs, + Hashtable attributes) { + debug("createSubHelpSet"); + + String spec = (String) attributes.get("location"); + URL base = hs.getHelpSetURL(); + + debug(" location: "+spec); + debug(" base helpset: "+base); + + URL u = null; + HelpSet subHS = null; + try { + u = new URL(base, spec); + // test and see if the file is there + // if it doesnt' through an exception all is ok + InputStream is = u.openStream(); + if (is != null) { + subHS = new HelpSet(hs.getLoader(), u); + if (subHS != null) { + hs.addSubHelpSet(subHS); + } + } + } catch (MalformedURLException ex) { + // ignore a malformed URL + // The subhelpset is just ignored + } catch (IOException ex) { + // ignore an IOException + // The subhelpset is just ignored + } catch (HelpSetException ex) { + parsingError("helpset.subHelpSetTrouble", spec); + } + } + + /** + * Reports an error message. + */ + public void reportMessage(String msg, boolean validParse) { + messages.addElement(msg); + this.validParse = this.validParse && validParse; + } + + /** + * Enumerates all the error messages. + */ + public Enumeration listMessages() { + return messages.elements(); + } + + /** + * Parsing has ended. Last chance to do something + * to the HelpSet. + * @param hs The HelpSet the parsing ended on. A null hs is valid. + */ + public HelpSet parsingEnded(HelpSet hs) { + HelpSet back = hs; + if (! validParse) { + // A parse with problems... + back = null; + + String errMsg = "Parsing failed for "+source; + //System.err.println(errMsg); + messages.addElement(errMsg); + + for (Enumeration e = messages.elements(); + e.hasMoreElements();) { + String msg = (String) e.nextElement(); + if(debug) + System.err.println(msg); + if(HelpSet.errorMsg == null) + HelpSet.errorMsg = msg; + else{ + HelpSet.errorMsg = HelpSet.errorMsg+"\n"; + HelpSet.errorMsg = HelpSet.errorMsg + msg; + } + + } + } + return back; + } + + // Convenience methods + private void parsingError(String key) { + String s = HelpUtilities.getText(key); + reportMessage(s, false); // tree will be wrong + } + + /** + * @throws Error if key is invalid. + */ + private void parsingError(String key, String s) { + String msg = HelpUtilities.getText(key, s); + reportMessage(msg, false); // tree will be wrong + } + + /** + * @throws Error if key is invalid. + */ + private void parsingError(String key, String s1, String s2) { + String msg = HelpUtilities.getText(key, s1, s2); + reportMessage(msg, false); // tree will be wrong + } + + private void parsingWarning(String key, String s1, String s2) { + String msg = HelpUtilities.getText(key, s1, s2); + reportMessage(msg, true); // warning only + } + + } // End of DefaultHelpSetFactory + + + /** + * HelpSet Presentation class. Contains information concerning a + * presentation in a HelpSet file + * @since 2.0 + */ + public static class Presentation { + + private String name; + private boolean displayViews; + private boolean displayViewImages; + private Dimension size; + private Point location; + private String title; + private boolean toolbar; + private Vector helpActions; + private Map.ID imageID; + + public Presentation (String name, + boolean displayViews, + boolean displayViewImages, + Dimension size, + Point location, + String title, + Map.ID imageID, + boolean toolbar, + Vector helpActions) { + this.name = name; + this.displayViews = displayViews; + this.displayViewImages = displayViewImages; + this.size = size; + this.location = location; + this.title = title; + this.imageID = imageID; + this.toolbar = toolbar; + this.helpActions = helpActions; + } + + public String getName() { + return name; + } + + public String getTitle() { + return title; + } + + public Map.ID getImageID() { + return imageID; + } + + public boolean isViewDisplayed() { + return displayViews; + } + + public boolean isViewImagesDisplayed() { + return displayViewImages; + } + + public Dimension getSize() { + return size; + } + + public Point getLocation() { + return location; + } + + public boolean isToolbar() { + return toolbar; + } + + /** + * Returns an Enumeration HelpActions created from the + * list of Actions in the Presentation. + * + * @see HelpAction + */ + public Enumeration getHelpActions(HelpSet hs, Object control) { + Vector actions = new Vector(); + ClassLoader loader = hs.getLoader(); + Class klass; + Constructor konstructor; + HelpAction action; + + if (helpActions == null) { + // got a nutziod who didn't check the isToolbar + // just return back the empty vector elements + return actions.elements(); + } + Enumeration actionEnum = helpActions.elements(); + while (actionEnum.hasMoreElements()) { + HelpSetFactory.HelpAction act = + (HelpSetFactory.HelpAction)actionEnum.nextElement(); + + try { + Class types[] = { Object.class }; + Object args[] = { control }; + if (loader == null) { + klass = Class.forName(act.className); + } else { + klass = loader.loadClass(act.className); + } + konstructor = klass.getConstructor(types); + action = (HelpAction) konstructor.newInstance(args); + + // The HelpAction has been added now add any known + // attributes + if (act.attr.containsKey("image")) { + String imageID = (String) act.attr.get("image"); + try { + Map.ID id = Map.ID.create(imageID, hs); + javax.swing.ImageIcon icon = null; + Map map = hs.getCombinedMap(); + URL url = map.getURLFromID(id); + icon = new javax.swing.ImageIcon(url); + action.putValue("icon", icon); + } catch (Exception ex) { + } + } + actions.add(action); + } catch (Exception ex) { + throw new RuntimeException("Could not create HelpAction " + + act.className); + } + } + + return actions.elements(); + } + + } + + // =========== Protected Methods for use by subclasses ========== + + /** + * Adds a NavigatorView to the current list. + */ + protected void addView(NavigatorView view) { + views.addElement(view); + } + + /** + * Adds a SubHelpSet to the current list. + */ + + protected void addSubHelpSet(HelpSet hs) { + subHelpSets.addElement(hs); + } + + /** + * Adds a HelpSet.Presentation to the current list. + */ + protected void addPresentation(HelpSet.Presentation presentation, + boolean defaultPres) { + presentations.addElement(presentation); + if (defaultPres) { + defaultPresentation = presentation; + } + } + + // ============= Simple registry ============ + + /** + * Gets some Data for a Key in a given context. + * Local (per HelpSet instance) data is searched first, then defaults. + */ + + public Object getKeyData(Object context, + String key) { + Object back = null; + Hashtable h = (Hashtable) localKeys.get(context); + if (h != null) { + back = h.get(key); + } + if (back == null) { + h = (Hashtable) defaultKeys.get(context); + if (h != null) { + back = h.get(key); + } + } + return back; + } + + /** + * Sets some local KeyData on a given context. The information is set on + * a per-HelpSet basis. + */ + public void setKeyData(Object context, + String key, + Object data) { + Hashtable h = (Hashtable) localKeys.get(context); + if (h == null) { + h = new Hashtable(); + localKeys.put(context, h); + } + h.put(key, data); + } + + /** + * Default initialization. This can only be done from within this class. + */ + private static void setDefaultKeyData(Object context, + String key, + Object data) { + if (defaultKeys == null) { + defaultKeys = new Hashtable(); + } + Hashtable h = (Hashtable) defaultKeys.get(context); + if (h == null) { + h = new Hashtable(); + defaultKeys.put(context, h); + } + h.put(key, data); + } + + + /** + * Initializes the default registries. + */ + static { + setDefaultKeyData(implRegistry, + helpBrokerClass, "javax.help.DefaultHelpBroker"); + setDefaultKeyData(kitTypeRegistry, + "text/html", "com.sun.java.help.impl.CustomKit"); + + ClassLoader cl = HelpSet.class.getClassLoader(); + if (cl != null) { + setDefaultKeyData(implRegistry, + helpBrokerLoader, cl); + setDefaultKeyData(kitLoaderRegistry, + "text/html", cl); + } + } + + //======== Private members ========= + + private String title; // the title for this helpset + private Map map; // the local map + private TryMap combinedMap; // the combined ID<->URL map + private URL helpset; // the HelpSet from where to search + private String homeID; + private Locale locale = Locale.getDefault(); + + private transient ClassLoader loader; // encapsulates loading... + + private Vector views = new Vector(); + + private Vector presentations = new Vector(); + + private HelpSet.Presentation defaultPresentation = null; + + private Vector helpsets; // All the helpsets added to this one + + private static HelpBroker defaultHelpBroker = null; // the default HelpBroker + + private Vector subHelpSets = new Vector(); + + // Default and Local Hashtables for keys + + private static Hashtable defaultKeys; + private Hashtable localKeys = new Hashtable(); + + private PropertyChangeSupport changes = new PropertyChangeSupport(this); + + // ============= PRIVATE Parsing Class ======== + + /** + * Inner class for parsing a TOC stream. + * + * WARNING!! This class is an interim solution until when we move to a + * real XML parser. This is not a public class. Clients should only use + * the parse method in the enclosing class. + */ + + private static class HelpSetParser implements ParserListener { + private Stack tagStack; // the collection of active Parse tags + private Locale defaultLocale; + private Locale lastLocale; + private HelpSet myHS; // my HelpSet + private Locale myHSLocale; // its locale + private HelpSetFactory factory; // the factory + + + private String tagName; // genericly used for views and presentation + private String viewLabel; + private String viewType; + private String viewEngine; + private String tagImage; + private String helpActionImage; + private String viewData; + private String viewMergeType; + private Hashtable htData; + + private boolean defaultPresentation = false; + private boolean displayViews = true; + private boolean displayViewImages = true; + private Dimension size; + private Point location; + private String presentationTitle; + private boolean toolbar; + private Vector helpActions; + private String helpAction; + + /** + * Creates a Parser (Listener) instance. + */ + HelpSetParser (HelpSetFactory factory) { + this.factory = factory; + } + + /** + * Parses a reader into a HelpSet. + */ + synchronized void parseInto(Reader src, + HelpSet hs) + throws IOException + { + tagStack = new Stack(); + defaultLocale = hs.getLocale(); + lastLocale = defaultLocale; + myHS = hs; + myHSLocale = hs.getLocale(); + Parser parser = new Parser(src); // the XML parser instance + parser.addParserListener(this); + parser.parse(); + } + + public void tagFound(ParserEvent e) { + debug("tagFound " + e.getTag().name); + Locale locale = null; + LangElement le; + Tag tag = e.getTag(); + String name = tag.name; + int x=0, y=0, width=0, height=0; + TagProperties attr = tag.atts; + Hashtable ht = (attr == null) ? null : attr.getHashtable(); + + if (attr != null) { + String lang = attr.getProperty("xml:lang"); + locale = HelpUtilities.localeFromLang(lang); + viewMergeType = attr.getProperty("mergetype"); + helpActionImage = attr.getProperty("image"); + String value = null; + value = attr.getProperty("width"); + if (value != null) { + width = Integer.parseInt(value); + } + value = null; + value = attr.getProperty("height"); + if (value != null) { + height = Integer.parseInt(value); + } + value = null; + value = attr.getProperty("x"); + if (value != null) { + x = Integer.parseInt(value); + } + value = null; + value = attr.getProperty("y"); + if (value != null) { + y = Integer.parseInt(value); + } + value = null; + value = attr.getProperty("default"); + if (value != null && value.equals("true")) { + defaultPresentation = true; + } + value = null; + value = attr.getProperty("displayviews"); + if (value != null && value.equals("false")) { + displayViews = false; + } + value = null; + value = attr.getProperty("displayviewimages"); + if (value != null && value.equals("false")) { + displayViewImages = false; + } + } + if (locale == null) { + locale = lastLocale; + } + + if (name.equals("helpset")) { + if (tag.isEnd) { + removeTag(tag); + } else { + // Check and see if the locale is different from the + // defaultLocale. If it is then reset the locale. + if (! locale.equals(defaultLocale) && + ! locale.equals(myHSLocale)) { + if (locale != null) { + myHS.setLocale(locale); + defaultLocale = locale; + } + } + if (attr != null) { + String version = attr.getProperty("version"); + if (version != null && + (version.compareTo("1.0") != 0 && + version.compareTo("2.0") != 0)) { + parsingError("helpset.unknownVersion", version); + } + } + addTag(tag, locale); + } + return; + } + + if (tagStack.empty()) { + parsingError("helpset.wrongTopLevel", name); + } + + // Get the parents name + le = (LangElement) tagStack.peek(); + String pname = ((Tag) le.getTag()).name; // the parent + + if (name.equals("title")) { + // TITLE tag + if (tag.isEnd) { + removeTag(tag); // processing was done in textFound() + } else { + if ((! pname.equals("helpset")) && + (! pname.equals("presentation"))){ + wrongParent(name, pname); + } + if (! locale.equals(defaultLocale) && + ! locale.equals(myHSLocale)) { + wrongLocale(locale, defaultLocale, myHSLocale); + } + addTag(tag, locale); + } + } else if (name.equals("homeID")) { + // HOMEID tags + if (tag.isEnd) { + removeTag(tag); // processing was done in textFound() + } else { + if (! pname.equals("maps")) { + wrongParent(name, pname); + } + addTag(tag, locale); + } + } else if (name.equals("mapref")) { + // MAPREF tags + + // Remove from stack if an empty tag + if (tag.isEnd && !tag.isEmpty) { + removeTag(tag); + } else { + if (! pname.equals("maps")) { + wrongParent(name, pname); + } + // add the tag if not an empty tag + if (! tag.isEmpty) { + addTag(tag, locale); + } + // Process the tag + factory.processMapRef(myHS, + ht); + } + } else if (name.equals("data")) { + // DATA tag + if (tag.isEnd) { + removeTag(tag); + } else { + if (! pname.equals("view")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + htData = ht; + } + } else if (name.equals("name") || + name.equals("type") || + name.equals("image")){ + // NAME, TYPE, IMAGE tag + if (tag.isEnd) { + removeTag(tag); + } else { + if ((! pname.equals("view")) && + (! pname.equals("presentation"))) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("label")) { + // LABEL tag + // Special processing to check the locale attribute. + if (tag.isEnd) { + removeTag(tag); + } else { + if (! pname.equals("view")) { + wrongParent(name, pname); + } else { + if (! locale.equals(defaultLocale) && + ! locale.equals(myHSLocale)) { + wrongLocale(locale, defaultLocale, myHSLocale); + } + addTag(tag, locale); + } + } + } else if (name.equals("view")) { + // VIEW tag + if (tag.isEnd) { + removeTag(tag); + + if (tagImage != null) { + if (htData == null) { + htData = new Hashtable(); + } + htData.put("imageID", tagImage); + } + + if (viewMergeType != null) { + if(htData == null) { + htData = new Hashtable(); + } + htData.put("mergetype",viewMergeType); + } + + factory.processView(myHS, + tagName, + viewLabel, + viewType, + ht, + viewData, + htData, + locale); + tagName = null; + viewLabel = null; + viewType = null; + tagImage = null; + viewData = null; + htData = null; + viewMergeType = null; + + } else { + if (! pname.equals("helpset")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("presentation")) { + // Presentation tag + if (tag.isEnd) { + removeTag(tag); + + factory.processPresentation(myHS, + tagName, + defaultPresentation, + displayViews, + displayViewImages, + size, + location, + presentationTitle, + tagImage, + toolbar, + helpActions); + + tagName = null; + defaultPresentation = false; + displayViews = true; + displayViewImages = true; + size = null; + location = null; + presentationTitle = null; + tagImage = null; + toolbar = false; + helpActions = null; + + } else { + if (! pname.equals("helpset")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("size")) { + // DATA tag + if (tag.isEnd) { + if (size == null) { + size = new Dimension(width, height); + } else { + size.setSize(width, height); + } + width = 0; + height = 0; + if (!tag.isEmpty) { + removeTag(tag); + } + } else { + if (! pname.equals("presentation")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + size = new Dimension(); + } + } + } else if (name.equals("location")) { + // DATA tag + if (tag.isEnd) { + if (location == null) { + location = new Point(x, y); + } else { + location.setLocation(x, y); + } + x = 0; + y = 0; + if (!tag.isEmpty) { + removeTag(tag); + } + } else { + if (! pname.equals("presentation")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + location = new Point(); + } + } + } else if (name.equals("toolbar")) { + // DATA tag + if (tag.isEnd) { + removeTag(tag); + } else { + if (! pname.equals("presentation")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + helpActions = new Vector(); + toolbar = true; + } + } + } else if (name.equals("helpaction")) { + // DATA tag + if (tag.isEnd) { + removeTag(tag); + if (helpAction != null) { + Hashtable tmp = new Hashtable(); + helpActions.add(new HelpSetFactory.HelpAction(helpAction, tmp)); + if (helpActionImage != null) { + tmp.put("image", helpActionImage); + helpActionImage = null; + } + helpAction = null; + } + } else { + if (! pname.equals("toolbar")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("maps")) { + // MAPS tag + if (tag.isEnd) { + removeTag(tag); + } else { + if (! pname.equals("helpset")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("subhelpset")) { + // SUBHELPSET tag + + // Remove from stack if an empty tag + if (tag.isEnd && !tag.isEmpty) { + removeTag(tag); + } else { + // Add the tag if it isn't an inline tag + if (!tag.isEmpty) { + addTag(tag, locale); + } + // Process the tag + factory.processSubHelpSet(myHS, ht); + } + } else if (name.equals("impl")) { + // Presentation tag + if (tag.isEnd) { + removeTag(tag); + // Nothing to do here. Everything is done while + // processing the sub tags + } else { + if (! pname.equals("helpset")) { + wrongParent(name, pname); + } else { + addTag(tag, locale); + } + } + } else if (name.equals("helpsetregistry")) { + if (tag.isEnd && !tag.isEmpty) { + removeTag(tag); + } else { + if (! pname.equals("impl")) { + wrongParent(name, pname); + } else { + if (!tag.isEnd) { + addTag(tag, locale); + } + if (attr != null) { + String hbClass = attr.getProperty("helpbrokerclass"); + if (hbClass != null) { + myHS.setKeyData(implRegistry, + helpBrokerClass, + hbClass); + } + } + } + } + } else if (name.equals("viewerregistry")) { + if (tag.isEnd && !tag.isEmpty) { + removeTag(tag); + } else { + if (! pname.equals("impl")) { + wrongParent(name, pname); + } else { + if (!tag.isEnd) { + addTag(tag, locale); + } + if (attr != null) { + String viewerType = attr.getProperty("viewertype"); + String viewerClass = attr.getProperty("viewerclass"); + if (viewerType != null && viewerClass != null) { + ClassLoader cl = HelpSet.class.getClassLoader(); + myHS.setKeyData(kitTypeRegistry, + viewerType, viewerClass); + myHS.setKeyData(kitLoaderRegistry, + viewerType, cl); + } + } + } + } + } + } + + public void piFound(ParserEvent e) { + factory.processPI(myHS, e.getTarget(), e.getData()); + } + + public void doctypeFound(ParserEvent e) { + factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId()); + } + + private void checkNull(String name, String t) { + if (! t.equals("")) { + parsingError("helpset.wrongText", name, t); + } + } + + public void textFound(ParserEvent e) { + debug("textFound: "); + debug(" text: "+e.getText()); + + if (tagStack.empty()) { + return; // ignore + } + LangElement le = (LangElement) tagStack.peek(); + Tag tag = le.getTag(); + TagProperties attr = tag.atts; + Hashtable ht = (attr == null) ? null : attr.getHashtable(); + String text = e.getText().trim(); + String name = tag.name; + + if (name.equals("helpset")) { + // HELPSET tag + checkNull("helpset", text); + return; + } + int depth = tagStack.size(); + String pname = ""; + if (depth >= 2) { + le = (LangElement) tagStack.elementAt(depth-2); + pname = ((Tag) le.getTag()).name; // the parent + } + + if (name.equals("title")) { + // TITLE tag + if (pname.equals("helpset")) { + factory.processTitle(myHS, text); + } else { + presentationTitle = text.trim(); + } + } else if (name.equals("homeID")) { + // HOMEID tag + factory.processHomeID(myHS, text); + } else if (name.equals("mapref")) { + checkNull("mapref", text); + } else if (name.equals("subhelpset")) { + checkNull("subhelpset", text); + } else if (name.equals("data")) { + // DATA tag -- this is in a view + viewData = text.trim(); + } else if (name.equals("label")) { + // LABEL tag -- this is in a view + viewLabel = text.trim(); + } else if (name.equals("name")) { + // NAME tag -- this is in a view + tagName = text.trim(); + } else if (name.equals("helpaction")) { + // NAME tag -- this is in a view + helpAction = text.trim(); + } else if (name.equals("type")) { + // TYPE tag -- this is in a view + viewType = text.trim(); + } else if (name.equals("image")) { + // IMAGE tag -- this is in the view + tagImage = text.trim(); + } else if (name.equals("view")) { + // VIEW tag + checkNull("view", text); + } else if (name.equals("maps")) { + // MAP tag + checkNull("maps", text); + } else if (name.equals("mergetype")) { + checkNull("mergetype",text); + } + } + + /** + * Method used to parse a HelpSet. + */ + public void errorFound(ParserEvent e) { + // Ignore it for now + } + + /** + * Method used to parse a HelpSet. + */ + public void commentFound(ParserEvent e) { + // Ignore it for now + } + + /** + * addTag keeps track of tags and their locale attributes. + */ + protected void addTag(Tag tag, Locale locale) { + LangElement el = new LangElement(tag, locale); + tagStack.push(el); + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It is impossible for locale to be null + if (lastLocale == null) { + lastLocale = locale; + return; + } + if (locale == null) { + lastLocale = locale; + return; + } + if (! lastLocale.equals(locale)) { + lastLocale = locale; + } + } + + /** + * removeTag removes a tag from the tagStack. The tagStack is + * used to keep track of tags and locales. + */ + protected void removeTag(Tag tag) { + LangElement el; + String name = tag.name; + Locale newLocale = null; + + for (;;) { + if (tagStack.empty()) + unbalanced(name); + el = (LangElement) tagStack.pop(); + if (el.getTag().name.equals(name)) { + if (tagStack.empty()) { + newLocale = defaultLocale; + } else { + el = (LangElement) tagStack.peek(); + newLocale = el.getLocale(); + } + break; + } + } + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It also possible for locale to be null so if lastLocale is set + // then reset lastLocale to null; + // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale + if (lastLocale == null) { + lastLocale = newLocale; + return; + } + if (newLocale == null) { + lastLocale = newLocale; + return; + } + if (! lastLocale.equals(newLocale)) { + lastLocale = newLocale; + } + } + + /** + * Handy error message methods. + */ + + private void parsingError(String key) { + String s = HelpUtilities.getText(key); + factory.reportMessage(s, false); // tree will be wrong + } + + private void parsingError(String key, String s) { + String msg = HelpUtilities.getText(key, s); + factory.reportMessage(msg, false); // tree will be wrong + } + + private void parsingError(String key, String s1, String s2) { + String msg = HelpUtilities.getText(key, s1, s2); + factory.reportMessage(msg, false); // tree will be wrong + } + + private void wrongParent(String name, String pname) { + parsingError("helpset.wrongParent", name, pname); + } + + private void unbalanced(String name) { + parsingError("helpset.unbalanced", name); + } + + private void wrongLocale(Locale found, Locale l1, Locale l2) { + String msg = HelpUtilities.getText("helpset.wrongLocale", + found.toString(), + l1.toString(), + l2.toString()); + factory.reportMessage(msg, true); // will continue + } + } // End of HelpSetParser + + /** + * For printf debugging. + */ + private final static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("HelpSet: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java new file mode 100644 index 0000000000000000000000000000000000000000..21b5baa30c0b68844305c88ae65725164b045cc4 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java @@ -0,0 +1,50 @@ +/* + * @(#)HelpSetException.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Locale; + +/** + * This exeception reports generic failures in HelpSet. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.12 10/30/06 + */ + +public class HelpSetException extends Exception { + /** + * Constructs a HelpSetException with a specified detailed message. + * A detail message is a String that describes this particular exception. + * @params s The detailed message. If s is null it is the same as if + * no detailed message was specified. + */ + public HelpSetException(String s) { + super(s); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..791ff61a835106c097d495ac61dbc53cd185cb10 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java @@ -0,0 +1,195 @@ +/* + * @(#)HelpSetFactory.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Hashtable; +import java.util.Locale; +import java.util.Enumeration; +import java.util.Vector; +import java.net.URL; +import java.awt.Dimension; +import java.awt.Point; + +/** + * A factory for creating HelpSets. This can be used to reuse our parser. + * + * @author Eduardo Pelegri-Llopart + * @(#)HelpSetFactory.java 1.12 10/30/06 + */ + +interface HelpSetFactory { + /** + * Parsing starts. + * + * @param url URL to the document being parsed + */ + public void parsingStarted(URL source); + + /** + * Processes a DOCTYPE + * + * @param root The root tag of the document + * @param publicID PublicID from the DOCTYPE + * @param systemID SystemID from the DOCTYPE + */ + public void processDOCTYPE(String root, String publicID, String systemID); + + /** + * A Processing Instruction. + * + * @param target The target of the PI + * @param data A String for the data in the PI + */ + public void processPI(HelpSet hs, + String target, + String data); + + /** + * process <title> + * + * @param hs The Helpset + * @param title The title of the HelpSet + */ + public void processTitle(HelpSet hs, + String title); + + /** + * Processes <homeID>. + * + * @param hs The Helpset + * @param homeID The home ID for the helpset + */ + public void processHomeID(HelpSet hs, + String homeID); + + /** + * Process a &l;mapref>. + * + * @param hs The HelpSet + * @param Attributes for this tag + */ + public void processMapRef(HelpSet hs, + Hashtable attributes); + + /** + * Creates a NavigatorView from the data. + * + * @param hs The HelpSet + */ + + public void processView(HelpSet hs, + String name, + String label, + String type, + Hashtable viewAttributes, + String data, + Hashtable dataAttributes, + Locale locale); + + /** + * Processes a sub-HelpSet tag. + * + * @param base The base URL from where to locate the sub-HelpSet. + * @param att A collection of attributes that might be used. + * @returns A HelpSet to be added. + */ + public void processSubHelpSet(HelpSet hs, + Hashtable attributes); + + /** + * Creates a HelpSet.Presentation from the data. The hs and name + * parameters are the only required parameters. All others may be null. + * + * @param hs The HelpSet + * @param name Name of the Presentation + * @param default Is the Presenation the default Presentation + * @param displayViews Display the Views in the Presentation + * @param displayViewImages Display the Views Images in the Presentation + * @param size Size of the Presentation + * @param location Location of the Presentation + * @param title Title for the presentation + * @param toolbar Is there a custom toolbar for the presentation + * @param helpActions A Vector of HelpAction(s). + * + * + */ + + public void processPresentation(HelpSet hs, + String name, + boolean defaultPresentation, + boolean displayViews, + boolean displayViewImages, + Dimension size, + Point location, + String title, + String imageMapID, + boolean toolbar, + Vector helpActions); + + /** + * Reports some parsing error. + * + * @param msg The message to report. + * @param validParse Whether the on-going parse should return a valid object. + */ + public void reportMessage(String msg, boolean validParse); + + /** + * Enumerated all the error mesages. + */ + public Enumeration listMessages(); + + /** + * Parsing ends. Last chance to do something + * to the HelpSet + */ + public HelpSet parsingEnded(HelpSet hs); + + /** + * Internal storage of HelpAction defined in a Presentaion + */ + public class HelpAction { + + /** + * Name of the Action + */ + public String className = null; + + /** + * Attributes of the Action + */ + public Hashtable attr = null; + + public HelpAction (String className, Hashtable attr) { + this.className = className; + this.attr = attr; + } + } + + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java new file mode 100644 index 0000000000000000000000000000000000000000..8c6b76b3533cadd725afc9d64fbd89c606618e77 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java @@ -0,0 +1,881 @@ +/* + * @(#)HelpUtilities.java 1.56 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; + +import java.io.InputStream; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Vector; + +import java.beans.BeanInfo; +import java.beans.Introspector; + +import java.text.CollationElementIterator; +import java.text.Collator; +import java.text.MessageFormat; +import java.text.RuleBasedCollator; + +import java.awt.Component; +import java.awt.IllegalComponentStateException; + + +/** + * Provides a number of utility functions: + * + * Support for Beans, mapping from a Bean class to its HelpSet and to + * its ID. + * Support for finding localized resources. + * Support for getting the default Query Engine + * + * This class has no public constructor. + * + * @author Eduardo Pelegri-Llopart + * @author Roger D. Brinkley + * @version 1.56 10/30/06 + */ + +public class HelpUtilities { + + //========= + + /** + * Beans support + */ + + /** + * Given the class for a bean, get its HelpSet. + * Returns the helpSetName property of the BeanDescriptor if defined. + * Otherwise it returns a name as follows: + * If the class is in the unnamed package, it returns <em>beanClassName</em>Help.hs. + * Otherwise if it's in the form <em>package.ClassName</em> it returns + * <em>package</em>/Help.hs after replacing "." with "/" in <em>package</em>. + * + * @param beanClass The Class + * @return A String with the name of the HelpSet + */ + + public static String getHelpSetNameFromBean(Class beanClass) { + String helpSetName; + try { + BeanInfo bi = Introspector.getBeanInfo(beanClass); + helpSetName = + (String) bi.getBeanDescriptor().getValue("helpSetName"); + } catch (Exception ex) { + helpSetName = null; + } + if (helpSetName == null) { + String className = beanClass.getName(); + int index = className.lastIndexOf("."); + if (index == -1) { + // unnamed package + helpSetName = className + "Help.hs"; + } else { + String packageName = className.substring(0, index); + helpSetName = packageName.replace('.','/') + "/Help.hs"; + } + } + return helpSetName; + } + + /** + * Given the class for a bean, get its ID string. + * Returns the helpID property of the BeanDescriptor if defined, + * otherwise it returns <em>beanName</em>.topID. + * + * @param beanClass the Class + * @return A String with the ID to use + */ + + public static String getIDStringFromBean(Class beanClass) { + String helpID; + try { + BeanInfo bi = Introspector.getBeanInfo(beanClass); + helpID = (String) bi.getBeanDescriptor().getValue("helpID"); + } catch (Exception ex) { + helpID = null; + } + if (helpID == null) { + String className = beanClass.getName(); + helpID = className + ".topID"; + } + return helpID; + } + + + //======= + /** + * Default for the search engine + */ + public static String getDefaultQueryEngine() { + return "com.sun.java.help.search.DefaultSearchEngine"; + } + + //======== + + /** + * I18N/ L10N support + */ + + /** + * Search for a helpset file following the standard conventions + * used in ResourceBundle. + */ + + /** + * Locate a resource relative to a given classloader CL. + * The name of the resource is composed by using FRONT, + * adding _LANG _COUNTRY _VARIANT (with the usual rules) + * and ending with BACK, which will usually be an extension + * like ".hs" for a HelpSet, or ".class" for a class + * + * This method is a convenience method for getLocalizedResource() with + * a tryRead parameter set to false. + * + * This functionality should likely be exposed as part of JDK1.2 + * @param cl The ClassLoader to get the resource from. If cl is null the default + * ClassLoader is used. + * @returns the URL to the localized resource or null if not found. + */ + public static URL getLocalizedResource(ClassLoader cl, + String front, + String back, + Locale locale) { + return getLocalizedResource(cl, front, back, locale, false); + } + + /** + * Locate a resource relative to a given classloader CL. + * The name of the resource is composed by using FRONT, + * adding _LANG _COUNTRY _VARIANT (with the usual rules) + * and ending with BACK, which is usually an extension + * like ".hs" for a HelpSet, or ".class" for a class + * + * This version accepts an explicit argument to work around some browser bugs. + * + * This functionality should likely be exposed as part of JDK1.2 + * @param cl The ClassLoader to get the resource from. If cl is null the default + * ClassLoader is used. + * @returns the URL to the localized resource or null if not found. + */ + public static URL getLocalizedResource(ClassLoader cl, + String front, + String back, + Locale locale, + boolean tryRead) { + URL url; + for (Enumeration tails = getCandidates(locale); + tails.hasMoreElements(); ) { + String tail = (String) tails.nextElement(); + String name = (new StringBuffer(front)).append(tail).append(back).toString(); + if (cl == null) { + url = ClassLoader.getSystemResource(name); + } else { + url = cl.getResource(name); + } + if (url != null) { + if (tryRead) { + // Try doing an actual read to be sure it exists + try { + InputStream is = url.openConnection().getInputStream(); + if (is != null) { + int i = is.read(); + is.close(); + if (i != -1) { + return url; + } + } + } catch (Throwable t) { + // ignore and continue looking + } + } else { + return url; + } + } + } + return null; + } + + private static Hashtable tailsPerLocales = new Hashtable(); + + /** + * This returns an enumeration of String tails. + * + * The core functionality on which getLocalizedResource is based. + * + * The suffixes are based on (1) the desired locale and (2) the default locale + * in the following order from lower-level (more specific) to parent-level + * (less specific): + * <p> "_" + language1 + "_" + country1 + "_" + variant1 + * <BR> "_" + language1 + "_" + country1 + * <BR> "_" + language1 + * <BR> "" + * <BR> "_" + language2 + "_" + country2 + "_" + variant2 + * <BR> "_" + language2 + "_" + country2 + * <BR> "_" + language2 + * + * The enumeration is of StringBuffer. + * We pay some attention to efficiency in case a method like this is promoted, + * hence we cache per locale. + */ + + public static synchronized Enumeration getCandidates(Locale locale) { + Vector tails; + LocalePair pair = new LocalePair(locale, Locale.getDefault()); + tails = (Vector) tailsPerLocales.get(pair); + if (tails != null) { + debug("getCandidates - cached copy"); + return tails.elements(); + } + + String lname1 = locale.toString(); + StringBuffer name1 = new StringBuffer("_").append(lname1); + if (lname1 == null) { + name1.setLength(0); + } + tails = new Vector(); + // Now add them to the vector + while (name1.length() != 0) { + debug(" adding ", name1); + String s = name1.toString(); + tails.addElement(s); + int lastUnder = s.lastIndexOf('_'); + if (lastUnder != -1) { + name1.setLength(lastUnder); + } + } + debug(" addign -- null -- "); + tails.addElement(""); + if (locale != Locale.getDefault()) { + // Otherwise, no need to search twice + String lname2 = Locale.getDefault().toString(); + StringBuffer name2 = new StringBuffer("_").append(lname2); + if (lname2 == null) { + name2.setLength(0); + } + while (name2.length() != 0) { + debug(" adding ", name2); + String s = name2.toString(); + tails.addElement(s); + int lastUnder = s.lastIndexOf('_'); + if (lastUnder != -1) { + name2.setLength(lastUnder); + } + } + } + tailsPerLocales.put(pair, tails); + debug("tails is == ", tails); + return tails.elements(); + } + + /** + * Auxiliary class used in dealing with locale. + */ + + static class LocalePair { + LocalePair(Locale locale1, Locale locale2) { + this.locale1 = locale1; + this.locale2 = locale2; + } + + public int hashCode() { + return locale1.hashCode() + locale2.hashCode(); + } + + public boolean equals(Object obj) { + if (obj == null || ! (obj instanceof LocalePair)) { + return false; + } else { + LocalePair p = (LocalePair) obj; + return locale1.equals(p.locale1) && locale2.equals(p.locale2); + } + } + + Locale locale1; + Locale locale2; + } + + // ========== + + /** + * Get a localized Error String + */ + private static Hashtable bundles; + private static ResourceBundle lastBundle = null; + private static Locale lastLocale = null; + + /** + * Gets the locale of a component. If the component is null + * it returns the defaultLocale. If the call to component.getLocale + * returns an IllegalComponentStateException, the defaultLocale is + * returned. + */ + public static Locale getLocale(Component c) { + if (c == null) { + return Locale.getDefault(); + } + try { + return c.getLocale(); + } catch (IllegalComponentStateException ex) { + return Locale.getDefault(); + } + + } + + static synchronized private ResourceBundle getBundle(Locale l) { + if (lastLocale == l) { + return lastBundle; + } + if (bundles == null) { + bundles = new Hashtable(); + } + ResourceBundle back = (ResourceBundle) bundles.get(l); + if (back == null) { + try { + back = ResourceBundle.getBundle("javax.help.resources.Constants", + l); + } catch (MissingResourceException ex) { + throw new Error("Fatal: Resource for javahelp is missing"); + } + bundles.put(l, back); + } + lastBundle = back; + lastLocale = l; + return back; + } + + + /** + * Get the Text message for the default locale. + * + * The getString version does not involve a format. + */ + static public String getString(String key) { + return getString(Locale.getDefault(), key); + } + + static public String getText(String key) { + return getText(Locale.getDefault(), key, null, null); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + */ + static public String getText(String key, String s1) { + return getText(Locale.getDefault(), key, s1, null); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + * @param s2 The first parameter of a string. A null is valid for s2. + */ + static public String getText(String key, String s1, String s2) { + return getText(Locale.getDefault(), key, s1, s2); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + * @param s2 The first parameter of a string. A null is valid for s2. + * @param s3 The first parameter of a string. A null is valid for s3. + */ + static public String getText(String key, String s1, String s2, String s3) { + return getText(Locale.getDefault(), key, s1, s2, s3); + } + + /** + * Versions with an explicit locale. +*/ + static public String getString(Locale l, String key) { + ResourceBundle bundle = getBundle(l); + try { + return bundle.getString(key); + } catch (MissingResourceException ex) { + throw new Error("Fatal: Localization data for JavaHelp is broken. Missing "+key+" key."); + } + } + + static public String[] getStringArray(Locale l, String key) { + ResourceBundle bundle = getBundle(l); + try { + return bundle.getStringArray(key); + } catch (MissingResourceException ex) { + throw new Error("Fatal: Localization data for JavaHelp is broken. Missing "+key+" key."); + } + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + * @param s2 The first parameter of a string. A null is valid for s2. + * @param s3 The first parameter of a string. A null is valid for s3. + */ + static public String getText(Locale l, String key) { + return getText(l, key, null, null, null); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + */ + static public String getText(Locale l, String key, String s1) { + return getText(l, key, s1, null, null); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + * @param s2 The first parameter of a string. A null is valid for s2. + */ + static public String getText(Locale l, String key, String s1, String s2) { + return getText(l, key, s1, s2, null); + } + + /** + * @param s1 The first parameter of a string. A null is valid for s1. + * @param s2 The first parameter of a string. A null is valid for s2. + * @param s3 The first parameter of a string. A null is valid for s3. + */ + static public String getText(Locale l, String key, + String s1, String s2, String s3) { + ResourceBundle bundle = getBundle(l); + // workaround bugs in JDK 1.1.6 + // This mimic's what JDK 1.2 will do. + if (s1 == null) { + s1 = "null"; + } + if (s2 == null) { + s2 = "null"; + } + if (s3 == null) { + s3 = "null"; + } + // end workaround + try { + String fmt = bundle.getString(key); + String[] args = {s1, s2, s3}; + MessageFormat format = new MessageFormat(fmt); + // workaround a bug in MessageFormat.setLocale + try { + format.setLocale(l); + } catch (NullPointerException ee) { + } + return format.format(args); + } catch (MissingResourceException ex) { + throw new Error("Fatal: Localization data for JavaHelp is broken. Missing "+key+" key."); + } + } + + /** + * Convenient method for creating a locale from a <tt>lang</tt> string. + * Takes the <tt>lang</tt> string in the form of "language_country_variant" + * or "language-country-variant" and + * parses the string and creates an appropriate locale. + * @param lang A String representation of a locale, with the language, + * country and variant separated by underbars. Language is always lower + * case, and country is always upper case. If the language is missing the + * String begins with an underbar. If both language and country fields are + * missing, a null Locale is returned. If lang is null a null Locale is + * returned + * @returns The locale based on the string or null if the Locale could + * not be constructed or lang was null. + */ + public static Locale localeFromLang(String lang) { + String language; + String country; + String variant=null; + Locale newlocale=null; + if (lang == null) { + return newlocale; + } + int lpt = lang.indexOf("_"); + int lpt2 = lang.indexOf("-"); + if (lpt == -1 && lpt2 == -1) { + language = lang; + country = ""; + newlocale = new Locale(language, country); + } else { + if (lpt == -1 && lpt2 != -1) { + lpt = lpt2; + } + language = lang.substring(0, lpt); + int cpt = lang.indexOf("_", lpt+1); + int cpt2 = lang.indexOf("-", lpt+1); + if (cpt == -1 && cpt2 == -1) { + country = lang.substring(lpt+1); + newlocale = new Locale(language, country); + } else { + if (cpt == -1 && cpt2 != -1) { + cpt = cpt2; + } + country = lang.substring(lpt+1, cpt); + variant = lang.substring(cpt+1); + newlocale = new Locale(language, country, variant); + } + } + return newlocale; + } + + /** + * Returns information about whether a string is + * contained in another string. Compares the character data stored in two + * different strings based on the collation rules. + */ + public static boolean isStringInString(RuleBasedCollator rbc, + String source, + String target) { + // The basic algorithm here is that we use CollationElementIterators + // to step through both the source and target strings. We compare each + // collation element in the source string against the corresponding one + // in the target, checking for differences. + // + // If a difference is found, we set <result> to false. + // + // However, it's not that simple. If we find a tertiary difference + // (e.g. 'A' vs. 'a') near the beginning of a string, it can be + // overridden by a primary difference (e.g. "A" vs. "B") later in + // the string. For example, "AA" < "aB", even though 'A' > 'a'. + // + // To keep track of this, we use strengthResult to keep track of the + // strength of the most significant difference that has been found + // so far. When we find a difference whose strength is greater than + // strengthResult, it overrides the last difference (if any) that + // was found. + + debug("isStringInString source=" + source + " targe =" + target); + + // Initial sanity checks + if (source == null || target == null) { + return false; + } + if (source.length() == 0 && target.length() == 0) { + return true; + } + + // on to the real code + int strengthResult = Collator.IDENTICAL; + CollationElementIterator sourceCursor, targetCursor; + boolean isFrenchSec = false; + + // set up the RuleBasedCollator and extract + // various attributes + rbc.setDecomposition(Collator.FULL_DECOMPOSITION); + String rules = rbc.getRules(); + if (rules.startsWith("@")) { + // I suspect we are cheating here when multiple rules are merged + // One would think you could get this attribute but you can't + isFrenchSec = true; + } + + // Get the CollationElementIterators for the source and target + sourceCursor = rbc.getCollationElementIterator(source); + targetCursor = rbc.getCollationElementIterator(target); + + // Various locale specific matching parameters + int sOrder = 0, tOrder = 0; + int pSOrder, pTOrder; + short secSOrder, secTOrder; + short terSOrder, terTOrder; + boolean gets = true, gett = true; + int toffset = 0; + boolean initialCheckSecTer, checkSecTer, checkTertiary; + + startSearchForFirstMatch: + while(true) { + debug("while(true) toffset=" + toffset); + // Set the starting point for this comparison + try { + sourceCursor.setOffset(0); + } catch (NoSuchMethodError ex3) { + // ingnore it + } + sOrder = sourceCursor.next(); + try { + targetCursor.setOffset(toffset); + } catch (NoSuchMethodError ex4) { + // Can't really do anything here. Return false. + } catch (Exception e) { + // We can get an exception when the toffset is really the + // end of string + // Just catch it and return false; + return false; + } + tOrder = targetCursor.next(); + + if (tOrder == CollationElementIterator.NULLORDER) { + break; + } + + debug("sOrder=" + sOrder + " tOrder=" + tOrder); + + //Find the first character in the target that matches the first + // character in the source. Look for a complete match of + // primary, secondary and tertiary. Lacking that look for + // a match of just primary. + while (tOrder != CollationElementIterator.NULLORDER) { + if (sOrder == tOrder) { + try { + toffset = targetCursor.getOffset(); + } catch (NoSuchMethodError ex) { + //ignore it + } + break; + } + pSOrder = CollationElementIterator.primaryOrder(sOrder); + pTOrder = CollationElementIterator.primaryOrder(tOrder); + if (pSOrder == pTOrder) { + try { + toffset = targetCursor.getOffset(); + } catch (NoSuchMethodError ex2) { + //ignore it + } + break; + } + tOrder = targetCursor.next(); + debug("next tOrder=" + tOrder); + } + + // If at end there is no match + if (tOrder == CollationElementIterator.NULLORDER) { + return false; + } + + gets = false; + gett = false; + initialCheckSecTer = rbc.getStrength() >= Collator.SECONDARY; + checkSecTer = initialCheckSecTer; + checkTertiary = rbc.getStrength() >= Collator.TERTIARY; + + while (true) { + // Get the next collation element in each of the strings, unless + // we've been requested to skip it. + if (gets) { + sOrder = sourceCursor.next(); + } else { + gets = true; + } + if (gett) { + tOrder = targetCursor.next(); + } else { + gett = true; + } + + // If we've hit the end of one of the strings, jump out of the loop + if ((sOrder == CollationElementIterator.NULLORDER)|| + (tOrder == CollationElementIterator.NULLORDER)) { + debug("One string at end"); + break; + } + + pSOrder = CollationElementIterator.primaryOrder(sOrder); + pTOrder = CollationElementIterator.primaryOrder(tOrder); + + // If there's no difference at this position, we can skip it + if (sOrder == tOrder) { + if (isFrenchSec && pSOrder != 0) { + if (!checkSecTer) { + // in french, a secondary difference more to the + // right is stronger, + // so accents have to be checked with each base + // element + checkSecTer = initialCheckSecTer; + // but tertiary differences are less important + // than the first + // secondary difference, so checking tertiary + // remains disabled + checkTertiary = false; + } + } + debug("No diff at this positon continue"); + continue; + } + + // Compare primary differences first. + if ( pSOrder != pTOrder ) { + if (sOrder == 0) { + // The entire source element is ignorable. + // Skip to the next source element, + // but don't fetch another target element. + gett = false; + continue; + } + if (tOrder == 0) { + // The entire target element is ignorable. + // Skip to the next target element, + // but don't fetch another source element. + gets = false; + continue; + } + + // The source and target elements aren't ignorable, + // but it's still possible + // for the primary component of one of the elements + // to be ignorable.... + + if (pSOrder == 0) { + // The source's primary is ignorable, + // but the target's isn't. We treat ignorables + // as a secondary differenc + if (checkSecTer) { + // (strength is SECONDARY) + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Strength is secondary pSOrder === 0"); + continue startSearchForFirstMatch; + } + // Skip to the next source element, + // but don't fetch another target element. + gett = false; + } else if (pTOrder == 0) { + // record differences - see the comment above. + if (checkSecTer) { + // (stength is SECONDARY) + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Strength is secondary - pTOrder == 0"); + continue startSearchForFirstMatch; + } + // Skip to the next source element, + // but don't fetch another target element. + gets = false; + } else { + // Neither of the orders is ignorable, + // and we already know that the primary + // orders are different because of the + // (pSOrder != pTOrder) test above. + // Record the difference and stop the + // comparison. + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Order are ignorable"); + continue startSearchForFirstMatch; + } + } else { // else of if ( pSOrder != pTOrder ) + // primary order is the same, but complete order is + // different. So there + // are no base elements at this point, only + // ignorables (Since the strings are + // normalized) + + if (checkSecTer) { + // a secondary or tertiary difference may + // still matter + secSOrder = CollationElementIterator.secondaryOrder(sOrder); + secTOrder = CollationElementIterator.secondaryOrder(tOrder); + if (secSOrder != secTOrder) { + // there is a secondary difference + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Secondary Difference"); + continue startSearchForFirstMatch; + // (strength is SECONDARY) + // (even in french, only the first + // secondary difference within + // a base character matters) + } else { + if (checkTertiary) { + // a tertiary difference may still matter + terSOrder = CollationElementIterator.tertiaryOrder(sOrder); + terTOrder = CollationElementIterator.tertiaryOrder(tOrder); + if (terSOrder != terTOrder) { + // there is a tertiary difference + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Tertiary difference"); + continue startSearchForFirstMatch; + // (strength is TERTIARY) + } + } + } + } // if (checkSecTer) + + } // if ( pSOrder != pTOrder ) + } // while() + + // There might be a match + // Just do some final checking + if (sOrder != CollationElementIterator.NULLORDER) { + // (tOrder must be CollationElementIterator::NULLORDER, + // since this point is only reached when sOrder or + // tOrder is NULLORDER.) + // The source string has more elements, + // but the target string hasn't. + do { + if (CollationElementIterator.primaryOrder(sOrder) != 0) { + // We found an additional non-ignorable base + // character in the source string. + // This is a primary difference, + // so the source is greater + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Additional non-ignborable base character in source string - source is greater"); + continue startSearchForFirstMatch; + // (strength is PRIMARY) + } + else if (CollationElementIterator.secondaryOrder(sOrder) != 0) { + // Additional secondary elements mean the + // source string is greater + if (checkSecTer) { + targetCursor.next(); + toffset = targetCursor.getOffset(); + debug("Additional secondary elements source is greater"); + continue startSearchForFirstMatch; + // (strength is SECONDARY) + } + } + } while ((sOrder = sourceCursor.next()) != CollationElementIterator.NULLORDER); + } + // Either the target string has more elements, + // but the source string hasn't or neither the target string + // or the source string have any more elemnts. + // In either case the source was contained in target + // return true; + return true; + } + return false; + } + + + + /** + * Debug support + */ + + private static final boolean debug = false; + private static void debug(Object msg1, Object msg2, Object msg3) { + if (debug) { + System.err.println("HelpUtilities: "+msg1+msg2+msg3); + } + } + private static void debug(Object msg1) { debug(msg1,"",""); } + private static void debug(Object msg1, Object msg2) { + debug(msg1,msg2,""); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java b/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java new file mode 100644 index 0000000000000000000000000000000000000000..0ecfafda19a6bd88e710fa15997dcb292551c436 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java @@ -0,0 +1,78 @@ +/* + * @(#)HomeAction.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.*; +import java.awt.event.*; +import javax.help.*; +import javax.help.event.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Stack; +import javax.swing.*; + +/** + * + * @author Stepan Marek + * @version 1.4 10/30/06 + */ +public class HomeAction extends AbstractHelpAction implements ActionListener { + + private static final String NAME = "HomeAction"; + + /** Creates new HomeAction */ + public HomeAction(Object control) { + super(control, NAME); + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + if (control instanceof JHelp) { + JHelp help = (JHelp) control; + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + } + } + + public void actionPerformed(java.awt.event.ActionEvent event) { + try { + JHelp help = (JHelp)getControl(); + HelpSet hs = help.getModel().getHelpSet(); + Map.ID homeID = hs.getHomeID(); + Locale locale = hs.getLocale(); + String string = HelpUtilities.getString(locale, "history.homePage"); + help.setCurrentID(homeID, string, help.getCurrentNavigator()); + } catch (Exception e) { + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java b/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java new file mode 100644 index 0000000000000000000000000000000000000000..91e4f8356d694267eb9eca6387078b5cd788eea5 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java @@ -0,0 +1,76 @@ +/* + * @(#)IndexItem.java 1.18 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Vector; +import java.util.Locale; +import javax.help.Map.ID; + +/** + * A class for individual index items. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.18 10/30/06 + */ + +public class IndexItem extends TreeItem { + + /** + * Create an IndexItem. + * + * @param id ID for the item. The ID can be null. + * @param hs A HelpSet scoping this item. + * @param locale The locale for this item + */ + public IndexItem(ID id, HelpSet hs, Locale locale) { + super(id, hs, locale); + } + + /** + * Create an IndexItem defaulting the HelpSet to that of its ID. + * + * @param id ID for the item. The ID can be null. + * @param locale The locale to use for this item. + */ + public IndexItem(ID id, Locale locale) { + super(id, locale); + HelpSet hs = null; + if (id != null) { + setHelpSet(id.hs); + } + + } + + /** + * Create a default IndexItem. + */ + public IndexItem() { + super(null, null, null); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/IndexView.java b/jhMaster/JavaHelp/src/new/javax/help/IndexView.java new file mode 100644 index 0000000000000000000000000000000000000000..c423efad26114a6063a43494461522f972f4a212 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/IndexView.java @@ -0,0 +1,620 @@ +/* + * @(#)IndexView.java 1.32 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.Component; +import java.net.URL; +import java.net.URLConnection; +import java.io.Reader; +import java.io.IOException; +import java.util.Stack; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; +import java.util.Enumeration; +import javax.help.Map.ID; +import javax.swing.tree.TreeNode; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.sun.java.help.impl.*; + + +/** + * Navigational View information for an Index + * + * @author Eduardo Pelegri-Llopart + * @version 1.17 03/16/99 + */ + +public class IndexView extends NavigatorView { + + /** + * PublicID (known to this XML processor) to the DTD for version 1.0 of the Index + */ + public static final String publicIDString = + "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN"; + + /** + * PublicID (known to this XML processor) to the DTD for version 2.0 of the Index + */ + public static final String publicIDString_V2 = + "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 2.0//EN"; + + /** + * Construct an IndexView with some given data. Locale defaults to that + * of the HelpSet. + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param params A hashtable providing different key/values for this type. + * A null for params is valid. + */ + public IndexView(HelpSet hs, + String name, + String label, + Hashtable params) { + super(hs, name, label, hs.getLocale(), params); + } + + /** + * Constructs an IndexView with some given data. + * + * @param hs The HelpSet that provides context information + * @param name The name of the View + * @param label The label (to show the user) of the View + * @param locale The default locale to interpret the data in this TOC. A + * null for locale will be interpreted as the defaultLocale. + * @param params A Hashtable providing different key/values for this type + * A null for params is valid. + */ + public IndexView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) { + super(hs, name, label, locale, params); + } + + /** + * create a navigator for a given model. + * @param model The HelpModel to create this navigator with. A null model + * is valid. + * @return The appropriate Component for this view. + */ + public Component createNavigator(HelpModel model) { + return new JHelpIndexNavigator(this, model); + } + + + /** + * Get the Index navigators mergeType. Overrides getMergeType in NavigatorView + */ + public String getMergeType() { + String mergeType = super.getMergeType(); + if (mergeType == null) { + return "javax.help.AppendMerge"; + } + return mergeType; + } + + // turn this on if you want messages on failures + private static boolean warningOfFailures = false; + + /** + * Gets a DefaultMutableTreeNode representing the + * information in this view instance. + * + * The default implementation parses the data in the URL, but a subclass may + * override this method and provide a different implemenation. For example, + * it may create the tree programatically. + */ + public DefaultMutableTreeNode getDataAsTree() { + HelpSet hs = getHelpSet(); + debug("helpSet in "+this+hs.toString()); + Hashtable params = getParameters(); + URL url; + + if (params == null || + (params != null && !params.containsKey("data"))) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(); + return node; + } + + try { + url = new URL(hs.getHelpSetURL(), (String) params.get("data")); + } catch (Exception ex) { + throw new Error("Trouble getting URL to Index data; "+ex); + } + debug("url,hs: "+url.toString()+";"+hs.toString()); + return parse(url, hs, hs.getLocale(), new DefaultIndexFactory()); + } + + /** + * Public method for parsing an Index in a URL. + * It returns a DefaultMutableTreeNode and its children + * that correspond to the indexitems in the Index. The factory is invoked to create + * the TreeItems that are included in the DefaultMutableTreeNode as user + * data. + * + * @param url Location of the Index. If null, causes null value to be returned. + * @param hs The HelpSet context for this Index. Null hs is ignored. + * @param locale The default locale to interpret the data in this Index. Null + * locale is treated as the default locale. + * @param factory A factory instance that is used to create the IndexItems + * @return a TreeNode that represents the Index. Returns null if parsing errors + * were encountered. + */ + public static DefaultMutableTreeNode parse(URL url, + HelpSet hs, + Locale locale, + TreeItemFactory factory) { + Reader src; + DefaultMutableTreeNode node = null; + try { + URLConnection uc = url.openConnection(); + src = XmlReader.createReader(uc); + factory.parsingStarted(url); + node = (new IndexParser(factory)).parse(src, hs, locale); + src.close(); + } catch (Exception e) { + factory.reportMessage("Exception caught while parsing "+url+ + e.toString(), + false); + } + return factory.parsingEnded(node); + } + + /** + * A default TreeItemFactory that can be used to parse TOC items as used + * by this navigator. + */ + public static class DefaultIndexFactory implements TreeItemFactory { + private Vector messages = new Vector(); + private URL source; + private boolean validParse = true; + + /** + * Parsing has started + */ + public void parsingStarted(URL source) { + if (source == null) { + throw new NullPointerException("source"); + } + this.source = source; + } + + /** + * Process a DOCTYPE + */ + public void processDOCTYPE(String root, + String publicID, + String systemID) { + if (publicID == null || + (publicID.compareTo(publicIDString) != 0 && + publicID.compareTo(publicIDString_V2) != 0)) { + reportMessage(HelpUtilities.getText("index.invalidIndexFormat", publicID), false); + } + } + + /** + * We have found a PI; ignore it + */ + public void processPI(HelpSet hs, String target, String data) { + } + + /** + * Creates an IndexItem with the given data. + * @param tagName The index type to create. + * Valid types are "indexitem". Null or invalid types throw an + * IllegalArgumentException. + * @param atts Attributes of the Item. Valid attributes are "target" + * and "text". A null <tt>atts</tt> is valid and means no attributes. + * @param hs The HelpSet this item was created under. + * @param locale Locale of this item. A null locale is valid. + * @returns A fully constructed TreeItem. + * @throws IllegalArgumentException if tagname is null or invalid. + */ + public TreeItem createItem(String tagName, + Hashtable atts, + HelpSet hs, + Locale locale) { + if (tagName == null || !tagName.equals("indexitem")) { + throw new IllegalArgumentException("tagName"); + } + IndexItem item = null; + String id = null; + String text = null; + String mergeType = null; + String expand = null; + String presentation = null; + String presentationName = null; + + if (atts != null ) { + id = (String) atts.get("target"); + text = (String) atts.get("text"); + mergeType = (String) atts.get("mergetype"); + expand = (String) atts.get("expand"); + presentation = (String) atts.get("presentationtype"); + presentationName = (String) atts.get("presentationname"); + } + + try { + item = new IndexItem(ID.create(id, hs), + hs, + locale); + } catch (BadIDException ex) { + item = new IndexItem(); + } + + if (text != null) { + item.setName(text); + } + if (mergeType != null){ + item.setMergeType(mergeType); + } + if (expand != null) { + if (expand.equals("true")) { + item.setExpansionType(TreeItem.EXPAND); + } else if (expand.equals("false")) { + item.setExpansionType(TreeItem.COLLAPSE); + } + } + + if (presentation != null){ + item.setPresentation(presentation); + } + + if (presentationName != null){ + item.setPresentationName(presentationName); + } + + return item; + } + + /** + * Creates a default IndexItem. + */ + public TreeItem createItem() { + return new IndexItem(); + } + + /** + * Reports an error message. + */ + public void reportMessage(String msg, boolean validParse) { + messages.addElement(msg); + this.validParse = this.validParse && validParse; + } + + /** + * Lists all the error messages. + */ + public Enumeration listMessages() { + return messages.elements(); + } + + /** + * Parsing has ended. The last chance to do something + * to the node + * @param node The DefaultMutableTreeNode that has been built during the + * the parsing. If <tt>node</tt> is null or there were parsing errors a null + * is returned. + * @returns A valid DefaultMutableTreeNode if the parsing succeded or null + * if it failed + */ + public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) { + DefaultMutableTreeNode back = node; + if (! validParse) { + // A parse with problems... + back = null; + System.err.println("Parsing failed for "+source); + for (Enumeration e = messages.elements(); + e.hasMoreElements();) { + String msg = (String) e.nextElement(); + // need to think about this one... + System.err.println(msg); + } + } + return back; + } + } + + + /** + * Inner class for parsing an Index stream. + * + * WARNING!! This class is an interim solution until JH moves to a + * real XML parser. This is not a public class. Clients should only use + * the parse method in the enclosing class. + */ + + private static class IndexParser implements ParserListener { + private HelpSet currentParseHS; // HelpSet we are parsing into + private Stack nodeStack; // to track the parsing + private Stack itemStack; + private Stack tagStack; + private Locale defaultLocale; + private Locale lastLocale; + private boolean startedindex; + private TreeItemFactory factory; + + /** + * Creates an Index Parser using a factory instance to create the item nodes. + * + * @param factory The ItemTreeFactory instance to use when a node + * has been recognized. + */ + + IndexParser(TreeItemFactory factory) { + this.factory = factory; + } + + /** + * Parse a reader into a DefaultMutableTreeNode. + * Only one of these at a time. + */ + synchronized DefaultMutableTreeNode parse(Reader src, + HelpSet context, + Locale locale) + throws IOException + { + nodeStack = new Stack(); + itemStack = new Stack(); + tagStack = new Stack(); + + if (locale == null) { + defaultLocale = Locale.getDefault(); + } else { + defaultLocale = locale; + } + lastLocale = defaultLocale; + + DefaultMutableTreeNode node = new DefaultMutableTreeNode(); + nodeStack.push(node); + + currentParseHS = context; + + Parser parser = new Parser(src); // the XML parser instance + parser.addParserListener(this); + parser.parse(); + return node; + } + + /** + * A Tag was parsed. This method is not intended to be of general use. + */ + public void tagFound(ParserEvent e) { + Locale locale = null; + Tag tag = e.getTag(); + TagProperties attr = tag.atts; + + if (attr != null) { + String lang = attr.getProperty("xml:lang"); + locale = HelpUtilities.localeFromLang(lang); + } + if (locale == null) { + locale = lastLocale; + } + + if (tag.name.equals("indexitem")) { + if (!startedindex) { + factory.reportMessage(HelpUtilities.getText("index.invalidIndexFormat"), + false); + } + if (tag.isEnd && ! tag.isEmpty) { + nodeStack.pop(); + itemStack.pop(); + removeTag(tag); + return; + } + + TreeItem item = null; + try { + Hashtable t = null; + if (attr != null) { + t = attr.getHashtable(); + } + item = factory.createItem("indexitem", + t, + currentParseHS, + locale); + } catch (Exception ex) { + if (warningOfFailures) { + String id=null; + if (attr != null) { + id = attr.getProperty("target"); + } + System.err.println("Failure in IndexItem Creation; "); + System.err.println(" id: "+id); + System.err.println(" hs: "+currentParseHS); + } + item = factory.createItem(); + } + + if (!itemStack.empty()) { + IndexItem parent = (IndexItem)itemStack.peek(); + if (item.getExpansionType() == TreeItem.DEFAULT_EXPANSION && + parent != null && + parent.getExpansionType() != TreeItem.DEFAULT_EXPANSION) { + item.setExpansionType(parent.getExpansionType()); + } + } + DefaultMutableTreeNode node = new DefaultMutableTreeNode(item); + DefaultMutableTreeNode parent = + (DefaultMutableTreeNode) nodeStack.peek(); + parent.add(node); + if (! tag.isEmpty) { + itemStack.push(item); + nodeStack.push(node); + addTag(tag, locale); + } + } else if (tag.name.equals("index")) { + if (!tag.isEnd) { + if (attr != null) { + String version = attr.getProperty("version"); + if (version != null && + (version.compareTo("1.0") != 0 && + version.compareTo("2.0") != 0 )) { + factory.reportMessage(HelpUtilities.getText("index.unknownVersion", version), false); + } + } + if (startedindex) { + factory.reportMessage(HelpUtilities.getText("index.invalidIndexFormat"), + false); + } + startedindex = true; + addTag(tag, locale); + } else { + if (startedindex) { + startedindex = false; + } + removeTag(tag); + } + return; + } + } + + /** + * A PI was parsed. This method is not intended to be of general use. + */ + public void piFound(ParserEvent e) { + // ignore + } + + /** + * A DOCTYPE was parsed. This method is not intended to be of general use. + */ + public void doctypeFound(ParserEvent e) { + // ignore for now + factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId()); + } + + /** + * A continous block of text was parsed. + */ + public void textFound(ParserEvent e) { + if (tagStack.empty()) { + return; // ignore + } + LangElement le = (LangElement) tagStack.peek(); + Tag tag = (Tag) le.getTag(); + if (tag.name.equals("indexitem")) { + IndexItem item = (IndexItem) itemStack.peek(); + String oldName = item.getName(); + if (oldName == null) { + item.setName(e.getText().trim()); + } else { + item.setName(oldName.concat(e.getText()).trim()); + } + } + } + + // The remaing events from Parser are ignored + public void commentFound(ParserEvent e) {} + + public void errorFound(ParserEvent e){ + factory.reportMessage(e.getText(), false); + } + + /** + * Keeps track of tags and their locale attributes. + */ + protected void addTag(Tag tag, Locale locale) { + LangElement el = new LangElement(tag, locale); + tagStack.push(el); + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It is impossible for locale to be null + if (lastLocale == null) { + lastLocale = locale; + return; + } + if (locale == null) { + lastLocale = locale; + return; + } + if (! lastLocale.equals(locale)) { + lastLocale = locale; + } + } + + /** + * Removes a tag from the tagStack. The tagStack is + * used to keep track of tags and locales. + */ + protected void removeTag(Tag tag) { + LangElement el; + String name = tag.name; + Locale newLocale=null; + + for (;;) { + if (tagStack.empty()) + break; + el = (LangElement) tagStack.pop(); + if (! el.getTag().name.equals(name)) { + if (tagStack.empty()) { + newLocale = defaultLocale; + } else { + el = (LangElement) tagStack.peek(); + newLocale = el.getLocale(); + } + break; + } + } + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It also possible for locale to be null so if lastLocale is set + // then reset lastLocale to null; + // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale + if (lastLocale == null) { + lastLocale = newLocale; + return; + } + if (newLocale == null) { + lastLocale = newLocale; + return; + } + if (! lastLocale.equals(newLocale)) { + lastLocale = newLocale; + } + } + + } + + /** + * Debugging code + */ + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("IndexView: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java b/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java new file mode 100644 index 0000000000000000000000000000000000000000..e0dda7932d9628a2ed78af3f65a8a1e42dc02a6d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java @@ -0,0 +1,69 @@ +/* + * @(#)InvalidHelpSetContextException.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +/** + * The HelpSet is not a (transitive) sub-HelpSet of some context HelpSet. + * + * For example, setting an ID to a HelpModel. + * + * @author Eduardo Pelegri-Llopart + * @version 1.3 01/29/99 + */ +public class InvalidHelpSetContextException extends Exception { + private HelpSet context; + private HelpSet hs; + + /** + * Create the exception. All parameters accept null values. + * + * @param msg The message. If msg is null it is the same as if + * no detailed message was specified. + */ + public InvalidHelpSetContextException(String msg, + HelpSet context, + HelpSet hs) { + super(msg); + this.context = context; + this.hs = hs; + } + + /** + * Get the context HelpSet + */ + public HelpSet getContext() { + return context; + } + + /** + * Get the offending HelpSet + */ + public HelpSet getHelpSet() { + return hs; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java b/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java new file mode 100644 index 0000000000000000000000000000000000000000..577093c90103e94f7a1c9e361c2fe6472b3709a3 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java @@ -0,0 +1,112 @@ +/* + * @(#)InvalidNavigatorViewException.java 1.14 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Hashtable; +import java.util.Locale; + +/** + * JHelpNavigator cannot deal with given NavigatorView. + * + * @author Eduardo Pelegri-Llopart + * @version 1.14 10/30/06 + */ + +public class InvalidNavigatorViewException extends Exception +{ + /** + * Create an exception. All parameters accept null values. + * + * @param msg The message. If msg is null it is the same as if + * no detailed message was specified. + */ + public InvalidNavigatorViewException(String msg, + HelpSet hs, + String name, + String label, + Locale locale, + String className, + Hashtable params) { + super(msg); + this.hs = hs; + this.name = name; + this.label = label; + this.locale = locale; + this.className = className; + this.params = params; + } + + /** + * @return The helpset + */ + public HelpSet getHelpSet() { + return hs; + } + + /** + * @return The name + */ + public String getName() { + return name; + } + + /** + * @return The label + */ + public String getLabel() { + return label; + } + + /** + * @return The locale + */ + public Locale getLocale() { + return locale; + } + + /** + * @return The className + */ + public String getClassName() { + return className; + } + + /** + * @return The parameters + */ + public Hashtable getParams() { + return params; + } + + private HelpSet hs; + private String name; + private String label; + private Locale locale; + private String className; + private Hashtable params; +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelp.java b/jhMaster/JavaHelp/src/new/javax/help/JHelp.java new file mode 100644 index 0000000000000000000000000000000000000000..4c946f933c16e22ed348084454db0e554c09a63d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelp.java @@ -0,0 +1,678 @@ +/* + * @(#)JHelp.java 1.78 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package javax.help; + +import java.net.URL; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.LookAndFeel; +import javax.accessibility.*; +import java.util.Vector; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Locale; +import java.io.InputStream; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.help.plaf.HelpUI; +import javax.help.event.HelpSetListener; +import javax.help.event.HelpSetEvent; +import javax.help.Map.ID; + +/** + * Displays HelpSet data with navigators and a content viewer. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @author Richard Gregor + * @version 1.78 10/30/06 + */ +public class JHelp extends JComponent implements HelpSetListener, Accessible { + protected TextHelpModel helpModel; + protected HelpHistoryModel historyModel; + protected Vector navigators; + protected boolean navDisplayed=true; + protected boolean toolbarDisplayed=true; + protected HelpSet.Presentation hsPres; + + protected JHelpContentViewer contentViewer; + + + /** + * Create a JHelp with a JHelpContentViewer and all Navigators + * requested in the HelpSet. + * + * @param hs The HelpSet. If hs is null the JHelp is created with a + * TextHelpModel with no HelpSet. + */ + public JHelp(HelpSet hs) { + this(new DefaultHelpModel(hs), + null, + hs==null? null : hs.getDefaultPresentation()); + } + + /** + * Create a JHelp component without a TextHelpModel. + */ + public JHelp() { + this((TextHelpModel)null); + } + + /** + * Create a JHelp using the TextHelpModel. + * + * @param model A model to use for the content and all the navigators. If <tt>model</tt> + * is null it is the same as creating without a TextHelpModel + */ + public JHelp(TextHelpModel model){ + this(model, null, null); + } + + /** + * Create a JHelp using the TextHelpModel and HelpHistoryModel + * + * @param model A model to use for the content and all the navigators. If <tt>model</tt> + * is null it is the same as creating without a TextHelpModel + * @param history A history model. If <<tt>history</tt> is null it is the same + * as creating without HelpHistoryModel + */ + public JHelp(TextHelpModel model, HelpHistoryModel history, + HelpSet.Presentation hsPres){ + super(); + + if(history == null) + this.historyModel = new DefaultHelpHistoryModel(this); + else + this.historyModel = history; + + this.hsPres = hsPres; + + navigators = new Vector(); + navDisplayed = true; + + // HERE -- need to do something about doc title changes.... + + this.contentViewer = new JHelpContentViewer(model); + + setModel(model); + if (model != null) { + setupNavigators(); + } + + updateUI(); + } + + protected void setupNavigators() { + HelpSet hs = helpModel.getHelpSet(); + // Simply return if the hs is null + if (hs == null) { + return; + } + + // Now add all the navigators + NavigatorView views[] = hs.getNavigatorViews(); + + debug("views: "+views); + + for (int i=0; i<views.length; i++) { + debug(" processing info: "+views[i]); + + // We are currently assuming all the Navigators are JComponents + JHelpNavigator nav + = (JHelpNavigator) views[i].createNavigator(helpModel); + + if (nav == null) { + // For now... + debug("no JHelpNavigator for given info"); + } else { + debug(" adding the navigator"); + navigators.addElement(nav); + // HERE -- I don't think we want to change again the model + // this.addHelpNavigator(nav); + } + } + } + + /** + * Sets the HelpModel that provides the data. + * + * @param newModel The new Model. If <tt>newModel</tt> is null the internal model is set + * to null. + */ + public void setModel(TextHelpModel newModel) { + TextHelpModel oldModel = helpModel; + if (newModel != oldModel) { + if (oldModel != null) { + oldModel.getHelpSet().removeHelpSetListener(this); + } + helpModel = newModel; + if (newModel != null) { + HelpSet hs = newModel.getHelpSet(); + if (hs != null) { + hs.addHelpSetListener(this); + } + } + firePropertyChange("helpModel", oldModel, helpModel); + + // Now tell all the components we control + contentViewer.setModel((TextHelpModel) newModel); + + getHistoryModel().setHelpModel((HelpModel) newModel); + + // We'll have to destroy all of the navigators and + // reload them from the HelpSet + HelpUI help = getUI(); + + // Skip the navigators if the ui hasn't been setup yet. + if (help == null) { + return; + } + + for (Enumeration e = getHelpNavigators(); + e.hasMoreElements(); ) { + JHelpNavigator nav = (JHelpNavigator) e.nextElement(); + help.removeNavigator(nav); + } + navigators.removeAllElements(); + setupNavigators(); + updateUI(); + } + } + + /** + * @return The HelpModel that is providing the data. + */ + public TextHelpModel getModel() { + return helpModel; + } + + /** + * Returns The HelpHistoryModel + * + * @return The HelpHistoryModel which provides history data + */ + public HelpHistoryModel getHistoryModel(){ + return historyModel; + } + + /** + * Set the HelpSet.Presentation. + * @see HelpSet.Presentation + */ + public void setHelpSetPresentation(HelpSet.Presentation hsPres) { + this.hsPres = hsPres; + return; + } + + + /** + * @return The HelpSet.Presentation. + * @see HelpSet.Presentation + */ + public HelpSet.Presentation getHelpSetPresentation() { + return hsPres; + } + + + // HERE - need customizers, etc... -epll + // HERE - this is probably broken + /** + * Set the URL to the HelpSet. This forces the HelpSet to be reloaded. + * + * @param spec Where to locate the HelpSet. A null spec is valid + */ + public void setHelpSetSpec(String spec) { + URL url; + HelpSet hs; + ClassLoader loader = this.getClass().getClassLoader(); + try { + url = new URL(spec); + hs = new HelpSet(loader, url); + } catch (Exception ex) { + System.err.println("Trouble setting HelpSetSpec to spec |"+spec+"|"); + System.err.println(" ex: "+ex); + hs = null; + } + contentViewer.setModel(new DefaultHelpModel(hs)); + setModel(contentViewer.getModel()); + updateUI(); + } + + /** + * @return The URL to the HelpSet. + */ + public URL getHelpSetURL() { + HelpSet hs = contentViewer.getModel().getHelpSet(); + if (hs == null) { + return null; + } + return hs.getHelpSetURL(); + } + + // === The JComponent methods + + /** + * Sets the HelpUI that will provide the current look and feel. + * @param ui The HelpUI to set for this component. A null value for ui + * is valid. + */ + public void setUI(HelpUI ui) { + if ((HelpUI)this.ui != ui) { + super.setUI(ui); + } + } + + /** + * Returns the HelpUI that is providing the current look and feel. + */ + public HelpUI getUI() { + return (HelpUI)ui; + } + + /** + * Replaces the UI with the latest version from the default + * UIFactory. + * + * @overrides updateUI in class JComponent + */ + public void updateUI() { + SwingHelpUtilities.installUIDefaults(); + setUI((HelpUI)UIManager.getUI(this)); + invalidate(); + } + + /** + * @return "HelpUI" + */ + public String getUIClassID() + { + return "HelpUI"; + } + + /* + * Findd the navigator with a given name. + */ + private JHelpNavigator findNavigator(String name) { + debug("findNavigator("+name+")"); + for (Enumeration e = getHelpNavigators(); + e.hasMoreElements(); ) { + JHelpNavigator nav = (JHelpNavigator) e.nextElement(); + debug(" nav: "+nav); + debug(" nav.getName: "+nav.getNavigatorName()); + if (nav.getNavigatorName().equals(name)) { + return nav; + } + } + return null; + } + + /** + * Adds a new HelpSet to "our" HelpSet. + * + * @param e HelpSetEvent + * @see javax.help.event.HelpSetEvent + * @see javax.help.event.HelpSetListener + */ + public void helpSetAdded(HelpSetEvent e) { + debug("helpSetAdded("+e+")"); + HelpSet ehs = e.getHelpSet(); + addHelpSet(ehs); + } + + /* + * Adds a HelpSet. + */ + private void addHelpSet(HelpSet ehs) { + debug("helpset :"+ehs); + NavigatorView eviews[] = ehs.getNavigatorViews(); + + //if master help set is created using new HelpSet() -without arguments it hasn't got any navigators to merge + //we will create new navigators + + int count = 0; + for (Enumeration e = getHelpNavigators() ; e.hasMoreElements() ;e.nextElement()) { + ++count; + } + if(count == 0){ + debug("master helpset without navigators"); + HelpModel newModel= new DefaultHelpModel(ehs); + setModel((TextHelpModel)newModel); + setupNavigators(); + return; + } + + + for (int i=0; i<eviews.length; i++) { + String n = eviews[i].getName(); + debug("addHelpSet: looking for navigator for "+n); + JHelpNavigator nav = findNavigator(n); + if (nav != null) { + debug(" found"); + if (nav.canMerge(eviews[i])) { + debug(" canMerge: true; merging..."); + nav.merge(eviews[i]); + } else { + debug(" canMerge: false"); + } + } else { + debug(" not found"); + } + } + // In this version, we can only add views that appear at the top + } + + /** + * Removes a HelpSet from "our" HelpSet. + */ + public void helpSetRemoved(HelpSetEvent e) { + debug("helpSetRemoved("+e+")"); + HelpSet ehs = e.getHelpSet(); + removeHelpSet(ehs); + } + + private void removeHelpSet(HelpSet ehs) { + NavigatorView eviews[] = ehs.getNavigatorViews(); + + for (int i=0; i<eviews.length; i++) { + String n = eviews[i].getName(); + debug("removeHelpSet: looking for navigator for "+n); + JHelpNavigator nav = findNavigator(n); + if (nav != null) { + debug(" found"); + if (nav.canMerge(eviews[i])) { + debug(" canMerge: true; removing..."); + nav.remove(eviews[i]); + } else { + debug(" canMerge: false"); + } + } else { + debug(" not found"); + } + } + + // set the last displayed URL from Help. Set other than removed HelpSet, recount history + //helpModel.removeFromHistory(ehs); + //firePropertyChange("removeHelpSet",null,ehs); + getHistoryModel().removeHelpSet(ehs); + } + + /** + * Visits a given ID. Propagates down into the model. + * + * @param id The ID to visit. Null id is valid for TextHelpModel.setCurrentID. + * @exception InvalidHelpSetContextException if id.hs is not contained in getHelpSet() + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException { + if (helpModel != null) { + helpModel.setCurrentID(id); + } + } + + /** + * Visits a given ID. Propagates down into the model. + * + * @param id The ID to visit. Null id is valid for TextHelpModel.setCurrentID. + * @param historyName The name for history entry + * @param navigator The JHelpNavigator + * @exception InvalidHelpSetContextException if id.hs is not contained in getHelpSet() + */ + public void setCurrentID(ID id, String historyName, JHelpNavigator navigator)throws InvalidHelpSetContextException{ + if (helpModel != null) { + helpModel.setCurrentID(id,historyName,navigator); + } + } + + /** + * Convenience version of the above. The implicit HelpSet is + * the current HelpSet. + * + * @param id The String to visit. Null id is valid for TextHelpModel.setCurrentID. + * @exception BadIDException if the string is not in the map for the HelpSet. + */ + public void setCurrentID(String id) throws BadIDException { + try { + helpModel.setCurrentID(ID.create(id, getModel().getHelpSet())); + } catch (InvalidHelpSetContextException ex) { + // cannot happen + } + } + + /** + * Visits a given URL. Propagates down into the model. + * + * @param url The URL to visit + */ + public void setCurrentURL(URL url) { + helpModel.setCurrentURL(url); + } + + /** + * Visits a given URL. Propagates down into the model. + * + * @param url The URL to visit + */ + public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator) { + helpModel.setCurrentURL(url, historyName, navigator); + } + + /** + * Returns a list of selected items from the current navigator + */ + public TreeItem[] getSelectedItems() { + return getCurrentNavigator().getSelectedItems(); + } + + /** + * Sets the list of selected items + */ + /* + public void setSelectedItems(TreeItem[] selectedItems) { + getCurrentNavigator().setSelectedItems(selectedItems); + firePropertyChange("SelectedItemsChangedProperty", oldValue, this.selectedItems); + } + */ + + /** + * A JHelp can have a number of navigators. + * One of navigators is active. + * How they are presented depends on the UI, but they may be a collection + * of tabs, with the active tab being at the front. + * <br> + * Each navigator listens to changes to the HelpModel. + * A navigator can also tell the model to change--the change + * is propagated to the other navigators, this component, and + * the content viewer if they all use the same + * HelpModel instance. + * + * @param navigator The Navigator to explicitly add to the JHelp. + */ + public void addHelpNavigator(JHelpNavigator navigator) { + debug("addHelpNavigator("+navigator+")"); + navigators.addElement(navigator); + HelpUI help = getUI(); + help.addNavigator(navigator); + + // force a common model + navigator.setModel(getModel()); + } + + /** + * Removes a navigator. + * + * @param navigator The Navigator to explicitly add to the JHelp. + */ + public void removeHelpNavigator(JHelpNavigator navigator) { + debug("removeHelpNavigator("+navigator+")"); + if (navigator == null) { + throw new NullPointerException("navigator"); + } + navigators.removeElement(navigator); + HelpUI help = getUI(); + help.removeNavigator(navigator); + } + + /** + * @return An Enumeration of HelpNavigators in the HelpUI. + */ + public Enumeration getHelpNavigators() { + return navigators.elements(); + } + + /** + * Sets the current navigator in the HelpUI. + * + * @param navigator The navigator + * @exception throws InvalidNavigatorException if not a one of HELPUI + * navigators. + */ + public void setCurrentNavigator(JHelpNavigator navigator) { + HelpUI help = getUI(); + help.setCurrentNavigator(navigator); + } + + /** + * @return The current navigator in the HelpUI + */ + public JHelpNavigator getCurrentNavigator() { + HelpUI help = getUI(); + return help.getCurrentNavigator(); + } + + /** + * Hidess/Displays the Navigators in the HelpUI. + * + * @displayed Whether to display or not + */ + public void setNavigatorDisplayed(boolean displayed) { + if (navDisplayed != displayed) { + navDisplayed = displayed; + firePropertyChange("navigatorDisplayed", !displayed, displayed); + } + } + + /** + * Determines if the Navigators are hidden/displayed in the HelpUI. + * + * @return Are the navigators displayed? + * @since 2.0 + */ + public boolean isNavigatorDisplayed() { + return navDisplayed; + } + + /** + * Hidess/Displays the Toolbar in the HelpUI. + * + * @displayed Whether to display or not + * @since 2.0 + */ + public void setToolbarDisplayed(boolean displayed) { + if (toolbarDisplayed != displayed) { + toolbarDisplayed = displayed; + firePropertyChange("toolbarDisplayed", !displayed, displayed); + } + } + + /** + * Determines if the Navigators are hidden/displayed in the HelpUI. + * + * @return is the toolbar displayed? + * @since 2.0 + */ + public boolean isToolbarDisplayed() { + return toolbarDisplayed; + } + + /** + * Retrieves what is the current content viewer + * Read-Only property? + */ + public JHelpContentViewer getContentViewer() { + return contentViewer; + } + + /** + * Debug code + */ + + private boolean debug = false; + private void debug(String msg) { + if (debug) { + System.err.println("JHelp: "+msg); + } + } + + /* + * Make sure the Look and Feel will be set for the Help Component + */ + static { + SwingHelpUtilities.installLookAndFeelDefaults(); + } + +///////////////// +// Accessibility support +//////////////// + + /** + * Get the AccessibleContext associated with this JComponent. + * + * @return The AccessibleContext of this JComponent + */ + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJHelp(); + } + return accessibleContext; + } + + /** + * The class used to obtain the accessible role for this object. + * <p> + * <strong>Warning:</strong> + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is appropriate + * for short term storage or RMI between applications running the same + * version of Swing. A future release of Swing will provide support for + * long term persistence. + */ + protected class AccessibleJHelp extends AccessibleJComponent { + + /** + * Get the role of this object. + * + * @return an instance of AccessibleRole describing the role of the + * object + */ + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PANEL; + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java new file mode 100644 index 0000000000000000000000000000000000000000..2f9b7aac3379da5d98869af9c4fc1c0ea1021786 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java @@ -0,0 +1,425 @@ +/* + * @(#)JHelpContentViewer.java 1.34 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.LookAndFeel; +import javax.swing.JEditorPane; +import javax.accessibility.*; +import java.util.Hashtable; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.help.event.*; +import javax.help.plaf.HelpContentViewerUI; +import javax.swing.text.EditorKit; +import javax.help.Map.ID; + +/** + * A component to represent the Help viewer that can be embedded if desired. + * + * @author Eduardo Pelegri-Llopart + * @version 1.34 10/30/06 + */ +public class JHelpContentViewer extends JComponent implements Accessible{ + protected TextHelpModel model; + /** + * Mark this JHelpContentViewer as synchronized with navigators + * It is false for JHelpContentviewer used inside of glossary + */ + private boolean synch = true; + + /** + * Creates a JHelp with an instance of DefaultHelpModel as its data model. + * + * @param hs The HelpSet that provides context information. A null hs is valid + * and creates a TextHelpModel with no HelpSet defined. + */ + public JHelpContentViewer(HelpSet hs) { + super(); + setModel(new DefaultHelpModel(hs)); + updateUI(); + } + + /** + * Creates a JHelp with a default TextHelpModel. + */ + public JHelpContentViewer() { + super(); + setModel(new DefaultHelpModel(null)); // no HelpSet here! + updateUI(); + } + + /** + * Creates a JHelp with an specific TextHelpModel as its data model. + * + * @param model The TextHelpModel. A null model is valid. + */ + public JHelpContentViewer(TextHelpModel model) { + super(); + setModel(model); + updateUI(); + } + + /** + * Sets the HelpModel that provides the data. + * Necessary to convert navigation action into visits... + * + * @param newModel The new Model to provide events for this viewer. + */ + public void setModel(TextHelpModel newModel) { + debug("setModel: "+newModel); + TextHelpModel oldModel = model; + if (newModel != oldModel) { + model = newModel; + firePropertyChange("helpModel", oldModel, model); + invalidate(); + } + } + /** + * @return The HelpModel that provides the events. + */ + public TextHelpModel getModel() { + return model; + } + + /** + * Sets the HelpViewerUI that provides the current look and feel. + * + * @param ui Provides the ComponentUI object. A null ui is valid. + */ + public void setUI(HelpContentViewerUI ui) { + debug("setUI"); + if ((HelpContentViewerUI)this.ui != ui) { + super.setUI(ui); + repaint(); + } + } + + /** + * @return The HelpViewerUI that provides the current look and feel. + */ + public HelpContentViewerUI getUI() { + return (HelpContentViewerUI)ui; + } + + /** + * Replaces the UI with the latest version from the default + * UIFactory. + * + * @overrides updateUI in class JComponent + */ + public void updateUI() { + SwingHelpUtilities.installUIDefaults(); + setUI((HelpContentViewerUI)UIManager.getUI(this)); + invalidate(); + } + + /** + * @return "HelpViewerUI" + */ + public String getUIClassID() + { + return "HelpContentViewerUI"; + } + + /* + * Make sure the Look and Feel is set for the Help Component. + */ + static { + SwingHelpUtilities.installLookAndFeelDefaults(); + } + + /** + * Visits a given ID. Propagates down into the model. + * + * @param id The ID to visit. + * @exception InvalidHelpSetContextException if id.hs is not contained in the + * HelpSet of the current model. + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException { + model.setCurrentID(id); + } + + /** + * Visits a given ID. Propagates down into the model. + * + * @param id The String to visit. Relative to the HS of the current model. + * @exception BadIDException The ID is not valid for the HelpSet for the current model. + */ + public void setCurrentID(String id) throws BadIDException { + try { + model.setCurrentID(ID.create(id, getModel().getHelpSet())); + } catch (InvalidHelpSetContextException ex) { + // cannot happen + } + } + + /** + * Visits a given URL. Propagates down into the model. + * + * @param url The URL to visit. Relative to the HS of the current model + */ + public void setCurrentURL(URL url) { + model.setCurrentURL(url); + } + + /** + * @return The URL currently being presented in the viewer. + */ + public URL getCurrentURL() { + return model.getCurrentURL(); + } + + /** + * @return The document title. + */ + + public String getDocumentTitle() { + return model.getDocumentTitle(); + } + + /** + * Hightlights a section of the current document from p0 to p1. + * + * @param p0 Starting position. + * @param p1 Ending position. + */ + public void addHighlight(int p0, int p1) { + model.addHighlight(p0,p1); + } + + /** + * Removes any Highlights. + */ + public void removeAllHighlights() { + model.removeAllHighlights(); + } + + /** + * Sets synchronization of this JHelpContentViewer with navigators. + * If true then JHelpContentViewer will contain homeID page when comes up at first time. + * False value causes blank page in this case. + */ + public void setSynch(boolean value){ + synch = value; + } + /** + * Returns synchronization mode + */ + public boolean getSynch(){ + return synch; + } + + /** + * The local kitRegistry, indexed by mime type. + */ + private Hashtable kitRegistry; + + /* + * Creation of EditorKits. + * This is similar to the registry used in JEditorPane, except: + * <p> + * (1) A separate registry is used so as to not interfere with other uses of JEditorPane + * <br> + * (2) The registry is centered around a HelpSet + */ + + /** + * Creates a handler for the given type from the registry of editor kits. + * If the registered class has not yet been loaded, an attempt + * is made to dynamically load the prototype of the kit for the + * given type. If the type was registered with a ClassLoader, + * that ClassLoader is used to load the prototype. If there + * was no registered ClassLoader, the ClassLoader for the HelpSet + * is used to load the prototype. + * <p> + * Once a prototype EditorKit instance is successfully located, + * it is cloned and the clone is returned. + * + * @param type the content type + * @return the editor kit, or null if one cannot be created + */ + public EditorKit createEditorKitForContentType(String type) { + EditorKit k = null; + if (kitRegistry == null) { + // nothing has been loaded yet. + kitRegistry = new Hashtable(); + } else { + k = (EditorKit) kitRegistry.get(type); + } + if (k == null) { + // try to dynamically load the support + HelpSet hs = model.getHelpSet(); + String classname = + (String) hs.getKeyData(HelpSet.kitTypeRegistry, + type); + // I don't know of a class for this type + if (classname == null) { + return null; + } + ClassLoader loader = + (ClassLoader) hs.getKeyData(HelpSet.kitLoaderRegistry, + type); + if (loader == null) { + loader = hs.getLoader(); + } + try { + Class c; + if (loader != null) { + c = loader.loadClass(classname); + } else { + c = Class.forName(classname); + } + k = (EditorKit) c.newInstance(); + kitRegistry.put(type, k); + } catch (Throwable e) { + e.printStackTrace(); + k = null; + } + } + + // create a copy of the prototype or null if there + // is no prototype. + if (k != null) { + return (EditorKit) k.clone(); + } else { + // null, check the JEditorPane registry + k = JEditorPane.createEditorKitForContentType(type); + } + return k; + } + + /** + * Adds a listener for the TExtHelpModelEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.TextHelpModel#removeHelpModelListener + */ + public void addTextHelpModelListener(TextHelpModelListener l) { + getModel().addTextHelpModelListener(l); + } + + /** + * Removes a listener previously added with <tt>addTextHelpModelListener</tt> + * + * @param l - The listener to remove. + * @see javax.help.TextHelpModel#addTextHelpModelListener + */ + public void removeHelpModelListener(TextHelpModelListener l) { + getModel().removeTextHelpModelListener(l); + } + + /** + * Adds a listener for the HelpModelEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.HelpModel#removeHelpModelListener + */ + public void addHelpModelListener(HelpModelListener l) { + getModel().addHelpModelListener(l); + } + + /** + * Removes a listener previously added with <tt>addHelpModelListener</tt> + * + * @param l - The listener to remove. + * @see javax.help.HelpModel#addHelpModelListener + */ + public void removeHelpModelListener(HelpModelListener l) { + getModel().removeHelpModelListener(l); + } + + /** + * Cleans the content + */ + public void clear(){ + firePropertyChange("clear", " ","xyz"); + } + + /** + * Reloads the content + */ + public void reload(){ + firePropertyChange("reload", " ","xyz"); + } + + + /** + * Debug code + */ + private boolean debug = false; + private void debug(String msg) { + if (debug) { + System.err.println("JHelpContentViewer: "+msg); + } + } + +///////////////// +// Accessibility support +//////////////// + + /** + * Get the AccessibleContext associated with this JComponent + * + * @return the AccessibleContext of this JComponent + */ + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJHelpContentViewer(); + } + return accessibleContext; + } + + /** + * The class used to obtain the accessible role for this object. + * <p> + * <strong>Warning:</strong> + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is appropriate + * for short term storage or RMI between applications running the same + * version of Swing. A future release of Swing will provide support for + * long term persistence. + */ + protected class AccessibleJHelpContentViewer extends AccessibleJComponent { + + /** + * Get the role of this object. + * + * @return an instance of AccessibleRole describing the role of the + * object + */ + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PANEL; + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..ada12fb956c3c1801ac934979efb4e453b5bf714 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java @@ -0,0 +1,137 @@ +/* + * @(#)JHelpFavoritesNavigator.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import javax.swing.event.ChangeListener; +import javax.swing.event.ChangeEvent; +import javax.swing.Action; + +/** + * JHelpFavoritesNavigator is a JHelpNavigator for Favorites. + * + * All the tree navigation and selection has been delegated to the UI + * where the JTree is created. + * + * @author Richard Gregor + * @version 1.4 10/30/06 + */ +public class JHelpFavoritesNavigator extends JHelpNavigator { + + /** + * Creates an Index navigator. + * + * @param view The NavigatorView + */ + public JHelpFavoritesNavigator(NavigatorView view) { + super(view, null); + } + + /** + * Creates a Index navigator. + * + * @param view The NavigatorView. + * @param model The model for the Navigator. + */ + public JHelpFavoritesNavigator(NavigatorView view, HelpModel model) { + super(view, model); + } + + // HERE - label & Locale? + // HERE - URL data vs Hashtable? + /** + * Creates an Index navigator with explicit arguments. Note that this should not throw + * an InvalidNavigatorViewException since we are implicitly passing the type. + * + * @param hs HelpSet + * @param name The name identifying this HelpSet. + * @param label The label to use (for this locale). + * @param data The "data" part of the parameters, a URL location of the TOC data. + */ + public JHelpFavoritesNavigator(HelpSet hs, + String name, String label, URL data) + throws InvalidNavigatorViewException { + super(new FavoritesView(hs, name, label, createParams(data))); + } + + /** + * Gets the UID for this JComponent. + */ + public String getUIClassID() { + return "HelpFavoritesNavigatorUI"; + } + + /** + * Determines if this instance of a JHelpNavigator can merge its data with another one. + * + * @param view The data to merge + * @return Whether it can be merged + * + * @see merge(NavigatorView) + * @see remove(NavigatorView) + */ + public boolean canMerge(NavigatorView view) { + return false; + } + + /** + * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible. + * + * @param target The target to expand + */ + public void expandID(String target){ + firePropertyChange("expand"," ",target); + } + + /** + * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty. + * + * @param target The target to collapse + */ + public void collapseID(String target){ + firePropertyChange("collapse"," ",target); + } + + /** + * Returns an AddAction object for this navigator + * + */ + public Action getAddAction(){ + return this.getUI().getAddAction(); + } + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("JHelpIndexNavigator: "+msg); + } + } +} + + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..c202926732c612d0cc765725c432578e0c7752f7 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java @@ -0,0 +1,99 @@ +/* + * @(#)JHelpGlossaryNavigator.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.Icon; +import javax.swing.UIManager; +import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; +import javax.help.*; +import java.beans.*; + +/** + * JHelpGlossaryNavigator is a JHelpNavigator for a Glossary + * + * @author Roger Brinkley + * @author Richard Gregor + * @version 1.2 10/30/06 + */ + +public class JHelpGlossaryNavigator extends JHelpNavigator { + + /** + * Creates JHelpGlossaryNavigator from given GlossaryView + * + * @param info The GlossaryView + */ + public JHelpGlossaryNavigator(NavigatorView info) { + super(info); + } + /** + * Creates JHelpGlossaryNavigator from given GlossaryView and HelpModel + * + * @param info The GlossaryView + * @param model The HelpModel + */ + public JHelpGlossaryNavigator(NavigatorView info, HelpModel model) { + super(info, model); + } + + /** + * Creates JHelpGlossaryNavigator from given HelpSet, name and title + * + * @param hs The HelpSet + * @param name The name of GlossaryView + * @param title The title + */ + + public JHelpGlossaryNavigator(HelpSet hs, String name, String title) + throws InvalidNavigatorViewException + { + super(new GlossaryView(hs, name, title, null)); + } + + + /** + * Returns UIClassID + * + * @return The ID of UIClass representing JHelpGlossaryNavigator + */ + public String getUIClassID() { + return "HelpGlossaryNavigatorUI"; + } + + + + private static final boolean debug = false; + private static void debug(Object m1, Object m2, Object m3) { + if (debug) { + System.err.println("JHelpGlossaryNavigator: "+m1+m2+m3); + } + } + private static void debug(Object m1) { debug(m1,null,null); } + private static void debug(Object m1, Object m2) { debug(m1,m2,null); } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..e3b28c33373fe47f4818894fd3bb48522d2d156f --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java @@ -0,0 +1,161 @@ +/* + * @(#)JHelpIndexNavigator.java 1.40 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import javax.help.plaf.HelpNavigatorUI; + +/** + * JHelpIndexNavigator is a JHelpNavigator for an Index. + * + * All the tree navigation and selection has been delegated to the UI + * where the JTree is created. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.40 10/30/06 + */ + +public class JHelpIndexNavigator extends JHelpNavigator { + /** + * Creates an Index navigator. + * + * @param view The NavigatorView + */ + public JHelpIndexNavigator(NavigatorView view) { + super(view, null); + } + + /** + * Creates a Index navigator. + * + * @param view The NavigatorView. + * @param model The model for the Navigator. + */ + public JHelpIndexNavigator(NavigatorView view, HelpModel model) { + super(view, model); + } + + + + // HERE - label & Locale? + // HERE - URL data vs Hashtable? + /** + * Creates an Index navigator with explicit arguments. Note that this should not throw + * an InvalidNavigatorViewException since we are implicitly passing the type. + * + * @param hs HelpSet + * @param name The name identifying this HelpSet. + * @param label The label to use (for this locale). + * @param data The "data" part of the parameters, a URL location of the TOC data. + */ + public JHelpIndexNavigator(HelpSet hs, + String name, String label, URL data) + throws InvalidNavigatorViewException + { + super(new IndexView(hs, name, label, createParams(data))); + } + + /** + * Gets the UID for this JComponent. + */ + public String getUIClassID() { + return "HelpIndexNavigatorUI"; + } + + /** + * Determines if this instance of a JHelpNavigator can merge its data with another one. + * + * @param view The data to merge + * @return Whether it can be merged + * + * @see merge(NavigatorView) + * @see remove(NavigatorView) + */ + public boolean canMerge(NavigatorView view) { + if (view instanceof IndexView && + getNavigatorName().equals(view.getName())) { + return true; + } + return false; + } + + /** + * Merges some NavigatorView into this instance. + * + * @param view The data to merge + * @exception IllegalArgumentException + * @exception IllegalStateException + * + * @see canMerge(NavigatorView) + * @see remove(NavigatorView) + */ + public void merge(NavigatorView view) { + debug("merge of: "+view); + this.getUI().merge(view); + } + + /** + * Removes a NavigatorView from this instance. + * + * @param view The data to merge + * @exception IllegalArgumentException + * @exception IllegalStateException + * + * @see canMerge(NavigatorView) + * @see merge(NavigatorView) + */ + public void remove(NavigatorView view) { + this.getUI().remove(view); + } + + /** + * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible. + * + * @param target The target to expand + */ + public void expandID(String target){ + firePropertyChange("expand"," ",target); + } + + /** + * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty. + * + * @param target The target to collapse + */ + public void collapseID(String target){ + firePropertyChange("collapse"," ",target); + } + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("JHelpIndexNavigator: "+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..47a21e8b7d691b61b29898be41c7becce906d130 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java @@ -0,0 +1,372 @@ +/* + * @(#)JHelpNavigator.java 1.68 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.accessibility.*; +import java.net.*; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Hashtable; +import java.beans.*; +import javax.help.event.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.Map.ID; + +/** + * A JHelpNavigator is a control that presents navigational help data. + * It is identified by a type and it interacts with a HelpModel. + * + * There are three JHelpNavigators that most JavaHelp implementations should + * support: + * + * @see javax.help.JHelpTOCNavigator + * @see javax.help.JHelpIndexNavigator + * @see javax.help.JHelpSearchNavigator + * + * This class is intended to be extended. To use this class by itself + * requires a platform look and feel (plaf) class that extends + * <tt>javax.help.plaf.HelpNavigatorUI</tt>. Additionally, + * the UIDefaults table requires an entry for "HelpViewerUI" that points to + * the plaf class. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Richard Gregor + * @version 1.68 10/30/06 + */ + +public class JHelpNavigator extends JComponent implements Accessible{ + protected HelpModel helpModel; + protected String type; + private static String jhPackageName; + private NavigatorView view; + private TreeItem[] selectedItems; + + + /** + * Returns a JHelpNavigator with an instance of DefaultHelpModel as its + * data model. + * + * @param view The NavigatorView to use. If <tt>view</tt> is null it creates a JHelpTOCNavigator + * with a null NavigatorView. + */ + public JHelpNavigator(NavigatorView view) { + super(); + this.view = view; + if (view != null) { + setModel(new DefaultHelpModel(view.getHelpSet())); + } else { + setModel(null); + } + updateUI(); + } + + /** + * Constructs a JHelpNavigator from some view and with a preexisting model and in default initial state of navigation + * entries. + * + * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpNavigator + * with a null NavigatorView. + * @param model The model that generates changes. + * If <tt>model</tt> is null it creates a JHelpNavigator without a model. + */ + public JHelpNavigator(NavigatorView view, HelpModel model) { + super(); + this.view = view; + setModel(model); + updateUI(); + + } + + /** + * Returns a list of selected items + */ + public TreeItem[] getSelectedItems() { + if(selectedItems == null) { + return new TreeItem[0]; + } else { + return (TreeItem[]) selectedItems.clone(); + } + } + + /** + * Sets the list of selected items + */ + public void setSelectedItems(TreeItem[] selectedItems) { + TreeItem[] oldValue = this.selectedItems; + this.selectedItems = selectedItems; + firePropertyChange("SelectedItemsChangedProperty", oldValue, this.selectedItems); + } + + /** + * @return "HelpNavigatorUI" + */ + public String getUIClassID() + { + return "HelpNavigatorUI"; + } + + /** + * Determines if this instance of a JHelpNavigator can merge its data with another one. + * + * @param view The data to merge. + * @return Whether it can be merged. + * + * @see merge(NavigatorView) + * @see remove(NavigatorView) + */ + public boolean canMerge(NavigatorView view) { + return false; + } + + /** + * Merged a NavigatorView into this instance. + * + * @param view The data to merge + * @exception UnsupportedOperationException + * + * @see canMerge(NavigatorView) + * @see remove(NavigatorView) + */ + public void merge(NavigatorView view) { + throw new UnsupportedOperationException(); + } + + /** + * Removes a NavigatorView from this instance. + * + * @param view The data to merge + * @exception UnsupportedOperationException + * + * @see canMerge(NavigatorView) + * @see merge(NavigatorView) + */ + public void remove(NavigatorView view) { + throw new UnsupportedOperationException(); + } + + // ========= Navigator Identification ======== + + /** + * Names this Navigator. + * + * @return The name of this Navigator. This is locale independent and can be + * used by the application to identify the view. + */ + public String getNavigatorName() { + return view.getName(); + } + + /** + * Gets the NavigatorView that created this Navigator View. + * + * @return the NavigatorView + */ + public NavigatorView getNavigatorView() { + return view; + } + + // HERE -- Do we want these, or just the getNavigatorView()? - epll + + /** + * Gets the name of this navigator view. + * + * @return The label for this NavigatorView. + */ + public String getNavigatorLabel() { + return view.getLabel(); + } + + /** + * Gets locale-dependent name for this navigator view. + * + * @return the label for this NavigatorView. If locale is null it is + * treated as the default Locale. + */ + public String getNavigatorLabel(Locale locale) { + return view.getLabel(locale); + } + + /** + * Gets an icon to identify this Navigator. Currently this is a read-only + * property. + * + * @return An icon to identify this navigator. + */ + public Icon getIcon() { + return getUI().getIcon(); + } + + + // =========== Model and UI methods =========== + + /** + * Sets the HelpModel that provides the data. + * @param newModel The HelpModel for this component. A null for newModel + * is valid. + */ + public void setModel(HelpModel newModel) { + HelpModel oldModel = helpModel; + if (newModel != oldModel) { + helpModel = newModel; + firePropertyChange("helpModel", oldModel, helpModel); + invalidate(); + } + } + + /** + * Returns the HelpModel that provides the data. + */ + public HelpModel getModel() { + return helpModel; + } + + /** + * Sets the HelpUI that provides the current look and feel. + */ + public void setUI(HelpNavigatorUI ui) { + if ((HelpNavigatorUI)this.ui != ui) { + super.setUI(ui); + } + } + + /** + * Returns the HelpUI that provides the current look and feel. + */ + public HelpNavigatorUI getUI() { + return (HelpNavigatorUI)ui; + } + + /** + * Replaces the UI with the latest version from the default + * UIFactory. + * + * @overrides updateUI in class JComponent + */ + public void updateUI() { + SwingHelpUtilities.installUIDefaults(); + setUI((HelpNavigatorUI)UIManager.getUI(this)); + invalidate(); + } + + /* + * Makes sure the Look and Feel will be set for the Help Component. + */ + static { + SwingHelpUtilities.installLookAndFeelDefaults(); + } + + // Be a source for HelpModelEvents + + /** + * Adds a listener for the HelpModelEvent posted after the model has + * changed. + * + * @param l - The listener to add. + * @see javax.help.HelpModel#removeHelpModelListener + */ + public void addHelpModelListener(HelpModelListener l) { + getModel().addHelpModelListener(l); + } + + /** + * Removes a listener previously added with <tt>addHelpModelListener</tt>. + * + * @param l - The listener to remove. + * @see javax.help.HelpModel#addHelpModelListener + */ + public void removeHelpModelListener(HelpModelListener l) { + getModel().removeHelpModelListener(l); + } + + /** + * Creates the parameters for a Navigator from data stored in a URL. + * + * @return A Hashtable of parameters + */ + + protected static Hashtable createParams(URL data) { + Hashtable back = new Hashtable(); + back.put("data", data.toString()); + return back; + } + + + + /** + * For printf debugging. + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.err.println("JHelpNavigator: " + str); + } + } + +///////////////// +// Accessibility support +//////////////// + + /** + * Get the AccessibleContext associated with this JComponent. + * + * @return The AccessibleContext of this JComponent + */ + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJHelpNavigator(); + } + return accessibleContext; + } + + /** + * The class used to obtain the accessible role for this object. + * <p> + * <strong>Warning:</strong> + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is appropriate + * for short term storage or RMI between applications running the same + * version of Swing. A future release of Swing will provide support for + * long term persistence. + */ + protected class AccessibleJHelpNavigator extends AccessibleJComponent { + + /** + * Get the role of this object. + * + * @return An instance of AccessibleRole describing the role of the + * object + */ + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PANEL; + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..ccebc85bbf42a761d06dc9daef870af401f9f639 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java @@ -0,0 +1,204 @@ +/* + * @(#)JHelpSearchNavigator.java 1.52 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import javax.help.search.SearchEngine; +import javax.help.search.MergingSearchEngine; + +/** + * A JHelpNavigator for search data. + * All of the tree navigation and selection has been delegated to the UI. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.52 10/30/06 + */ + +public class JHelpSearchNavigator extends JHelpNavigator { + private MergingSearchEngine search; // our search engine + + + /** + * Creates a Search navigator + * + * @param view The NavigatorView. If view is null it creates a JHelpSearchNavigator + * with a null NavigatorView. + */ + public JHelpSearchNavigator(NavigatorView view) { + super(view, null); + } + + /** + * Creates a Search navigator. + * + * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpSearchNavigator + * with a null NavigatorView. + * @param model The HelpModel this Navigator is presenting. If <tt>model</tt> is null it + * creates a JHelpSearchNavigator witout a model. + */ + public JHelpSearchNavigator(NavigatorView view, HelpModel model) { + super(view, model); + } + + + + // HERE - label & Locale? + /** + * Creates a TOC navigator with explicit arguments. Note that this should not throw + * an InvalidNavigatorViewException since the type is passed implicitly. + * + * @param hs HelpSet + * @param name The name indentifying this HelpSet. + * @param label The label to use (for this locale). + * @param data The "data" part of the parameters, a URL to the location of the TOC data. + */ + public JHelpSearchNavigator(HelpSet hs, + String name, String label, URL data) + throws InvalidNavigatorViewException + { + super(new SearchView(hs, name, label, createParams(data))); + } + + + /** + * The UID for this JComponent. + */ + public String getUIClassID() { + return "HelpSearchNavigatorUI"; + } + + /** + * Search Database methods. + */ + + /** + * Instantiates and returns a SearchEngine class. + * The default query engine to use is <tt>com.sun.java.help.search.SearchEngine</tt>, + * but this can be changed through the <engine></engine> attribute + * of the view. + * + * @return The SearchEngine instantiation. + */ + public SearchEngine getSearchEngine() { + if (search == null) { + search = new MergingSearchEngine(getNavigatorView()); + } + return search; + } + + /** + * Explicitly changes the default (overriding what is in the HelpSet). + * + * @param search A SearchEngine instantiation. + */ + public void setSearchEngine(SearchEngine search) { + this.search = new MergingSearchEngine(search); + } + + /** + * Default for the search engine. + */ + + protected String getDefaultQueryEngine() { + return HelpUtilities.getDefaultQueryEngine(); + } + + /** + * Determines if this instance of a JHelpNavigator can merge its data with another one. + * + * @param view The data to merge. + * @return Whether it can be merged. + * + * @see merge(NavigatorView) + * @see remove(NavigatorView) + */ + public boolean canMerge(NavigatorView view) { + if (view instanceof SearchView && + getNavigatorName().equals(view.getName())) { + debug("canMerge: true"); + return true; + } + debug("canMerge: false"); + return false; + } + + /** + * Merges a NavigatorView into this instance. + * + * @param view The data to merge. + * @exception IllegalArgumentException + * @exception IllegalStateException + * + * @see canMerge(NavigatorView) + * @see remove(NavigatorView) + */ + public void merge(NavigatorView view) { + // Add the requested query engine to our list of engines + debug("JHelpSearchNavigator.merge invoked"); + debug(" params: "+view.getParameters()); + if (search == null) { + search = (MergingSearchEngine) getSearchEngine(); + } + search.merge(view); + debug("merge: "+view); + this.getUI().merge(view); + } + + /** + * Removes a NavigatorView from this instance. + * + * @param view The data to merge. + * @exception IllegalArgumentException + * @exception IllegalStateException + * + * @see canMerge(NavigatorView) + * @see merge(NavigatorView) + */ + public void remove(NavigatorView view) { + // Remove the requested query engine from our list of engines + debug("JHelpSearchNavigator.remove invoked"); + debug(" params: "+view.getParameters()); + if (search == null) { + search = (MergingSearchEngine) getSearchEngine(); + } + search.remove(view); + debug("remove: "+view); + this.getUI().remove(view); + } + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("JHelpSearchNavigator: "+msg); + } + } + + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java new file mode 100644 index 0000000000000000000000000000000000000000..1103c7e82ea253452447bde380bbf4f7417c79ba --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java @@ -0,0 +1,172 @@ +/* + * @(#)JHelpTOCNavigator.java 1.44 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; + + +/** + * A JHelpNavigator for a TOC. + * + * All of the tree navigation and selection has been delegated to the UI + * where the JTree is created. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.44 10/30/06 + */ + +public class JHelpTOCNavigator extends JHelpNavigator { + + /** + * Create a TOC navigator + * + * @param view The NavigatorView. If view is null it creates a JHelpTOCNavigator + * without a HelpModel and a null NavigatorView. + */ + public JHelpTOCNavigator(NavigatorView view) { + super(view, null); + } + + /** + * Creates a TOC navigator. + * + * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpTOCNavigator + * with a null NavigatorView. + * @param model The model for the Navigator. If <tt>model</tt> is null it creates a + * JHelpTOCNavigator witout a model. + */ + + public JHelpTOCNavigator(NavigatorView view, HelpModel model) { + super(view, model); + } + + + + /** + * Creates a TOC navigator with explicit arguments. Note that this should not throw + * an InvalidNavigatorViewException since the type is implicitly passed. + * + * @param hs HelpSet + * @param name The name indentifying this HelpSet. + * @param label The label to use (for this locale). + * @param data The "data" part of the parameters, a URL location of the TOC data. + */ + public JHelpTOCNavigator(HelpSet hs, + String name, String label, URL data) + throws InvalidNavigatorViewException + { + super(new TOCView(hs, name, label, createParams(data))); + } + + + /** + * The UID for this JComponent. + */ + public String getUIClassID() { + return "HelpTOCNavigatorUI"; + } + + /** + * Determines if this instance of a JHelpNavigator can merge its data with another one. + * + * @param view The data to merge. + * @return Whether it can be merged. + * @see merge() + * @see remove() + */ + public boolean canMerge(NavigatorView view) { + if (view instanceof TOCView && + getNavigatorName().equals(view.getName())) { + debug("canMerge: true"); + return true; + } + debug("canMerge: false"); + return false; + } + + /** + * Merges a NavigatorView into this instance. + * + * @param view The data to merge. This must be a TOCView. + * @see canMerge() + * @see remove() + * @exception IllegalArgumentException + * @exception IllegalStateException + */ + public void merge(NavigatorView view) { + debug("merge: "+view); + this.getUI().merge(view); + } + + /** + * Removes a NavigatorView from this instance. + * + * @param view The data to merge. + * @see canMerge() + * @see merge() + * @exception IllegalArgumentException + * @exception IllegalStateException + */ + public void remove(NavigatorView view) { + // this should recompute the view + this.getUI().remove(view); + } + + /** + * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible. + * + * @param target The target to expand + */ + public void expandID(String target){ + firePropertyChange("expand"," ",target); + } + + + /** + * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty. + * + * @param target The target to collapse + */ + public void collapseID(String target){ + firePropertyChange("collapse"," ",target); + } + + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("JHelpTOCNavigator: "+msg); + } + } + + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java b/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..a2edfc29659ceeb71c9c090c8f5c1d3165fd880e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java @@ -0,0 +1,99 @@ +/* + * @(#)MainWindow.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + + +/** + * MainWindow is a class that will create a single main help + * window for an application. Although there is generally only one per + * application there can be multiple MainWindow. + * By default it is a tri-paned fully decorated window + * consisting of a toolbar, navigator pane, and help content view. By default + * the class is not destroyed when the window exits. + * + * @author Roger D.Brinkley + * @version 1.3 10/30/06 + * @since 2.0 + * + * @see javax.help.WindowPresentation + * @see javax.help.Presentation + */ + +public class MainWindow extends WindowPresentation { + + private MainWindow(HelpSet hs) { + super(hs); + } + + /** + * Creates a new MainWindow for a given HelpSet and + * HelpSet.Presentation "name". If the "name"d HelpSet.Presentation + * does not exist in HelpSet then the default HelpSet.Presentation + * is used. + * + * @param hs The HelpSet used in this presentation + * @param name The name of the Presentation to create - also the name + * of the HelpSet.Presentation to use. + * @returns Presentation A unique MainWindow. + */ + static public Presentation getPresentation(HelpSet hs, String name) { + MainWindow mwp = new MainWindow(hs); + if (hs != null) { + HelpSet.Presentation presentation = null; + + // get a named presentation if one exists + if (name != null) { + presentation = hs.getPresentation(name); + } + + // get the default presentation if one exits + if (presentation == null) { + presentation = hs.getDefaultPresentation(); + } + + // set the presentation + // a null is ok here as it will just return. + mwp.setHelpSetPresentation(presentation); + } + return mwp; + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("MainWindow: "+msg); + } + } + +} + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/Map.java b/jhMaster/JavaHelp/src/new/javax/help/Map.java new file mode 100644 index 0000000000000000000000000000000000000000..3bd3e954cd65701a0a1232efa22e04e2c2694280 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/Map.java @@ -0,0 +1,200 @@ +/* + * @(#)Map.java 1.13 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.net.MalformedURLException; +import java.util.*; +import java.io.Serializable; + +/** + * A Map is the interface to ID<->URL mapping. + * + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version 1.13 10/30/06 + */ +public interface Map { + /** + * Determines if the ID is valid (defined in the map file). + * + * @param id The String ID. + * @param hs The HelpSet against which to resolve the string. + * @return True if the ID is valid, false if not valid. + */ + + public boolean isValidID(String id, HelpSet hs); + + /** + * Gets an enumeration of all the IDs in a Map. + * + * @return An enumeration of all the IDs in a Map. + */ + // We need this so we can add FlatMaps to TryMaps - epll + public Enumeration getAllIDs(); + + /** + * Gets the URL that corresponds to a given ID in the Map. + * + * @param id The ID to get the URL for. + * @return URL The matching URL. Null if this map cannot solve the ID. + * @exception MalformedURLException if the URL is malformed + */ + public URL getURLFromID(ID id) throws MalformedURLException; + + /** + * Determines if the URL corresponds to an ID in the Map. + * + * @param url The URL to check on. + * @return True if this is an ID, false otherwise. + */ + public boolean isID(URL url); + + /** + * Determines the ID for this URL. + * + * @param url The URL to get the ID for. + * @return The ID (or null if URL does not correspond to an ID). + */ + public ID getIDFromURL(URL url); + + // HERE - do we want this. It is *very* expensive to do - epll + + /** + * Determines the ID that is "closest" to this URL (with a given anchor). + * + * The definition of this is up to the implementation of Map. In particular, + * it may be the same as getIDFromURL(). + * + * @param url A URL + * @return The closest ID in this map to the given URL. + */ + public ID getClosestID(URL url); + + /** + * Determines the IDs related to this URL. + * + * @param URL The URL to which to compare the Map IDs. + * @return Enumeration of Map.Key (Strings/HelpSet) + */ + public Enumeration getIDs(URL url); + + /** + * An ID is a pair of String, HelpSet. + * + * An ID fully identifies a "location" within a HelpSet. + */ + + final public class ID implements Serializable{ + public String id; + public HelpSet hs; + + /** + * A location within a HelpSet. If id or hs are null, a null ID is returned. + * + * @param id The String + * @param hs The HelpSet + * @exception BadIDException if String is not within the Map of the + * HelpSet. + */ + + public static ID create(String id, HelpSet hs) throws BadIDException { + if (hs == null || + id == null) { + return null; + } + + Map map = hs.getCombinedMap(); + if (! map.isValidID(id, hs)) { + throw new BadIDException("Not valid ID: "+id, map, id, hs); + } + return new ID(id, hs); + } + + /** + * Creates an ID object. + */ + + private ID(String id, HelpSet hs) throws BadIDException { + this.id = id; + this.hs = hs; + } + + /** Getter for property hs. + * @return Value of property hs. + */ + public HelpSet getHelpSet() { + return hs; + } + + /** Getter for property id. + * @return Value of property id. + */ + public String getIDString() { + return id; + } + + /** + * Returns the URL that the Map.ID refers to. + * + * @return URL The matching URL. Null if the map cannot solve the ID. + * @exception MalformedURLException if the URL is malformed + * @see javax.help.Map#getURLFromID(javax.help.Map.ID id) + */ + public URL getURL() throws MalformedURLException { + if (hs == null || id == null) { + return null; + } + try { + return hs.getCombinedMap().getURLFromID(this); + } catch (MalformedURLException e) { + throw e; + } + } + + /** + * Determines if two IDs are equal. + * @param o The object to compare. + */ + + public boolean equals(Object o) { + if (o instanceof ID) { + ID id2 = (ID) o; + return (id2.id.equals(id) && (id2.hs.equals(hs))); + } + return false; + } + + /** + * Gets an external represenation of an ID. + */ + public String toString() { + return("ID: "+id+", "+hs); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/Merge.java b/jhMaster/JavaHelp/src/new/javax/help/Merge.java new file mode 100644 index 0000000000000000000000000000000000000000..c2a40c05686c02875107cff47f66879b2a8a063d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/Merge.java @@ -0,0 +1,158 @@ +/* + * @(#)Merge.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Locale; +import javax.swing.tree.TreeNode; +import javax.swing.tree.DefaultMutableTreeNode; +import java.lang.reflect.Constructor; + +/** + * Common superclass for all merge types + * + * @author Richard Gregor + * @version 1.6 10/30/06 + */ +public abstract class Merge { + + /** + * Slave node + */ + protected DefaultMutableTreeNode slaveTopNode; + + /** + * HelpSet's locale which is used in sorting + */ + protected Locale locale; + + /** + * Constructs Merge for master and slave NavigatorViews + * + * @param master The master NavigatorView + * @param slave The slave NavigatorView + */ + protected Merge(NavigatorView master, NavigatorView slave){ + + try { + Class clss = Class.forName("javax.help.TOCView"); + if (clss.isInstance(slave)) { + this.slaveTopNode = ((TOCView)slave).getDataAsTree(); + } + clss = Class.forName("javax.help.IndexView"); + if (clss.isInstance(slave)) { + this.slaveTopNode = ((IndexView)slave).getDataAsTree(); + } + } catch(ClassNotFoundException exp) { + System.err.println(exp); + } + + locale = master.getHelpSet().getLocale(); + if(locale == null) + locale = Locale.getDefault(); + } + + /** + * Processes merge. Changes master node according merge rules using slave node. + * + * @param node The master node + * @return The changed master node + */ + public abstract TreeNode processMerge(TreeNode node); + + /** + * Merge Nodes. Merge two nodes according to the merging rules of the + * masterNode. Each Subclass should override this implementation. + * + * @param master The master node to merge with + * @param slave The node to merge into the master + */ + public static void mergeNodes(TreeNode master, TreeNode slave) { + // Doesn't do anything + } + + /** + * Merge Node Children. Merge the children of a node according to the + * merging rules of the parent. Each subclass must implement this method + * + * @param node The parent node from which the children are merged + */ + public static void mergeNodeChildren(TreeNode node) { + // Doesn't do anything + } + + /** + * Default Merge factory which creates concrete Merge objects + */ + public static class DefaultMergeFactory { + + /** + * Returns suitable Merge object + * + * @param masterView The master NavigatorView + * @param slaveView The slave NavigatorView + * @return The Merge object + */ + public static Merge getMerge(NavigatorView masterView, NavigatorView slaveView) { + + Merge mergeObject = null; + // throw an NPE early + if (masterView == null || slaveView == null) { + throw new NullPointerException("masterView and/or slaveView are null"); + + } + String mergeType = masterView.getMergeType(); + HelpSet hs = masterView.getHelpSet(); + Locale locale = hs.getLocale(); + ClassLoader loader = hs.getLoader(); + Class klass; + Constructor konstructor; + + if (mergeType != null) { + try { + Class types[] = { NavigatorView.class, + NavigatorView.class }; + Object args[] = { masterView, slaveView }; + if (loader == null) { + klass = Class.forName(mergeType); + } else { + klass = loader.loadClass(mergeType); + } + konstructor = klass.getConstructor(types); + mergeObject = (Merge) konstructor.newInstance(args); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException("Could not create Merge type " + + mergeType); + } + } else { + mergeObject = new AppendMerge(masterView, slaveView); + } + return mergeObject; + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java new file mode 100644 index 0000000000000000000000000000000000000000..9729e50a76d39f35dc002b6ce2dc7c51f3a898d9 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java @@ -0,0 +1,291 @@ +/* + * @(#)MergeHelpUtilities.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.*; +import java.util.*; +import java.text.*; +import java.lang.reflect.Method; + +/** + * Common utilities for merge types + * + * @author Richard Gregor + * @version 1.9 10/30/06 + */ + +public class MergeHelpUtilities extends Object { + + + /** + * Merge the nodes according the merging rules of the masterNode's + * merge type + * + * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType + * @param masterNode The master node to merge into + * @param slaveNode A secondary node that will merge into the master node + */ + public static void mergeNodes(String masterMergeType, + DefaultMutableTreeNode masterNode, + DefaultMutableTreeNode slaveNode) { + if (slaveNode.isLeaf()) { + return; + } + String mergeType = getMergeType(masterNode); + if (mergeType == null) { + mergeType = masterMergeType; + } + + Class klass; + Class types[] = { TreeNode.class, + TreeNode.class }; + Method m; + Object args[] = { masterNode, slaveNode }; + try { + klass = Class.forName(mergeType); + m = klass.getDeclaredMethod("mergeNodes", types); + m.invoke(null, args); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException + ("Could not find or execute mergeNodes for " + + mergeType); + } + } + + /** + * Merge a nodes children according the merging rules of the node's + * merge type + * + * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType + * @param node The node + */ + public static void mergeNodeChildren(String masterMergeType, DefaultMutableTreeNode node) { + if (node.isLeaf()) { + return; + } + String mergeType = getMergeType(node); + if (mergeType == null) { + mergeType = masterMergeType; + } + Class klass; + Class types[] = { TreeNode.class }; + Method m; + Object args[] = { node }; + try { + klass = Class.forName(mergeType); + m = klass.getDeclaredMethod("mergeNodeChildren", types); + m.invoke(null, args); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException + ("Could not find or execute mergeNodeChildren for " + + mergeType); + } + } + + /** + * Returns node's merge type + * + * @param node The node + * @return The node's merge type + */ + private static String getMergeType(DefaultMutableTreeNode node) { + TreeItem item = (TreeItem)node.getUserObject(); + if (item == null) { + return null; + } else { + return item.getMergeType(); + } + } + + /** + * Returns name of node + * + * @param node The node + * @return The name of node + */ + public static String getNodeName(DefaultMutableTreeNode node) { + if (node == null) { + return null; + } + TreeItem item = (TreeItem)node.getUserObject(); + if (item == null) { + return null; + } + return item.getName(); + } + + /** + * Returns node with given name + * + * @param parent The parent node + * @param name The name of child + * @return The child with given name + */ + public static DefaultMutableTreeNode getChildWithName(DefaultMutableTreeNode parent,String name) { + DefaultMutableTreeNode childAtI = null; + DefaultMutableTreeNode result = null; + + for (int i = 0; i < parent.getChildCount(); i++) { + childAtI = (DefaultMutableTreeNode)parent.getChildAt(i); + if (getNodeName(childAtI).equals(name)) { + result = childAtI; + break; + } + } + return result; + + } + + /** + * Returns locale of node + * + * @param node The node + * @return The locale object + */ + public static Locale getLocale(DefaultMutableTreeNode node) { + Locale locale = null; + TreeItem item = (TreeItem)node.getUserObject(); + if (item != null) { + locale = item.getLocale(); + } + if (locale == null) { + locale = Locale.getDefault(); + } + return locale; + } + + /** + * Compares name of nodes + * + * @param master The master node + * @param slave The slave node + * @return negative is master is lexically lower than slave; + * positive if master is lexically higher than slave and zero if lexically + * identical. + */ + public static int compareNames(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) { + + TreeItem masterItem = (TreeItem)master.getUserObject(); + debug("haveEqualName - master:"+masterItem); + TreeItem slaveItem = (TreeItem)slave.getUserObject(); + debug("haveEqualName - slave:"+slaveItem); + + String masterName = masterItem.getName(); + if (masterName == null) { + masterName = " "; + } + + String slaveName = slaveItem.getName(); + if (slaveName == null) { + slaveName = " "; + } + + Collator collator = Collator.getInstance(getLocale(master)); + return collator.compare(masterName, slaveName); + } + + /** + * Method for comparing ID of nodes + * + * @param master The master node + * @param slave The slave node + * @return True if ID is the same + */ + public static boolean haveEqualID(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) { + TreeItem masterItem = (TreeItem)master.getUserObject(); + TreeItem slaveItem = (TreeItem)slave.getUserObject(); + + if (masterItem.getID() == null) { + if (slaveItem.getID() == null) { + return true; + } else { + return false; + } + } else { + if (slaveItem.getID() == null) { + return false; + } + } + + //items are not null + + Map.ID masterMapID = masterItem.getID(); + Map.ID slaveMapID = slaveItem.getID(); + + if (masterMapID.id == null) { + if (slaveMapID.id == null) { + return true; + } else { + return false; + } + } else { + if (slaveMapID.id == null) { + return false; + } + } + + return masterMapID.id.equals(slaveMapID.id); + } + + + /** + * Marks nodes with the same name but diferent IDs with their HelpSet title + * + * @param master The master node to mark + * @param slave The slave node to mark + */ + + public static void markNodes(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) { + debug("MarkNodes"); + TreeItem masterItem = (TreeItem)master.getUserObject(); + TreeItem slaveItem = (TreeItem)slave.getUserObject(); + HelpSet masterHS = masterItem.getHelpSet(); + HelpSet slaveHS = slaveItem.getHelpSet(); + + if (masterItem.getName() != null) { + masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")"); + } else { + masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")"); + } + if (slaveItem.getName() != null) { + slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")"); + } else { + slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")"); + } + } + + private static boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.out.println("MergeHelpUtilities :"+msg); + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java b/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java new file mode 100644 index 0000000000000000000000000000000000000000..39d8b33cfbd86862dfb262f26b6df93e369e8675 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java @@ -0,0 +1,219 @@ +/* + * @(#)NavigatorView.java 1.28 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Locale; +import java.util.Hashtable; +import java.awt.Component; +import java.lang.reflect.*; +import java.io.Serializable; + +/** + * Navigational View information + * + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version 1.28 10/30/06 + */ + +public abstract class NavigatorView implements Serializable{ + private HelpSet hs; + + private String name; + private String label; + private Locale locale; + private Hashtable params; + private Map.ID imageID; + private String mergeType; + + /** + * Constructs a Navigator with some given data. This is protected + * so subclasses can use it. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param locale The default locale to interpret the data in this View. + * @param params A hashtable that provides different key/values for this type. + */ + + protected NavigatorView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) + { + if (name == null || label == null) { + throw new NullPointerException("Invalid name or label"); + } + this.imageID = null; + if (params != null) { + String imageID = (String)params.get("imageID"); + if (imageID != null) + this.imageID = Map.ID.create(imageID, hs); + this.mergeType = (String)params.get("mergetype"); + } + this.hs = hs; + this.name = name; + this.label = label; + this.locale = locale; + this.params = params; + } + + /** + * Creates a NavigatorView for some given information. + * The type is used to determine a NavigatorView class within the + * ClassLoader. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param className The type for the View (its class name). + * @param params A hashtable that provides different key/values for this type. + * @return The desired NavigatorView object. + * @throws InvalidNavigatorViewException if <tt>hs</tt>, <tt>name</tt>, + * <tt>label</tt>, <tt>locale</tt>, <tt>className</tt>, or <tt>params</tt> + * are null, or if a valid NavigatorView cannot be constructed from the + * parameters. + */ + public static NavigatorView create(HelpSet hs, + String name, + String label, + Locale locale, + String className, + Hashtable params) + throws InvalidNavigatorViewException + { + ClassLoader loader; + Class klass; + NavigatorView back; + + try { + loader = hs.getLoader(); + Constructor konstructor; + Class types[] = { HelpSet.class, + String.class, String.class, Locale.class, + Hashtable.class }; + Object args[] = { hs, + name, label, locale, + params }; + if (loader == null) { + klass = Class.forName(className); + } else { + klass = loader.loadClass(className); + } + konstructor = klass.getConstructor(types); + back = (NavigatorView) konstructor.newInstance(args); + return back; + } catch (Exception ex) { + throw new InvalidNavigatorViewException("Could not create", + hs, + name, label, locale, + className, params); + } + } + + /** + * Creates a navigator for a given model. Really a JHelpNavigator right now. + * + * @param model The model for the Navigator. + */ + public abstract Component createNavigator(HelpModel model); + + + + /** + * Gets the HelpSet for this Navigator view. + * + * @return the HelpSet + */ + public HelpSet getHelpSet() { + return hs; + } + + /** + * Gets the name of this Navigator view. + * + * @return the Name of the view + */ + public String getName() { + return name; + } + + /** + * Gets the locale-dependent name of this View. + * + * @return The locale-dependent name of this view. + */ + public String getLabel(Locale locale) { + return getLabel(); + } + + /** + * Gets the locale-dependent name of this View + * + * @return The locale-dependent name of this view + */ + public String getLabel() { + return label; + } + + /** + * @return The locale. + */ + public Locale getLocale() { + return locale; + } + + /** + * Gets parameters passed to this View. + * + * @return The parameters passed to this View. + */ + public Hashtable getParameters() { + return params; + } + + /** + * Gets merge type of this Navigator view + * + * @return The merge type of this Navigator view + */ + public String getMergeType(){ + return mergeType; + } + + /** + * Returns Map ID of icons passed to this View. + * + * @return the Map ID of icons passed to this View + */ + public Map.ID getImageID() { + return imageID; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java b/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java new file mode 100644 index 0000000000000000000000000000000000000000..cef28b7645e4dcf1ed823dccac0799420bdd966d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java @@ -0,0 +1,98 @@ +/* + * @(#)NoMerge.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.*; +import java.util.*; +import java.text.*; + +/** + * No merge type + * + * @author Roger Brinkley + * @version 1.3 10/30/06 + */ +public class NoMerge extends Merge{ + + /** + * Constructs NoMerge + * + * @param master The master NavigatorView + * @param slave The slave NavigatorView + */ + public NoMerge(NavigatorView master, NavigatorView slave){ + super(master,slave); + + } + + /** + * Processes no merge + * + * @param node The master node + * @return the master node + */ + public TreeNode processMerge(TreeNode node){ + debug("start merge"); + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node; + + // There is no merging here but we will make sure + // the master children are handled correctly + MergeHelpUtilities.mergeNodeChildren("javax.help.NoMerge", + masterNode); + return masterNode; + } + + /** + * Merge Nodes. Merge two nodes according to the merging rules of the + * masterNode. Each Subclass should override this implementation. + * + * @param master The master node to merge with + * @param slave The node to merge into the master + */ + public static void mergeNodes(TreeNode master, TreeNode slave) { + // Doesn't do anything + } + + /** + * Merge Node Children. Merge the children of a node according to the + * merging rules of the parent. Each subclass must implement this method + * + * @param node The parent node from which the children are merged + */ + public static void mergeNodeChildren(TreeNode node) { + // Doesn't do anything + } + + private static boolean debug = false; + private static void debug(String msg){ + if (debug) { + System.out.println("NoMerge :"+msg); + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/Popup.java b/jhMaster/JavaHelp/src/new/javax/help/Popup.java new file mode 100644 index 0000000000000000000000000000000000000000..d3387b741184bdc273c09a962dd5a99c7ecc573d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/Popup.java @@ -0,0 +1,711 @@ +/* + * @(#)Popup.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.Dialog; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRootPane; +import javax.swing.JWindow; +import javax.swing.JFrame; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.MouseInputAdapter; +import java.lang.reflect.Method; +import java.util.Vector; +import com.sun.java.help.impl.JHSecondaryViewer; + +/** + * Popup is a Presentation class that will create a popup help window for an + * application. There is only one popup per application. A popup contains only + * a content viewer. It is intended to provide immediate help and then allow + * the user to continue working. Once a popup loses focus, it is destroyed. + * + * @author Roger D. Brinkley + * @version 1.5 10/30/06 + * @since 2.0 + * + * @see javax.help.Presentation + */ + +public class Popup extends Presentation implements ActionListener{ + + private JHelpContentViewer jheditor; + private Component invoker = null; + private JWindow window = null; + private Vector grabbed = null; + private PopupComponentAdapter pca= null; + private PopupKeyAdapter pka=null; + private PopupMouseAdapter pma=null; + private PopupMouseWheelListener pmwl=null; + private PopupWindowAdapter pwa=null; + private Rectangle internalBounds=null; + static private final String SHOW = "show"; + static private final String CANCEL = "cancel"; + static private boolean on1dot4 = false; + + static { + try { + // Test if method introduced in 1.4 is available. + Class klass = Class.forName("java.awt.event.MouseWheelEvent"); + on1dot4 = (klass == null); + } catch (ClassNotFoundException e) { + on1dot4 = false; + } + } + + + /* + * The currentPopup is the Popup that is currently displayed on the + * screen. This state is maintained for positioning purposes when a + * popup invokes a popup to use the currently displayed invoker rather + * than the invoker passed in. + */ + static Popup currentPopup = null; + + /* + * Private costructor + */ + private Popup(HelpSet hs) { + setHelpSet(hs); + } + + /** + * create a new Popup for a given HelpSet and HelpSet.Presentation + * "name". If the "name"d HelpSet.Presentation does not exist in the + * HelpSet then the defaultHelpSet.Presentation if used. + * + * @param hs The HelpSEt used in this presentation + * @param name The name of the HelpSet.Presentation to use + * @returns Presentation A Popup. + */ + static public Presentation getPresentation(HelpSet hs, String name) { + + Popup thePopup = new Popup(hs); + + if (hs != null) { + HelpSet.Presentation presentation = null; + + // get a named presentation if one exists + if (name != null) { + presentation = hs.getPresentation(name); + } + + // get the default presentation if one exits + if (presentation == null) { + presentation = hs.getDefaultPresentation(); + } + + // set the presentation + // a null is ok here as it will just return. + thePopup.setHelpSetPresentation(presentation); + } + return thePopup; + } + + /** + * Get the Component that invoked this popup + * + * @return Component The invoking component + */ + public Component getInvoker() { + return invoker; + } + + /** + * Set the invoking component for this popup. This must be called before + * setDisplayed(true) is called. If there is an invoker already set it will + * be used instead of the new invoker. + * + * @param invoker The component that invoked this popup + * @throws an IllegalArgumentException if the invoker or it's parents are + * not showing. + */ + public void setInvoker(Component invoker) { + this.invoker = invoker; + // If we have a JMenuItem circulate up to the JMenu + if (invoker instanceof JMenuItem) { + while (!(this.invoker instanceof JMenu)) { + this.invoker = this.invoker.getParent(); + if (this.invoker instanceof JPopupMenu) { + this.invoker = ((JPopupMenu)this.invoker).getInvoker(); + } + } + } + if (this.invoker == null) { + throw new IllegalArgumentException("invoker"); + } + } + + + /** + * Get the internal bounds for the invoker. + */ + public Rectangle getInvokerInternalBounds() { + return internalBounds; + } + + /** + * Set the the internal bounds for an invoker. For some invokers like + * JTrees and JTables it is necessary to set an internal bounds to + * further define the location of where to place the popup. + * + * @param bounds A Rectangle of the internal bounds + */ + public void setInvokerInternalBounds(Rectangle bounds) { + internalBounds = bounds; + } + + /** + * return the JWindow if created. Will return a null if not created. + */ + private JWindow getWindow() { + return window; + } + + /** + * Displays the presentation to the user + */ + public void setDisplayed(boolean b) { + Container top = getTopMostContainer(); + + // if the window is null and they don't want it displayed just return + if (window == null && !b) { + return; + } + + // if window is null create the window + if (window == null) { + window = new JWindow((Window)getTopMostContainer()); + jheditor = new JHelpContentViewer(getHelpModel()); + window.getRootPane().setBorder(BorderFactory.createLineBorder(Color.black, 2)); + + window.getContentPane().add(jheditor, BorderLayout.CENTER); + } + if (grabbed == null) { + grabbed = new Vector(); + pca = new PopupComponentAdapter(); + pma = new PopupMouseAdapter(); + pwa = new PopupWindowAdapter(); + pka = new PopupKeyAdapter(); + if (on1dot4) { + pmwl = new PopupMouseWheelListener(); + } + } else { + grabbed.clear(); + } + grabContainer(top); + window.addWindowListener(pwa); + if (on1dot4) { + try { + Class types[] = { Class.forName("java.awt.event.WindowFocusListener") }; + Object args[] = { pwa }; + Method m = window.getClass().getMethod("addWindowFocusListener", types); + m.invoke(window, args); + // window.addWindowFocusListener(pwa); + } catch (java.lang.Exception ex) { + //ignore it + } + } + + JRootPane root = getRootPane(); + if (root != null) { + root.registerKeyboardAction(this, "cancel", + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } else if (top != null) { + top.addKeyListener(pka); + } + window.getRootPane().registerKeyboardAction(this, "cancel", + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + if (b) { + showPopup(); + } else { + cancelPopup(); + } + } + + public boolean isDisplayed() { + if (window != null) { + return true; + } + return false; + } + + public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + if (command == "cancel") { + cancelPopup(); + } + } + + /** + * show the window + */ + private void showPopup() { + if (currentPopup != null && + SwingUtilities.getAncestorOfClass(JWindow.class, invoker) == + currentPopup.getWindow()) { + setInvoker(currentPopup.getInvoker()); + } + + Rectangle popupBounds = computePopupBounds(getSize()); + + jheditor.setPreferredSize(new Dimension(popupBounds.width, + popupBounds.height)); + window.setBounds(popupBounds.x, popupBounds.y, + popupBounds.width, popupBounds.height); + window.pack(); + window.show(); + currentPopup = this; + } + + private Rectangle computePopupBounds(Dimension popupSize) { + // Note all Points in computePopupBounds are either relative to + // the screen. The desired boundry must fit on the screen. If it is + // in a Modal Dialg it has to fit within the dialog + + Rectangle absBounds; + Point p; + + // Calculate the absolute boundry. Modal Dialogs must be within the + // Dialog. + boolean inModalDialog = inModalDialog(); + + /** Workaround for modal dialogs. See also JPopupMenu.java **/ + if ( inModalDialog ) { + Dialog dlg = getDialog(); + if ( dlg instanceof JDialog ) { + JRootPane rp = ((JDialog)dlg).getRootPane(); + p = rp.getLocationOnScreen(); + absBounds = rp.getBounds(); + absBounds.x = p.x; + absBounds.y = p.y; + } else { + absBounds = dlg.getBounds(); + } + } else { + Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize(); + absBounds = new Rectangle(0, 0, scrSize.width, scrSize.height); + } + + if (internalBounds == null) { + internalBounds = invoker.getBounds(); + } + debug("\nabsBounds=" + absBounds + "\ninternalBounds=" + internalBounds + "\n"); + + // Get a rectangle below and to the right and see if it fits + p = new Point(internalBounds.x, + internalBounds.y + internalBounds.height); + SwingUtilities.convertPointToScreen(p, invoker); + Rectangle br = new Rectangle(p.x, p.y, + popupSize.width, popupSize.height); + debug("below/right " + br + "\n"); + if ( SwingUtilities.isRectangleContainingRectangle(absBounds, br) ) { + // below and to the right fits return the rectangle + return br; + } + + // below and right failed - try to adjust the right side to fit + Rectangle bradjust = new Rectangle(br); + bradjust.setLocation(br.x + internalBounds.width - br.width, + br.y); + debug("below/right adjust " + bradjust + "\n"); + if ( SwingUtilities.isRectangleContainingRectangle(absBounds, + bradjust) ) { + // below and to the right fits return the rectangle + return bradjust; + } + + // below and right adjust failed - try above right + Rectangle ar = new Rectangle(br.x, + br.y-(br.height+internalBounds.height), + br.width, br.height); + debug("above/right " + ar + "\n"); + if (SwingUtilities.isRectangleContainingRectangle(absBounds, ar)) { + // above and to the right fits return the rectangle + return ar; + } + + // above and right failed - adjust the right side to fit + Rectangle aradjust = new Rectangle(ar); + aradjust.setLocation(ar.x + internalBounds.width - ar.width, + aradjust.y); + debug("above/right adjust " + aradjust + "\n"); + if ( SwingUtilities.isRectangleContainingRectangle(absBounds, + aradjust) ) { + // below and to the right fits return the rectangle + return aradjust; + } + + // above and right adjust failed - try right below + p = new Point(internalBounds.x + internalBounds.width, + internalBounds.y); + SwingUtilities.convertPointToScreen(p, invoker); + Rectangle rb = new Rectangle(p.x, p.y, + popupSize.width, popupSize.height); + debug("right/below " + rb + "\n"); + if (SwingUtilities.isRectangleContainingRectangle(absBounds, rb)) { + // right and below fits return the rectangle + return rb; + } + + // right and below failed - adjust the top side to fit + Rectangle rbadjust = new Rectangle(rb); + rbadjust.setLocation(rbadjust.x, + rb.y + internalBounds.height - rb.height); + debug("right/below adjust " + rbadjust + "\n"); + if ( SwingUtilities.isRectangleContainingRectangle(absBounds, + rbadjust) ) { + // right and below adjusted fits return the rectangle + return rbadjust; + } + + // right and below adjust failed - try left and below + Rectangle lb = new Rectangle(rb.x-(rb.width+internalBounds.width), + rb.y, + rb.width, rb.height); + debug("left/below " + lb + "\n"); + if (SwingUtilities.isRectangleContainingRectangle(absBounds, lb)) { + // right and below fits return the rectangle + return lb; + } + + // left and below failed - adjust the top side to fit + Rectangle lbadjust = new Rectangle(lb); + lbadjust.setLocation(lbadjust.x, + lb.y + internalBounds.height - lb.height); + debug("left/below adjust " + lbadjust + "\n"); + if ( SwingUtilities.isRectangleContainingRectangle(absBounds, + lbadjust) ) { + // right and below fits return the rectangle + return lbadjust; + } + + // Bummer - tried all around the object so no try covering it up + // Nothing fancy here upper left corner + Rectangle cover = new Rectangle(0, 0, + popupSize.width, + popupSize.height); + debug("upper left hand corner " + cover + "\n"); + if (SwingUtilities.isRectangleContainingRectangle(absBounds, cover)) { + // covering up the object fits return the rectangle + return cover; + } + + // Humm. The desired size is just to large. Shrink to fit. + SwingUtilities.computeIntersection(absBounds.x, + absBounds.y, + absBounds.width, + absBounds.height, + cover); + return cover; + } + + private Container getTopMostContainer() { + if (invoker == null) { + return null; + } + + for(Container p=((invoker instanceof Container) ? (Container)invoker : + invoker.getParent()); + p != null; p = p.getParent()) { + if (p instanceof JPopupMenu) { + Component comp = ((JPopupMenu)p).getInvoker(); + if (comp instanceof Container) { + p = (Container) comp; + } + } + if (p instanceof Window || p instanceof Applet) { + return p; + } + } + return null; + } + + private JRootPane getRootPane() { + Container parent = null; + JRootPane pane = null; + if (invoker == null || !(invoker instanceof JComponent)) { + return null; + } + + pane = ((JComponent)invoker).getRootPane(); + if (pane != null) { + return pane; + } + + // for loop through the parents until you reach a Dialog or null + for ( parent = ((invoker instanceof Container) ? (Container)invoker : + invoker.getParent()); + parent != null && !(parent instanceof JDialog) && + !(parent instanceof JWindow) && !(parent instanceof JFrame) ; + parent = parent.getParent() ) { + if (parent instanceof JPopupMenu) { + Component comp = ((JPopupMenu)parent).getInvoker(); + if (comp instanceof Container) { + parent = (Container) comp; + } + } + } + + if (parent instanceof JFrame) { + pane = ((JFrame)parent).getRootPane(); + } else if (parent instanceof JWindow) { + pane = ((JWindow)parent).getRootPane(); + } else if (parent instanceof JDialog) { + pane = ((JDialog)parent).getRootPane(); + } + + return pane; + } + + + /* + * Get the Dialog from the invoker + */ + private Dialog getDialog() { + Container parent; + if (invoker == null) { + return null; + } + + // for loop through the parents until you reach a Dialog or null + for ( parent = ((invoker instanceof Container) ? (Container)invoker : + invoker.getParent()); + parent != null && !(parent instanceof Dialog) ; + parent = parent.getParent() ); + + // return the dialog if we got one + if ( parent instanceof Dialog ) + return (Dialog) parent; + else + return null; + } + + private boolean inModalDialog() { + return (getDialog() != null); + } + + private class PopupWindowAdapter extends WindowAdapter { + + public void windowClosing(WindowEvent e) { + cancelPopup(); + } + + public void windowClosed(WindowEvent e) { + cancelPopup(); + } + + public void windowIconified(WindowEvent e) { + cancelPopup(); + } + + public void windowGainedFocus(WindowEvent e) { + window.toFront(); + } + + } + + private class PopupMouseAdapter extends MouseInputAdapter { + + public void mousePressed(MouseEvent e) { + cancelPopup(); + } + } + + private class PopupMouseWheelListener implements MouseWheelListener { + public void mouseWheelMoved(MouseWheelEvent e) { + cancelPopup(); + } + } + + private class PopupComponentAdapter extends ComponentAdapter { + + public void componentResized(ComponentEvent e) { + cancelPopup(); + } + + public void componentMoved(ComponentEvent e) { + cancelPopup(); + } + + public void componentShown(ComponentEvent e) { + cancelPopup(); + } + + public void componentHidden(ComponentEvent e) { + cancelPopup(); + } + + } + + /* + * Only used for AWT components + */ + private class PopupKeyAdapter extends KeyAdapter { + + public void keyReleased(KeyEvent e) { + int code = e.getKeyCode(); + if (code == KeyEvent.VK_ESCAPE) { + cancelPopup(); + } + } + } + + private void grabContainer (Container c) { + if(c instanceof java.awt.Window) { + ((java.awt.Window)c).addWindowListener(pwa); + ((java.awt.Window)c).addComponentListener(pca); + grabbed.addElement(c); + } + synchronized(c.getTreeLock()) { + int ncomponents = c.getComponentCount(); + Component[] component = c.getComponents(); + for (int i = 0 ; i < ncomponents ; i++) { + Component comp = component[i]; + if(!comp.isVisible()) + continue; + comp.addMouseListener(pma); + comp.addMouseMotionListener(pma); + if (on1dot4) { + try { + Class types[] = { Class.forName("java.awt.event.MouseWheelListener") }; + Object args[] = { pmwl }; + Method m = window.getClass().getMethod("addMouseWheelListener", types); + m.invoke(comp, args); + // comp.addMouseWheelListener(pmwl); + } catch (java.lang.Exception ex) { + //ignore it + } + } + grabbed.addElement(comp); + if (comp instanceof Container) { + Container cont = (Container) comp; + grabContainer(cont); + } + } + } + } + + void ungrabContainers() { + int i,c; + Component cpn; + for(i=0,c=grabbed.size();i<c;i++) { + cpn = (Component)grabbed.elementAt(i); + if(cpn instanceof java.awt.Window) { + ((java.awt.Window)cpn).removeWindowListener(pwa); + ((java.awt.Window)cpn).removeComponentListener(pca); + } else { + cpn.removeMouseListener(pma); + cpn.removeMouseMotionListener(pma); + if (on1dot4) { + try { + Class types[] = { Class.forName("java.awt.event.MouseWheelListener") }; + Object args[] = { pmwl }; + Method m = window.getClass().getMethod("removeMouseWheelListener", types); + m.invoke(cpn, args); + // cpn.removeMouseWheelListener(pmwl); + } catch (java.lang.Exception ex) { + //ignore it + } + } + } + } + grabbed = null; + } + + private void cancelPopup() { + Container top = getTopMostContainer(); + ungrabContainers(); + JRootPane root = getRootPane(); + if (root != null) { + root.unregisterKeyboardAction + (KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)); + } else if (top != null) { + top.removeKeyListener(pka); + } + window.removeWindowListener(pwa); + if (on1dot4) { + try { + Class types[] = { Class.forName("java.awt.event.WindowFocusListener") }; + Object args[] = { pwa }; + Method m = window.getClass().getMethod("removeWindowFocusListener", types); + m.invoke(window, args); + // window.removeWindowFocusListener(pwa); + } catch (java.lang.Exception ex) { + //ignore it + } + } + window.getRootPane().unregisterKeyboardAction + (KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)); + window.dispose(); + window = null; + jheditor = null; + currentPopup = null; + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("Popup: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/Presentation.java b/jhMaster/JavaHelp/src/new/javax/help/Presentation.java new file mode 100644 index 0000000000000000000000000000000000000000..183c382b96060142752d1965c2671850e8039485 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/Presentation.java @@ -0,0 +1,309 @@ +/* + * @(#)Presentation.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Locale; +import java.awt.Font; +import java.awt.Dimension; +import javax.help.Map.ID; +import java.net.URL; + + +/** + * Presentation is an abstract class providing a generic interface for + * the development of alternative Presentations. Each implementation of + * Presentation will need to override the static method getPresentation + * according to it's own needs. For instance Popup creates a single object + * whereas SecondaryWindow looks for an existing secondary window that matches + * the parameters before creating a new SecondaryWindow and MainWindow will + * always create a new Presentation. + * + * Presentation implements several generic methods required in all + * presentations. + * + * @author Roger D.Brinkley + * @version 1.5 10/30/06 + * @since 2.0 + * + * @see javax.help.HelpSet + */ + +public abstract class Presentation { + + private HelpSet helpset = null; + private TextHelpModel model = null; + private Locale locale = null; + private Font font = null; + private int width = 645; + private int height = 495; + + /** + * Get a "name" Presentation given the passed HelpSet. + * The presentation returned will vary depending on the implementing + * class. All classes will set the HelpSetPresentation based on the + * name if a HelpSet.Presentation matching that name exists in the + * HelpSet. If no named HelpSet.Presentation exits the default + * HelpSet.Presentation is used if present, otherwise the implementing + * class defaults will be used. + * Implementation of Presentation will + * override this implementation to return their own type. Implementation + * also have the descression to reuse "name"d presentations or create + * new Presentations. Presentation will return null unless otherwise + * overriden. + * + * @param hs The helpset used to get the Presentation + * @param name The name of the presentation. + */ + static public Presentation getPresentation(HelpSet hs, String name) { + return null; + } + + /** + * Set the Presentation attributes from a named presentation in a HelpSet. + * Extension of this class should extend this class by adding additional + * attributes + * + * @params hsPres - the HelpSet.Presentation to retrieve the presentation + * information from + * + * @see HelpSet.Presentation + */ + public void setHelpSetPresentation (HelpSet.Presentation hsPres) { + debug("setHelpSetPresentation"); + if (hsPres == null) { + return; + } + + // get the presentation size + Dimension size = hsPres.getSize(); + if (size != null) { + setSize(size); + } + + } + + /** + * Determines which ID is displayed (if any). + * @returns the current ID or null if there is none + */ + public ID getCurrentID() { + debug("getCurrentID"); + if (model != null) { + return model.getCurrentID(); + } + return null; + } + + /** + * Shows this ID as content relative to the (top) HelpSet for the Presentation + * instance--HelpVisitListeners are notified. + * + * @param id A string that identifies the topic to show for the loaded (top) HelpSet + * @exception BadIDException The ID is not valid for the HelpSet + */ + public void setCurrentID(String id) throws BadIDException { + debug("setCurrentID - String"); + try { + setCurrentID(ID.create(id, helpset)); + } catch (InvalidHelpSetContextException ex) { + // this should not happen + new Error("internal error?"); + } + } + + /** + * Displays this ID--HelpVisitListeners are notified. + * + * @param id a Map.ID indicating the URL to display + * @exception InvalidHelpSetContextException if the current helpset does not contain + * id.helpset + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException { + debug("setCurrentID - ID"); + + createHelpModel(); + model.setCurrentID(id); + } + + /** + * Determines which URL is displayed. + */ + public URL getCurrentURL() { + debug("getCurrentURL"); + if (model != null) { + return model.getCurrentURL(); + } + return null; + } + + + /** + * sets the current URL. + * HelpVisitListeners are notified. + * The currentID changes if there is a mathing ID for this URL + * @param url The url to display. A null URL is a valid url. + */ + public void setCurrentURL(URL url) { + debug("setCurrentURL"); + createHelpModel(); + model.setCurrentURL(url); + } + + /** + * Returns the default HelpSet + */ + public HelpSet getHelpSet() { + debug("getHelpSet"); + return helpset; + } + + /** + * Changes the HelpSet for this presentation. + * @param hs The HelpSet to set for this presentation. + * A null hs is valid parameter. + */ + public void setHelpSet(HelpSet hs) { + debug("setHelpSet"); + // If we already have a model check if the HelpSet has changed. + // If so change the model + // This could be made smarter to cache the helpmodels per HelpSet + if (hs != null && helpset != hs) { + model = new DefaultHelpModel(hs); + helpset = hs; + + } + } + + /** + * Displays the presentation to the user. + */ + abstract public void setDisplayed(boolean b); + + /** + * Determines if the presentation is displayed. + */ + abstract public boolean isDisplayed(); + + /** + * Gets the font for this Presentation. + */ + public Font getFont () { + debug("getFont"); + return font; + } + + /** + * Sets the font for this this Presentation. Concrete implementations must + * make sure that the font is properly set by extending this class. + * @param f The font. + */ + public void setFont (Font f) { + debug("setFont"); + font = f; + } + + /** + * Gets the locale of this component. + * @return This component's locale. If this component does not + * have a locale, the defaultLocale is returned. + * @see #setLocale + */ + public Locale getLocale() { + debug("getLocale"); + if (locale == null) { + return Locale.getDefault(); + } + return locale; + } + + /** + * Sets the locale of this Presentation. The locale is propagated to + * the presentation. Concrete implemenation must make sure they override + * this class to properly set the locale. + * + * @param l The locale to become this component's locale. A null locale + * is the same as the defaultLocale. + * @see #getLocale + */ + public void setLocale(Locale l) { + debug("setLocale"); + locale = l; + } + + /** + * Requests the size of the presentation. + * @returns Point the location of the presentation. + */ + public Dimension getSize() { + debug("getSize"); + return new Dimension(width, height); + } + + /** + * Requests the presentation be set to a given size. + * Concrete implementation must override this method to properly set the + * size. + * + * @param d - a Dimension to set the size to. + */ + public void setSize(Dimension d) { + debug("setSize"); + width = d.width; + height = d.height; + } + + /* + * private implementations + */ + private void createHelpModel() { + if (model == null) { + model = new DefaultHelpModel(helpset); + } + } + + protected TextHelpModel getHelpModel () { + if (model == null) { + createHelpModel(); + } + return model; + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("Presentation: "+msg); + } + } + +} + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java b/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java new file mode 100644 index 0000000000000000000000000000000000000000..b4706828a936e1fd90df5a4d2f5bb7cb3dfe4fc8 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java @@ -0,0 +1,107 @@ +/* + * @(#)PrintAction.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.net.URL; +import java.util.Locale; +import javax.swing.UIManager; +import com.sun.java.help.impl.JHelpPrintHandler; + +/** + * + * @author Stepan Marek + * @version 1.3 10/30/06 + */ +public class PrintAction extends AbstractHelpAction implements PropertyChangeListener, ActionListener { + + private static final String NAME = "PrintAction"; + + private JHelpPrintHandler handler = null; + + /** Creates new BackAction */ + public PrintAction(Object control) { + + super(control, NAME); + + if (control instanceof JHelp) { + + JHelp help = (JHelp)control; + + handler = JHelpPrintHandler.getJHelpPrintHandler(help); + handler.addPropertyChangeListener(this); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + + } + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + } + + public void actionPerformed(ActionEvent event) { + if (handler != null) { + JHelp help = (JHelp)getControl(); + URL[] urls = null; + TreeItem[] items = help.getSelectedItems(); + if (items != null) { + urls = new URL[items.length]; + for (int i = 0; i < items.length; i++) { + urls[i] = items[i].getURL(); + } + } + if ((urls != null) && (urls.length > 0)) { + handler.print(urls); + } else { + handler.print(help.getModel().getCurrentURL()); + } + } + } + + + /** + * This method gets called when a bound property is changed. + * @param evt A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("enabled")) { + setEnabled(((Boolean)evt.getNewValue()).booleanValue()); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java b/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java new file mode 100644 index 0000000000000000000000000000000000000000..3bb6b85b1b8b3d617f2a6d9269bbfd93b8636f34 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java @@ -0,0 +1,92 @@ +/* + * @(#)PrintSetupAction.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Locale; +import javax.swing.UIManager; +import com.sun.java.help.impl.JHelpPrintHandler; + +/** + * + * @author Stepan Marek + * @version 1.3 10/30/06 + */ +public class PrintSetupAction extends AbstractHelpAction implements PropertyChangeListener, ActionListener { + + private static final String NAME = "PrintSetupAction"; + + private JHelpPrintHandler handler = null; + + /** Creates new BackAction */ + public PrintSetupAction(Object control) { + + super(control, NAME); + + if (getControl() instanceof JHelp) { + + JHelp help = (JHelp)control; + + handler = JHelpPrintHandler.getJHelpPrintHandler(help); + handler.addPropertyChangeListener(this); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + + } + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + } + + public void actionPerformed(ActionEvent event) { + if (handler != null) { + handler.printSetup(); + } + } + + /** + * This method gets called when a bound property is changed. + * @param evt A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("enabled")) { + setEnabled(((Boolean)evt.getNewValue()).booleanValue()); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java b/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java new file mode 100644 index 0000000000000000000000000000000000000000..e021e21f1483b2b4033100e88b355d4cdb207382 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java @@ -0,0 +1,73 @@ +/* + * @(#)ReloadAction.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.*; +import java.awt.event.*; +import javax.help.*; +import javax.help.event.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Stack; +import javax.swing.*; + +/** + * + * @author Roger Brinkley + * @version 1.3 10/30/06 + */ +public class ReloadAction extends AbstractHelpAction implements ActionListener { + + private static final String NAME = "ReloadAction"; + + /** Creates new ReloadAction */ + public ReloadAction(Object control) { + super(control, NAME); + + putValue("icon", UIManager.getIcon(NAME + ".icon")); + + if (control instanceof JHelp) { + JHelp help = (JHelp) control; + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + + putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME)); + putValue("access", HelpUtilities.getString(locale, "access." + NAME)); + } + } + + public void actionPerformed(java.awt.event.ActionEvent event) { + JHelp help = (JHelp)getControl(); + JHelpContentViewer viewer = help.getContentViewer(); + viewer.reload(); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java b/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java new file mode 100644 index 0000000000000000000000000000000000000000..b543ac8807b9eea67a5a81dcaab750130dcb6858 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java @@ -0,0 +1,64 @@ +/* + * @(#)SearchHit.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) SearchHit.java 1.4 - last change made 10/30/06 + */ + +package javax.help; + +/** + * Stores search information for individual Search hits. + * + * @author Roger D. Brinkley + * @version 1.4 10/30/06 + */ + +public class SearchHit { + + private double confidence; + private int begin; + private int end; + + public SearchHit(double confidence, int begin, int end) { + this.confidence = confidence; + this.begin = begin; + this.end = end; + } + + public double getConfidence() { + return confidence; + } + + public int getBegin() { + return begin; + } + + public int getEnd() { + return end; + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java b/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java new file mode 100644 index 0000000000000000000000000000000000000000..edc03d8aaabb3c16dace96048c984ebd9077ea88 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java @@ -0,0 +1,152 @@ +/* + * @(#)SearchTOCItem.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) SearchTOCItem.java 1.9 - last change made 10/30/06 + */ + +package javax.help; + +import java.net.URL; +import java.net.MalformedURLException; +import java.util.Vector; +import java.util.Enumeration; +import java.util.NoSuchElementException; +import java.util.Locale; +import javax.help.Map.ID; +import javax.help.search.SearchItem; + +/** + * Stores Search TOC items. This class extends TOCItems with additonal + * search hits. Can be used as part of the TOC tree or as an appendage to + * the tree for items not contained in the tree. + * + * @author Roger D. Brinkley + * @version 1.9 10/30/06 + */ + +public class SearchTOCItem extends TOCItem { + + private URL url; + private Vector sivec; + private boolean inTOC; + private double confidence; + + public SearchTOCItem(ID id, ID imageID, HelpSet hs, Locale locale) { + super (id, imageID, hs, locale); + inTOC = true; + this.url = null; + sivec = new Vector(); + confidence = 0; + } + + // SearchItem should handle Locale, no Lang + public SearchTOCItem(SearchItem item) { + super (null, null, null, HelpUtilities.localeFromLang(item.getLang())); + inTOC = false; + setName(item.getTitle()); + try { + this.url = new URL(item.getBase(), item.getFilename()); + } catch (MalformedURLException me) { + this.url = null; + } + sivec = new Vector(); + SearchHit info = new SearchHit(item.getConfidence(), + item.getBegin(), + item.getEnd()); + confidence = item.getConfidence(); + sivec.addElement(info); + } + + /** + * Adds a SearchHit. + */ + public void addSearchHit(SearchHit si) { + // these are in sorted order so look at the bottom + // entry first + // + // This sorted order needs to be looked at for FCS + if (sivec.isEmpty()) { + sivec.addElement(si); + confidence = si.getConfidence(); + } else { + for (int i = sivec.size() - 1; i >= 0 ; i--) { + SearchHit test = (SearchHit)sivec.elementAt(i); + if (test.getConfidence() <= si.getConfidence()) { + sivec.insertElementAt(si, i+1); + break; + } + if (i == 0) { + sivec.insertElementAt(si, 0); + confidence = si.getConfidence(); + } + } + } + } + + public URL getURL() { + return url; + } + + public double getConfidence() { + // The confidence level is the max confidence value + // The max value is determined at the time a Search Hit is + // added + return confidence; + } + + public Enumeration getConfidences() { + return new Enumeration() { + int count = 0; + + public boolean hasMoreElements() { + return count < sivec.size(); + } + + public Object nextElement() { + synchronized (sivec) { + if (count < sivec.size()) { + return new Double(((SearchHit)sivec.elementAt(count++)).getConfidence()); + } + } + throw new NoSuchElementException("Vector Enumeration"); + } + }; + } + + public boolean inTOC() { + return inTOC; + } + + public Enumeration getSearchHits() { + return sivec.elements(); + } + + public int hitCount() { + return sivec.size(); + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchView.java b/jhMaster/JavaHelp/src/new/javax/help/SearchView.java new file mode 100644 index 0000000000000000000000000000000000000000..d24b8c611d9557694196c22a5c67dd49eeae704a --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SearchView.java @@ -0,0 +1,84 @@ +/* + * @(#)SearchView.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Hashtable; +import java.awt.Component; +import java.util.Locale; + +/** + * Navigational View information for a Search + * + * @author Eduardo Pelegri-Llopart + * @version 1.5 01/29/99 + */ + +public class SearchView extends NavigatorView { + /** + * Constructs a SearchView with some given data. Locale of the View defaults + * to that of the HelpSet. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param locale The default locale to interpret the data in this TOC. + * @param params A hashtable that provides different key/values for this type. + */ + public SearchView(HelpSet hs, + String name, + String label, + Hashtable params) { + super(hs, name, label, hs.getLocale(), params); + } + + /** + * Constructs a SearchView with some given data. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param locale The default locale to interpret the data in this TOC. + * @param params A hashtable that provides different key/values for this type. + */ + public SearchView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) { + super(hs, name, label, locale, params); + } + + /** + * Creates a navigator for a given model. + */ + public Component createNavigator(HelpModel model) { + return new JHelpSearchNavigator(this, model); + } + + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java b/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..3b5c63f9a0e27bcb5094a2a54f1831a1a5b4f884 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java @@ -0,0 +1,152 @@ +/* + * @(#)SecondaryWindow.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Hashtable; + +/** + * MainWindowPresentation is a class that will create a single main help + * window for an application. Although there is generally only one per + * application there can be multiple MainWindowPresentation. + * By default it is a tri-paned fully decorated window + * consisting of a toolbar, navigator pane, and help content view. By default + * the class is not destroyed when the window exits. + * + * @author Roger D.Brinkley + * @version 1.5 10/30/06 + * @since 2.0 + * + * @see javax.help.WindowPresentation + * @see javax.help.Presentation + */ + +public class SecondaryWindow extends WindowPresentation { + + static private Hashtable windows = new Hashtable(); + private String name; + + private SecondaryWindow(HelpSet hs, String name) { + super(hs); + this.name = name; + } + + /** + * Get a named SecondaryWindow for a given HelpSet. + * Named SecondaryWindows are stored. If a named + * SecondaryWindow exits then it is returned, otherwise a new + * secondary window is created. If there is a HelpSet.Presentation of the + * same name the presentation attibutes will be used, otherwise, the + * default HelpSet.Presentation is used. + * + * @param hs The HelpSet used in this presentation + * @param name The name of the Presentation to create - also the name + * of the HelpSet.Presentation to use. + * @returns Presentation A unique MainWindowPresentation. + */ + static public Presentation getPresentation(HelpSet hs, String name) { + debug ("getPresentation"); + SecondaryWindow swp; + + String winName = name; + if (name == null) { + winName = ""; + } + + // Use the secondary window if one exists + swp = (SecondaryWindow) windows.get(winName); + if (swp != null) { + if (swp.getHelpSet() != hs) { + swp.setHelpSet(hs); + } + return swp; + } + + debug ("no Presentation - start again"); + swp = new SecondaryWindow(hs, winName); + + // Set the SecondaryWindow defaults + swp.setViewDisplayed(false); + swp.setToolbarDisplayed(false); + swp.setDestroyOnExit(true); + swp.setTitleFromDocument(true); + + if (hs != null) { + HelpSet.Presentation presentation = null; + + // get a named presentation if one exists + if (name != null) { + presentation = hs.getPresentation(name); + } + + // get the default presentation if one exits + if (presentation == null) { + presentation = hs.getDefaultPresentation(); + } + + // set the presentation + // a null is ok here as it will just return. + swp.setHelpSetPresentation(presentation); + + windows.put(winName, swp); + } + return swp; + } + + /** + * Gets a SecondaryWindow if one exists. Does not + * create a Presentation if one does not exist. + * + * @param name Name of the presentation to get + * @return SecondaryWindow The found Presentation or null + */ + static public SecondaryWindow getPresentation(String name) { + debug ("getPresenation(name)"); + return (SecondaryWindow) windows.get(name); + } + + /** + * Destroy the SecondaryWindowPresentatin. Specifically remove it from + * the list of SecondaryWindows. + */ + public void destroy() { + super.destroy(); + windows.remove(name); + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("SecondaryWindow: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java b/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java new file mode 100644 index 0000000000000000000000000000000000000000..6e5ce0d0e44c26e76fd7ff55833f0b06d38feb86 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java @@ -0,0 +1,47 @@ +/* + * @(#)SeparatorAction.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.*; +import java.awt.event.*; +import javax.help.*; +import javax.help.event.*; +import java.util.Enumeration; +import java.util.Stack; +import javax.swing.*; + +/** + * + * @author Stepan Marek + * @version 1.2 10/30/06 + */ +public class SeparatorAction extends AbstractHelpAction { + public SeparatorAction(Object control) { + super(control, "SeparatorAction"); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java new file mode 100644 index 0000000000000000000000000000000000000000..c882a24343428adf19163ab67d3fb45edee07137 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java @@ -0,0 +1,400 @@ +/* + * @(#)ServletHelpBroker.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.help; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.net.URL; +import java.net.MalformedURLException; +import java.awt.*; +import java.awt.event.*; +import javax.help.Map.ID; +import java.util.Locale; +import java.awt.Font; +import java.awt.Dimension; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspWriter; +import javax.swing.tree.DefaultMutableTreeNode; +import java.io.IOException; + +/** + * An implmentation of the HelpBroker interface for Servlets + * + * @author Roger Brinkley + * @version 1.3 10/30/06 + */ + +public class ServletHelpBroker implements HelpBroker { + + protected HelpSet helpset = null; + protected DefaultHelpModel model = null; + protected NavigatorView curNav = null; + protected boolean viewDisplayed = true; + protected Locale locale=null; + protected Font font; + + /** + * Zero-argument constructor. + * It should be followed by a setHelpSet() invocation. + */ + + public ServletHelpBroker() { + } + + /** + * Returns the default HelpSet + */ + public HelpSet getHelpSet() { + return helpset; + } + + /** + * Changes the HelpSet for this broker. + * @param hs The HelpSet to set for this broker. + * A null hs is valid parameter. + */ + public void setHelpSet(HelpSet hs) { + if (hs != null && helpset != hs) { + model = new DefaultHelpModel(hs); + helpset = hs; + } + } + + + /** + * Gets the locale of this component. + * @return This component's locale. If this component does not + * have a locale, the defaultLocale is returned. + * @see #setLocale + */ + public Locale getLocale() { + if (locale == null) { + return Locale.getDefault(); + } + return locale; + } + + /** + * Sets the locale of this HelpBroker. The locale is propagated to + * the presentation. + * @param l The locale to become this component's locale. A null locale + * is the same as the defaultLocale. + * @see #getLocale + */ + public void setLocale(Locale l) { + locale = l; + } + + /** + * Gets the font for this HelpBroker. + */ + public Font getFont () { + return font; + } + + /** + * Sets the font for this this HelpBroker. + * @param f The font. + */ + public void setFont (Font f) { + font = f; + } + + /** + * Set the currentView to the navigator with the same + * name as the <tt>name</tt> parameter. + * + * @param name The name of the navigator to set as the + * current view. If nav is null or not a valid Navigator + * in this HelpBroker then an + * IllegalArgumentException is thrown. + * @throws IllegalArgumentException if nav is null or not a valid Navigator. + */ + public void setCurrentView(String name) { + + NavigatorView views[] = helpset.getNavigatorViews(); + for (int i=0; i<views.length; i++) { + if (views[i].getName().equals(name)) { + curNav = views[i]; + return; + } + } + // did find a suitable navigator + throw new IllegalArgumentException("Invalid view name"); + } + + /** + * Determines the current navigator. + */ + public String getCurrentView() { + // if the current Nav isn't set then use the first Nav from the + // the helpset. + if (curNav == null) { + if (helpset != null) { + NavigatorView views[] = helpset.getNavigatorViews(); + curNav = views[0]; + } else { + // Argh! there werent' any navigators in the helpset + // return null; + return null; + } + } + return curNav.getName(); + } + + + /** + * Returns the current navigator as a NavigatorView. + */ + public NavigatorView getCurrentNavigatorView() { + // if the current Nav isn't set then use the first Nav from the + // the helpset. + if (curNav == null) { + if (helpset != null) { + NavigatorView views[] = helpset.getNavigatorViews(); + curNav = views[0]; + } else { + // Argh! there werent' any navigators in the helpset + // return null; + return null; + } + } + return curNav; + } + + + /** + * Initializes the presentation. + * Not implemented in ServletHelpBroker. + */ + public void initPresentation() { + } + + /** + * Displays the presentation to the user. + */ + public void setDisplayed(boolean b) { + // ignore this is always displayed + } + + /** + * Determines if the presentation is displayed. + */ + public boolean isDisplayed() { + return true; + } + + /** + * Requests the presentation be located at a given position. + * This operation throws an UnsupportedOperationException + * in ServletHelpBroker + */ + public void setLocation(Point p) throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Requests the location of the presentation. + * This operation throws an UnsupportedOperationException + * in ServletHelpBroker + */ + public Point getLocation() throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Requests the presentation be set to a given size. + * This operation throws an UnsupportedOperationException + * in ServletHelpBroker + */ + public void setSize(Dimension d) throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Requests the size of the presentation. + * throws UnsupportedOperationException in ServletHelpBroker. + */ + public Dimension getSize() throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Requests the presentation be set to a given screen. + * This operation throws an UnsupportedOperationException + * in ServletHelpBroker + */ + public void setScreen(int screen) throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Requests the screen of the presentation. + * throws UnsupportedOperationException in ServletHelpBroker. + */ + public int getScreen() throws javax.help.UnsupportedOperationException { + throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker"); + } + + /** + * Hides/Shows view. + */ + public void setViewDisplayed(boolean displayed) { + viewDisplayed = displayed; + } + + /** + * Determines if the current view is visible. + */ + public boolean isViewDisplayed() { + return viewDisplayed; + } + + /** + * Shows this ID as content relative to the (top) HelpSet for the HelpBroker + * instance--HelpVisitListeners are notified. + * + * @param id A string that identifies the topic to show for the loaded (top) HelpSet + * @exception BadIDException The ID is not valid for the HelpSet + */ + public void setCurrentID(String id) throws BadIDException { + try { + setCurrentID(ID.create(id, helpset)); + } catch (InvalidHelpSetContextException ex) { + // this should not happen + new Error("internal error?"); + } + } + + /** + * Displays this ID--HelpVisitListeners are notified. + * + * @param id a Map.ID indicating the URL to display + * @exception InvalidHelpSetContextException if the current helpset does not contain + * id.helpset + */ + public void setCurrentID(ID id) throws InvalidHelpSetContextException { + debug("setCurrentID"); + + model.setCurrentID(id); + } + + /** + * Determines which ID is displayed (if any). + */ + public ID getCurrentID() { + return model.getCurrentID(); + } + + /** + * Displays this URL. + * HelpVisitListeners are notified. + * The currentID changes if there is a mathing ID for this URL + * @param url The url to display. A null URL is a valid url. + */ + public void setCurrentURL(URL url) { + model.setCurrentURL(url); + } + + /** + * Determines which URL is displayed. + */ + public URL getCurrentURL() { + return model.getCurrentURL(); + } + + + // Context-Senstive methods + /** + * Enables the Help key on a Component. + * Not implemented in ServletHelpBroker + */ + public void enableHelpKey(Component comp, String id, HelpSet hs) { + } + + /** + * Enables help for a Component. + * Not implemented in ServletHelpBroker + */ + public void enableHelp(Component comp, String id, HelpSet hs) + { + } + + /** + * Enables help for a MenuItem. + * Not implemented in ServletHelpBroker + */ + public void enableHelp(MenuItem comp, String id, HelpSet hs) + { + } + + /** + * Enables help for a Component. + * Not implemented in ServletHelpBroker + */ + public void enableHelpOnButton(Component comp, String id, HelpSet hs) + { + } + + /** + * Enables help for a MenuItem. + * Not implemented in ServletHelpBroker. + */ + public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs) + { + } + + // Investigate if the following need to be implemented + public void setHelpSetPresentation(HelpSet.Presentation pres) { + } + public void showID(String id, String presentation, + String presentationName) throws BadIDException { + } + public void showID(ID id, String presentation, String presentationName) + throws InvalidHelpSetContextException { + } + public void enableHelpKey(Component comp, String id, HelpSet hs, + String presentation, String presentationName) { + } + public void enableHelpOnButton(Object obj, String id, HelpSet hs, + String presentation, + String presentationName) + { + } + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("ServletHelpBroker: "+msg); + } + } + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java b/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java new file mode 100644 index 0000000000000000000000000000000000000000..48d836c1083e4c025e53342983024810813ddeb2 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java @@ -0,0 +1,254 @@ +/* + * @(#)SortMerge.java 1.12 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import java.util.*; +import java.text.*; + +/** + * Sort merge type + * + * @author Richard Gregor + * @version 1.12 10/30/06 + */ +public class SortMerge extends Merge{ + + /** + * Constructs SortMerge + * + * @param master The master NavigatorView + * @param slave The slave NavigatorView + */ + public SortMerge(NavigatorView master, NavigatorView slave) { + super(master,slave); + } + + /** + * Processes sort merge + * + * @param node The master node (This node must be sorted) + * @return Merged master node + */ + public TreeNode processMerge(TreeNode node) { + debug("processMerge started"); + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode) node; + + //if master and slave are the same object return the + // masterNode + if (masterNode.equals(slaveTopNode)) { + return masterNode; + } + + // If there are no children in slaveTopNode return the + // masterNode + if (slaveTopNode.getChildCount() == 0) { + return masterNode; + } + + // If there are no children in the masterNode process the slaveTopNode + // and return the slaveTopNode + if (masterNode.getChildCount() == 0) { + MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge", + slaveTopNode); + // It would be better to return the slaveNode but that causes + // problems in the UIs so return the masterNode after adding + // all the slavNodes + while (slaveTopNode.getChildCount() > 0) { + masterNode.add((DefaultMutableTreeNode) slaveTopNode.getFirstChild()); + } + return masterNode; + } + + mergeNodes(masterNode, slaveTopNode); + debug("process merge ended"); + return masterNode; + } + + /** + * Merge Nodes. Merge two nodes according to the Sort merging rules + * + * @param masterNode The master node to merge with + * @param slaveNode The node to merge into the master + */ + public static void mergeNodes(TreeNode master, TreeNode slave) { + debug("mergeNodes started"); + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master; + DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave; + + // It is important that the masterNode already be sorted + sortNode(slaveNode, MergeHelpUtilities.getLocale(slaveNode)); + int masterCnt = masterNode.getChildCount(); + int m = 0; + DefaultMutableTreeNode masterAtM=null; + + if (masterCnt > 0) { + masterAtM = (DefaultMutableTreeNode)masterNode.getChildAt(m); + } + + DefaultMutableTreeNode slaveNodeChild = null; + + //Loop through the slaves + while (slaveNode.getChildCount() > 0 && masterAtM != null) { + slaveNodeChild = (DefaultMutableTreeNode)slaveNode.getFirstChild(); + + // compare this slaveChild to the masterChild + int compareVal = MergeHelpUtilities.compareNames(masterAtM, + slaveNodeChild); + + // if < 0 get the next master child + if (compareVal < 0 ) { + ++m; + // break out if we've done all we can do. + if (m >= masterCnt) { + break; + } + masterAtM = (DefaultMutableTreeNode)masterNode.getChildAt(m); + continue; + } else if (compareVal > 0) { + // slaveNodeChild is lexically procedes the masterNodeChild + // add the slaveNodeChild and merge in the node children + // and then continue. You automatically get the next + // slaveNodeChild + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge", + slaveNodeChild); + continue; + } else { + // The masterChild and slaveChild are equal + if (MergeHelpUtilities.haveEqualID(masterAtM, slaveNodeChild)) { + + // Merge the masterchild and slaveNodeChild together + // based on the mergetype of the masterChild + MergeHelpUtilities.mergeNodes("javax.help.SortMerge", + masterAtM, slaveNodeChild); + + // Need to remove the slaveNodeChild from the list + slaveNodeChild.removeFromParent(); + slaveNodeChild = null; + } else { + // Names are the same but the ID are not + // Mark the nodes and add the slaveChild + MergeHelpUtilities.markNodes(masterAtM, slaveNodeChild); + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge", + slaveNodeChild); + } + } + } + + // Add the remainong slave node children + while (slaveNode.getChildCount() > 0) { + slaveNodeChild = (DefaultMutableTreeNode)slaveNode.getFirstChild(); + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge", + slaveNodeChild); + } + + // ok make sure the masterNode is sorted + mergeNodeChildren(masterNode); + debug ("mergeNode ended"); + } + + + /** + * Merge Node Children. Merge the children of a node according to the + * Sort merging rules. + * + * @param node The parent node from which the children are merged + */ + public static void mergeNodeChildren(TreeNode node) { + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node; + debug("mergeNodeChildren master=" + MergeHelpUtilities.getNodeName(masterNode)); + + // Sort the children + sortNode(masterNode, MergeHelpUtilities.getLocale(masterNode)); + + // merge the children's children + for (int i=0; i < masterNode.getChildCount(); i++) { + DefaultMutableTreeNode child = + (DefaultMutableTreeNode)masterNode.getChildAt(i); + if (!child.isLeaf()) { + MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge", + child); + } + } + } + + /** + * Sorts children of node using Array.sort + * + * @param node The node to sort + * @param locale The locale + * @return Sorted node + */ + public static void sortNode(DefaultMutableTreeNode node, Locale locale) { + debug ("sortNode"); + if (locale == null) { + locale = Locale.getDefault(); + } + + //Locale locale = MergeHelpUtilities.getLocale(node); + CollationKey temp; + int size = node.getChildCount(); + DefaultMutableTreeNode sortedNode = new DefaultMutableTreeNode(); + + Collator collator = Collator.getInstance(locale); + CollationKey[] keys = new CollationKey[size]; + + for (int i = 0; i < size; i++) { + String string = MergeHelpUtilities.getNodeName((DefaultMutableTreeNode)node.getChildAt(i)); + debug("String , i:"+string+" , "+i); + keys[i] = collator.getCollationKey(string); + } + + Arrays.sort(keys); + + for (int i = 0; i < size; i++) { + DefaultMutableTreeNode child = MergeHelpUtilities.getChildWithName(node,keys[i].getSourceString()); + if (child != null) { + sortedNode.add(child); + } + } + + while (sortedNode.getChildCount() > 0) { + node.add((DefaultMutableTreeNode) sortedNode.getFirstChild()); + } + + debug ("end sortNode"); + } + + + private static boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.out.println("SortMerge :"+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java new file mode 100644 index 0000000000000000000000000000000000000000..252c0ea55d84756de704d0ae6618472971996a8a --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java @@ -0,0 +1,395 @@ +/* + * @(#)SwingHelpUtilities.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.LookAndFeel; +import javax.swing.UIDefaults; +import javax.swing.plaf.ComponentUI; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Provides a number of utility functions: + * + * Support for Beans, mapping from a Bean class to its HelpSet and to + * its ID. + * Support for LAF changes. + * Support for finding localized resources. + * + * This class has no public constructor. + * + * @author Eduardo Pelegri-Llopart + * @author Roger D. Brinkley + * @version 1.10 10/30/06 + */ + +public class SwingHelpUtilities implements PropertyChangeListener { + + private static UIDefaults uiDefaults = null; + private static SwingHelpUtilities myLAFListener = new SwingHelpUtilities(); + private static String contentViewerUI = null; + + static { + installUIDefaults(); + } + + //========= + /** + * LAF support + */ + + /** + * The PropertyChange method is used to track changes to LookAndFeel + * via the "lookAndFeel" property. + */ + + public void propertyChange(PropertyChangeEvent event) { + String changeName = event.getPropertyName(); + if (changeName.equals("lookAndFeel")) { + installLookAndFeelDefaults(); + } + } + + /** + * Installs UIDefaults for Help components and installs "lookAndFeel" + * property change listener. + */ + static void installUIDefaults() { + UIDefaults table = UIManager.getLookAndFeelDefaults(); + if (uiDefaults != table) { + uiDefaults = table; + UIManager.removePropertyChangeListener(myLAFListener); + installLookAndFeelDefaults(); + UIManager.addPropertyChangeListener(myLAFListener); + } + } + + /** + * Set the default ContentViewerUI + * + * param cvUI - full class name of the content viewer UI + */ + public static void setContentViewerUI(String cvUI) { + if (cvUI != null) { + try { + Class c = Class.forName(cvUI); + // an error will be thrown if the class doesn't exist + contentViewerUI = cvUI; + } catch (Throwable e) { + System.out.println("ContentViewerClass " + cvUI + " doesn't exist"); + } + } + } + + /** + * Adds look and feel constants for Help components into UIDefaults table. + */ + static void installLookAndFeelDefaults() { + LookAndFeel lnf = UIManager.getLookAndFeel(); + UIDefaults table = UIManager.getLookAndFeelDefaults(); + + debug("installLookAndFeelDefaults - " + lnf); + + if ((lnf != null) && (table != null)) { + if (lnf.getID().equals("Motif")) { + installMotifDefaults(table); + } else if (lnf.getID().equals("Windows")) { + installWindowsDefaults(table); + } else if (lnf.getID().equals("GTK")) { + installGTKDefaults(table); + } else { + // Default + installMetalDefaults(table); + } + } + debug ("verifing UIDefaults; HelpUI=" + table.getString("HelpUI")); + + } + + /** + * Dynamically invoke a cursor factory to get a cursor. + */ + private static Object createIcon(String factoryName, + String method) { + ClassLoader loader = HelpUtilities.class.getClassLoader(); + try { + Class types[] = new Class[0]; + Object args[] = new Object[0]; + Class klass; + + if (loader == null) { + klass = Class.forName(factoryName); + } else { + klass = loader.loadClass(factoryName); + } + Method m = klass.getMethod(method, types); + Object back = m.invoke(null, args); + return back; + } catch (Exception ex) { + return null; + } + } + + static Object basicOnItemCursor = new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return createIcon("javax.help.plaf.basic.BasicCursorFactory", + "getOnItemCursor"); + } + }; + + static Object basicDnDCursor = new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return createIcon("javax.help.plaf.basic.BasicCursorFactory", + "getDnDCursor"); + } + }; + + static Object gtkOnItemCursor = new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return createIcon("javax.help.plaf.gtk.GTKCursorFactory", + "getOnItemCursor"); + } + }; + + static Object gtkDnDCursor = new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return createIcon("javax.help.plaf.gtk.GTKCursorFactory", + "getDnDCursor"); + } + }; + + + /* + * Utility method that creates a UIDefaults.LazyValue that creates + * an ImageIcon for the specified <code>image</code> + * filename. I tried to use the similar LookAndFeel.makeIcon() method but it + * creates IconUIResource instaed of Icon Image and buttons cannot then produce + * disabled icon from it. + */ + static private Object makeBasicIcon(final String image) { + return new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return SwingHelpUtilities.getImageIcon(javax.help.plaf.basic.BasicHelpUI.class, image); + } + }; + } + + /** + * The basic LAF does what we need. + */ + static private void installBasicDefaults(UIDefaults table) { + + String basicPackageName = "javax.help.plaf.basic."; + + String basicContentViewerUI = basicPackageName + "BasicContentViewerUI"; + if (contentViewerUI != null) { + basicContentViewerUI = contentViewerUI; + } + + Object[] uiDefaults = { + "HelpUI", basicPackageName + "BasicHelpUI", + "HelpTOCNavigatorUI", basicPackageName + "BasicTOCNavigatorUI", + "HelpIndexNavigatorUI", basicPackageName + "BasicIndexNavigatorUI", + "HelpSearchNavigatorUI", basicPackageName + "BasicSearchNavigatorUI", + "HelpGlossaryNavigatorUI", basicPackageName + "BasicGlossaryNavigatorUI", + "HelpFavoritesNavigatorUI", basicPackageName + "BasicFavoritesNavigatorUI", + "HelpContentViewerUI", basicContentViewerUI, + "HelpDnDCursor", basicDnDCursor, + "HelpOnItemCursor", basicOnItemCursor, + "BackAction.icon", makeBasicIcon("images/Back.gif"), + "ForwardAction.icon", makeBasicIcon("images/Forward.gif"), + "PrintAction.icon", makeBasicIcon("images/Print.gif"), + "PrintSetupAction.icon", makeBasicIcon("images/PrintSetup.gif"), + "ReloadAction.icon", makeBasicIcon("images/Reload.gif"), + "FavoritesAction.icon", makeBasicIcon("images/Favorites.gif"), + "HomeAction.icon", makeBasicIcon("images/Home.gif"), + "FavoritesNav.icon", makeBasicIcon("images/FavoritesNav.gif"), + "IndexNav.icon", makeBasicIcon("images/IndexNav.gif"), + "TOCNav.icon", makeBasicIcon("images/TOCNav.gif"), + "SearchNav.icon", makeBasicIcon("images/SearchNav.gif"), + "GlossaryNav.icon", makeBasicIcon("images/GlossaryNav.gif"), + "HistoryNav.icon", makeBasicIcon("images/HistoryNav.gif"), + "SearchLow.icon", makeBasicIcon("images/SearchLow.gif"), + "SearchMedLow.icon", makeBasicIcon("images/SearchMedLow.gif"), + "SearchMed.icon", makeBasicIcon("images/SearchMed.gif"), + "SearchMedHigh.icon", makeBasicIcon("images/SearchMedHigh.gif"), + "SearchHigh.icon", makeBasicIcon("images/SearchHigh.gif") + }; + + table.putDefaults(uiDefaults); + } + + /** + * If we had any LAF-specific classes, they would be invoked from here. + */ + static private void installMetalDefaults(UIDefaults table) { + installBasicDefaults(table); + } + + static private void installWindowsDefaults(UIDefaults table) { + installBasicDefaults(table); + } + + static private void installMotifDefaults(UIDefaults table) { + installBasicDefaults(table); + } + + /* + * Utility method that creates a UIDefaults.LazyValue that creates + * an ImageIcon for the specified <code>image</code> + * filename. I tried to use the similar LookAndFeel.makeIcon() method but it + * creates IconUIResource instaed of Icon Image and buttons cannot then produce + * disabled icon from it. + */ + static private Object makeGTKIcon(final String image) { + return new UIDefaults.LazyValue() { + public Object createValue(UIDefaults table) { + return SwingHelpUtilities.getImageIcon(javax.help.plaf.gtk.GTKCursorFactory.class, + image); + } + }; + } + + static private void installGTKDefaults(UIDefaults table) { + String basicPackageName = "javax.help.plaf.basic."; + String gtkPackageName = "javax.help.plaf.gtk."; + + String basicContentViewerUI = basicPackageName + "BasicContentViewerUI"; + if (contentViewerUI != null) { + basicContentViewerUI = contentViewerUI; + } + + Object[] uiDefaults = { + "HelpUI", basicPackageName + "BasicHelpUI", + "HelpTOCNavigatorUI", basicPackageName + "BasicTOCNavigatorUI", + "HelpIndexNavigatorUI", basicPackageName + "BasicIndexNavigatorUI", + "HelpSearchNavigatorUI", basicPackageName + "BasicSearchNavigatorUI", + "HelpGlossaryNavigatorUI", basicPackageName + "BasicGlossaryNavigatorUI", + "HelpFavoritesNavigatorUI", basicPackageName + "BasicFavoritesNavigatorUI", + "HelpContentViewerUI", basicContentViewerUI, + "HelpDnDCursor", gtkDnDCursor, + "HelpOnItemCursor", gtkOnItemCursor, + "BackAction.icon", makeGTKIcon("images/Back.png"), + "ForwardAction.icon", makeGTKIcon("images/Forward.png"), + "PrintAction.icon", makeGTKIcon("images/Print.png"), + "PrintSetupAction.icon", makeGTKIcon("images/PrintSetup.png"), + "ReloadAction.icon", makeGTKIcon("images/Reload.png"), + "FavoritesAction.icon", makeGTKIcon("images/Favorites.png"), + "HomeAction.icon", makeGTKIcon("images/Home.png"), + "FavoritesNav.icon", makeGTKIcon("images/FavoritesNav.png"), + "IndexNav.icon", makeGTKIcon("images/IndexNav.gif"), + "TOCNav.icon", makeGTKIcon("images/TOCNav.gif"), + "SearchNav.icon", makeGTKIcon("images/SearchNav.gif"), + "GlossaryNav.icon", makeGTKIcon("images/GlossaryNav.gif"), + "HistoryNav.icon", makeGTKIcon("images/HistoryNav.gif"), + "SearchLow.icon", makeGTKIcon("images/SearchLow.gif"), + "SearchMedLow.icon", makeGTKIcon("images/SearchMedLow.gif"), + "SearchMed.icon", makeGTKIcon("images/SearchMed.gif"), + "SearchMedHigh.icon", makeGTKIcon("images/SearchMedHigh.gif"), + "SearchHigh.icon", makeGTKIcon("images/SearchHigh.gif") + }; + + table.putDefaults(uiDefaults); + } + + /** + * Create an Icon from a given resource. + * + * This works uisng getResourceAsStream() because several browsers do not + * correctly implement getResource(). + * + * This method may change... + */ + + public static ImageIcon getImageIcon(final Class baseClass, + final String image) { + if (image == null) { + return null; + } + final byte[][] buffer = new byte[1][]; + try { + InputStream resource = baseClass.getResourceAsStream(image); + if (resource == null) { + return null; + } + BufferedInputStream in = new BufferedInputStream(resource); + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + buffer[0] = new byte[1024]; + int n; + while ((n = in.read(buffer[0])) > 0) { + out.write(buffer[0], 0, n); + } + in.close(); + out.flush(); + buffer[0] = out.toByteArray(); + } catch (IOException ioe) { + System.err.println(ioe.toString()); + return null; + } + if (buffer[0] == null) { + System.err.println(baseClass.getName() + "/" + + image + " not found."); + return null; + } + if (buffer[0].length == 0) { + System.err.println("warning: " + image + + " is zero-length"); + return null; + } + + return new ImageIcon(buffer[0]); + } + + static void addPropertyChangeListener(Object object, PropertyChangeListener listener) { + try { + Class types[] = { PropertyChangeListener.class }; + Object args[] = { listener }; + object.getClass().getMethod("addPropertyChangeListener", types).invoke(object, args); + } catch (Exception ex) { + } + } + + /** + * Debug support + */ + + private static final boolean debug = false; + private static void debug(Object msg1) { + if (debug) { + System.err.println("GUIHelpUtilities: "+msg1); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java b/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java new file mode 100644 index 0000000000000000000000000000000000000000..e478dc854424989f98aa5bfef029166d748cdb11 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java @@ -0,0 +1,92 @@ +/* + * @(#)TOCItem.java 1.17 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.help.Map.ID; +import java.util.Locale; + +/** + * A class for individual TOC items + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-llopart + * @(#)TOCItem.java 1.13 01/29/99 + */ + +public class TOCItem extends TreeItem { + private ID imageID; + + /** + * Creates a TOCItem. + * + * @param id ID for the item. A null ID is valid. + * @param image The ID for image to be displayed for this item. A null + * image is valid. + * @param hs The HelpSet scoping this item. In almost all cases + * this is the same as the HelpSet of the id field. A null ID is valid. + * @param lang The locale for this item. A null locale indicates the + * default locale. + */ + public TOCItem(ID id, ID imageID, HelpSet hs, Locale locale) { + super(id, hs, locale); + this.imageID = imageID; + } + + /** + * Creates a TOCItem with a default HelpSet based on its ID. + * + * @param id ID for the item. The ID can be null. + * @param image The image to be displayed for this item. + * @param lang The locale for this item + */ + public TOCItem(ID id, ID imageID, Locale locale){ + super(id, locale); + HelpSet hs = null; + if (id != null) { + setHelpSet(id.hs); + } + this.imageID = imageID; + } + + /** + * Creates a default TOCItem. + */ + + public TOCItem() { + super(null, null, null); + this.imageID = null; + } + + /** + * Returns the image for this TOCItem. + */ + public ID getImageID() { + return imageID; + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/TOCView.java b/jhMaster/JavaHelp/src/new/javax/help/TOCView.java new file mode 100644 index 0000000000000000000000000000000000000000..f61b5677483dd3ad66973a58a59a29f8694df25e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TOCView.java @@ -0,0 +1,744 @@ +/* + * @(#)TOCView.java 1.37 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.awt.Component; +import java.net.URL; +import java.net.URLConnection; +import java.io.Reader; +import java.io.IOException; +import java.util.Stack; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; +import java.util.Enumeration; +import javax.help.Map.ID; +import javax.swing.tree.TreeNode; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.sun.java.help.impl.*; + +/** + * Navigational View information for a TOC. + * This includes information about how to parse the data format. + * + * @author Eduardo Pelegri-Llopart + * @version 1.18 03/10/99 + */ + +public class TOCView extends NavigatorView { + + /** + * PublicID (known to this XML processor) to the DTD for version 1.0 of the TOC. + */ + public static final String publicIDString = + "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN"; + + /** + * PublicID (known to this XML processor) to the DTD for version 2.0 of the TOC. + */ + public static final String publicIDString_V2 = + "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 2.0//EN"; + + + private ID categoryOpenImageID = null; + private ID categoryClosedImageID = null; + private ID topicImageID = null; + + /** + * Constructs a TOC VIew with some given data. Locale defaults to that + * of the HelpSet. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param params A hashtable that provides different key/values for this type. + */ + public TOCView(HelpSet hs, + String name, + String label, + Hashtable params) { + this(hs, name, label, hs.getLocale(), params); + } + + /** + * Constructs a TOC VIew with some given data. + * + * @param hs The HelpSet that provides context information. + * @param name The name of the View. + * @param label The label (to show the user) of the View. + * @param locale The default locale to interpret the data in this TOC. + * @param params A hashtable that provides different key/values for this type. + */ + public TOCView(HelpSet hs, + String name, + String label, + Locale locale, + Hashtable params) { + super(hs, name, label, locale, params); + } + + /** + * Creates a navigator for a given model. + */ + public Component createNavigator(HelpModel model) { + return new JHelpTOCNavigator(this, model); + } + + /** + * Get the TOC navigators mergeType. Overrides getMergeType in NavigatorView + */ + public String getMergeType() { + String mergeType = super.getMergeType(); + if (mergeType == null) { + return "javax.help.AppendMerge"; + } + return mergeType; + } + + // turn this on if you want messages on failures + private static boolean warningOfFailures = false; + + /** + * Public method that gets a DefaultMutableTreeNode representing the information in this + * view instance. + * + * The default implementation parses the data in the URL but a subclass may + * override this method and provide a different implemenation--for example, + * by creating the tree programatically. + */ + public DefaultMutableTreeNode getDataAsTree() { + HelpSet hs = getHelpSet(); + Hashtable params = getParameters(); + URL url; + + if (params == null || + (params != null && !params.containsKey("data"))) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(); + return node; + } + + try { + url = new URL(hs.getHelpSetURL(), (String) params.get("data")); + } catch (Exception ex) { + throw new Error("Trouble getting URL to TOC data; "+ex); + } + + return parse(url, hs, hs.getLocale(), new DefaultTOCFactory(), this); + } + + /** + * Public method for parsing a TOC in a URL. + * Returns a DefaultMutableTreeNode whose children are the DefaultMutableTreeNode + * corresponding to the tocitem's in the TOC. + * The factory is invoked to create the TreeItems that are included in the + * DefaultMutableTreeNode as user data. + * The factory is also invoked with start data, and whenever any parsing error + * is found. + * + * @param url Where the TOC lives. If null, returns a null value. + * @param hs The HelpSet context for this TOC. Null hs is ignored. + * @param locale The default locale to interpret the data in this TOC. Null locale + * is treated as the default locale. + * @param factory A factory instance used to create the TOCItems. + * @return A TreeNode that represents the TOC. Returns null if parsing errors were + * encountered. + */ + public static DefaultMutableTreeNode parse(URL url, + HelpSet hs, + Locale locale, + TreeItemFactory factory) { + return parse(url, hs, locale, factory, null); + } + + /** + * Public method for parsing a TOC in a URL. + * Returns a DefaultMutableTreeNode whose children are the DefaultMutableTreeNode + * corresponding to the tocitem's in the TOC. + * The factory is invoked to create the TreeItems that are included in the + * DefaultMutableTreeNode as user data. + * The factory is also invoked with start data, and whenever any parsing error + * is found. + * + * @param url Where the TOC lives. If null, returns a null value. + * @param hs The HelpSet context for this TOC. Null hs is ignored. + * @param locale The default locale to interpret the data in this TOC. Null locale + * is treated as the default locale. + * @param factory A factory instance used to create the TOCItems. + * @param view The TOCView instance. May be null + * @return A TreeNode that represents the TOC. Returns null if parsing errors were + * encountered. + */ + public static DefaultMutableTreeNode parse(URL url, + HelpSet hs, + Locale locale, + TreeItemFactory factory, + TOCView view) { + Reader src; + DefaultMutableTreeNode node = null; + try { + URLConnection uc = url.openConnection(); + src = XmlReader.createReader(uc); + factory.parsingStarted(url); + TOCParser tocParser = new TOCParser(factory, view); + node = (tocParser.parse(src, hs, locale)); + src.close(); + } catch (Exception e) { + factory.reportMessage("Exception caught while parsing "+url+ + e.toString(), false); + } + return factory.parsingEnded(node); + } + + /** + * Set the default category open image ID. + * + * param String ID of catagory open image + */ + public void setCategoryOpenImageID(String imageID) { + if (imageID == null) { + return; + } + try { + categoryOpenImageID = ID.create(imageID, getHelpSet()); + } catch (BadIDException bex) { + } + } + + /** + * Returns the default category open image ID. + * + * return ID the ID for the category open image, if the category open image + * is null return the category closed image if it is defined, + * otherwise return null + */ + public ID getCategoryOpenImageID() { + if (categoryOpenImageID == null) { + // if categoryOpenImageID is null return the categoryClosedImageID + // it might be null but that is ok. + return categoryClosedImageID; + } + return categoryOpenImageID; + } + + /** + * Set the default category closed image ID. + * + * param String ID of catagory closed image + */ + public void setCategoryClosedImageID(String imageID) { + if (imageID == null) { + return; + } + try { + categoryClosedImageID = ID.create(imageID, getHelpSet()); + } catch (BadIDException bex) { + } + } + + /** + * Returns the default category closed image ID. + * + * return ID the ID for the category closed image or null if not defined + */ + public ID getCategoryClosedImageID() { + return categoryClosedImageID; + } + + /** + * Set the topic image ID + * + * param String ID for the topic image + */ + public void setTopicImageID(String imageID) { + if (imageID == null) { + topicImageID = null; + return; + } + try { + topicImageID = ID.create(imageID, getHelpSet()); + } catch (BadIDException bex) { + } + } + + /** + * Returns the topic image ID. + * + * return String the ID for the topic image or null if not defined + */ + public ID getTopicImageID() { + return topicImageID; + } + + /** + * A default TreeItemFactory that can be used to parse TOC items as used + * by this navigator. + */ + public static class DefaultTOCFactory implements TreeItemFactory { + private Vector messages = new Vector(); + private URL source; + private boolean validParse = true; + + /** + * Starts parsing. + */ + public void parsingStarted(URL source) { + if (source == null) { + throw new NullPointerException("source"); + } + this.source = source; + } + + /** + * Processes a DOCTYPE. + */ + public void processDOCTYPE(String root, + String publicID, + String systemID) { + if (publicID == null || + (publicID.compareTo(publicIDString) != 0 && + publicID.compareTo(publicIDString_V2) != 0)) { + reportMessage(HelpUtilities.getText("toc.wrongPublicID", publicID), false); + } + } + + /** + * Finds a PI--ignore it. + */ + public void processPI(HelpSet hs, String target, String data) { + } + + /** + * Create an TOCItem with the given data. + * @param tagName The TOC type to create. + * Valid types are "tocitem". Null or invalid types will throw an + * IllegalArgumentException + * @param atts Attributes of the Item. Valid attributes are "target", + * "image", and "text". A null atts is valid and means no attributes + * @param hs HelpSet this item was created under. + * @param locale Locale of this item. A null locale is valid. + * @returns A fully constructed TreeItem. + * @throws IllegalArgumentExcetpion if tagname is null or invalid. + */ + public TreeItem createItem(String tagName, + Hashtable atts, + HelpSet hs, + Locale locale) { + if (tagName == null || !tagName.equals("tocitem")) { + throw new IllegalArgumentException("tagName"); + } + TOCItem item = null; + String id = null; + String imageID = null; + String text = null; + String mergeType = null; + String expand = null; + String presentation = null; + String presentationName = null; + + if (atts != null) { + id = (String) atts.get("target"); + imageID = (String) atts.get("image"); + text = (String) atts.get("text"); + mergeType = (String) atts.get("mergetype"); + expand = (String) atts.get("expand"); + presentation = (String) atts.get("presentationtype"); + presentationName = (String) atts.get("presentationname"); + } + + Map.ID mapID = null; + Map.ID imageMapID = null; + try { + mapID = ID.create(id, hs); + } catch (BadIDException bex1) { + } + try { + imageMapID = ID.create(imageID, hs); + } catch (BadIDException bex2) { + } + item = new TOCItem(mapID, imageMapID, hs, locale); + if (text != null) { + item.setName(text); + } + + if (mergeType != null){ + item.setMergeType(mergeType); + } + + if (expand != null) { + if (expand.equals("true")) { + item.setExpansionType(TreeItem.EXPAND); + } else if (expand.equals("false")) { + item.setExpansionType(TreeItem.COLLAPSE); + } + } + + if (presentation != null){ + item.setPresentation(presentation); + } + + if (presentationName != null){ + item.setPresentationName(presentationName); + } + return item; + } + + /** + * Creates a default TOCItem. + */ + public TreeItem createItem() { + return new TOCItem(); + } + + /** + * Reports an error message. + */ + public void reportMessage(String msg, boolean validParse) { + messages.addElement(msg); + this.validParse = this.validParse && validParse; + } + + /** + * Lists all the error messages. + */ + public Enumeration listMessages() { + return messages.elements(); + } + + /** + * Ends parsing. Last chance to do something + * to the node. + * @param node The DefaultMutableTreeNode that has been built during the + * the parsing. If <tt>node</tt> is null or there were parsing errors a null + * is returned. + * @returns A valid DefaultMutableTreeNode if the parsing succeded or null + * if it failed. + */ + public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) { + DefaultMutableTreeNode back = node; + if (! validParse) { + // A parse with problems... + back = null; + System.err.println("Parsing failed for "+source); + for (Enumeration e = messages.elements(); + e.hasMoreElements();) { + String msg = (String) e.nextElement(); + // need to think about this one... + System.err.println(msg); + } + } + return back; + } + } + + + /** + * Inner class for parsing a TOC stream. + * + * WARNING!! This class is an interim solution until JavaHelp moves to a + * real XML parser. This is not a public class. Clients should only use + * the parse method in the enclosing class. + */ + private static class TOCParser implements ParserListener { + private HelpSet currentParseHS; // HelpSet we are parsing into + private Stack nodeStack; // to track the parsing + private Stack itemStack; + private boolean startedtoc; + private Stack tagStack; + private Locale defaultLocale; + private Locale lastLocale; + private TreeItemFactory factory; + private TOCView tocView; + + + /** + * Creates a TOC Parser using a factory instance to create the item nodes. + * + * @param factory The ItemTreeFactory instance to use when a node + * has been recognized. + */ + + TOCParser(TreeItemFactory factory, TOCView tocView) { + this.factory = factory; + this.tocView = tocView; + } + + /** + * Parses a reader into a DefaultMutableTreeNode. + * Only one of these at a time. + */ + synchronized DefaultMutableTreeNode parse(Reader src, + HelpSet context, + Locale locale) + throws IOException + { + nodeStack = new Stack(); + tagStack = new Stack(); + itemStack = new Stack(); + + if (locale == null) { + defaultLocale = Locale.getDefault(); + } else { + defaultLocale = locale; + } + lastLocale = defaultLocale; + + DefaultMutableTreeNode node = new DefaultMutableTreeNode(); + nodeStack.push(node); + + currentParseHS = context; + + Parser parser = new Parser(src); // the XML parser instance + parser.addParserListener(this); + parser.parse(); + return node; + } + + /** + * A Tag was parsed. + */ + public void tagFound(ParserEvent e) { + Locale locale = null; + Tag tag = e.getTag(); + debug("TagFound: "+tag.name); + TagProperties attr = tag.atts; + + if (attr != null) { + String lang = attr.getProperty("xml:lang"); + locale = HelpUtilities.localeFromLang(lang); + } + if (locale == null) { + locale = lastLocale; + } + + if (tag.name.equals("tocitem")) { + if (!startedtoc) { + factory.reportMessage(HelpUtilities.getText("toc.invalidTOCFormat"), false); + } + if (tag.isEnd && !tag.isEmpty) { + nodeStack.pop(); + itemStack.pop(); + removeTag(tag); + return; + } + + + TOCItem item; + try { + Hashtable t = null; + if (attr != null) { + t = attr.getHashtable(); + } + item = (TOCItem) factory.createItem("tocitem", + t, + currentParseHS, + locale); + } catch (Exception ex) { + if (warningOfFailures) { + String id = null; + String imageID = null; + if (attr != null) { + id = attr.getProperty("target"); + imageID = attr.getProperty("image"); + } + System.err.println("Failure in IndexItem Creation; "); + System.err.println(" id: "+id); + System.err.println(" hs: "+currentParseHS); + } + item = (TOCItem) factory.createItem(); + } + + if (!itemStack.empty()) { + TOCItem parent = (TOCItem)itemStack.peek(); + if (item.getExpansionType() == TreeItem.DEFAULT_EXPANSION && + parent != null && + parent.getExpansionType() != TreeItem.DEFAULT_EXPANSION) { + item.setExpansionType(parent.getExpansionType()); + } + } + DefaultMutableTreeNode node = new DefaultMutableTreeNode(item); + DefaultMutableTreeNode parent = + (DefaultMutableTreeNode) nodeStack.peek(); + parent.add(node); + if (! tag.isEmpty) { + itemStack.push(item); + nodeStack.push(node); + addTag(tag, locale); + } + } else if (tag.name.equals("toc")) { + debug("attr: "+attr); + if (!tag.isEnd) { + if (attr != null) { + String version = attr.getProperty("version"); + if (version != null && + (version.compareTo("1.0") != 0 && + version.compareTo("2.0") != 0)) { + factory.reportMessage(HelpUtilities.getText("toc.unknownVersion",version), false); + } + if (tocView != null) { + tocView.setCategoryOpenImageID(attr.getProperty("categoryopenimage")); + tocView.setCategoryClosedImageID(attr.getProperty("categoryclosedimage")); + tocView.setTopicImageID(attr.getProperty("topicimage")); + } + } + if (startedtoc) { + factory.reportMessage(HelpUtilities.getText("toc.invalidTOCFormat"), false); + } + startedtoc = true; + addTag(tag, locale); + } else { + if (startedtoc) { + startedtoc = false; + } + removeTag(tag); + } + return; + } + } + + /** + * A PI was parsed. This method is not intended for general use. + */ + public void piFound(ParserEvent e) { + // ignore + } + + /** + * A DOCTYPE was parsed. This method is not intended for general use. + */ + public void doctypeFound(ParserEvent e) { + // ignore for now + } + + /** + * A continous block of text was parsed. + */ + public void textFound(ParserEvent e) { + debug("TextFound: "+e.getText().trim()); + + // Ignore text if there isn't a tag + if (tagStack.empty()) { + return; + } + LangElement le = (LangElement) tagStack.peek(); + Tag tag = (Tag) le.getTag(); + if (tag.name.equals("tocitem")) { + TOCItem item = (TOCItem) itemStack.peek(); + String oldName = item.getName(); + if (oldName == null) { + item.setName(e.getText().trim()); + } else { + item.setName(oldName.concat(e.getText()).trim()); + } + } + } + + // The remaing events from Parser are ignored + public void commentFound(ParserEvent e) {} + + public void errorFound(ParserEvent e){ + factory.reportMessage(e.getText(), false); + } + + /** + * Tracks tags and their locale attributes. + */ + protected void addTag(Tag tag, Locale locale) { + LangElement el = new LangElement(tag, locale); + tagStack.push(el); + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It is impossible for locale to be null + if (lastLocale == null) { + lastLocale = locale; + return; + } + if (locale == null) { + lastLocale = locale; + return; + } + if (! lastLocale.equals(locale)) { + lastLocale = locale; + } + } + + /** + * Removes a tag from the tagStack. The tagStack is + * used to track tags and locales. + */ + protected void removeTag(Tag tag) { + LangElement el; + String name = tag.name; + Locale newLocale = null; + + for (;;) { + if (tagStack.empty()) + break; + el = (LangElement) tagStack.pop(); + if (el.getTag().name.equals(name)) { + if (tagStack.empty()) { + newLocale = defaultLocale; + } else { + el = (LangElement) tagStack.peek(); + newLocale = el.getLocale(); + } + break; + } + } + // It's possible for lastLocale not be specified ergo null. + // If it is then set lastLocale to null even if locale is null. + // It also possible for locale to be null so if lastLocale is set + // then reset lastLocale to null; + // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale + if (lastLocale == null) { + lastLocale = newLocale; + return; + } + if (newLocale == null) { + lastLocale = newLocale; + return; + } + if (! lastLocale.equals(newLocale)) { + lastLocale = newLocale; + } + } + + } + + /** + * Debugging code + */ + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("TOCView: "+msg); + } + } + + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java new file mode 100644 index 0000000000000000000000000000000000000000..30f3410b1be80c4aa9e119623048a3f56662d1de --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java @@ -0,0 +1,109 @@ +/* + * @(#)TextHelpModel.java 1.7 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.help.event.*; + +/** + * The interface to a HelpModel that manipulates text. + * + * It provides additional text operations. + */ + +public interface TextHelpModel extends HelpModel { + /** + * Gets the title of the document. + * + * @return The title of document visited. + */ + public String getDocumentTitle(); + + /** + * Sets the title of the document. + * A property change event is generated. + * + * @param title The title currently shown. + */ + public void setDocumentTitle(String title); + + + /** + * Removes all highlights on the current document. + */ + public void removeAllHighlights(); + + /** + * Adds a highlight to a range of positions in a document. + * + * @param pos0 Start position. + * @param pos1 End position. + */ + public void addHighlight(int pos0, int pos1); + + /** + * Sets the highlights to be a range of positions in a document. + * + * @param h The array of highlight objects. + */ + public void setHighlights(Highlight[] h); + + /** + * Gets all highlights. + */ + public Highlight[] getHighlights(); + + /** + * Adds a listener for a TextHelpModel. + */ + public void addTextHelpModelListener(TextHelpModelListener l); + + /** + * Removes a listener for a TextHelpModel. + */ + public void removeTextHelpModelListener(TextHelpModelListener l); + + /** + * This is very similar to javax.swing.text.Highlighter.Highlight + * except that it does not use the notion of HighlightPainter. + */ + public interface Highlight { + /** + * Gets the starting model offset of the highlight. + * + * @return The starting offset >= 0. + */ + public int getStartOffset(); + + /** + * Gets the ending model offset of the highlight. + * + * @return The ending offset >= 0. + */ + public int getEndOffset(); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java b/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java new file mode 100644 index 0000000000000000000000000000000000000000..c5c0eea4f9e86395f3c250b46a7da84a05b7bcbf --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java @@ -0,0 +1,257 @@ +/* + * @(#)TreeItem.java 1.28 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.help.Map.ID; +import java.util.Locale; +import java.net.URL; +import java.io.Serializable; +import java.io.IOException; + +/** + * The base items known to TOC, Index and Favorites Navigators. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Richard Gregor + * @version 1.28 10/30/06 + */ + +public class TreeItem implements Serializable +{ + + /** + * A state of expansion determined by the view + */ + public static final int DEFAULT_EXPANSION = -1; + + /** + * Show the children of the node collapsed in the view + */ + public static final int COLLAPSE = 0; + + /** + * Show the children of the node expanded in the view + */ + public static final int EXPAND = 1; + + private String name; + private ID id; + protected Locale locale; + private String mergeType; + private int expand = DEFAULT_EXPANSION; + private String presentation; + private String presentationName; + private HelpSet hs; + + /** + * Create an TreeItem. + * + * @param id ID for the item. The ID can be null. + * @param hs A HelpSet scoping this item. + * @param locale The locale for this item + */ + public TreeItem(ID id, HelpSet hs, Locale locale) { + this.id = id; + this.hs = hs; + this.locale = locale; + } + + /** + * Creates a TreeItem. + * + * @param id ID for the item. Null is a valid ID. + * @param The lang for this item. A null is valid and indicates the default + * locale. + */ + public TreeItem(ID id, Locale locale){ + this (id, null, locale); + } + /** + * Creates a TreeItem. + * + * @param name The name for the item. + */ + public TreeItem(String name){ + this(null,null, null); + setName(name); + } + + /** + * Creates an empty TreeItem. + */ + public TreeItem(){ + this(null,null); + } + /** + * Sets the name of the item. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns the name of the item. + */ + public String getName() { + return name; + } + + /** + * Set the ID for the item. + */ + public void setID (ID id) { + this.id = id; + } + + /** + * Returns the ID for the item. + */ + public ID getID() { + return id; + } + + /** + * Returns the URL for the item. + */ + public URL getURL() { + try { + return id.getURL(); + } catch (Exception e) { + return null; + } + } + + /** + * Set the HelpSet for this TreeItem. + */ + public void setHelpSet(HelpSet hs) { + this.hs = hs; + } + + /** + * Returns the HelpSet scoping this IndexItem. Will return the ID HelpSet + * if one exists. Null otherwise + */ + public HelpSet getHelpSet() { + return hs; + } + + /** + * Returns the locale for the item. + */ + public Locale getLocale() { + return locale; + } + + /** + * Sets the merge type + */ + public void setMergeType(String mergeType){ + this.mergeType = mergeType; + } + + /** + * Returns the merge type for the item + */ + public String getMergeType(){ + return mergeType; + } + + /** + * Sets the expansion type + * @throws IllegalArgumentException if not a valid type + */ + public void setExpansionType(int type) { + if (type < DEFAULT_EXPANSION || type > EXPAND) { + throw new IllegalArgumentException("Invalid expansion type"); + } + expand = type; + } + + /** + * Returns the exansion type + */ + public int getExpansionType() { + return expand; + } + + /** + * Sets the presentation + * @see Presentation + */ + public void setPresentation(String presentation) { + this.presentation = presentation; + } + + /** + * Returns the presentation + * @see Presentation + */ + public String getPresentation() { + return presentation; + } + + /** + * Sets the presentation name + * @see Presentation + */ + public void setPresentationName(String presentationName) { + this.presentationName = presentationName; + } + + /** + * Returns the presentation name + * @see Presentation + */ + public String getPresentationName() { + return presentationName; + } + + /** + * Returns a String used when displaying the object. + * Used by CellRenderers. + * + * @see TOCCellRenderer + */ + public String toString() { + return (id+"("+name+")"); + } + + // for serialization + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + //ignore so that FavoritesItem will work + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + //ignore so that FavoritesItem will work + } + + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java b/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..b2e2b6f65d2960fbe23687d3877bf2d203d31bd5 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java @@ -0,0 +1,111 @@ +/* + * @(#)TreeItemFactory.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.util.Hashtable; +import java.util.Locale; +import java.util.Enumeration; +import java.net.URL; +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * A factory for creating TreeItems. This can be used to reuse the parsers. + * + * @author Eduardo Pelegri-Llopart + * @(#)TreeItemFactory.java 1.7 01/29/99 + */ + +public interface TreeItemFactory { + /** + * Starts parsing. + * + * @param source The URL of the document being parsed. + */ + public void parsingStarted(URL source); + + + /** + * Processes a DOCTYPE. + * + * @param root The root tag of the document. + * @param publicID PublicID from the DOCTYPE. + * @param systemID SystemID from the DOCTYPE. + */ + public void processDOCTYPE(String root, String publicID, String systemID); + + /** + * A Processing Instruction. + * + * @param target The target of the PI. + * @param data A String for the data in the PI. + */ + public void processPI(HelpSet hs, + String target, + String data); + + /** + * Creates a TreeItem from the given data. + * + * @param tagName The name of the tag (for example, treeItem, or tocItem) + * @param attributes A hashtable with all the attributes. Null is a valid value. + * @param hs A HelpSet that provides context. + * @param lang The locale. + * @return A TreeItem. + */ + public TreeItem createItem(String tagName, + Hashtable attributes, + HelpSet hs, + Locale locale); + + /** + * Creates a default TreeItem. + * + * @return A TreeItem + */ + public TreeItem createItem(); + + /** + * Reports a parsing error. + * + * @param msg The message to report. + * @param validParse Whether the result of the parse is still valid. + */ + public void reportMessage(String msg, boolean validParse); + + /** + * Lists all the error messages. + */ + public Enumeration listMessages(); + + /** + * Ends parsing. Last chance to do something + * to the node. Return null to be sure the result is discarded. + */ + public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node); +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/TryMap.java b/jhMaster/JavaHelp/src/new/javax/help/TryMap.java new file mode 100644 index 0000000000000000000000000000000000000000..c44feadf50d5646057fa36255fe937c5cb81000b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/TryMap.java @@ -0,0 +1,271 @@ +/* + * @(#)TryMap.java 1.19 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import java.net.URL; +import java.net.MalformedURLException; +import java.util.*; +import java.io.*; +import java.beans.*; +import javax.help.event.*; +import javax.help.Map.ID; + +/** + * A Map that can combine a number of other Maps in an + * efficient manner. + * + * Currently this is a brute-force implementation. + * + * @author Eduardo Pelegri-Llopart + * @version 1.11 03/10/99 + */ +public class TryMap implements Map, Serializable { + private Vector maps; // All the maps + + /** + * Creates an empty Map. + * This is useful for filtering and to add/remove to/from it. + */ + public TryMap() { + maps = new Vector(); + } + + /** + * Adds a map to a "filter" Map. + * Adding a composed map to another is equivalent to + * adding the entire Map individually. + * + * @param map The new Map to add. If Map is null it is not added. + */ + public void add(Map map) { + maps.addElement(map); + } + + /** + * Removes a Map from this "filter" Map. + * + * @param map The Map to add. + * @return Whether the Map is already present. If the Map is + * null or was not previously added, returns "false". + */ + public boolean remove(Map map) { + return maps.removeElement(map); + } + + /** + * Enumerates all the Maps in this TryMap. + * + * @return An enumeration of the Maps added. + */ + public Enumeration getMaps() { + return maps.elements(); + } + + /** + * Determines if the ID is valid (known to in the project file). + * + * @param id The ID to check. A null ID is a valid parameter + * @param hs The HelpSet against which to resolve the string. + * @return True if id is valid, false if not valid. + */ + + public boolean isValidID(String id, HelpSet hs) { + debug("isValidID "+id); + for (Enumeration e = maps.elements(); + e.hasMoreElements();) { + Map m = (Map) e.nextElement(); + if (m.isValidID(id, hs)) { + return true; + } + } + return false; + } + + /** + * Gets an enumeration of all the IDs in a Map. + * + * @param An enumeration of all the IDs in a Map. + */ + public Enumeration getAllIDs() { + return new TryEnumeration(maps.elements(), null); + } + + /** + * Gets the URL that corresponds to a given ID in the Map. + * + * @param id The ID for which to get the URL. If <tt>id</tt> is null it is + * treated as an unresolved ID and returns null. + * @return URL The matching URL. Null if this Map cannot resolve the ID. + * @exception MalformedURLException if the URL specification found is malformed + */ + public URL getURLFromID(ID id) throws MalformedURLException { + debug("getURLFromID("+id+")"); + URL back = null; + for (Enumeration e = maps.elements(); + e.hasMoreElements(); ) { + Map m = (Map) e.nextElement(); + back = m.getURLFromID(id); + if (back != null) { + return back; + } + } + return back; + } + + /** + * Determines if the URL corresponds to an ID in the Map. + * + * @param url The URL to check on. + * @return True if this is an ID, false otherwise. + */ + public boolean isID(URL url) { + for (Enumeration e = maps.elements(); + e.hasMoreElements(); ) { + Map m = (Map) e.nextElement(); + if (m.isID(url)) { + return true; + } + } + return false; + } + + + /** + * Determines the ID for this URL. + * + * @param url The URL to get the ID for. + * @return The ID (Map.ID), or null if URL is not an ID + */ + public ID getIDFromURL(URL url) { + debug("getIDFromURL("+url+")"); + ID back = null; + for (Enumeration e = maps.elements(); + e.hasMoreElements(); ) { + Map m = (Map) e.nextElement(); + back = m.getIDFromURL(url); + if (back != null) { + return back; + } + } + return null; + } + + /** + * Determines the ID that is "closest" to this URL (with a given anchor). + * + * @param url A URL + * @return The closest ID in this map to the given URL + */ + public ID getClosestID(URL url) { + ID back = null; + // See if there is an exact match + back = getIDFromURL(url); + if (back != null) { + return back; + } + + // for backwards compatability return a null if the URL is null + if (back == null && url == null) { + return null; + } + + // no exact match try removing the ref if there is one + String ref = url.getRef(); + if (ref != null) { + String urlString = url.toExternalForm(); + urlString = urlString.substring(0,urlString.lastIndexOf(ref)-1); + try { + URL newURL = new URL(urlString); + for (Enumeration e = maps.elements(); + e.hasMoreElements(); ) { + Map m = (Map) e.nextElement(); + back = m.getIDFromURL(newURL); + if (back != null) { + return back; + } + } + } catch (MalformedURLException mue) { + } + } + return null; + } + + /** + * Gets the the IDs related to this URL. + * + * @param URL The URL to compare the Map IDs to. + * @return Enumeration of IDs (Strings) + */ + public Enumeration getIDs(URL url) { + return new TryEnumeration(maps.elements(), url); + } + + private static class TryEnumeration implements Enumeration { + private Enumeration e; // the maps + private Enumeration k; // the IDs within a map + private URL url; + + public TryEnumeration(Enumeration e, URL url) { + this.e = e; + this.k = null; + this.url = url; + } + + public boolean hasMoreElements() { + while (k == null || + !k.hasMoreElements()) { + if (! e.hasMoreElements()) { + return false; + } + Map m = (Map) e.nextElement(); + if (url == null) { + k = m.getAllIDs(); + } else { + k = m.getIDs(url); + } + } + return k.hasMoreElements(); + } + + public Object nextElement() { + return k.nextElement(); // this is an ID + } + + } + + /** + * For printf debugging. + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("TryMap: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java b/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java new file mode 100644 index 0000000000000000000000000000000000000000..40d57322dd40f9318944411f1965f551ac8b738d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java @@ -0,0 +1,172 @@ +/* + * @(#)UniteAppendMerge.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import java.util.Locale; +/** + * Unite-append merge type + * + * @author Richard Gregor + * @version 1.8 10/30/06 + */ + +public class UniteAppendMerge extends Merge{ + + /** + * Constructs UniteAppendMerge + * + * @param master The master NavigatorView + * @param slave The slave NavigatorView + */ + public UniteAppendMerge(NavigatorView master, NavigatorView slave) { + super(master, slave); + } + + /** + * Processes unite-append merge + * + * @param node The master node + * @return Merged master node + */ + public TreeNode processMerge(TreeNode node) { + + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode) node; + + //if master and slave are the same object return the + // masterNode + if (masterNode.equals(slaveTopNode)) { + return masterNode; + } + + // If there are not children in slaveTopNode return the + // masterNode + if (slaveTopNode.getChildCount() == 0) { + return masterNode; + } + + mergeNodes(masterNode, slaveTopNode); + return masterNode; + } + + + /** + * Merge Nodes. Merge two nodes according to the UniteAppend merging rules + * + * @param masterNode The master node to merge with + * @param slaveNode The node to merge into the master + */ + public static void mergeNodes(TreeNode master, TreeNode slave) { + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master; + DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave; + debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode) + + " slave=" + MergeHelpUtilities.getNodeName(slaveNode)); + + + int masterCnt = masterNode.getChildCount(); + + // loop thru the slaves + while (slaveNode.getChildCount() > 0) { + DefaultMutableTreeNode slaveNodeChild = + (DefaultMutableTreeNode)slaveNode.getFirstChild(); + + //loop thru the master children + for (int m=0; m < masterCnt; m++) { + DefaultMutableTreeNode masterAtM = + (DefaultMutableTreeNode)masterNode.getChildAt(m); + + // see if the names are the same + if (MergeHelpUtilities.compareNames(masterAtM, + slaveNodeChild) == 0) { + // See if the IDs are the same + if (MergeHelpUtilities.haveEqualID(masterAtM, + slaveNodeChild)) { + // ID and name the same merge the slave node in + MergeHelpUtilities.mergeNodes("javax.help.UniteAppendMerge", + masterAtM, + slaveNodeChild); + // Need to remove the slaveNodeChild from the list + slaveNodeChild.removeFromParent(); + slaveNodeChild = null; + break; + } else { + // Names are the same but the ID are not + // Mark the nodes and add the slaveChild + MergeHelpUtilities.markNodes(masterAtM, + slaveNodeChild); + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge", + slaveNodeChild); + slaveNodeChild = null; + break; + } + } + } + if (slaveNodeChild != null) { + masterNode.add(slaveNodeChild); + MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge", + slaveNodeChild); + } + } + // There are no more children. + // Remove slaveNode from it's parent + slaveNode.removeFromParent(); + slaveNode = null; + } + + /** + * Merge Node Children. Merge the children of a node according to the + * UniteAppend merging. + * + * @param node The parent node from which the children are merged + */ + public static void mergeNodeChildren(TreeNode node) { + DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node; + debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode)); + + + // The rules are there are no rules. Nothing else needs to be done + // except for merging through the children + for (int i=0; i < masterNode.getChildCount(); i++) { + DefaultMutableTreeNode child = + (DefaultMutableTreeNode)masterNode.getChildAt(i); + if (!child.isLeaf()) { + MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge", child); + } + } + } + + private static boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.out.println("UniteAppendMerge :"+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java b/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java new file mode 100644 index 0000000000000000000000000000000000000000..d4e1decfdc9c01eb0f207d8c8d6b82ab872eae58 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java @@ -0,0 +1,49 @@ +/* + * @(#)UnsupportedOperationException.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +/** + * This is a platform-independent stand-in for the java.lang class + */ +public class UnsupportedOperationException extends RuntimeException { + + /** + * Constructs an UnsupportedOperationException with no detail message. + */ + public UnsupportedOperationException() { + } + + /** + * Constructs an UnsupportedOperationException with the specified + * detail message. A null message is valid. + */ + public UnsupportedOperationException(String message) { + super(message); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java b/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java new file mode 100644 index 0000000000000000000000000000000000000000..68a9294271aaa7212468a486eb8eaebf053fdec0 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java @@ -0,0 +1,1109 @@ +/* + * @(#)WindowPresentation.java 1.22 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.MenuComponent; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Enumeration; +import java.util.Locale; +import javax.swing.ImageIcon; + +/** + * Window Presentation is an abstract class providing a generic interface for + * the development of Window Presentations. Each implementation of + * Presentation will need to override the static method getPresentation + * according to it's own needs. + * + * WindowPresentation implements several generic methods required in all + * window presentations. Includes the ability to handle modal and non-modal + * activation of the help window. + * + * @author Roger D.Brinkley + * @version 1.22 10/30/06 + * @since 2.0 + * + * @see javax.help.HelpSet + * @see javax.help.JHelpNavigator + * @see javax.help.HelpVisitListener + */ + +public abstract class WindowPresentation extends Presentation { + + private HelpSet.Presentation hsPres=null; + private JFrame frame = null; + private JHelp jhelp = null; + private JDialog dialog = null; + private Window ownerWindow = null; + private boolean modallyActivated = false; + private Point location = null; + private String title = null; + private Image image = null; + private String currentView = null; + private boolean viewDisplayed = true; + private boolean toolbarDisplayed = true; + private boolean destroyOnExit = false; + private boolean titleFromDocument = false; + private WindowPropertyChangeListener propertyChangeListener = null; + private int screen = 0; + + public WindowPresentation (HelpSet hs) { + setHelpSet(hs); + } + + /** + * Set the Presentation attributes specific to WindowPresentations from a + * named presentation in a HelpSet. + * + * @params hsPres - the HelpSet.Presentation to retrieve the presentation + * information from + * + * @see HelpSet.Presentation + */ + public void setHelpSetPresentation (HelpSet.Presentation hsPres) { + debug("setHelpSetPrsentation"); + if (hsPres == null) { + return; + } + + // make sure the underlying presentation attributes are set + super.setHelpSetPresentation(hsPres); + + // get the presentation location + Point location = hsPres.getLocation(); + if (location != null) { + setLocation(location); + } + + // get the Title + String title = hsPres.getTitle(); + if (title != null) { + setTitle(title); + } + + // get the imageID + javax.help.Map.ID imageID = hsPres.getImageID(); + if (imageID != null) { + ImageIcon icon = null; + try { + javax.help.Map map = getHelpSet().getCombinedMap(); + URL url = map.getURLFromID(imageID); + icon = new ImageIcon(url); + image = icon.getImage(); + } catch (Exception e) { + } + } + + if (hsPres.isToolbar()) { + setToolbarDisplayed(true); + } + + if (hsPres.isViewDisplayed()) { + setViewDisplayed(true); + } + + this.hsPres = hsPres; + } + + /** + * Return the HelpSet.Presentation if one was set + * @returns HelpSet.Presentation - the HelpSet.Presentation used in this + * Presentation. + * + * @see HelpSet.Presentation + */ + public HelpSet.Presentation getHelpSetPresentation() { + return hsPres; + } + + /** + * Get the activation window. + * + * @returns Window - the activation window if activatated from a modal + * modal dialog, otherwise null. + */ + public Window getActivationWindow() { + debug("getActivationWindow"); + return ownerWindow; + } + + /** + * Set the activation window. If the window is an instance of a + * Dialog and the is modal, modallyActivated help is set to true and + * ownerDialog is set to the window. In all other instances + * modallyActivated is set to false and ownerDialog is set to null. + * @param window the activating window + */ + public void setActivationWindow(Window window) { + debug("setActivationWindow"); + if (window != null && window instanceof Dialog) { + Dialog tmpDialog = (Dialog) window; + if (tmpDialog.isModal()) { + ownerWindow = window; + modallyActivated = true; + } else { + ownerWindow = null; + modallyActivated = false; + } + } else { + ownerWindow = null; + modallyActivated = false; + } + } + + /** + * Set the activation window from given Component or MenuItem. It find Window component + * in the component tree from given Component or MenuItem end call + * <pre>setActivationWindow</pre>. + * @parem comp the activation Component or MenuItem + * @since 2.0 + * + * @see setActivationWindow + */ + public void setActivationObject(Object comp) { + debug("setActivationObject"); + while (comp instanceof MenuComponent) { + comp = ((MenuComponent)comp).getParent(); + } + + Window owner = null; + if (comp instanceof Frame) { + owner = (Window)comp; + } else if (comp instanceof Component) { + owner = SwingUtilities.windowForComponent((Component)comp); + } + + setActivationWindow(owner); + } + + /** + * Determines the current navigator. + */ + public String getCurrentView() { + debug("getCurrentView"); + // always use the current view if the jhelp exists. + if (jhelp != null) { + currentView = jhelp.getCurrentNavigator().getNavigatorName(); + } + return currentView; + } + + + /** + * Set the currentView to the navigator with the same + * name as the <tt>name</tt> parameter. + * + * @param name The name of the navigator to set as the + * current view. If nav is null or not a valid Navigator + * in this WindowPresentation then an + * IllegalArgumentException is thrown. + * @throws IllegalArgumentException if nav is null or not a valid Navigator. + */ + public void setCurrentView(String name) { + debug("setCurrentView"); + // if the jhelp already exists then set the currentview + if (jhelp != null) { + + JHelpNavigator nav = getNavigatorByName(name); + + if (nav == null) { + throw new IllegalArgumentException("Invalid view name"); + } + jhelp.setCurrentNavigator(nav); + } else { + // jhelp didn't exist so make sure view is in HelpSet + HelpSet hs = getHelpSet(); + NavigatorView view = hs.getNavigatorView(name); + if (view == null) { + throw new IllegalArgumentException("Invalid view name"); + } + } + currentView = name; + } + + /* + * Internal method to return a Navigator by name from a jhelp + */ + private JHelpNavigator getNavigatorByName(String name) { + JHelpNavigator nav = null; + if (jhelp != null) { + for (Enumeration e = jhelp.getHelpNavigators(); + e.hasMoreElements(); ) { + nav = (JHelpNavigator) e.nextElement(); + if (nav.getNavigatorName().equals(name)) { + break; + } + nav = null; + } + } + return nav; + } + + + /** + * Determines if the presentation should be distroyed on exit + */ + public boolean isDestroyedOnExit() { + debug("isDestoryedOnExit"); + return destroyOnExit; + } + + /** + * Destory the window on exit + */ + public void setDestroyOnExit(boolean destroy) { + debug("setDestoryOnExit"); + destroyOnExit = destroy; + } + + /** + * Destroy this object. Implementation of WindowPresentation that + * maintian a list of objects should override this method and call + * super.destroy to clear up the WindowPresentation internal fields. + */ + public void destroy() { + frame = null; + jhelp = null; + dialog = null; + ownerWindow = null; + location = null; + title = null; + currentView = null; + propertyChangeListener = null; + screen = 0; + } + + /** + * Changes the HelpSet for this presentation. + * @param hs The HelpSet to set for this presentation. + * A null hs is valid parameter. + */ + public void setHelpSet(HelpSet hs) { + debug("setHelpSet"); + + HelpSet helpset = super.getHelpSet(); + // If we already have a model check if the HelpSet has changed. + // If so change the model + // This could be made smarter to cache the helpmodels per HelpSet + if (hs != null && helpset != hs) { + super.setHelpSet(hs); + if (jhelp != null) { + jhelp.setModel(super.getHelpModel()); + } + } + } + + /** + * Displays the presentation to the user. + */ + public void setDisplayed(boolean b) { + debug ("setDisplayed"); + // if the jhelp is null and they don't want it displayed just return + if (jhelp == null && !b) { + return; + } + + // The call to createHelpWindow is necessary as the modality + // might have been changed and we need to change from a dialog + // to a frame. This is only done in createHelpWindow. + createHelpWindow(); + if (modallyActivated) { + if (b) { + dialog.show(); + } else { + dialog.hide(); + } + } else { + frame.setVisible(b); + + // We should be able to just + // try { + // frame.setState(Frame.NORMAL) + // } catch (NoSuchMethodError ex) { + // } + // but IE4.0 barfs very badly at this + // So... + + try { + Class types[] = {Integer.TYPE}; + Method m = Frame.class.getMethod("setState", types); + + if (m != null) { + Object args[] = {new Integer(0)}; // Frame.NORMAL + m.invoke(frame, args); + } + } catch (NoSuchMethodError ex) { + // as in JDK1.1 + } catch (NoSuchMethodException ex) { + // as in JDK1.1 + } catch (java.lang.reflect.InvocationTargetException ex) { + // + } catch (java.lang.IllegalAccessException ex) { + // + } + } + } + + /** + * Determines if the presentation is displayed. + */ + public boolean isDisplayed() { + debug ("isDisplayed"); + if (jhelp == null) { + return false; + } + if (modallyActivated) { + if (dialog != null) { + return dialog.isShowing(); + } else { + return false; + } + } else { + if (frame != null) { + if (! frame.isShowing()) { + return false; + } + else { + // We should be able to just + // try { + // return (frame.getState() == Frame.NORMAL) + // } catch (NoSuchMethodError ex) { + // } + // but IE4.0 barfs very badly at this + // So... + + try { + Method m = Frame.class.getMethod("getState", + (java.lang.Class[]) null); + + if (m != null) { + int value =((Integer)(m.invoke(frame, + (java.lang.Object[])null))).intValue(); + if (value == 0) + return true; + else + return false; + + } + } catch (NoSuchMethodError ex) { + // as in JDK1.1 + } catch (NoSuchMethodException ex) { + // as in JDK1.1 + } catch (java.lang.reflect.InvocationTargetException ex) { + // + } catch (java.lang.IllegalAccessException ex) { + // + } + // On 1.1 I can't tell if it's raised or not. + // It's on the screen so true. + return true; + } + } else { + return false; + } + } + } + + /** + * Sets the font for this this WindowPresentation. + * @param f The font. + */ + public void setFont (Font f) { + debug("setFont"); + super.setFont(f); + if (jhelp != null && f != null) { + jhelp.setFont(f); + } + } + + /** + * Gets the font for this WindowPresentation + */ + public Font getFont() { + debug("getFont"); + Font font = super.getFont(); + if (font == null) { + if (jhelp == null) { + createHelpWindow(); + } + return jhelp.getFont(); + } + return font; + } + + /** + * Sets the locale of this Presentation. The locale is propagated to + * the presentation. + * @param l The locale to become this component's locale. A null locale + * is the same as the defaultLocale. + * @see #getLocale + */ + public void setLocale(Locale l) { + debug("setLocale"); + super.setLocale(l); + if (jhelp != null) { + jhelp.setLocale(l); + } + } + + + /** + * internal method to test for Xinerama mode + */ + private boolean isXinerama () { + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gds = ge.getScreenDevices(); + if (gds.length == 1) { + return false; + } else { + for (int i=0; i<gds.length; i++) { + GraphicsConfiguration loopgc = + gds[i].getDefaultConfiguration(); + Rectangle bounds = loopgc.getBounds(); + if (bounds.x != 0 || bounds.y !=0) { + return true; + } + } + } + return false; + } + + /** + * Requests the location of the presentation. + * + * @returns Point the location of the presentation. + */ + public Point getLocation() { + debug("getLocation"); + if (location != null && jhelp == null) { + return location; + } + if (jhelp == null) { + createHelpWindow(); + } + if (modallyActivated) { + Point dlocation = dialog.getLocation(); + if (isXinerama()) { + GraphicsConfiguration gc = dialog.getGraphicsConfiguration(); + Rectangle gcBounds = gc.getBounds(); + return new Point(dlocation.x - gcBounds.x, + dlocation.y - gcBounds.y); + } + return dlocation; + } else { + Point flocation = frame.getLocation(); + if (isXinerama()) { + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + Rectangle gcBounds = gc.getBounds(); + return new Point(flocation.x - gcBounds.x, + flocation.y - gcBounds.y); + } + return flocation; + } + } + + /** + * Requests the presentation be located at a given position. + */ + public void setLocation(Point p) { + debug("setLocation"); + location = p; + + + if (jhelp != null) { + if (modallyActivated) { + if (dialog != null) { + GraphicsConfiguration gc = + dialog.getGraphicsConfiguration(); + Rectangle gcBounds = gc.getBounds(); + Point loc = new Point (gcBounds.x + p.x, + gcBounds.y + p.y); + dialog.setLocation(loc); + } + } else { + if (frame != null) { + GraphicsConfiguration gc = + frame.getGraphicsConfiguration(); + Rectangle gcBounds = gc.getBounds(); + Point loc = new Point (gcBounds.x + p.x, + gcBounds.y + p.y); + frame.setLocation(loc); + } + } + } + } + + /** + * Requests the screen of the presentation + * @returns int the screen of the presentation + */ + public int getScreen() { + debug("getScreen"); + // If there is no jhelp componet then it hasn't been "realized" + // yet so just return the screen + if (jhelp == null) { + return screen; + } + + // Help is showing so get the screen from the presentation + GraphicsConfiguration gc = null; + if (modallyActivated) { + if (dialog != null) { + gc = dialog.getGraphicsConfiguration(); + } + } else { + if (frame != null) { + gc = frame.getGraphicsConfiguration(); + } + } + if (gc != null) { + GraphicsDevice device = gc.getDevice(); + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + for (int i=0; i < gs.length; i++) { + if (gs[i] == device) { + // got our match + screen = i; + return screen; + } + } + } + return screen; + } + + /** + * Sets the screen of the presentation + * @param screen the screen number + * @throws IllegalArgumentException if the screen is invalid + */ + public void setScreen(int screen) { + debug ("setScreen"); + + if (screen == this.screen) { + // There is nothing to do as it is either already the screen + // or the + return; + } + + if (screen < 0) { + throw new IllegalArgumentException("Invalid screen"); + } + + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[]gs = ge.getScreenDevices(); + + // make sure there is a screen device + if (gs.length <= screen) { + throw new IllegalArgumentException ("Invalid Screen"); + } + + this.screen = screen; + + if (jhelp != null) { + + boolean xinerama = isXinerama(); + + GraphicsDevice gd = gs[screen]; + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + Rectangle gcBounds = gc.getBounds(); + if (modallyActivated) { + if (dialog != null) { + if (xinerama) { + Point p = getLocation(); + Point loc = new Point (gcBounds.x + p.x, + gcBounds.y + p.y); + dialog.setLocation(loc); + } else { + location = getLocation(); + dialog.hide(); + dialog = null; + createHelpWindow(); + } + } + } else { + if (frame != null) { + if (xinerama) { + Point p = getLocation(); + Point loc = new Point (gcBounds.x + p.x, + gcBounds.y + p.y); + frame.setLocation(loc); + } else { + location = getLocation(); + frame.setVisible(false); + frame = null; + createHelpWindow(); + } + } + } + } + } + + /** + * Requests the size of the presentation. + * @returns Point the location of the presentation. + */ + public Dimension getSize() { + debug("getSize"); + // if the jhelp is created then just use the current sizes + if (jhelp != null) { + if (modallyActivated) { + if (dialog != null) { + return dialog.getSize(); + } + } else { + if (frame != null) { + return frame.getSize(); + } + } + } + return super.getSize(); + } + + /** + * Requests the presentation be set to a given size. Updates the + * the presentation on the fly. This is an override of + * Presentation.SetSize. + */ + public void setSize(Dimension d) { + debug("setSize"); + super.setSize(d); + if (jhelp != null) { + if (modallyActivated) { + dialog.setSize(d); + dialog.validate(); + } else { + frame.setSize(d); + frame.validate(); + } + } + } + + public String getTitle() { + debug("getTitle"); + + // if the title comes from the document use that first if + // jhelp exists + if (titleFromDocument && jhelp != null) { + String docTitle = jhelp.getContentViewer().getDocumentTitle(); + if (docTitle != null) { + return docTitle; + } + } + + // otherwise use the title that has been set... + if (title != null) { + return title; + } else { + // Unless there wasn't a title set and then use the HelpSet + // title + HelpSet hs = getHelpSet(); + if (hs != null) { + title = hs.getTitle(); + } + } + return title; + } + + public void setTitle(String title) { + debug("setTitle"); + this.title = title; + if (jhelp != null) { + if (modallyActivated) { + dialog.setTitle(title); + dialog.validate(); + } else { + frame.setTitle(title); + frame.validate(); + } + } + + } + + /** + * Is the title set from the Document. This is generally useful + * in SecondaryWindows. + * @return boolean True if title is set from the Document, false otherwise. + */ + public boolean isTitleSetFromDocument() { + debug("isTitleSetFromDocument"); + return titleFromDocument; + } + + /** + * Set the title from the Document. + * @param b if true will set the title form the document, otherwise will + * set the title from the HelpSet. + */ + public void setTitleFromDocument(boolean b) { + debug("setTitleFromDocument"); + if (titleFromDocument != b) { + titleFromDocument = b; + if (titleFromDocument) { + propertyChangeListener = new WindowPropertyChangeListener(); + if (jhelp != null) { + jhelp.getContentViewer(). + addPropertyChangeListener("page", + propertyChangeListener); + } + } else { + if (jhelp != null) { + jhelp.getContentViewer(). + removePropertyChangeListener("page", + propertyChangeListener); + } + } + } + } + + /** + * Determines if the current view is visible. + */ + public boolean isViewDisplayed() { + debug ("isViewDisplayed"); + if (jhelp != null) { + return jhelp.isNavigatorDisplayed(); + } + return viewDisplayed; + } + + /** + * Hides/Shows view. + */ + public void setViewDisplayed(boolean displayed) { + debug ("setViewDisplayed"); + if (jhelp != null) { + jhelp.setNavigatorDisplayed(displayed); + } + viewDisplayed = displayed; + } + + /** + * Determines if the toolbar is visible. + */ + public boolean isToolbarDisplayed() { + debug ("isToolbarDisplayed"); + if (jhelp != null) { + return jhelp.isToolbarDisplayed(); + } + return toolbarDisplayed; + } + + /** + * Hides/Shows Toolbar + */ + public void setToolbarDisplayed(boolean displayed) { + debug ("setToolbarDisplayed=" + displayed); + if (jhelp != null) { + jhelp.setToolbarDisplayed(displayed); + } + toolbarDisplayed = displayed; + } + + private synchronized void createJHelp() { + debug ("createJHelp"); + if (jhelp == null) { + jhelp = new JHelp(getHelpModel(), null, getHelpSetPresentation()); + Font font = super.getFont(); + if (font != null) { + jhelp.setFont(font); + } + Locale locale = getLocale(); + if (locale != null) { + jhelp.setLocale(locale); + } + jhelp.setToolbarDisplayed(toolbarDisplayed); + jhelp.setNavigatorDisplayed(viewDisplayed); + if (currentView != null) { + JHelpNavigator nav = getNavigatorByName(currentView); + if (nav != null) { + jhelp.setCurrentNavigator(nav); + } + } + if (titleFromDocument) { + jhelp.getContentViewer(). + addPropertyChangeListener("page", propertyChangeListener); + } + } + } + + WindowListener dl; + boolean modalDeactivated = true; + + public synchronized void createHelpWindow() { + debug ("createHelpWindow"); + // pos is used for determining the screen adjust location of a + // dialog or frame that already exist. This should only be used + // when a switch is required. If it is null this is a creation. + Point pos = null; + Dimension size = getSize(); + JDialog tmpDialog = null; + + createJHelp(); + + + // The graphics variables below are only used during the initial + // creation. If there is a modality change then the actual position + // of the Window would be used instead. + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gds = ge.getScreenDevices(); + GraphicsDevice gd = gds[screen]; + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + Rectangle gcBounds = gc.getBounds(); + + if (modallyActivated) { + // replace dialog.getOwner() with the following code + Window owner=null; + try { + Method m = Window.class.getMethod("getOwner", + (java.lang.Class[]) null); + + if (m != null && dialog != null) { + owner = (Window) m.invoke(dialog, + (java.lang.Class[]) null); + } + } catch (NoSuchMethodError ex) { + // as in JDK1.1 + } catch (NoSuchMethodException ex) { + // as in JDK1.1 + } catch (java.lang.reflect.InvocationTargetException ex) { + // + } catch (java.lang.IllegalAccessException ex) { + // + } + + if (dialog == null || owner != ownerWindow || modalDeactivated) { + if (frame != null) { + // pos is already screen adjusted + pos = frame.getLocation(); + size = frame.getSize(); + frame = null; + } + if (dialog != null) { + // pos is already screen adjusted + pos = dialog.getLocation(); + size = dialog.getSize(); + tmpDialog = dialog; + } + dialog = new JDialog((Dialog)ownerWindow, getTitle(), + false, gc); + + // Modal dialogs are really tricky. When the modal dialog + // is dismissed the JDialog will be dismissed as well. + // When that happens we need to make sure the ownerWindow + // is set to null so that a new dialog will be created so + // that events aren't blocked in the HelpViewer. + dl = new WindowAdapter() { + public void windowClosing(WindowEvent e) { + debug ("modal window closing"); + if (destroyOnExit) { + destroy(); + return; + } + // JDK1.2.1 bug not closing owned windows + if (dialog.isShowing()) { + dialog.hide(); + } + if (ownerWindow != null) + ownerWindow.removeWindowListener(dl); + ownerWindow = null; + modalDeactivated = true; + } + + public void windowClosed(WindowEvent e) { + debug ("modal window closing"); + if (destroyOnExit) { + destroy(); + return; + } + } + }; + debug ("adding windowlistener"); + + ownerWindow.addWindowListener(dl); + modalDeactivated = false; + if (size != null) { + dialog.setSize(size); + } else { + dialog.setSize(getSize()); + } + + // if the pos variable is not null then either a frame + // or a dialog already exists and you should use that position + // instead. If it is null then base the point on the location + // and screen or just the screen + if (pos != null) { + dialog.setLocation(pos); + } else { + // set based on location and screen or just screen + Point loc = null; + if (location != null) { + if (isXinerama()) { + loc = new Point (gcBounds.x + location.x, + gcBounds.y + location.y); + } else { + loc = location; + } + dialog.setLocation(loc); + } + } + dialog.setTitle(getTitle()); + dialog.getContentPane().add(jhelp); + if (tmpDialog != null) { + tmpDialog.hide(); + tmpDialog = null; + } + } + } else { + if (frame == null) { + frame = new JFrame(getTitle(), gc); + + WindowListener l = new WindowAdapter() { + public void windowClosing(WindowEvent e) { + if (destroyOnExit) { + destroy(); + return; + } + frame.setVisible(false); + } + public void windowClosed(WindowEvent e) { + frame.setVisible(false); + if (destroyOnExit) { + destroy(); + return; + } + } + }; + frame.addWindowListener(l); + if (image != null) { + frame.setIconImage(image); + } + } + if (dialog != null) { + // pos is already screen adjusted + pos = dialog.getLocation(); + size = dialog.getSize(); + dialog.hide(); + dialog = null; + ownerWindow = null; + } + if (size != null) { + frame.setSize(size); + } else { + frame.setSize(getSize()); + } + + + // if the pos variable is not null then either a frame + // or a dialog already exists and you should use that position + // instead. If it is null then base the point on the location + // and screen or just the screen + if (pos != null) { + frame.setLocation(pos); + } else { + // set based on location and screen or just screen + Point loc = null; + if (location != null) { + if (isXinerama()) { + loc = new Point (gcBounds.x + location.x, + gcBounds.y + location.y); + } else { + loc = location; + } + frame.setLocation(loc); + } + } + frame.getContentPane().add(jhelp); + frame.setTitle(getTitle()); + } + + } + + /** + * Get the current window that help is displayed in + * + * @returns Window the current Window + */ + public Window getHelpWindow() { + if (modallyActivated) { + return dialog; + } + return frame; + } + + private class WindowPropertyChangeListener implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + String changeName = event.getPropertyName(); + if (changeName.equals("page")) { + String title = getTitle(); + if (modallyActivated) { + dialog.setTitle(title); + } else { + frame.setTitle(title); + } + } + } + } + + /** + * Debugging code... + */ + + private static final boolean debug = false; + private static void debug(Object msg) { + if (debug) { + System.err.println("WindowPresentation: "+msg); + } + } + +} + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java b/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java new file mode 100644 index 0000000000000000000000000000000000000000..3df508b70732706d0dc481c988e1d1c57c1511aa --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java @@ -0,0 +1,273 @@ +/* + * @(#)EventListenerList.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +import java.io.*; +import java.util.*; + +/** + * This class is a copy of the javax.swing.event.EventListenerList class. + * + * It is duplicated here because we do not want to introduce a dependency + * on Swing to HelpSet and DefaultHelpModel, which are otherwise Swing-free. + */ + +/** + * A class that holds a list of EventListeners. A single instance + * can be used to hold all listeners (of all types) for the instance + * using the list. It is the responsiblity of the class using the + * EventListenerList to provide a type-safe API (preferably conforming + * to the JavaBeans specification) and methods that dispatch event notification + * methods to appropriate Event Listeners on the list. + * + * The main benefits this class provides are that it is relatively + * cheap if there are no listeners, provides serialization for + * eventlistener lists in a single place, and provides a degree of MT safety + * (when used correctly). + * + * Usage example: + * If one is defining a class that sends out FooEvents, and wants + * to allow users of the class to register FooListeners and receive + * notification when FooEvents occur. The following should be added + * to the class definition: + <pre> + EventListenerList listenrList = new EventListnerList(); + FooEvent fooEvent = null; + + public void addFooListener(FooListener l) { + listenerList.add(FooListener.class, l); + } + + public void removeFooListener(FooListener l) { + listenerList.remove(FooListener.class, l); + } + + + // Notify all listeners that have registered interest for + // notification on this event type. The event instance + // is lazily created using the parameters passed into + // the fire method. + + protected void firefooXXX() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==FooListener.class) { + // Lazily create the event: + if (fooEvent == null) + fooEvent = new FooEvent(this); + ((FooListener)listeners[i+1]).fooXXX(fooEvent); + } + } + } + </pre> + * foo should be changed to the appropriate name, and Method to the + * appropriate method name (one firing method should exist for each + * notification method in the FooListener interface). + * <p> + * Warning: Serialized objects of this class are not be compatible with + * future Swing releases. The current serialization support is appropriate + * for short term storage or RMI between Swing1.0 applications. It will + * not be possible to load serialized Swing1.0 objects with future releases + * of Swing. The JDK1.2 release of Swing will be the compatibility + * baseline for the serialized form of Swing objects. + * + * @version 1.19 03/18/98 + * @author Georges Saab + * @author Hans Muller + * @author James Gosling + */ +public class EventListenerList implements Serializable { + /* A null array to be shared by all empty listener lists*/ + private final static Object[] NULL_ARRAY = new Object[0]; + /* The list of ListenerType - Listener pairs */ + protected transient Object[] listenerList = NULL_ARRAY; + + /** + * This passes back the event listener list as an array + * of ListenerType - listener pairs. Note that for + * performance reasons, this implementation passes back + * the actual data structure in which the listener data + * is stored internally! + * This method is guaranteed to pass back a non-null + * array, so that no null-checking is required in + * fire methods. A zero-length array of Object should + * be returned if there are currently no listeners. + * + * WARNING!!! Absolutely NO modification of + * the data contained in this array should be made -- if + * any such manipulation is necessary, it should be done + * on a copy of the array returned rather than the array + * itself. + */ + public Object[] getListenerList() { + return listenerList; + } + + /** + * Returns the total number of listeners for this listenerList. + */ + public int getListenerCount() { + return listenerList.length/2; + } + + /** + * Returns the total number of listeners of the supplied type + * for this listenerList. + */ + public int getListenerCount(Class t) { + int count = 0; + Object[] lList = listenerList; + for (int i = 0; i < lList.length; i+=2) { + if (t == (Class)lList[i]) + count++; + } + return count; + } + /** + * Adds the listener as a listener of the specified type. + * @param t The type of the listener to be added. + * @param l The listener to be added. + * @throws IllegalArgumentException if <tt>l</tt> or <tt>t</tt> is + * null or <tt>t</tt> is not an instance of <tt>l</tt>. + */ + public synchronized void add(Class t, EventListener l) { + if (l ==null || t == null) { + throw new IllegalArgumentException("Listener " + l + + " is null"); + } + if (!t.isInstance(l)) { + throw new IllegalArgumentException("Listener " + l + + " is not of type " + t); + } + if (listenerList == NULL_ARRAY) { + // if this is the first listener added, + // initialize the lists + listenerList = new Object[] { t, l }; + } else { + // Otherwise copy the array and add the new listener + int i = listenerList.length; + Object[] tmp = new Object[i+2]; + System.arraycopy(listenerList, 0, tmp, 0, i); + + tmp[i] = t; + tmp[i+1] = l; + + listenerList = tmp; + } + } + + /** + * Removes the listener as a listener of the specified type. If the + * listener for a given class does not exist in the list, it is ignored. + * @param t The type of the listener to be removed. + * @param l The listener to be removed. + * @throws IllegalArgumentException if <tt>l</tt> or <tt>t</tt> is + * null or <tt>t</tt> is not an instance of <tt>l</tt>. + */ + public synchronized void remove(Class t, EventListener l) { + if (l == null || t == null) { + throw new IllegalArgumentException("Listener " + l + + " is null"); + } + + if (!t.isInstance(l)) { + throw new IllegalArgumentException("Listener " + l + + " is not of type " + t); + } + // Is l on the list? + int index = -1; + for (int i = listenerList.length-2; i>=0; i-=2) { + if ((listenerList[i]==t) && (listenerList[i+1] == l)) { + index = i; + break; + } + } + + // If so, remove it + if (index != -1) { + Object[] tmp = new Object[listenerList.length-2]; + // Copy the list up to index + System.arraycopy(listenerList, 0, tmp, 0, index); + // Copy from two past the index, up to + // the end of tmp (which is two elements + // shorter than the old list) + if (index < tmp.length) + System.arraycopy(listenerList, index+2, tmp, index, + tmp.length - index); + // set the listener array to the new array or null + listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp; + } + } + + // Serialization support. + private void writeObject(ObjectOutputStream s) throws IOException { + Object[] lList = listenerList; + s.defaultWriteObject(); + + // Save the non-null event listeners: + for (int i = 0; i < lList.length; i+=2) { + Class t = (Class)lList[i]; + EventListener l = (EventListener)lList[i+1]; + if ((l!=null) && (l instanceof Serializable)) { + s.writeObject(t.getName()); + s.writeObject(l); + } + } + + s.writeObject(null); + } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + listenerList = NULL_ARRAY; + s.defaultReadObject(); + Object listenerTypeOrNull; + + while (null != (listenerTypeOrNull = s.readObject())) { + EventListener l = (EventListener)s.readObject(); + add(Class.forName((String)listenerTypeOrNull), l); + } + } + + /** + * Returns a string representation of the EventListenerList. + */ + public String toString() { + Object[] lList = listenerList; + String s = "EventListenerList: "; + s += lList.length/2 + " listeners: "; + for (int i = 0 ; i <= lList.length-2 ; i+=2) { + s += " type " + ((Class)lList[i]).getName(); + s += " listener " + lList[i+1]; + } + return s; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..3f4d5d74818f9e48d52ff192dcd92cf15a9f45a7 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java @@ -0,0 +1,76 @@ +/* + * @(#)HelpHistoryModelEvent.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +/** + * Notifies interested parties that a change in a + * Help History Model source has occurred. + * + * @author Richard Gregor + * @version 1.4 10/30/06 + */ + +public class HelpHistoryModelEvent extends java.util.EventObject{ + + private boolean next; + private boolean previous; + + /** + * Represents a history change + * + * @param source The source for this event. + * @param previous If true a previous action is allowed. + * @param next If true a next action is allowed. + * @throws IllegalArgumentException if source is null. + */ + public HelpHistoryModelEvent(Object source, boolean previous, + boolean next) { + super(source); + this.next = next; + this.previous = previous; + } + + /** + * Returns if action "previous" is allowed. + * + * @return True if action is allowed, false otherwise. + */ + public boolean isPrevious(){ + return previous; + } + + /** + * Returns if action "next" is allowed + * + * @return True if action is allowed, false otherwise. + */ + public boolean isNext() { + return next; + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java new file mode 100644 index 0000000000000000000000000000000000000000..34bd1cd2898b34044758dadedfd446f6f4fafcf1 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java @@ -0,0 +1,44 @@ +/* + * @(#)HelpHistoryModelListener.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package javax.help.event; + +/** + * @author Richard Gregor + * @version 1.2 10/30/06 + */ + +public interface HelpHistoryModelListener extends java.util.EventListener{ + /** + * Tells the listener that the history has changed. + * + * @param e The HelpHistoryModelEvent + */ + public void historyChanged(HelpHistoryModelEvent e); + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..90a45ecdf2869d5609dbd10df61051c46aff3c00 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java @@ -0,0 +1,155 @@ +/* + * @(#)HelpModelEvent.java 1.21 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; +import javax.help.HelpSet; +import javax.help.Map.ID; +import javax.help.JHelpNavigator; + + +/** + * Notifies interested parties that a change in a + * Help Model source has occurred. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Richard Gregor + * @version 1.16 03/10/99 + */ + +public class HelpModelEvent extends java.util.EventObject { + private ID id; + private URL url; + private String historyName; + private JHelpNavigator navigator; + + /** + * Represents a change in the JavaHelp in the current ID or URL. + * @see javax.help.JavaHelp + * + * @param source The source for this event. + * @param id The ID that has changed. Should be null if URL is specified. + * @param url The URL that has changed. Should be null if ID is specified. + * @throws IllegalArgumentException if source is null. + * @throws IllegalArgumentException of both ID and URL are null. + */ + public HelpModelEvent(Object source, ID id, URL url) { + this(source,id,url,(String)null, (JHelpNavigator)null); + } + + /** + * Represents a change in the JavaHelp in the current ID or URL. + * @see javax.help.JavaHelp + * + * @param source The source for this event. + * @param id The ID that has changed. Should be null if URL is specified. + * @param url The URL that has changed. Should be null if ID is specified. + * @param historyName The name of selected entry + * @param navigator The JHelpNavigator + * @throws IllegalArgumentException if source is null. + * @throws IllegalArgumentException of both ID and URL are null. + */ + public HelpModelEvent(Object source, ID id, URL url, String historyName, JHelpNavigator navigator){ + super(source); + if ((id == null) && (url == null)) { + throw new IllegalArgumentException("ID or URL must not be null"); + } + this.id = id; + this.url = url; + this.historyName = historyName; + this.navigator = navigator; + } + + + /** + * Creates a HelpModelEvent for highlighting. + * + * @param source The source for this event. + * @param pos0 Start position. + * @param pos1 End position. + * @throws IllegalArgumentException if source is null. + */ + public HelpModelEvent(Object source, int pos0, int pos1) { + super (source); + this.pos0 = pos0; + this.pos1 = pos1; + } + /** + * Returns the current ID in the HelpModel. + * @return The current ID. + */ + public ID getID() { + return id; + } + + /** + * Returns the current URL in the HelpModel. + * @return The current URL. + */ + public URL getURL() { + return url; + } + + /** + * Returns the name of this entry + * + * @return The entry name + */ + public String getHistoryName() { + return historyName; + } + + /** + * Returns the navigator of this entry + * + * @return The navigator name + */ + public JHelpNavigator getNavigator() { + return navigator; + } + + private int pos0, pos1; + + // HERE - Review this highlighting; it is a different type of beast than the rest - epll + /** + * @return The start position of this (highlighting) event. + */ + public int getPos0() { + return pos0; + } + + /** + * @return The end position of this (highlighting) event. + */ + public int getPos1() { + return pos1; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java new file mode 100644 index 0000000000000000000000000000000000000000..8b31e5109fccf399ba552ee67fa7cb1840aeb499 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java @@ -0,0 +1,48 @@ +/* + * @(#)HelpModelListener.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +/** + * Defines the interface for an object that listens to + * changes in a HelpModel. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.13 01/29/99 + */ + +public interface HelpModelListener extends java.util.EventListener { + /** + * Tells the listener that the current ID in the HelpModel has + * changed. + * All highlights from the previous location change at this point. + * + * @param e The event + */ + public void idChanged(HelpModelEvent e); +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..9ccb78e37219633ed8e9859eb9d4cceac6ee1988 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java @@ -0,0 +1,99 @@ +/* + * @(#)HelpSetEvent.java 1.13 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +import javax.help.HelpSet; + +/** + * Conveys information when a HelpSet is added/removed. + * + * @author Eduardo Pelegri-Llopart + * @version 1.10 03/10/99 + */ + +public class HelpSetEvent extends java.util.EventObject { + + /** + * Creates a HelpSetEvent. + * + * @param source Source of this Event. + * @param helpset The HelpSet being added/removed. + * @param action HELPSET_ADDED or HELPSET_REMOVED. + * @throws IllegalArgumentException if source is null or if action is not + * a valid action. + */ + public HelpSetEvent(Object source, HelpSet helpset, int action) { + super(source); + this.helpset = helpset; + if (helpset == null) { + throw new NullPointerException("helpset"); + } + this.action = action; + if (action < 0 || action > 1) { + throw new IllegalArgumentException("invalid action"); + } + } + + /** + * A HelpSet was added + */ + public static final int HELPSET_ADDED = 0; + + /** + * A HelpSet was removed + */ + public static final int HELPSET_REMOVED = 1; + + /** + * @return The HelpSet. + */ + public HelpSet getHelpSet() { + return helpset; + } + + /** + * @return The action + */ + public int getAction() { + return action; + } + + /** + * Returns textual about the instance. + */ + public String toString() { + if (action==HELPSET_ADDED) { + return "HelpSetEvent("+source+", "+helpset+"; added"; + } else { + return "HelpSetEvent("+source+", "+helpset+"; removed"; + } + } + + private HelpSet helpset; + private int action; +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java new file mode 100644 index 0000000000000000000000000000000000000000..0961522da54a7a0b2232796112399f8a156236f0 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java @@ -0,0 +1,53 @@ +/* + * @(#)HelpSetListener.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +/** + * Defines the interface of an object that listens to + * changes in the HelpSet. + * + * @author Eduardo Pelegri-Llopart + * @version 1.8 01/29/99 + */ + +public interface HelpSetListener extends java.util.EventListener { + + /** + * Invoked when a new HelpSet is added. + * + * @param e The event + */ + public void helpSetAdded(HelpSetEvent e); + + /** + * Invoked when a new HelpSet is removed. + * + * @param e The event + */ + public void helpSetRemoved(HelpSetEvent e); +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..75f9c484ac913dc2a4d5a63dca9091c05f6518b1 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java @@ -0,0 +1,56 @@ +/* + * @(#)TextHelpModelEvent.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +import java.net.URL; +import java.util.Vector; +import java.util.Enumeration; +import javax.help.HelpSet; +import javax.help.Map.ID; + +/** + * Notifies interested parties when a change in a + * TextHelpModel occurs. The listener should query the source + * for details. + * + * @author Eduardo Pelegri-Llopart + * @author Roger D. Brinkley + * @version 1.6 10/30/06 + */ + +public class TextHelpModelEvent extends java.util.EventObject { + /** + * Creates a TextHelpModelEvent. + * + * @param source The source for this event. Implements TextHelpModel + * @throws IllegalArgumentException if source is null. + */ + public TextHelpModelEvent(Object source) { + super (source); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java new file mode 100644 index 0000000000000000000000000000000000000000..ddf69752707ca6f44cc5df42c4b6f3340269d958 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java @@ -0,0 +1,47 @@ +/* + * @(#)TextHelpModelListener.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.event; + +/** + * Defines the interface for an object that listens to + * changes in a TextHelpModel. + * + * @author Eduardo Pelegri-Llopart + * @author Roger D. Brinkley + * @version 1.5 10/30/06 + */ + +public interface TextHelpModelListener extends java.util.EventListener { + /** + * Invoked when the set of highlights changess. + * Note that this event is <em>not</em> generated when an idChanged() event + * is generated, since all the highlights are reset at that point. + */ + public void highlightsChanged(TextHelpModelEvent e); + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/package.html b/jhMaster/JavaHelp/src/new/javax/help/event/package.html new file mode 100644 index 0000000000000000000000000000000000000000..d5563edfe48af13462aa6246cadd5aae836620a2 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/event/package.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.1 98/10/15 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Supports event changes in JavaHelp classes. +<code>HelpModelEvent</code> and +<code>HelpModelListener</code> support changes to the +locations within HelpSets being presented, +<code>TextHelpModelEvent</code> and +<code>TextHelpModelListener</code> support textual changes +and <code>HelpSetEvent</code>, and +<code>HelpSetListener</code> support changes to the HelpSet +itself. + +<p> +<code>EventListenerList</code> is used as a convenience +class to maintain lists of listeners and it is functionally +equivalent to the equivalent Swing class--it is included to +avoid adding unwanted dependencies on Swing. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see the <em>JavaHelp System User's Guide</em>. + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/package.html b/jhMaster/JavaHelp/src/new/javax/help/package.html new file mode 100644 index 0000000000000000000000000000000000000000..6b5215492bc08c96f63150a8667da3abf3772a0e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/package.html @@ -0,0 +1,155 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.4 98/10/19 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Supports presentation of online documentation with both +content and contextual views of this information. +This is the main package for the JavaHelp standard extension. +The main focus of JavaHelp is online help, +but it can be used for any online content. + +<p> +JavaHelp supports the notion of a HelpSet that encompases +all documentation information. +There is a simple way to read a HelpSet, +create a presentation for it, and interact with it +and there is also a collection of Swing components that +can be used directly for additional control. +JavaHelp presents content using Swing's EditorKits, +which provide for extensibility of content. +JavaHelp also provides for extensibility of context via +the notion of a NavigatorView; +several views are standard. +One of the standard views provides full-text search, +which relies on a simple search package to communicate with +search engines. + + +<h3>Basic Classes</h3> + +<code>HelpSet</code> is the main class, providing +access to a HelpSet file. +A visual presentation of a HelpSet can be obtained through +a <code>HelpBroker</code> which is an abstraction +that permits interaction regardless of the presentation +details; +the default presentation is <code>DefaultHelpBroker</code>. +An application can provide online help using only these two classes. + +<p> +Helpsets can be merged dynamically or statically, and +can be associated with Beans. + +<h3>Swing components</h3> + +JavaHelp provides a collection of Swing components that are used to +implement the DefaultHelpBroker and can also be used directly. The +components follow the standard MVC from Swing. +<code>HelpModel</code> models changes to the location within a +HelpSet--components that want to respond to these changes should +listen to events originating within the model (this is how +synchronized views work). <code>TextHelpModel</code> provides +additional information when the content is textual. +<code>DefaultHelpModel</code> is the default model that implements both +models. + +<p> +<code>JHelpContentViewer</code> +is the Swing component for HTML content, +while context corresponds to several subclasses of +<code>JHelpNavigator</code>. +<code>JHelp</code> is a common grouping of these +classes into synchronized views of content. + + +<h3>Extensibility</h3> + +Context extensibility is described through a +<code>NavigatorView</code> which provides access to context +information, plus a way of presenting this information. +<code>TOCView</code>, <code>IndexView</code>, and +<code>SearchView</code> are standard views for table of contents, +index, and full-text search. + +<p> +The standard views yield standard <code>JHelpTOCNavigator</code>, +<code>JHelpIndexNavigator</code>, and +<code>JHelpSearchNavigator</code> Swing components. The standard +views also provide access to the content--this access is +provides through subclasses +of <code>TreeItem</code>. + +<p> +New views can be added, +for instance a new TOC presentation can be obtained by +subclassing TOCView and changing the JHelpNavigator +returned by it. + +<h3>Context Sensitive Help</h3> + +JavaHelp supports a <code>Map</code> between identifiers and URLs. +<code>FlatMap</code> and <code>TryMap</code> are two +implementations. + +The main class used to associate specific content with graphic +objects is <code>CSH</code>, while <code>DialogSupport</code> +provides support in Dialogs (this may migrate to Swing at some +point). + +<h3>Search</h3> +JavaHelp supports a standard full-text search view and navigator. +The view interacts with a search engine through the types in the +<code>javax.javahelp.search</code> package. The reference +implementation provides a search engine that implements these interfaces, +but others can also be used. The specific search engine is part +of the information given to the search view. This separation +provides the full-text search functionality but does not +imposing specific formats. + + +<!-- +<H2>Package Specification</H2> +<p> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see the <em>JavaHelp System User's Guide</em>. + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java new file mode 100644 index 0000000000000000000000000000000000000000..a992ad978979e84eafd49395d83ec573838b99cc --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java @@ -0,0 +1,42 @@ +/* + * @(#)HelpContentViewerUI.java 1.14 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf; + +import javax.swing.plaf.ComponentUI; +import javax.swing.text.EditorKit; +import javax.help.event.HelpModelEvent; +/** + * UI factory interface for JHelpContentViewer. + * + * @author Eduardo Pelegri-Llopart + * @author Roger Brinkley + * @version 1.14 10/30/06 + */ + +public abstract class HelpContentViewerUI extends ComponentUI { +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..0ec0b369a34d1c820ddf9303e630a5461f456684 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java @@ -0,0 +1,113 @@ +/* + * @(#)HelpNavigatorUI.java 1.26 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf; + +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.*; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.help.HelpModel; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import javax.help.NavigatorView; +import javax.help.Map; +import java.net.URL; +import javax.swing.Action; +import javax.swing.AbstractAction; + +/** + * UI factory interface for JHelpNavigator. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version %I 10/30/06 + */ + +public abstract class HelpNavigatorUI extends ComponentUI { + + private Icon icon; + + /** + * Sets the icon for this HelpNavigator. + * + * @param icon the Icon + */ + public void setIcon(Icon icon) { + this.icon = icon; + } + + /** + * @return the Icon for this HelpNavigator + */ + public Icon getIcon() { + return icon; + } + + /** + * Merges a Navigator View. + */ + public void merge(NavigatorView view){ + throw new UnsupportedOperationException("merge is not supported"); + } + + /** + * Removes a Navigator View. + */ + public void remove(NavigatorView view){ + throw new UnsupportedOperationException("remove is not supported"); + } + + /** + * Returns icon associated with the view. + * + * @param view the view + * @return the ImageIcon for the view + */ + public ImageIcon getImageIcon(NavigatorView view) { + ImageIcon icon = null; + Map.ID id = view.getImageID(); + if (id != null) { + try { + Map map = view.getHelpSet().getCombinedMap(); + URL url = map.getURLFromID(id); + icon = new ImageIcon(url); + } catch (Exception e) { + } + } + return icon; + } + + /** + * Returns an AddAction object. Has sense only for favorites navigator + */ + public Action getAddAction(){ + throw new UnsupportedOperationException("getAddAction is not supported"); + //return (Action)null; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java new file mode 100644 index 0000000000000000000000000000000000000000..f2873252e892cd3aa785d3b31acc144544ad91cb --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java @@ -0,0 +1,73 @@ +/* + * @(#)HelpUI.java 1.21 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf; + +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.*; +import javax.help.JHelpNavigator; +import java.util.Enumeration; + +/** + * UI factory interface for JHelp. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.21 10/30/06 + */ + +public abstract class HelpUI extends ComponentUI { + + /** + * Adds a Navigator. + * + * @param nav the Navigator to add + */ + public abstract void addNavigator(JHelpNavigator nav); + + /** + * Remove a Navigator. + * + * @param nav The Navigator to remove. + */ + public abstract void removeNavigator(JHelpNavigator nav); + + /** + * Sets the current Navigator. + * + * @param nav The current Navigator to show. + */ + public abstract void setCurrentNavigator(JHelpNavigator nav); + + /** + * Gets the current Navigator. + * + * @param nav The current Navigator to show. + */ + public abstract JHelpNavigator getCurrentNavigator(); + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java new file mode 100644 index 0000000000000000000000000000000000000000..70d040d4054326be786363510dd3ced3d9e20e3e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java @@ -0,0 +1,607 @@ +/* + * @(#)BasicContentViewerUI.java 1.57 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicContentViewerUI.java 1.57 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpContentViewerUI; +import javax.help.event.*; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Hashtable; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TextUI; +import javax.swing.border.*; +import javax.swing.event.*; +import javax.swing.text.html.*; +import javax.swing.text.html.parser.*; +import javax.swing.text.Element; +import java.awt.*; +import java.awt.event.*; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.*; +import javax.help.Map.ID; + +/** + * The default UI for JHelpContentViewer. + * + * @author Eduardo Pelegri-Llopart + * @author Richard Gregor + * @version 1.57 10/30/06 + */ + +public class BasicContentViewerUI extends HelpContentViewerUI +implements HelpModelListener, TextHelpModelListener, HyperlinkListener, PropertyChangeListener, Serializable { + // Suggestion: Refactor the class and remove the menu bar and the + // HTML viewer into subclasses. This would allow easier + // replacement of both components to + // + protected JHelpContentViewer theViewer; + + private static Dimension PREF_SIZE = new Dimension(200, 300); + private static Dimension MIN_SIZE = new Dimension(80, 80); + + private JEditorPane html; + private JViewport vp; + + private Hashtable registry; + private boolean loadingURL; + private TextHelpModelEvent pendingHighlightsEvent; + + public static ComponentUI createUI(JComponent x) { + debug("createUI"); + return new BasicContentViewerUI((JHelpContentViewer) x); + } + + public BasicContentViewerUI(JHelpContentViewer b) { + debug("createUI - sort of"); + } + + public void setEditorKit(String type, EditorKit kit) { + debug("setEditorKit("+type+", "+kit+")"); + if (registry == null) { + registry = new Hashtable(3); + } + registry.put(type, kit); + if (html != null) { + debug(" type: "+type); + debug(" kit: "+kit); + html.setEditorKitForContentType(type, kit); + if (debug) + debug(" kit got: "+html.getEditorKitForContentType(type)); + } + } + + /** + * Subclass of JEditorPane that uses the JHelpContentViewer type registry. + */ + + class JHEditorPane extends JEditorPane { + private Hashtable typeHandlers; + + public EditorKit getEditorKitForContentType(String type) { + if (typeHandlers == null) { + typeHandlers = new Hashtable(3); + } + EditorKit k = (EditorKit) typeHandlers.get(type); + if (k == null) { + k = theViewer.createEditorKitForContentType(type); + if (k != null) { + setEditorKitForContentType(type, k); + typeHandlers.put(type, k); + } + } + if (k == null) { + k = super.getEditorKitForContentType(type); + if (k != null) { + typeHandlers.put(type, k); + } + } + return k; + } + + } + + + public void installUI(JComponent c) { + debug("installUI"); + theViewer = (JHelpContentViewer)c; + theViewer.setLayout(new BorderLayout()); + + // listen to property changes... + theViewer.addPropertyChangeListener(this); + + TextHelpModel model = theViewer.getModel(); + if (model != null) { + // listen to id changes... + model.addHelpModelListener(this); + // listen to highlight changes... + model.addTextHelpModelListener(this); + } + + html = new JHEditorPane(); + html.addPropertyChangeListener(this); + html.getAccessibleContext().setAccessibleName(HelpUtilities.getString(HelpUtilities.getLocale(html), "access.contentViewer")); + html.setEditable(false); + html.addHyperlinkListener(this); + + // if the model has a current URL then set it + if (model != null) { + URL url = model.getCurrentURL(); + if (url != null) { + try { + html.setPage(url); + } catch (IOException ex) { + // just igonore it + } + } + } + + JScrollPane scroller = new JScrollPane(); + scroller.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.white, + Color.gray)); + vp = scroller.getViewport(); + vp.add(html); + vp.setBackingStoreEnabled(true); + + theViewer.add("Center", scroller); + loadingURL = false; + pendingHighlightsEvent = null; + } + + public void uninstallUI(JComponent c) { + debug("uninstallUI"); + JHelpContentViewer viewer = (JHelpContentViewer) c; + viewer.removePropertyChangeListener(this); + html.removePropertyChangeListener(this); + TextHelpModel model = viewer.getModel(); + if (model != null) { + model.removeHelpModelListener(this); + model.removeTextHelpModelListener(this); + } + viewer.setLayout(null); + viewer.removeAll(); + } + + public Dimension getPreferredSize(JComponent c) { + return PREF_SIZE; + } + + public Dimension getMinimumSize(JComponent c) { + return MIN_SIZE; + } + + public Dimension getMaximumSize(JComponent c) { + // This doesn't seem right. But I'm not sure what to do for now + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public void idChanged(HelpModelEvent e) { + ID id = e.getID(); + URL url = e.getURL(); + TextHelpModel model = theViewer.getModel(); + debug("idChanged("+e+")"); + debug(" = " + id + " " + url); + debug(" my helpModel: "+model); + + model.setDocumentTitle(null); + + // HERE - REMIND - event should be generated after visit + // with the title already in there - epll. + try { + Highlighter h = html.getHighlighter(); + debug("removeAllHighlights"); + h.removeAllHighlights(); + try { + loadingURL = true; + html.setPage(url); + } catch (Exception ex) { + loadingURL = false; + // IGNORE FOR EA2 --- !! - epll + } + debug("html current EditorKit is: "+html.getEditorKit()); + debug("html current ContentType is: "+html.getContentType()); + } catch (Exception e3) { + // e.g. and incorrect URL will generate a nullexception!! + // ignore + debug("Exception geneartated"); + } + debug("done with idChanged"); + } + + private void rebuild() { + debug("rebuild"); + TextHelpModel model = theViewer.getModel(); + if (model == null) { + debug("rebuild-end: model is null"); + return; + } + // The model has changed. I'll need to clear the HTML viewer and + // put in the home page + Highlighter h = html.getHighlighter(); + debug("removeAllHighlights"); + h.removeAllHighlights(); + HelpSet hs = model.getHelpSet(); + // for glossary - not set homeID page - glossary is not synchronized + if(theViewer.getSynch()){ + try { + Map.ID homeID = hs.getHomeID(); + Locale locale = hs.getLocale(); + String name = HelpUtilities.getString(locale, "history.homePage"); + model.setCurrentID(homeID, name, (JHelpNavigator)null); + html.setPage(model.getCurrentURL()); + } catch (Exception e) { + // ignore + } + } + debug("rebuild-end"); + } + + public void propertyChange(PropertyChangeEvent event) { + debug("propertyChange: " + event.getPropertyName() + "\n\toldValue:" + event.getOldValue() + "\n\tnewValue:" + event.getNewValue()); + + if (event.getSource() == theViewer) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + TextHelpModel oldModel = (TextHelpModel) event.getOldValue(); + TextHelpModel newModel = (TextHelpModel) event.getNewValue(); + if (oldModel != null) { + oldModel.removeHelpModelListener(this); + oldModel.removeTextHelpModelListener(this); + } + if (newModel != null) { + newModel.addHelpModelListener(this); + newModel.addTextHelpModelListener(this); + } + rebuild(); + } else if (changeName.equals("font")) { + debug("font changed"); + Font newFont = (Font)event.getNewValue(); + EditorKit ek = html.getEditorKit(); + if (ek instanceof HTMLEditorKit) { + + StringBuffer buf = new StringBuffer(60); + buf.append("body { font: "); + buf.append(newFont.getSize()).append("pt "); + if (newFont.isBold()) { + buf.append("bold "); + } + if (newFont.isItalic()) { + buf.append("italic "); + } + buf.append('"').append(newFont.getFamily()).append('"'); + buf.append(" }"); + String cssData = buf.toString(); + + StyleSheet styleSheet; + + /* Update the default style sheet: */ + styleSheet = ((HTMLEditorKit) ek).getStyleSheet(); + styleSheet.addRule(cssData); + + /* + * Update the current document's style sheet, thus forcing + * the view to be refreshed: + */ + styleSheet = ((HTMLDocument) html.getDocument()).getStyleSheet(); + styleSheet.addRule(cssData); + } + }else if (changeName.equals("clear")) { + html.setText(""); + }else if (changeName.equals("reload")) { + URL url = html.getPage(); + if (url != null) { + try { + html.setPage(url); + } catch (IOException ex) { + // just igonore it + } + } + } + } else if (event.getSource() == html) { + String changeName = event.getPropertyName(); + if (changeName.equals("page")) { + debug("page finished loading"); + loadingURL = false; + if (pendingHighlightsEvent != null) { + debug("Loading the highlights now"); + highlightsChanged(pendingHighlightsEvent); + pendingHighlightsEvent = null; + } + Document doc = html.getDocument(); + String title = (String)doc.getProperty(Document.TitleProperty); + TextHelpModel model = theViewer.getModel(); + model.setDocumentTitle(title); + + // Propogate this to property listeners of the ContentViewer. + // Can't acutally send the real thing because Objects and + // Strings aren't supported. + theViewer.firePropertyChange(event.getPropertyName(), + false, true); + } + } + } + + /** + * Notification of a change relative to a + * hyperlink. + */ + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + // If in a frame do something different + if (e instanceof HTMLFrameHyperlinkEvent) { + ((HTMLDocument)html.getDocument()).processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent)e); + } else { + // Not a frame + linkActivated(e.getURL()); + } + } + } + + /** + * Follows the reference in an + * link. The given url is the requested reference. + * By default this calls <a href="#setPage">setPage</a>, + * and if an exception is thrown the original previous + * document is restored and a beep sounded. If an + * attempt was made to follow a link, but it represented + * a malformed url, this method will be called with a + * null argument. + * + * @param u the URL to follow + */ + protected void linkActivated(URL u) { + debug("linkActivated - URL=" + u ); + Cursor c = html.getCursor(); + Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + html.setCursor(waitCursor); + // workaround for bug #418959 + // if there is an anchor make sure the file doesn't end in "/" or "\" + // if it does then get the current file name and append the ref + String ref = u.getRef(); + if (ref != null) { + String file = u.getFile(); + if (file.endsWith("/") || file.endsWith("\\")) { + u = html.getPage(); + debug("current u=" + u); + file = u.getFile(); + debug("file=" + file); + try { + u = new URL(u.getProtocol(), u.getHost(), + u.getPort(), file + "#" + ref); + } catch (MalformedURLException e2) { + return; + } + debug("new u=" + u); + } + } + SwingUtilities.invokeLater(new PageLoader(u, c)); + } + + /** + * Temporary class that loads synchronously (although + * later than the request so that a cursor change + * can be done). + */ + class PageLoader implements Runnable { + String title = null; + PageLoader(URL u, Cursor c) { + url = u; + cursor = c; + } + + public void run() { + if (url == null) { + // restore the original cursor + html.setCursor(cursor); + + RepaintManager.currentManager(html).markCompletelyDirty(html); + } else { + Document doc= html.getDocument(); + //String title; + try { + html.setPage(url); + loadingURL = true; + doc = html.getDocument(); + title = (String)doc.getProperty(Document.TitleProperty); + String anchor = url.getRef(); + //if the title is not known (Hyperlink without anchor activated) parse title + if(title == null) + title = findTitle(url); + //in case there is an anchor append it to the title + if(anchor != null) + title = title + "-" + anchor; + TextHelpModel model = theViewer.getModel(); + model.setDocumentTitle(title); + ID id = model.getHelpSet().getCombinedMap().getIDFromURL(url); + if (id != null) { + try { + model.setCurrentID(id,title, (JHelpNavigator)null); + } catch (InvalidHelpSetContextException ex) { + model.setCurrentURL(url, title,(JHelpNavigator)null); + } + } else { + model.setCurrentURL(url, title, (JHelpNavigator)null); + } + } catch (IOException ioe) { + loadingURL = false; + html.setDocument(doc); + html.getToolkit().beep(); + } finally { + // schedule the cursor to revert after + // the paint has happended. + url = null; + SwingUtilities.invokeLater(this); + } + } + } + + URL url; + Cursor cursor; + + /** + * Finds the title of HTML document on given URL + * + * @param url The URL of HTML file + * @return The title of the document + */ + private String findTitle(URL url){ + HTMLEditorKit.ParserCallback callback; + try{ + URLConnection conn = url.openConnection(); + Reader rd = new InputStreamReader(conn.getInputStream()); + ParserDelegator parser = new ParserDelegator(); + callback = new Callback(); + parser.parse(rd,callback,true); + }catch (Exception exp){ + System.err.println(exp); + } + return title; + + } + + /** + * Class provided the parser callback + */ + class Callback extends HTMLEditorKit.ParserCallback{ + boolean wasTitle = false; + + public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos){ + if(t.equals(HTML.Tag.TITLE)){ + wasTitle = true; + } + } + public void handleText(char[] data, int pos){ + if(wasTitle){ + title = new String(data); + wasTitle = false; + } + } + + } + } + + + + /** + * Determines if highlights have changed. + * Collects all the highlights and marks the presentation. + * + * @param e The TextHelpModelEvent. + */ + public void highlightsChanged(TextHelpModelEvent e) { + debug("highlightsChanged "+e); + + // if we're loading this url this event will need to wait + // until we're notified that the page has finished loaded. + // we could wait(), but that would prevent the execution of + // other events in this thread. Instead preserve the + // TextHelpModelEvent and recall this method when the notification + // occurs. + if (loadingURL) { + debug("Humm. loadingURL wait a little"); + pendingHighlightsEvent = e; + return; + } + + Highlighter h = html.getHighlighter(); + debug1("removeAllHighlights"); + h.removeAllHighlights(); + + TextHelpModel m = (TextHelpModel) e.getSource(); + TextHelpModel.Highlight highlights[] = m.getHighlights(); + + Highlighter.HighlightPainter p = + new DefaultHighlighter.DefaultHighlightPainter(html.getSelectionColor()); + for (int i=0; i<highlights.length; i++) { + int pos0 = highlights[i].getStartOffset(); + int pos1 = highlights[i].getEndOffset(); + debug(" highlight: "+pos0+", "+pos1); + try { + h.addHighlight(pos0, pos1, p); + + // scroll to the first position + if (i == 0) { + Runnable callScrollToPosition = new ScrollToPosition(html, + pos1); + SwingUtilities.invokeLater(callScrollToPosition); + } + } catch (BadLocationException bl) { + debug("badLocationExcetpion thrown - " + bl); + } + } + RepaintManager.currentManager(html).markCompletelyDirty(html); + } + + private class ScrollToPosition implements Runnable { + private int pos; + private JEditorPane html; + + public ScrollToPosition(JEditorPane html, int pos) { + this.html = html; + this.pos = pos; + } + + public void run() { + try { + Rectangle rec = html.modelToView(pos); + if (rec != null) { + html.scrollRectToVisible(rec); + } + } catch (BadLocationException bl) { + } + } + } + + /** + * For printf debugging. + */ + private final static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicContentViewerUI: " + str); + } + } + private final static boolean debug1 = false; + private static void debug1(String str) { + if (debug1) { + System.out.println("BasicContentViewerUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..34967be9e893a316667bbc843910fa8dffb7fd3e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java @@ -0,0 +1,195 @@ +/* + * @(#)BasicCursorFactory.java 1.11 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf.basic; + +import java.io.*; +import javax.swing.ImageIcon; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.util.ResourceBundle; +import java.util.MissingResourceException; +import java.util.PropertyResourceBundle; + +/** + * Factory object that can vend cursors appropriate for the basic L & F. + * <p> + * + * @version 1.11 10/30/06 + * @author Roger D. Brinkley + */ +public class BasicCursorFactory { + private static Cursor onItemCursor; + private static Cursor dndCursor; + private static BasicCursorFactory theFactory; + + /** + * Returns the OnItem cursor. + */ + public static Cursor getOnItemCursor() { + debug ("getOnItemCursor"); + if (theFactory == null) { + theFactory = new BasicCursorFactory(); + } + if (onItemCursor == null) { + onItemCursor = theFactory.createCursor("OnItemCursor"); + } + return onItemCursor; + } + + /** + * Returns the DnDCursor. + */ + public static Cursor getDnDCursor(){ + debug("getDnDCursor"); + if (theFactory == null) { + theFactory = new BasicCursorFactory(); + } + if (dndCursor == null) { + dndCursor = theFactory.createCursor("DnDCursor"); + } + return dndCursor; + } + + private Cursor createCursor(String name) { + String gifFile = null; + String hotspot = null; + ImageIcon icon; + Point point; + + debug("CreateCursor for " + name); + + // Get the Property file + InputStream is = getClass().getResourceAsStream("images/" + name + ".properties"); + if (is == null) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " not found."); + return null; + } + try { + ResourceBundle resource = new PropertyResourceBundle(is); + gifFile = resource.getString("Cursor.File"); + hotspot = resource.getString("Cursor.HotSpot"); + } catch (MissingResourceException e) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " invalid."); + return null; + } catch (IOException e2) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " invalid."); + return null; + } + + // Create the icon + byte[] buffer = null; + try { + /* Copies resource into a byte array. This is + * necessary because several browsers consider + * Class.getResource a security risk because it + * can be used to load additional classes. + * Class.getResourceAsStream returns raw + * bytes, which JH can convert to an image. + */ + InputStream resource = + getClass().getResourceAsStream(gifFile); + if (resource == null) { + debug(getClass().getName() + "/" + + gifFile + " not found."); + return null; + } + BufferedInputStream in = + new BufferedInputStream(resource); + ByteArrayOutputStream out = + new ByteArrayOutputStream(1024); + buffer = new byte[1024]; + int n; + while ((n = in.read(buffer)) > 0) { + out.write(buffer, 0, n); + } + in.close(); + out.flush(); + + buffer = out.toByteArray(); + if (buffer.length == 0) { + debug("warning: " + gifFile + + " is zero-length"); + return null; + } + } catch (IOException ioe) { + debug(ioe.toString()); + return null; + } + + icon = new ImageIcon(buffer); + + // create the point + int k = hotspot.indexOf(','); + point = new Point(Integer.parseInt(hotspot.substring(0,k)), + Integer.parseInt(hotspot.substring(k+1))); + + debug ("Toolkit fetching cursor"); + try { + + Image image = icon.getImage(); + int width = icon.getIconWidth(); + int height = icon.getIconHeight(); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + Dimension d = toolkit.getBestCursorSize(width, height); + + if ((d.width > width) || (d.height > height)) { + try { + Image bimage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB); + bimage.getGraphics().drawImage(icon.getImage(), 0, 0, icon.getImageObserver()); + image = bimage; + } catch (Exception ex) { + } + } + + return toolkit.createCustomCursor(image, point, name); + + } catch (NoSuchMethodError err) { + // return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + return null; + } + } + + /** + * For printf debugging. + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicCursorFactory: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..6824c6cdb12182fd61abad579391827f5e4bd495 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java @@ -0,0 +1,93 @@ +/* + * @(#)BasicFavoritesCellRenderer.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package javax.help.plaf.basic; + +/** + * Cell Renderer for the favorites UI. + * + * @author Richard Gregor + * @version 1.4 10/30/06 + */ +import javax.swing.*; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import java.awt.*; +import java.net.URL; +import java.util.Locale; +import javax.help.TOCItem; +import javax.help.Map; +import javax.help.HelpUtilities; +import javax.help.Map.ID; +import javax.help.FavoritesItem; + +public class BasicFavoritesCellRenderer extends DefaultTreeCellRenderer { + + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + FavoritesItem item; + + Object o = ((DefaultMutableTreeNode)value).getUserObject(); + String stringValue = ""; + + item = (FavoritesItem) o; + if (item != null) { + stringValue = item.getName(); + } + + // Set the locale of this if there is a lang value + if (item != null) { + Locale locale = item.getLocale(); + if (locale != null) { + setLocale(locale); + } + } + + setText(stringValue); + + if (sel) + setForeground(getTextSelectionColor()); + else + setForeground(getTextNonSelectionColor()); + selected = sel; + + if(leaf) + setIcon(getDefaultLeafIcon()); + else if(expanded) + setIcon(getDefaultOpenIcon()); + else + setIcon(getDefaultClosedIcon()); + + return this; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..eb08a014056ab6f528ae83da6efc9c11393e833a --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java @@ -0,0 +1,1558 @@ +/* + * @(#)BasicFavoritesNavigatorUI.java 1.17 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.plaf.HelpUI; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import java.util.EventObject; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Locale; +import java.util.HashMap; +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.tree.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.io.Reader; +import java.io.Serializable; +import java.net.URL; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.event.ComponentEvent; +import javax.help.Map.ID; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.net.MalformedURLException; +import java.util.HashSet; +import javax.help.event.HelpSetListener; +import javax.help.event.HelpSetEvent; +import java.awt.Cursor; +import java.awt.image.BufferedImage; +import java.awt.geom.Rectangle2D.Float; +import java.awt.geom.Rectangle2D; +import java.awt.geom.AffineTransform; +import java.awt.datatransfer.*; +import java.awt.dnd.*; +import java.awt.dnd.peer.*; +import java.io.IOException; + +/** + * The default UI for JHelpNavigator of type Favorites + * + * @author Richard Gregor + * @version 1.17 10/30/06 + */ + +public class BasicFavoritesNavigatorUI extends HelpNavigatorUI +implements HelpModelListener, TreeSelectionListener, HelpSetListener, +PropertyChangeListener, TreeModelListener, Serializable { + + protected JHelpFavoritesNavigator favorites; + protected JScrollPane sp; + protected FavoritesNode topNode; + protected JTree tree; + private String contentTitle; + protected RuleBasedCollator rbc; + protected String oldText; + protected DefaultMutableTreeNode currentFindNode; + protected Action addAction; + protected Action removeAction; + protected Action cutAction; + protected Action pasteAction; + protected Action copyAction; + protected Action folderAction; + protected JPopupMenu popup; + + private HashMap dataMap = new HashMap(); + // node wich will contain parsed favorites data + private FavoritesNode favNode = null; + // node which contents will be saved + private FavoritesNode rootNode = null; + private Locale locale = null; + private FavoritesNode selectedNode = null; + private FavoritesItem selectedItem = null; + private TreePath selectedTreePath = null; + private Map.ID selectedID = null; + private JMenuItem newFolderMI = null; + private JMenuItem addMI = null; + private JSeparator separatorMI = null; + private JMenuItem cutMI = null; + private JMenuItem copyMI = null; + private JMenuItem pasteMI = null; + private JMenuItem removeMI = null; + private HashMap hsMap = null; + //HasMap with visible node from favNode as key and its related node from rootNode as a value + private HashMap connections = new HashMap(); + /** + * Vector of nodes used in CutAction + */ + private Vector nodeClipboard = new Vector(); + + static private boolean on1dot3 = false; + + static { + try { + // Test if method introduced in 1.3 or greater is available. + Class klass = Class.forName("javax.swing.InputVerifier"); + on1dot3 = (klass != null); + } catch (ClassNotFoundException e) { + on1dot3 = false; + } + } + + + public static ComponentUI createUI(JComponent x) { + return new BasicFavoritesNavigatorUI((JHelpFavoritesNavigator) x); + } + /** + * Creates BasicFavoritesUI for JHelpFavoritesNavigator + */ + public BasicFavoritesNavigatorUI(JHelpFavoritesNavigator b) { + ImageIcon icon = getImageIcon(b.getNavigatorView()); + if (icon != null) { + setIcon(icon); + } else { + setIcon(UIManager.getIcon("FavoritesNav.icon")); + } + } + + public void installUI(JComponent c) { + debug("installUI"); + + locale = HelpUtilities.getLocale(c); + addAction = new AddAction(); + removeAction = new RemoveAction(); + folderAction = new FolderAction(); + favorites = (JHelpFavoritesNavigator)c; + HelpModel model = favorites.getModel(); + + favorites.setLayout(new BorderLayout()); + favorites.addPropertyChangeListener(this); + if (model != null) { + model.addHelpModelListener(this); // for our own changes + model.addPropertyChangeListener(this); // for HelpSet change + HelpSet helpSet = model.getHelpSet(); + if(helpSet != null) + helpSet.addHelpSetListener(this); + } + + topNode = new FavoritesNode(new FavoritesItem("Favorites")); + if (on1dot3) { + // Use drag and drop if available + tree = new FavoritesTree(topNode); + } else { + tree = new JTree(topNode); + } + tree.setEditable(true); + tree.addMouseListener(new PopupListener()); + + cutAction = new CutAction(); + copyAction = new CopyAction(); + pasteAction = new PasteAction(); + + popup = new JPopupMenu(); + + newFolderMI = new JMenuItem((String)folderAction.getValue(folderAction.NAME)); + newFolderMI.addActionListener(folderAction); + popup.add(newFolderMI); + + addMI = new JMenuItem((String)addAction.getValue(addAction.NAME)); + addMI.addActionListener(addAction); + popup.add(addMI); + + separatorMI = new JSeparator(); + popup.add(separatorMI); + + cutMI = new JMenuItem((String)cutAction.getValue(cutAction.NAME)); + cutMI.addActionListener(cutAction); + cutMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,java.awt.Event.CTRL_MASK)); + popup.add(cutMI); + + copyMI = new JMenuItem((String)copyAction.getValue(copyAction.NAME)); + copyMI.addActionListener(copyAction); + copyMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,java.awt.Event.CTRL_MASK)); + popup.add(copyMI); + + pasteMI = new JMenuItem((String)pasteAction.getValue(pasteAction.NAME)); + pasteMI.addActionListener(pasteAction); + pasteMI.setEnabled(false); + pasteMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,java.awt.Event.CTRL_MASK)); + popup.add(pasteMI); + + removeMI = new JMenuItem((String) removeAction.getValue(removeAction.NAME)); + removeMI.addActionListener(removeAction); + + popup.add(removeMI); + + tree.getModel().addTreeModelListener(this); + tree.addTreeSelectionListener(this); + + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.addTreeSelectionListener(this); + + tree.setShowsRootHandles(true); + tree.setRootVisible(false); + + setCellRenderer(favorites.getNavigatorView(), tree); + + sp = new JScrollPane(); + sp.getViewport().add(tree); + + favorites.add("Center", sp); + + reloadData(); + } + + /** + * Sets the desired cell renderer on this tree. This is exposed for redefinition + * by subclases. + */ + protected void setCellRenderer(NavigatorView view, JTree tree) { + tree.setCellRenderer(new BasicFavoritesCellRenderer()); + } + + public void uninstallUI(JComponent c) { + debug("uninstallUI"); + HelpModel model = favorites.getModel(); + + favorites.removePropertyChangeListener(this); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.removeTreeSelectionListener(this); + favorites.setLayout(null); + favorites.removeAll(); + + if (model != null) { + model.removeHelpModelListener(this); + } + + favorites = null; + } + + public Dimension getPreferredSize(JComponent c) { + + return new Dimension(200,100); + + } + + public Dimension getMinimumSize(JComponent c) { + return new Dimension(100,100); + } + + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + + private void reloadData() { + debug("reloadData"); + + //needs refactoring - sholudn't parse each time!!! - only once + + if (favorites.getModel() == null) { + return; + } + + // remove all children + topNode.removeAllChildren(); + + FavoritesView view = (FavoritesView) favorites.getNavigatorView(); + + if (view == null) { + return; + } + + favNode = view.getDataAsTree(); + rootNode = favNode.getDeepCopy(); + + classifyNode(favNode); + while (favNode.getChildCount() > 0) { + // this looks strange but as you add a child to the top node + // it removes the child from the favNode so the getFirstChild + // will always get the first child + topNode.add((DefaultMutableTreeNode)favNode.getFirstChild()); + } + + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + + setVisibility(topNode); + + } + + /** + * Classifies the node. Determines wheter child will be visible or not according to node's HelpSet. + * Hides node without children when its HelpSet is not loaded + * + * @param node The FavoritesNode + */ + private void classifyNode(FavoritesNode node){ + debug("classifyNode"); + + if(node == null) + return; + + HelpModel model = favorites.getModel(); + if(model == null){ + node.removeAllChildren(); + return; + } + HelpSet masterHelpSet = model.getHelpSet(); + if(masterHelpSet == null){ + node.removeAllChildren(); + return; + } + hsMap = new HashMap(); + hsMap.put(masterHelpSet.getTitle(), masterHelpSet); + + fillHelpSetTitles(masterHelpSet); + + // tags node's children wheter they are visible or not + classifyChildren(node); + + } + + /** + * Fills HashMap with actual HelpSets and their titles + * + * @param masterHelpSet The master HelpSet + */ + private void fillHelpSetTitles(HelpSet masterHelpSet){ + for(Enumeration helpSets = masterHelpSet.getHelpSets();helpSets.hasMoreElements();){ + HelpSet hs = (HelpSet) helpSets.nextElement(); + if(hs != null){ + hsMap.put(hs.getTitle(), hs); + debug(" fill title: "+hs.getTitle()); + fillHelpSetTitles(hs); + } + } + } + + /** + * Classifies children of node + * + * @param node The FavoritesNode + */ + private void classifyChildren(FavoritesNode node){ + debug("classifyChildren: "+node); + + if(node == null) + return; + + boolean skipChild = true; + + for(Enumeration children = node.preorderEnumeration();children.hasMoreElements();){ + FavoritesNode chnode = (FavoritesNode)children.nextElement(); + + // Skip the first entry because it is node and we don't need + // to classify the node only it's children + if (skipChild) { + skipChild = false; + continue; + } + + // Add this child node to the root node. + + // Make a copy of the child node for the rootNode + FavoritesNode copy = chnode.getDeepCopy(); + + // establish the connection between the chnode and the copy + connections.put(chnode, copy); + // properly connect it to the childs corresponding parent in the + // rootnode. + FavoritesNode rootParent = (FavoritesNode)connections.get(chnode.getParent()); + if (rootParent == null) { + rootParent = rootNode; + } + rootParent.add(copy); + + // Now on to seeing if the item + FavoritesItem item = (FavoritesItem)chnode.getUserObject(); + debug("classify item: "+ item); + //shouldn't happen + if(item == null){ + debug("item is null : fillDataMap"); + continue; + } + String target = item.getTarget(); + String hsTitle = item.getHelpSetTitle(); + if(!hsMap.containsKey(hsTitle)){ + if(chnode.getVisibleChildCount() == 0){ + if(item.emptyInitState() && item.isFolder()){ + debug("empty init state"); + continue; + } + //chnode.removeFromParent(); + item.setVisible(false); + continue; + } + } + + if(target == null){ + debug("target is null:fillDataMap"); + continue; + } + + Map.ID id = null; + try{ + id = Map.ID.create(target, (HelpSet)hsMap.get(hsTitle)); + }catch(BadIDException ep){ + debug(ep.getMessage()); + continue; + } + + debug("put to the dataMap: "+item); + dataMap.put(item,id); + } + + //clear node + Vector toRemove = new Vector(); + Enumeration nodesToRem = node.breadthFirstEnumeration(); + while(nodesToRem.hasMoreElements()) { + FavoritesNode fn = (FavoritesNode)nodesToRem.nextElement(); + if(!fn.isVisible()){ + debug ("remove node:" +(FavoritesItem)fn.getUserObject()); + toRemove.addElement(fn); + } + } + for (int i=0; i < toRemove.size(); i++) { + debug("removing " + toRemove.elementAt(i)); + try { + node.remove((DefaultMutableTreeNode) toRemove.elementAt(i)); + } catch (IllegalArgumentException iae) { + // ignore - supernode is already removed + } + } + + } + + /** + * Expands entry path and entry itself( when entry is not empty) for specific id + * + * @param target The target of entry + */ + + private void expand(String target){ + debug("expand called"); + //find all nodes with certain id + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug("expandPath :"+node); + if(node.getChildCount() > 0){ + DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild(); + TreePath path = new TreePath(child.getPath()); + tree.makeVisible(path); + } + else{ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + //tree.scrollPathToVisible(path); + tree.makeVisible(path); + } + } + } + + /** + * Returns all nodes with certain id + * + * @param target The target of entry + * + */ + private Vector findNodes(String target){ + Enumeration nodes = topNode.preorderEnumeration(); + DefaultMutableTreeNode node = null; + Vector nodeFound = new Vector(); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug(" node :"+ node.toString()); + if(node != null){ + FavoritesItem favoritesItem = (FavoritesItem)node.getUserObject(); + if(favoritesItem == null) + debug("favoritesItem is null"); + else{ + //Map.ID id = favoritesItem.getID(); + Map.ID id = (Map.ID)dataMap.get(favoritesItem); + if(id != null){ + debug("id name :"+id.id); + debug("target :"+target); + Map.ID itemID = null; + try{ + itemID = Map.ID.create(target,favorites.getModel().getHelpSet()); + } + catch(BadIDException exp){ + System.err.println("Not valid ID :"+target ); + break; + } + if(id.equals(itemID)) + nodeFound.addElement(node); + } + } + } + } + + return nodeFound; + } + + /** + * Collapses entry specified by id. If entry is empty collapses it's parent. + * + * @param target The target of entry + */ + + private void collapse(String target){ + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + debug("collapse called"); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + if(node.getChildCount() > 0){ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + tree.collapsePath(path); + tree.collapseRow(tree.getRowForPath(path)); + } + else{ + DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent(); + TreePath path = new TreePath(parent.getPath()); + tree.collapseRow(tree.getRowForPath(path)); + } + } + } + + // Make all nodes visible + + private void setVisibility(DefaultMutableTreeNode node) { + tree.expandPath(new TreePath(node.getPath())); + if (! node.isLeaf()) { + int max = node.getChildCount(); + for (int i=0; i<max; i++) { + setVisibility((DefaultMutableTreeNode)node.getChildAt(i)); + } + } + } + + /** + * Processes and idChanged event. In this navigator works with url too. + * + * @param e The HelpModelEvent + */ + + public void idChanged(HelpModelEvent e) { + debug("idChanged("+e+")"); + + //next values + ID id = e.getID(); + contentTitle = e.getHistoryName(); + URL nurl = e.getURL(); + String nURL = null; + if (nurl != null) + nURL = nurl.toExternalForm(); + + //current values + ID currentID = null; + String currentURL = null; + String currentName = null; + FavoritesItem item = null; + + HelpModel helpModel = favorites.getModel(); + + + if (e.getSource() != helpModel) { + debug("Internal inconsistency!"); + debug(" "+e.getSource()+" != "+helpModel); + throw new Error("Internal error"); + } + + TreePath s = tree.getSelectionPath(); + if (s != null) { + Object o = s.getLastPathComponent(); + // should require only a TreeNode + if (o instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o; + item = (FavoritesItem) tn.getUserObject(); + if (item != null){ + currentID = (Map.ID) dataMap.get(item); + currentURL = item.getURLSpec(); + currentName = item.getName(); + } + if((currentName != null) && (currentName.equals(contentTitle))){ + if(currentID != null) + if(currentID.equals(id)) + return; + if(currentURL != null) + if(currentURL.equals(nURL)) + return; + } + } + } + + DefaultMutableTreeNode node = null; + + node = findID(topNode, id); + if(node == null) { + node = findURL(topNode, nURL); + } + + if (node == null) { + // node doesn't exist. Need to clear the selection. + tree.clearSelection(); + return; + } + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + } + + private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) { + debug("findID: ("+id+")"); + debug(" node: "+node); + + // check on the id + if (id == null) { + return null; + } + FavoritesItem item = (FavoritesItem) node.getUserObject(); + Map.ID itemID = (Map.ID) dataMap.get(item); + if (itemID != null) { + ID testID = itemID; + debug(" testID: "+testID); + if (testID != null && testID.equals(id)) { + return node; + } + } + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = findID(tmp, id); + if (test != null) { + return test; + } + } + return null; + } + /** + * Finds the subnode with certain url and name + */ + private DefaultMutableTreeNode findURL(DefaultMutableTreeNode node, String urlSpec){ + debug(" findURL: "+ urlSpec); + + if(urlSpec == null) + return null; + + for(Enumeration children = node.children(); children.hasMoreElements();){ + DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement(); + FavoritesItem childItem = (FavoritesItem) child.getUserObject(); + String childName = childItem.getName(); + String childURL = childItem.getURLSpec(); + if(urlSpec.equals(childURL)) + return child; + else + findURL(child,urlSpec); + } + return null; + } + + /** + * Finds the subnode with certain id and name + */ + + public void valueChanged(TreeSelectionEvent e) { + + selectedTreePath = e.getNewLeadSelectionPath(); + if (selectedTreePath == null) { + selectedNode = null; + return; + } + selectedNode = + (FavoritesNode)selectedTreePath.getLastPathComponent(); + if (selectedNode != null){ + selectedItem = (FavoritesItem)selectedNode.getUserObject(); + selectedID = (Map.ID)dataMap.get(selectedItem); + } + + HelpModel helpModel = favorites.getModel(); + HelpSet hs = helpModel.getHelpSet(); + + debug("ValueChanged: "+e); + debug(" model: "+helpModel); + if(helpModel == null) + return; + // send selected items into navigator + TreeItem[] items = null; + TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + removeAction.setEnabled(true); + items = new TreeItem[paths.length]; + for (int i = 0; i < paths.length; i++) { + if (paths[i] != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + FavoritesItem favItem = (FavoritesItem) node.getUserObject(); + // need to normalize this item so it looks like a real TreeItem + try { + String target = favItem.getTarget(); + if (target != null) { + ID id = Map.ID.create(favItem.getTarget(), hs); + favItem.setID(id); + } + } catch (BadIDException ee) { + } + items[i] = (TreeItem) favItem; + } + } + }else{ + removeAction.setEnabled(false); + pasteAction.setEnabled(false); + pasteMI.setEnabled(false); + return; + } + favorites.setSelectedItems(items); + + // change current id only if one item is selected + if (items != null && items.length == 1) { + FavoritesItem item = (FavoritesItem) items[0]; + if (item != null) { + Map.ID itemID = (Map.ID) dataMap.get(item); + if(itemID != null){ + debug("itemID: "+itemID); + try{ + // helpmodel.setCurrentID(item.getID()); + helpModel.setCurrentID(itemID, item.getName(), (JHelpNavigator)favorites); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + }else{ + if(item.getURLSpec() != null){ + try{ + URL url = new URL(item.getURLSpec()); + helpModel.setCurrentURL(url,item.getName(),(JHelpNavigator)favorites); + }catch(MalformedURLException ep){ + System.err.println(ep); + } + } + } + } + } + } + + public void propertyChange(PropertyChangeEvent event) { + debug("propertyChange: " + event.getSource() + " " + + event.getPropertyName()); + + if (event.getSource() == favorites) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + debug("model changed"); + reloadData(); + + } else if (changeName.equals("font")) { + debug("Font change"); + Font newFont = (Font)event.getNewValue(); + tree.setFont(newFont); + RepaintManager.currentManager(tree).markCompletelyDirty(tree); + } else if(changeName.equals("expand")){ + debug("Expand change"); + expand((String)event.getNewValue()); + } else if(changeName.equals("collapse")){ + debug("Collapse change"); + collapse((String)event.getNewValue()); + } else if(changeName.equals("navigatorChange")){ + debug("Navigator change"); + tree.clearSelection(); + } + + // changes to UI property? + + }else if (favorites != null){ + if (event.getSource() == favorites.getModel()) { + String changeName = event.getPropertyName(); + if( changeName.equals("helpSet")) { + reloadData(); + } + } + } + } + + public void helpSetAdded(HelpSetEvent ev){ + debug("HelpSet added"); + reloadData(); + } + + public void helpSetRemoved(HelpSetEvent ev){ + debug("HelpSet removed"); + reloadData(); + } + + /** + * Saves favorites to the file + */ + public void saveFavorites(){ + FavoritesView view = (FavoritesView)favorites.getNavigatorView(); + view.saveFavorites(rootNode); + } + + public void treeStructureChanged(javax.swing.event.TreeModelEvent treeModelEvent) { + debug("tree structure changed"); + } + + public void treeNodesInserted(javax.swing.event.TreeModelEvent treeModelEvent) { + debug("node inserted"); + int place = -1; + FavoritesNode parent = (FavoritesNode) treeModelEvent.getTreePath().getLastPathComponent(); + Object nodes[] = treeModelEvent.getChildren(); + int[] indices = treeModelEvent.getChildIndices(); + int firstIndex = indices[0]; + debug("index first "+firstIndex); + int lastIndex = (indices.length + firstIndex) - 1; + FavoritesNode rootParent = (FavoritesNode)connections.get(parent); + if(rootParent == null) + rootParent = rootNode; + + debug("root parent "+rootParent); + //nodes were inserted into first place in parent + if(firstIndex == 0){ + if(rootParent.getChildCount() == 0) + place = 0; + else{ + for(Enumeration en = rootParent.children(); en.hasMoreElements();){ + FavoritesNode node = (FavoritesNode)en.nextElement(); + if(node.isVisible()){ + debug("is visible : "+node); + place = rootParent.getIndex(node); + break; + } + } + } + //insert nodes in node place + if(place >= 0){ + for(int j = nodes.length - 1; j >= 0; j--){ + FavoritesNode copy = ((FavoritesNode) nodes[j]).getDeepCopy(); + rootParent.insert((DefaultMutableTreeNode)copy,place); + connections.put((FavoritesNode)nodes[j],copy); + } + } + + }else if (firstIndex > 0){ + //find what is before + FavoritesNode nodeBefore = (FavoritesNode)parent.getChildAt(firstIndex - 1); + FavoritesNode rootNode = (FavoritesNode)connections.get(nodeBefore); + place = rootParent.getIndex(rootNode)+1; + for(int k = nodes.length - 1; k >= 0; k--){ + FavoritesNode copyNode = ((FavoritesNode)nodes[k]).getDeepCopy(); + rootParent.insert((DefaultMutableTreeNode)copyNode,place); + connections.put((FavoritesNode)nodes[k],copyNode); + } + } + } + + public void treeNodesRemoved(javax.swing.event.TreeModelEvent treeModelEvent) { + debug("nodes removed"); + Object nodes[] = treeModelEvent.getChildren(); + for(int i = 0; i < nodes.length; i++){ + FavoritesNode originalNode = (FavoritesNode)nodes[i]; + FavoritesNode remNode = (FavoritesNode)connections.get(originalNode); + if(remNode != null) + remNode.removeFromParent(); + } + } + + public void treeNodesChanged(javax.swing.event.TreeModelEvent treeModelEvent) { + debug("node changed"); + TreeCellEditor editor = tree.getCellEditor(); + Object newName = editor.getCellEditorValue(); + + if((newName instanceof String) && selectedItem != null){ + debug("new name"); + //data of old item + Map.ID itemID = (Map.ID)dataMap.get(selectedItem); + //remove old data from dataMap + dataMap.remove(selectedItem); + FavoritesNode fromRootNode = (FavoritesNode)connections.get(getSelectedNode()); + //change name of old Item + selectedItem.setName((String)newName); + selectedNode.setUserObject(selectedItem); + if(fromRootNode != null){ + FavoritesItem fromRootItem = (FavoritesItem) fromRootNode.getUserObject(); + fromRootItem.setName((String)newName); + } + //put data to the dataMap + dataMap.put(selectedItem,itemID); + saveFavorites(); + } + } + + /** + * Returns the selected node + * + */ + public FavoritesNode getSelectedNode() { + return selectedNode; + } + + /** + * AddAction class. + * + */ + public class AddAction extends AbstractAction{ + + public AddAction(){ + super(HelpUtilities.getString(locale, "favorites.add"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/addToFav.gif")); + } + + public void actionPerformed(ActionEvent ev){ + debug("add"); + + String target = null; + String hstitle = null; + FavoritesItem favorite = null; + HelpModel helpModel = favorites.getModel(); + HelpSet hs = helpModel.getHelpSet(); + + Map.ID ID = helpModel.getCurrentID(); + URL url = helpModel.getCurrentURL(); + if(ID != null){ + target = ID.id; + hstitle = ID.hs.getTitle(); + } + if(hstitle == null){ + // need to determine the helpset title by looking at the + // starting URL of the + hstitle = getHelpSetTitle(hs, url); + if (hstitle == null) { + hstitle= hs.getTitle(); + } + } + String urlSpec = null; + if(target == null) { + urlSpec = url.toExternalForm(); + } + favorite = new FavoritesItem(contentTitle, target, urlSpec, + hstitle, Locale.getDefault()); + dataMap.put(favorite,ID); + + FavoritesNode node = new FavoritesNode(favorite); + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + model.insertNodeInto(node, topNode, topNode.getChildCount()); + + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + + saveFavorites(); + } + + /** + * retuns a helpset title for a given url + */ + private String getHelpSetTitle(HelpSet hs, URL url) { + URL baseURL = hs.getHelpSetURL(); + String urlExternal = url.toExternalForm(); + String baseURLExternal = baseURL.toExternalForm(); + if (urlExternal.startsWith(baseURLExternal)) { + return hs.getTitle(); + } + Enumeration helpsets = hs.getHelpSets(); + String title = null; + while (helpsets.hasMoreElements()) { + HelpSet testHS = (HelpSet) helpsets.nextElement(); + title = getHelpSetTitle(testHS, url); + if (title != null) { + break; + } + } + return title; + } + + } + + /** + * Returns the Add action + * + */ + public Action getAddAction(){ + return addAction; + } + + /** + * RemoveAction class. + * + */ + public class RemoveAction extends AbstractAction{ + + public RemoveAction(){ + super(HelpUtilities.getString(locale, "favorites.remove"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/remove.gif")); + } + + public void actionPerformed(ActionEvent ev){ + debug("remove"); + DefaultMutableTreeNode node = null; + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + TreePath[] paths = tree.getSelectionPaths(); + for(int i = 0 ; i < paths.length; i++){ + if(paths[i] != null){ + node = (DefaultMutableTreeNode)paths[i].getLastPathComponent(); + model.removeNodeFromParent(node); + if(node != null){ + FavoritesItem item = (FavoritesItem)node.getUserObject(); + dataMap.remove(item); + } + } + saveFavorites(); + } + } + } + + /** + * Returns the RemoveAction object + */ + public Action getRemoveAction(){ + return removeAction; + } + + /** + * FolderAction class. + * + */ + public class FolderAction extends AbstractAction{ + + public FolderAction(){ + super(HelpUtilities.getString(locale, "favorites.folder"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/folder.gif")); + } + + public void actionPerformed(ActionEvent ev){ + FavoritesItem favoriteFolder = new FavoritesItem(HelpUtilities.getString(locale, "favorites.folder")); + favoriteFolder.setAsFolder(); + FavoritesNode node = new FavoritesNode(favoriteFolder); + TreePath nodePath = tree.getSelectionPath(); + TreeNode parent = null; + if(nodePath == null) + parent = topNode; + else{ + FavoritesNode selNode = (FavoritesNode)nodePath.getLastPathComponent(); + parent = selNode.getParent(); + } + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + model.insertNodeInto(node,(DefaultMutableTreeNode)parent,parent.getChildCount()); + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + saveFavorites(); + } + } + + /** + * Returns the FolderAction object + */ + public Action getFolderAction(){ + return folderAction; + } + + /** + * CutAction class. + */ + public class CutAction extends AbstractAction{ + + public CutAction(){ + super(HelpUtilities.getString(locale,"favorites.cut")); + } + + public void actionPerformed(ActionEvent ev){ + debug("cut"); + DefaultMutableTreeNode node = null; + nodeClipboard.removeAllElements(); + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + TreePath[] paths = tree.getSelectionPaths(); + for(int i = 0 ; i < paths.length; i++){ + if(paths[i] != null){ + node = (DefaultMutableTreeNode)paths[i].getLastPathComponent(); + if(node != null){ + FavoritesItem item = (FavoritesItem)node.getUserObject(); + nodeClipboard.add(node); + } + model.removeNodeFromParent(node); + } + } + saveFavorites(); + pasteMI.setEnabled(true); + } + } + + /** + * Returns the CutAction object + */ + public Action getCutAction(){ + return cutAction; + } + + /** + * PasteAction class. + */ + public class PasteAction extends AbstractAction{ + + public PasteAction(){ + super(HelpUtilities.getString(locale,"favorites.paste")); + } + + public void actionPerformed(ActionEvent ev){ + debug("paste"); + + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + TreePath path = tree.getSelectionPath(); + FavoritesNode node = (FavoritesNode)path.getLastPathComponent(); + if(node != null){ + if(node.getAllowsChildren()){ + for(Enumeration nodes = nodeClipboard.elements(); nodes.hasMoreElements();){ + model.insertNodeInto((DefaultMutableTreeNode)nodes.nextElement(),(DefaultMutableTreeNode)node,node.getChildCount()); + } + } + else{ + DefaultMutableTreeNode parent = (DefaultMutableTreeNode)node.getParent(); + if(parent == null) + return; + int index = parent.getIndex(node); + for(Enumeration en = nodeClipboard.elements(); en.hasMoreElements();index++){ + model.insertNodeInto((DefaultMutableTreeNode)en.nextElement(),parent,index); + } + } + saveFavorites(); + } + + } + } + + /** + * Returns the PasteAction object + */ + public Action getPasteAction(){ + return pasteAction; + } + + /** + * CopyAction class. + */ + public class CopyAction extends AbstractAction{ + + public CopyAction(){ + super(HelpUtilities.getString(locale,"favorites.copy")); + } + + public void actionPerformed(ActionEvent ev){ + debug("paste"); + + DefaultMutableTreeNode node = null; + nodeClipboard.removeAllElements(); + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + TreePath[] paths = tree.getSelectionPaths(); + for(int i = 0 ; i < paths.length; i++){ + if(paths[i] != null){ + node = (DefaultMutableTreeNode)paths[i].getLastPathComponent(); + if(node != null){ + FavoritesItem item = (FavoritesItem)node.getUserObject(); + FavoritesNode copy = ((FavoritesNode)node).getDeepCopy(); + nodeClipboard.add(copy); + } + } + } + saveFavorites(); + pasteMI.setEnabled(true); + } + } + + /** + * Returns the CopyAction Object + */ + public Action getCopyAction(){ + return copyAction; + } + + /** + * PopupListener class + */ + public class PopupListener extends MouseAdapter{ + + public void mousePressed(MouseEvent e){ + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e){ + maybeShowPopup(e); + } + + private void maybeShowPopup(MouseEvent e) { + TreePath path = tree.getSelectionPath(); + TreePath clickPath = tree.getPathForLocation(e.getX(),e.getY()); + if (e.isPopupTrigger()) { + if (path != null && path.equals(clickPath)) { + separatorMI.setVisible(true); + cutMI.setVisible(true); + copyMI.setVisible(true); + pasteMI.setVisible(true); + removeMI.setVisible(true); + } else { + separatorMI.setVisible(false); + cutMI.setVisible(false); + copyMI.setVisible(false); + pasteMI.setVisible(false); + removeMI.setVisible(false); + } + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + } + + /** + * Class for JTree supported D&D features. + */ + public class FavoritesTree extends JTree implements DragGestureListener, DropTargetListener, DragSourceListener { + + protected Map.ID selectedID = null; + + private DragSource dragSource = null; + private DragSourceContext dragSourceContext = null; + private Point cursorLocation = null; + private TreePath pathSource; + private BufferedImage ghostImage; + private Point offset = new Point(); + private Point ptLast = new Point(); + private Rectangle2D ghostRect = new Rectangle2D.Float(); + + /** + * Data object of selected FavoritesNode + */ + private Map.ID hashCandidate; + /** + * Custom cursor + */ + private Cursor dndCursor; + + /** + * Creates FavoritesTree + * + * @param root The root node of the tree + */ + public FavoritesTree(FavoritesNode root) { + super(root); + + setEditable(true); + + dragSource = DragSource.getDefaultDragSource(); + + DragGestureRecognizer dgr = + dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_COPY_OR_MOVE,this); + + dgr.setSourceActions((dgr.getSourceActions()) &~ (InputEvent.BUTTON3_MASK)); + + DropTarget dropTarget = new DropTarget(this, this); + + Toolkit tk = this.getToolkit(); + if(tk.getBestCursorSize(16,16).equals(new Dimension(64,64))) + dndCursor = (Cursor) UIManager.get("HelpDnDCursor"); + if(dndCursor == null) + debug("cursor is null"); + putClientProperty("JTree.lineStyle", "None"); + } + + public void dragGestureRecognized(DragGestureEvent e) { + FavoritesNode dragNode = getSelectedNode(); + if (dragNode != null) { + + ghostImage = createGhostImage(e); + Transferable transferable = (Transferable) dragNode.getUserObject(); + hashCandidate = (Map.ID)dataMap.get((FavoritesItem)transferable); + + Cursor cursor = DragSource.DefaultCopyDrop; + int action = e.getDragAction(); + if(action == DnDConstants.ACTION_MOVE){ + debug("action move"); + cursor = DragSource.DefaultMoveDrop; + } + + dragSource.startDrag(e,dndCursor,ghostImage,new Point(5,5), transferable,this); + } + } + + private BufferedImage createGhostImage(DragGestureEvent e){ + debug("createGhostImage"); + + BufferedImage ghostImage = null; + Point ptDragOrigin = e.getDragOrigin(); + TreePath path = getPathForLocation(ptDragOrigin.x, ptDragOrigin.y); + if (path == null) + return ghostImage; + + Rectangle raPath = getPathBounds(path); + offset.setLocation(ptDragOrigin.x-raPath.x, ptDragOrigin.y-raPath.y); + + JLabel lbl = (JLabel) getCellRenderer().getTreeCellRendererComponent + (this,path.getLastPathComponent(),false, isExpanded(path),getModel().isLeaf(path.getLastPathComponent()),0,false); + lbl.setSize((int)raPath.getWidth(), (int)raPath.getHeight()); + + ghostImage = new BufferedImage((int)raPath.getWidth(), (int)raPath.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D g2 = ghostImage.createGraphics(); + + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.5f)); + lbl.paint(g2); + + Icon icon = lbl.getIcon(); + int nStartOfText = (icon == null) ? 0 : icon.getIconWidth()+lbl.getIconTextGap(); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 0.5f)); + g2.setPaint(new GradientPaint(nStartOfText, 0, SystemColor.controlShadow, + getWidth(), 0, new Color(255,255,255,0))); + g2.fillRect(nStartOfText, 0, getWidth(), ghostImage.getHeight()); + + g2.dispose(); + + return ghostImage; + } + + public void dragDropEnd(DragSourceDropEvent dsde) { + debug("dragDropEnd"); + } + + public void dragEnter(DragSourceDragEvent dsde) { + debug("dragEnter"); + setCursor(dsde); + } + + public void dragOver(DragSourceDragEvent dsde) { + debug("drag over"); + setCursor(dsde); + } + + public void dropActionChanged(DragSourceDragEvent dsde) { + debug("dropActionChanged"); + setCursor(dsde); + } + + public void dragExit(DragSourceEvent dsde) { + debug("dragExit"); + } + + /** + * Sets appropriate cursor type according to event + * + * @param dsde DrageSourceDrageEvent + */ + private void setCursor(DragSourceDragEvent dsde) { + + if (cursorLocation == null) return; + + TreePath destinationPath = + getPathForLocation(cursorLocation.x, cursorLocation.y); + + DragSourceContext dsc = dsde.getDragSourceContext(); + + if (testDropTarget(destinationPath, selectedTreePath) == null){ + dsc.setCursor(DragSource.DefaultCopyDrop); + + } + else { + dsc.setCursor(DragSource.DefaultCopyNoDrop); + } + } + + public void drop(DropTargetDropEvent e) { + debug("drop"); + try { + Transferable tr = e.getTransferable(); + + if (!tr.isDataFlavorSupported( FavoritesItem.FAVORITES_FLAVOR)){ + debug("drop rejected not data flavor"); + e.rejectDrop(); + } + + FavoritesItem childInfo = (FavoritesItem) tr.getTransferData( FavoritesItem.FAVORITES_FLAVOR ); + Point loc = e.getLocation(); + TreePath destinationPath = getPathForLocation(loc.x, loc.y); + + final String msg = testDropTarget(destinationPath, selectedTreePath); + if (msg != null) { + e.rejectDrop(); + debug("Error : "+msg); + return; + } + + FavoritesNode newParent = + (FavoritesNode) destinationPath.getLastPathComponent(); + + debug("new parent: "+newParent); + //get old parent node + FavoritesNode oldParent = (FavoritesNode) getSelectedNode().getParent(); + + FavoritesNode selNode = (FavoritesNode) getSelectedNode(); + FavoritesItem selItem = (FavoritesItem) selNode.getUserObject(); + + FavoritesNode newNode = selNode.getDeepCopy(); + + int action = e.getDropAction(); + boolean copyAction = (action == DnDConstants.ACTION_COPY); + debug("copy action: "+ copyAction); + //make new child node + FavoritesNode newChild = new FavoritesNode(childInfo); + debug("new child: "+newChild); + try { + if (!copyAction){ + FavoritesNode fromRootNode = (FavoritesNode)connections.get(getSelectedNode()); + if(fromRootNode != null) + fromRootNode.removeFromParent(); + oldParent.remove(getSelectedNode()); + } + DefaultTreeModel model = (DefaultTreeModel)getModel(); + + if (!newParent.getAllowsChildren()){ + TreeNode parent = newParent.getParent(); + if(parent != null){ + int index = parent.getIndex(newParent); + model.insertNodeInto(newNode,(DefaultMutableTreeNode)parent, index+1); + } + }else + model.insertNodeInto(newNode,newParent,newParent.getChildCount()); + + if (copyAction) + e.acceptDrop(DnDConstants.ACTION_COPY); + else e.acceptDrop(DnDConstants.ACTION_MOVE); + } + catch (java.lang.IllegalStateException ils) { + debug("drop ejected"); + e.rejectDrop(); + } + + e.getDropTargetContext().dropComplete(true); + + FavoritesItem newItem = (FavoritesItem) newNode.getUserObject(); + dataMap.put(newItem, hashCandidate); + DefaultTreeModel model = (DefaultTreeModel) getModel(); + model.reload(oldParent); + model.reload(newParent); + TreePath parentPath = new TreePath(newParent.getPath()); + expandPath(parentPath); + saveFavorites(); + } + catch (IOException io) { + e.rejectDrop(); + debug("drop rejected" + io); + } + catch (UnsupportedFlavorException ufe) { + e.rejectDrop(); + debug("drop rejected: "+ ufe); + } + } + + public void dragEnter(DropTargetDragEvent e) { + } + + public void dragExit(DropTargetEvent e) { + if (!DragSource.isDragImageSupported()) { + repaint(ghostRect.getBounds()); + } + } + + public void dragOver(DropTargetDragEvent e) { + + Point pt = e.getLocation(); + if (pt.equals(ptLast)) + return; + + ptLast = pt; + + Point cursorLocationBis = e.getLocation(); + TreePath destinationPath = getPathForLocation(cursorLocationBis.x, cursorLocationBis.y); + + Graphics2D g2 = (Graphics2D) getGraphics(); + + if(testDropTarget(destinationPath, selectedTreePath) == null){ + e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); + if (!DragSource.isDragImageSupported()) { + paintImmediately(ghostRect.getBounds()); + ghostRect.setRect(pt.x - offset.x, pt.y - offset.y, ghostImage.getWidth(), ghostImage.getHeight()); + g2.drawImage(ghostImage, AffineTransform.getTranslateInstance(ghostRect.getX(), ghostRect.getY()), null); + } + }else + e.rejectDrag(); + } + + public void dropActionChanged(DropTargetDragEvent e) { + } + + /** + * Tests whether drop location is valid or not + * + * @param destination The destination path + * @param dropper The path for the node to be dropped + * @return Null if no problems, otherwise an explanation + */ + private String testDropTarget(TreePath destination, TreePath dropper) { + + boolean destinationPathIsNull = destination == null; + if (destinationPathIsNull){ + return "Invalid drop location."; + //remove ghostLikeImage + } + + FavoritesNode node = (FavoritesNode) destination.getLastPathComponent(); + + if (destination.equals(dropper)) + return "Destination cannot be same as source"; + + + if ( dropper.isDescendant(destination)) + return "Destination node cannot be a descendant."; + + + if ( dropper.getParentPath().equals(destination)) + return "Destination node cannot be a parent."; + + return null; + } + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicFavoritesNavigatorUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..bcb8bb689bc8218f73c4266c84601ba8a969198c --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java @@ -0,0 +1,747 @@ +/* + * @(#)BasicGlossaryNavigatorUI.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.plaf.HelpUI; +import javax.help.plaf.basic.BasicHelpUI; +import javax.help.plaf.basic.BasicIndexCellRenderer; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import java.util.EventObject; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.tree.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.io.Reader; +import java.io.Serializable; +import java.net.URL; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.help.Map.ID; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.util.Locale; +import java.util.Stack; + +/** + * The default UI for JHelpNavigator of type Glossary. + * + * @author Roger D. Brinkley + * @author Richard Gregor + * @version 1.8 10/30/06 + */ + +public class BasicGlossaryNavigatorUI extends HelpNavigatorUI +implements HelpModelListener, TreeSelectionListener, +PropertyChangeListener, ActionListener, Serializable { + protected JHelpGlossaryNavigator glossary; + protected JScrollPane sp; + protected DefaultMutableTreeNode topNode; + protected JTree tree; + protected JTextField searchField; + protected RuleBasedCollator rbc; + protected String oldText; + protected DefaultMutableTreeNode currentFindNode; + protected JHelpContentViewer viewer; + + /** + * Creates UI + */ + public static ComponentUI createUI(JComponent x) { + return new BasicGlossaryNavigatorUI((JHelpGlossaryNavigator) x); + } + + public BasicGlossaryNavigatorUI(JHelpGlossaryNavigator b) { + ImageIcon icon = getImageIcon(b.getNavigatorView()); + if (icon != null) { + setIcon(icon); + } else { + setIcon(UIManager.getIcon("GlossaryNav.icon")); + } + } + + public void installUI(JComponent c) { + debug("installUI"); + + glossary = (JHelpGlossaryNavigator)c; + HelpModel model = glossary.getModel(); + + glossary.setLayout(new BorderLayout()); + glossary.addPropertyChangeListener(this); + if (model != null) { + //model.addHelpModelListener(this); // for our own changes + } + + topNode = new DefaultMutableTreeNode(); + + JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c), + "index.findLabel")); + searchField= new JTextField(); + search.setLabelFor(searchField); + + searchField.addActionListener(this); + JPanel box = new JPanel(); + box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS)); + box.add(search); + box.add(searchField); + + glossary.add("North", box); + + tree = new JTree(topNode); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.addTreeSelectionListener(this); + tree.setShowsRootHandles(true); + tree.setRootVisible(false); + + setCellRenderer(glossary.getNavigatorView(), tree); + + sp = new JScrollPane(); + sp.getViewport().add(tree); + + JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false); + splitPane.setOneTouchExpandable(true); + + splitPane.setTopComponent(sp); + + viewer = new JHelpContentViewer(model.getHelpSet()); + viewer.setSynch(false); + splitPane.setBottomComponent(viewer); + + glossary.add("Center",splitPane); + splitPane.setDividerLocation(180); + + reloadData(); + } + + /** + * Sets the desired cell renderer on this tree. + * This is exposed for redefinition + * by subclases. + */ + protected void setCellRenderer(NavigatorView view, JTree tree) { + tree.setCellRenderer(new BasicIndexCellRenderer()); + } + + /** + * Uninstalls UI + */ + public void uninstallUI(JComponent c) { + debug("uninstallUI"); + HelpModel model = glossary.getModel(); + + glossary.removePropertyChangeListener(this); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.removeTreeSelectionListener(this); + glossary.setLayout(null); + glossary.removeAll(); + + if (model != null) { + model.removeHelpModelListener(this); + } + + glossary = null; + } + + + public Dimension getPreferredSize(JComponent c) { + + return new Dimension(200,100); + + } + + public Dimension getMinimumSize(JComponent c) { + return new Dimension(100,100); + } + + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + private void reloadData() { + debug("reloadData"); + + // parse the glossary data into topNode + GlossaryView view = (GlossaryView) glossary.getNavigatorView(); + loadData(view); + } + + private void loadData(GlossaryView view) { + + if (view == null) { + return; + } + + // remove all children + topNode.removeAllChildren(); + + String mergeType = view.getMergeType(); + + Locale locale = view.getHelpSet().getLocale(); + + DefaultMutableTreeNode node = view.getDataAsTree(); + + // Make sure the children are all handled correctly + MergeHelpUtilities.mergeNodeChildren(mergeType, node); + + // This is a tricky one. As you remove the entries from one node to + // another the list shrinks. So you can't use an Enumated list to do + // the move. + while (node.getChildCount() > 0) { + topNode.add((DefaultMutableTreeNode) node.getFirstChild()); + } + + // add all subhelpsets + addSubHelpSets(view.getHelpSet()); + + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + + setVisibility(topNode); + } + + /** + * Reloads the presentation data using new help model. Changes the navigator if new model contains + * view with the same name as former view + **/ + private void reloadData(HelpModel model) { + debug("reloadData in using new model"); + GlossaryView glossaryView = null; + + HelpSet newHelpSet = model.getHelpSet(); + GlossaryView oldView = (GlossaryView) glossary.getNavigatorView(); + String oldName = oldView.getName(); + NavigatorView[] navViews = newHelpSet.getNavigatorViews(); + for(int i = 0 ; i < navViews.length; i++){ + if((navViews[i].getName()).equals(oldName)){ + NavigatorView tempView = navViews[i]; + if(tempView instanceof GlossaryView){ + glossaryView = (GlossaryView) tempView; + break; + } + } + } + + loadData(glossaryView); + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + protected void addSubHelpSets(HelpSet hs){ + debug ("addSubHelpSets"); + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if(glossary.canMerge(views[i])) + merge(views[i]); + } + addSubHelpSets( ehs ); + } + } + + /** + * Expands entry path and entry itself( when entry is not empty) for specific id + * + * @param target The target of entry + */ + + private void expand(String target){ + debug("expand called"); + //find all nodes with certain id + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug("expandPath :"+node); + if(node.getChildCount() > 0){ + DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild(); + TreePath path = new TreePath(child.getPath()); + tree.makeVisible(path); + } + else{ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + //tree.scrollPathToVisible(path); + tree.makeVisible(path); + } + } + } + + /** + * Returns all nodes with certain id + * + * @param target The target of entry + * + */ + private Vector findNodes(String target){ + Enumeration nodes = topNode.preorderEnumeration(); + DefaultMutableTreeNode node = null; + Vector nodeFound = new Vector(); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug(" node :"+ node.toString()); + if(node != null){ + IndexItem indexItem = (IndexItem)node.getUserObject(); + if(indexItem == null) + debug("indexItem is null"); + else{ + Map.ID id = indexItem.getID(); + if(id != null){ + debug("id name :"+id.id); + debug("target :"+target); + Map.ID itemID = null; + try{ + itemID = Map.ID.create(target,glossary.getModel().getHelpSet()); + } + catch(BadIDException exp){ + System.err.println("Not valid ID :"+target ); + break; + } + if(id.equals(itemID)) + nodeFound.addElement(node); + } + } + } + } + + return nodeFound; + } + + /** + * Collapses entry specified by id. If entry is empty collapses it's parent. + * + * @param target The target of entry + */ + + private void collapse(String target){ + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + debug("collapse called"); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + if(node.getChildCount() > 0){ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + tree.collapsePath(path); + tree.collapseRow(tree.getRowForPath(path)); + } + else{ + DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent(); + TreePath path = new TreePath(parent.getPath()); + tree.collapseRow(tree.getRowForPath(path)); + } + } + } + + + /** + * Merges in the navigational data from another IndexView. + */ + + public void doMerge(NavigatorView view) { + debug("merging data"); + + Merge mergeObject = Merge.DefaultMergeFactory.getMerge(glossary.getNavigatorView(),view); + if(mergeObject != null) { + mergeObject.processMerge(topNode); + } + + } + + /** + * Merges in the navigational data from another TOCView. + * + * @param view A GlossaryView. Note the actual argument is a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void merge(NavigatorView view) { + debug("merging data"); + doMerge(view); + + //reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Removes the navigational data from another GlossaryView. + * + * @param view An GlossaryView. Note the actual argument is a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void remove(NavigatorView view) { + debug("removing "+view); + + remove(topNode, view.getHelpSet()); + + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Recursively removes all children of the node that have either hs or a HelpSet that + * is included in hs as their HelpSet data. + * + * Recursion is stopped when a node is removed. This is because of the + * property of the merge mechanism. + * + * @param node The node from which to remove children. + * @param hs The non-null HelpSet to use. + */ + + private void remove(DefaultMutableTreeNode node, + HelpSet hs) { + debug("remove("+node+", "+hs+")"); + + // a simple node.children() does not work because the + // enumeration is voided when a child is removed + + // getNextSibling() has a linear search, so we won't do that either + + // Collect all to be removed + Vector toRemove = new Vector(); + + for (Enumeration e = node.children(); + e.hasMoreElements(); ) { + DefaultMutableTreeNode child + = (DefaultMutableTreeNode) e.nextElement(); + debug(" considering "+child); + IndexItem item = (IndexItem) child.getUserObject(); + HelpSet chs = item.getHelpSet(); + debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs)); + if (chs != null && + hs.contains(chs)) { + if (child.isLeaf()) { + // if the child has no children then just remove it + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // be carefull here. While the child hs is one to be + // removed it is possible that there are children that + // are not of this hs. Attempt to remove the + // child's children first. If they're are any children left + // the change the hs to be the hs of the first child + remove(child, hs); + if (child.isLeaf()) { + // no more children remove the child as well + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // nuts! There are children from different hs + // change the hs of the IndexItem to be the hs of the + // first child + DefaultMutableTreeNode childOne = + (DefaultMutableTreeNode) child.getFirstChild(); + IndexItem itemOne = (IndexItem) childOne.getUserObject(); + item.setHelpSet(itemOne.getHelpSet()); + debug(" orphaned children - changing hs: "+child); + } + } + } else { + // the child doesn't need to be removed but possibly it's + // children will + remove(child, hs); + } + } + + // Now remove them + for (int i=0; i<toRemove.size(); i++) { + debug(" removing "+toRemove.elementAt(i)); + node.remove((DefaultMutableTreeNode) toRemove.elementAt(i)); + } + } + + // Make all nodes visible + + private void setVisibility (DefaultMutableTreeNode node) { + IndexItem item = (IndexItem)node.getUserObject(); + if (node == topNode || + (item != null && item.getExpansionType() != TreeItem.COLLAPSE)) { + tree.expandPath(new TreePath(node.getPath())); + if (! node.isLeaf()) { + int max = node.getChildCount(); + for (int i=0; i<max; i++) { + setVisibility((DefaultMutableTreeNode)node.getChildAt(i)); + } + } + } + } + + // Process and idChanged event + + public void idChanged(HelpModelEvent e) { + ID id = e.getID(); + HelpModel helpModel = glossary.getModel(); + debug("idChanged("+e+")"); + + if (e.getSource() != helpModel) { + System.err.println("Internal inconsistency!"); + System.err.println(" "+e.getSource()+" != "+helpModel); + throw new Error("Internal error"); + } + + if (id == null) { + //return; + } + TreePath s = tree.getSelectionPath(); + if (s != null) { + Object o = s.getLastPathComponent(); + // should require only a TreeNode + if (o instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o; + IndexItem item = (IndexItem) tn.getUserObject(); + if (item != null) { + ID nId = item.getID(); + if (nId != null && nId.equals(id)) { + return; + } + } + } + } + + DefaultMutableTreeNode node = findID(topNode, id); + selectNode(node); + } + + // Note - this recursive implementation may need tuning for very large Index - epll + + private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) { + debug("findID: ("+id+")"); + debug(" node: "+node); + + // check on the id + if (id == null) { + return null; + } + IndexItem item = (IndexItem) node.getUserObject(); + if (item != null) { + ID testID = item.getID(); + debug(" testID: "+testID); + if (testID != null && testID.equals(id)) { + return node; + } + } + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = findID(tmp, id); + if (test != null) { + return test; + } + } + return null; + } + + protected JHelpContentViewer getContentViewer() { + return viewer; + } + + /** + * Select a certian node + */ + private void selectNode(DefaultMutableTreeNode node) { + if (node == null) { + // node doesn't exist. Need to clear the selection. + tree.clearSelection(); + return; + } + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + } + + protected JHelpNavigator getHelpNavigator() { + return glossary; + } + + public void valueChanged(TreeSelectionEvent e) { + + JHelpNavigator navigator = getHelpNavigator(); + HelpModel helpmodel = navigator.getModel(); + + debug("ValueChanged: "+e); + debug(" model: "+helpmodel); + + // send selected items into navigator + TreeItem[] items = null; + TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + items = new TreeItem[paths.length]; + for (int i = 0; i < paths.length; i++) { + if (paths[i] != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + items[i] = (TreeItem) node.getUserObject(); + } + } + } + navigator.setSelectedItems(items); + + // change current id only if one items is selected + if (items != null && items.length == 1) { + IndexItem item = (IndexItem) items[0]; + if (item != null && item.getID() != null) { + try { + getContentViewer().getModel().setCurrentID(item.getID(), item.getName(), navigator); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + } + } + } + + public void propertyChange(PropertyChangeEvent event) { + debug("propertyChange: " + event.getSource() + " " + + event.getPropertyName()); + + if (event.getSource() == glossary) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + debug("model changed"); + reloadData((HelpModel)event.getNewValue()); + } else if (changeName.equals("font")) { + debug("Font change"); + Font newFont = (Font)event.getNewValue(); + tree.setFont(newFont); + RepaintManager.currentManager(tree).markCompletelyDirty(tree); + }else if(changeName.equals("expand")){ + debug("Expand change"); + expand((String)event.getNewValue()); + } else if(changeName.equals("collapse")){ + debug("Collapse change"); + collapse((String)event.getNewValue()); + } + // changes to UI property? + } + } + + /** + * Handles Action from the JTextField component for searching. + */ + public void actionPerformed(ActionEvent evt) { + if (evt.getSource()==searchField) { + + // get a Collator based on the component locale + rbc = (RuleBasedCollator) Collator.getInstance(glossary.getLocale()); + + String text = searchField.getText(); + if (text != null) { + text = text.toLowerCase(); + } + if (oldText != null && text.compareTo(oldText) != 0) { + currentFindNode = null; + } + oldText = text; + + // find the node in the tree + DefaultMutableTreeNode node = searchName(topNode, text); + if (node == null) { + currentFindNode = null; + glossary.getToolkit().beep(); + return; + } + currentFindNode = node; + + //display it + TreePath path = new TreePath(node.getPath()); + tree.scrollPathToVisible(path); + tree.expandPath(path); + tree.setSelectionPath(path); + + } + } + + /** + * Searches in the tree for an index item with a name that starts with String name. + * Returns the node that contains the name, + * returns null if no node is found. + */ + private DefaultMutableTreeNode searchName(DefaultMutableTreeNode node, + String name) { + if (currentFindNode == null) { + IndexItem item = (IndexItem) node.getUserObject(); + if (item!=null) { + String itemName = item.getName(); + if (itemName !=null) { + itemName = itemName.toLowerCase(); + // compare the Node with the Name + //if (HelpUtilities.isStringInString(rbc, name, itemName)) { + if(itemName.startsWith(name)){ + return node; + } + } + } + } else { + if (currentFindNode == node) { + currentFindNode = null; + } + } + + // travel the the rest of the tree + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = searchName(tmp, name); + if (test != null) { + return test; + } + } + return null; + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicGlossaryNavigatorUI: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java new file mode 100644 index 0000000000000000000000000000000000000000..3ed5628b5a5bdc615549e5d9b5599c4f2458bd0e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java @@ -0,0 +1,513 @@ +/* + * @(#)BasicHelpUI.java 1.87 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicHelpUI.java 1.87 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.Map.ID; +import javax.help.plaf.HelpUI; +import javax.help.event.*; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Stack; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.border.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.net.URL; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.*; +import com.sun.java.help.impl.JHelpPrintHandler; +import java.awt.datatransfer.DataFlavor; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import javax.swing.Timer; + +/** + * The default UI for JHelp. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @author Richard Gregor + * @version 1.87 10/30/06 + */ + +public class BasicHelpUI extends HelpUI implements PropertyChangeListener, Serializable { + protected JHelp help; + protected JToolBar toolbar; + protected JSplitPane splitPane; + protected JTabbedPane tabbedPane; + protected Vector navs=new Vector(); + + private static Dimension PREF_SIZE = new Dimension(600,600); + private static Dimension MIN_SIZE = new Dimension(300,200); + static boolean noPageSetup = false; + + // Simple test to determine if pageSetup works on this system + // Yes for 1.2 on Windows, no for Solaris,Linux,HP + // Yes for 1.3 + static { + boolean on1dot2 = false; + try { + // Test if method introduced in 1.3 is available. + Method m = DataFlavor.class.getMethod("getTextPlainUnicodeFlavor", + (java.lang.Class[]) null); + on1dot2 = (m == null); + } catch (NoSuchMethodException e) { + on1dot2 = true; + } + + if (on1dot2) { + String osName[] = new String[] {""}; + osName[0] = System.getProperty("os.name"); + if (osName[0] != null) { + if ((osName[0].indexOf("Solaris") != -1) || + (osName[0].indexOf("SunOS") != -1) || + (osName[0].indexOf("Linux") != -1) || + (osName[0].indexOf("HP-UX") != -1)) { + noPageSetup = true; + } + } + } + } + + private int dividerLocation = 0; + private final double dividerLocationRatio = 0.30; + private JHelpFavoritesNavigator favorites = null; + + public static ComponentUI createUI(JComponent x) { + return new BasicHelpUI((JHelp) x); + } + + public BasicHelpUI(JHelp b) { + debug("createUI - sort of"); + } + + public void installUI(JComponent c) { + debug("installUI"); + help = (JHelp)c; + help.setLayout(new BorderLayout()); + + // listen to property changes + help.addPropertyChangeListener(this); + + // The navigators + tabbedPane = new JTabbedPane(); + tabbedPane.setVisible(false); + + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + false, + tabbedPane, + help.getContentViewer()); + + splitPane.setOneTouchExpandable(true); + help.add("Center", splitPane); + + JHelpNavigator first = null; + for (Enumeration e = help.getHelpNavigators(); e.hasMoreElements();) { + JHelpNavigator nav = (JHelpNavigator)e.nextElement(); + if(nav instanceof JHelpFavoritesNavigator) { + favorites = (JHelpFavoritesNavigator)nav; + } + addNavigator(nav); + if (first == null) { + first = nav; + } + } + + debug("setting the current Navigator"); + if (first != null) { + this.setCurrentNavigator(first); + } + // ToolBar should be visible externally. + + toolbar = createToolBar(HelpUtilities.getLocale(c)); + if (toolbar != null) { + toolbar.setFloatable(false); + help.add("North", toolbar); + } + + // load everything + rebuild(); + } + + protected JToolBar createToolBar(Locale locale) { + toolbar = new JToolBar(); + Enumeration actions = null; + + // get the actions from the Presentation Toolbar if one exits + HelpSet.Presentation hsPres = help.getHelpSetPresentation(); + if (hsPres != null && hsPres.isToolbar()) { + actions = hsPres.getHelpActions(getModel().getHelpSet(), help); + } + + if (actions == null || !actions.hasMoreElements()) { + actions = createDefaultActions(); + } + + while (actions.hasMoreElements()) { + HelpAction action = (HelpAction)actions.nextElement(); + if (action instanceof SeparatorAction) { + toolbar.addSeparator(); + } else { + toolbar.add(new HelpButton(action)); + } + } + + return toolbar; + } + + private Enumeration createDefaultActions() { + Vector actions = new Vector(5); + actions.add(new BackAction(help)); + actions.add(new ForwardAction(help)); + actions.add(new SeparatorAction(help)); + actions.add(new PrintAction(help)); + actions.add(new PrintSetupAction(help)); + actions.add(new SeparatorAction(help)); + if (favorites != null) { + actions.add(new FavoritesAction(help)); + } + return actions.elements(); + } + + private class HelpButton extends JButton implements PropertyChangeListener { + + HelpButton(HelpAction action) { + super(); + + setEnabled(action.isEnabled()); + + String name = (String)action.getValue("name"); + + Icon icon = (Icon)action.getValue("icon"); + if (icon == null) { + icon = UIManager.getIcon("HelpAction.icon"); + } + setIcon(icon); + + Locale locale = null; + try { + locale = help.getModel().getHelpSet().getLocale(); + } catch (NullPointerException npe) { + locale = Locale.getDefault(); + } + + String tooltip = (String)action.getValue("tooltip"); + setToolTipText(tooltip); + + String access = (String)action.getValue("access"); + getAccessibleContext().setAccessibleName(access); + + if (action instanceof MouseListener) { + addMouseListener((MouseListener)action); + } + + if (action instanceof ActionListener) { + addActionListener((ActionListener)action); + } + + action.addPropertyChangeListener(this); + + } + + /** + * This method gets called when a bound property is changed. + * @param evt A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("enabled")) { + setEnabled(((Boolean)evt.getNewValue()).booleanValue()); + } + } + + private boolean createEnablePropertyChangeSupport(HelpAction action) { + boolean back = false; + try { + Class types[] = { String.class, PropertyChangeListener.class }; + Method m = action.getClass().getMethod("addPropertyChangeListener", types); + Object args[] = { "enabled", this }; + m.invoke(action, args); + back = true; + } catch (Exception ex) { + } + return back; + } + + private boolean createPropertyChangeSupport(HelpAction action) { + boolean back = false; + try { + Class types[] = { PropertyChangeListener.class }; + Method m = action.getClass().getMethod("addPropertyChangeListener", types); + Object args[] = { this }; + m.invoke(action, args); + back = true; + } catch (Exception ex) { + } + return back; + } + + } + + public void uninstallUI(JComponent c) { + debug("uninstallUI"); + + help.removePropertyChangeListener(this); + help.setLayout(null); + help.removeAll(); + + HelpModel hm = getModel(); + if (hm != null) { + // hm.removeHelpModelListener(changeListener); + } + + help = null; + toolbar = null; + } + + public Dimension getPreferredSize(JComponent c) { + return PREF_SIZE; + } + + public Dimension getMinimumSize(JComponent c) { + return MIN_SIZE; + } + + public Dimension getMaximumSize(JComponent c) { + // This doesn't seem right. But I'm not sure what to do for now + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + private void rebuild() { + HelpModel hm = getModel(); + + if (hm == null) { + return; + } + //hm.addHelpModelListener(changeListener); + + // Discard any history + HelpHistoryModel historyModel = getHistoryModel(); + if(historyModel != null) + historyModel.discard(); + + try { + Map.ID currentID = hm.getCurrentID(); + if (currentID == null) { + HelpSet hs = hm.getHelpSet(); + Map.ID homeID = hs.getHomeID(); + Locale locale = hs.getLocale(); + String string = HelpUtilities.getString(locale, "history.homePage"); + hm.setCurrentID(homeID, string, null); + } + } catch (Exception e) { + // For example, a null HelpSet! + return; + } + } + + public void propertyChange(PropertyChangeEvent event) { + Object source = event.getSource(); + String propertyName = event.getPropertyName(); + + debug("propertyChange: " + propertyName); + + if (source == help) { + if (propertyName.equals("helpModel")) { + rebuild(); + } else if (propertyName.equals("font")) { + debug("Font change"); + Font newFont = (Font)event.getNewValue(); + help.getContentViewer().setFont(newFont); + help.getContentViewer().invalidate(); + Enumeration entries = help.getHelpNavigators(); + while (entries.hasMoreElements()) { + JHelpNavigator nav = (JHelpNavigator)entries.nextElement(); + nav.setFont(newFont); + } + } else if (propertyName.equals("navigatorDisplayed")) { + boolean display = ((Boolean)event.getNewValue()).booleanValue(); + if (display) { + // assume we're not displayed + help.add("Center", splitPane); + } else { + help.add("Center", help.getContentViewer()); + } + } else if (propertyName.equals("toolbarDisplayed")) { + toolbar.setVisible(((Boolean)event.getNewValue()).booleanValue()); + } + } + + } + + protected HelpModel getModel() { + if (help == null) { + return null; + } else { + return help.getModel(); + } + } + + /** + * Returns actual HelpHistoryModel + * + * @return The HelpHistoryModel + */ + protected HelpHistoryModel getHistoryModel(){ + if (help == null) { + return null; + } else { + return help.getHistoryModel(); + } + } + + public void addNavigator(JHelpNavigator nav) { + debug("addNavigator"); + navs.addElement(nav); + Icon icon = null; + // check and see if there is a presentation and if the presentation + // wants the view images displayed or not. + HelpSet.Presentation hsPres = help.getHelpSetPresentation(); + if (hsPres != null) { + if (hsPres.isViewImagesDisplayed()) { + icon = nav.getIcon(); + } + } else { + // Humm, no presentation so try to get the icon + icon = nav.getIcon(); + } + if (icon != null) { + tabbedPane.addTab("", icon, nav, nav.getNavigatorLabel()); + } else { + String name = nav.getNavigatorLabel(); + if (name == null) { + name = "<unknown>"; + } + tabbedPane.addTab(name, icon, nav); + } + nav.setVisible(false); + tabbedPane.setVisible(help.isNavigatorDisplayed()); + + help.invalidate(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + // The first time, arrange for the split size... + // This should be customizable + // setting a ratio at this point doesn't really work. + // instead we will set the point based on the ratio and the + // preferred sizes + if (dividerLocation == 0d) { + Dimension dem = splitPane.getSize(); + // if there is a size then perform the estimate + // otherwise use the default sizes + if (dem.width != 0) { + splitPane.setDividerLocation((int) + ((double)(dem.width - + splitPane.getDividerSize()) + * dividerLocationRatio)); + } + dividerLocation = splitPane.getDividerLocation(); + } + } + }); + } + + public void removeNavigator(JHelpNavigator nav) { + debug("removeNavigator"); + navs.removeElement(nav); + tabbedPane.remove(nav); + help.invalidate(); + } + + public Enumeration getHelpNavigators() { + return navs.elements(); + } + + /** + * Sets the current Navigator. + * + * @param navigator The navigator + * @exception throws InvalidNavigatorException if not one of the HELPUI + * navigators. + */ + public void setCurrentNavigator(JHelpNavigator nav) { + try { + tabbedPane.setSelectedComponent(nav); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException("JHelpNavigator must be added first"); + } + } + + public JHelpNavigator getCurrentNavigator() { + return (JHelpNavigator) tabbedPane.getSelectedComponent(); + } + + private ImageIcon getIcon(String name) { + return getIcon(BasicHelpUI.class, name); + } + + // public for now - need to reevalutate + public static ImageIcon getIcon(Class klass, String name) { + ImageIcon ig = null; + try { + ig = SwingHelpUtilities.getImageIcon(klass, name); + } catch (Exception ex) { + } + + if (debug || ig == null) { + System.err.println("GetIcon"); + System.err.println(" name: "+name); + System.err.println(" klass: "+klass); + URL url = klass.getResource(name); + System.err.println(" URL is "+url); + System.err.println(" ImageIcon is "+ig); + } + return ig; + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicHelpUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..ea1c10071b2bdc674a638e52e7ec8f6ba5a230d0 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java @@ -0,0 +1,97 @@ +/* + * @(#)BasicIndexCellRenderer.java 1.21 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.swing.tree.*; +import javax.swing.JTree; +import java.awt.Component; +import java.util.Locale; + +/** + * Cell Renderer for the index UI. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @version %I 10/30/06 + */ +public class BasicIndexCellRenderer extends DefaultTreeCellRenderer { + + /** + * Configures the renderer based on the passed in components. + * The value is set from messaging the tree with + * <code>convertValueToText</code>, which ultimately invokes + * <code>toString</code> on <code>value</code>. + * The foreground color is set based on the selection and the icon + * is set based on on leaf and expanded. + */ + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + // variable hasFocus was private to DefaultTreeCellRenderer since jdk1.3 + try { + this.hasFocus = hasFocus; + } catch (IllegalAccessError e) { + } + + IndexItem item + = (IndexItem) ((DefaultMutableTreeNode) value).getUserObject(); + + String stringValue = ""; + + if (item != null) { + stringValue = item.getName(); + } + + setText(stringValue); + if (sel) + setForeground(getTextSelectionColor()); + else + setForeground(getTextNonSelectionColor()); + + setIcon(null); + + selected = sel; + + // Set the locale of this if there is a lang value + if (item != null) { + Locale locale = item.getLocale(); + if (locale != null) { + setLocale(locale); + } + } + + return this; + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..843cb76a61d919f275ab1f9b1198f2041fb079bf --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java @@ -0,0 +1,885 @@ +/* + * @(#)BasicIndexNavigatorUI.java 1.92 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicIndexNavigatorUI.java 1.92 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.plaf.HelpUI; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import com.sun.java.help.impl.SwingWorker; +import java.util.EventObject; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Locale; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.RepaintManager; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.tree.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.io.Reader; +import java.io.Serializable; +import java.net.URL; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import javax.help.Map.ID; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.lang.reflect.Method; + +/** + * The default UI for JHelpNavigator of type Index. + * + * @author Roger D. Brinkley + * revised by Paul Dumais, Nov 7, 1997 + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @author Richard Gregor + * @version 1.92 10/30/06 + */ + +public class BasicIndexNavigatorUI extends HelpNavigatorUI + implements HelpModelListener, TreeSelectionListener, + PropertyChangeListener, ActionListener, + ComponentListener, Serializable +{ + protected JHelpIndexNavigator index; + protected JScrollPane sp; + protected DefaultMutableTreeNode topNode; + protected JTree tree; + protected JTextField searchField; + protected RuleBasedCollator rbc; + protected String oldText; + protected DefaultMutableTreeNode currentFindNode; + private SwingWorker worker = null; + + + public static ComponentUI createUI(JComponent x) { + return new BasicIndexNavigatorUI((JHelpIndexNavigator) x); + } + + public BasicIndexNavigatorUI(JHelpIndexNavigator b) { + ImageIcon icon = getImageIcon(b.getNavigatorView()); + if (icon != null) { + setIcon(icon); + } else { + setIcon(UIManager.getIcon("IndexNav.icon")); + } + } + + public void installUI(JComponent c) { + debug ("installUI"); + + index = (JHelpIndexNavigator)c; + HelpModel model = index.getModel(); + + index.setLayout(new BorderLayout()); + index.addPropertyChangeListener(this); + index.addComponentListener(this); + if (model != null) { + model.addHelpModelListener(this); // for our own changes + } + + topNode = new DefaultMutableTreeNode(); + + JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c), + "index.findLabel")); + // should be a JButton + // search.addActionListener(this); + searchField= new JTextField(); + search.setLabelFor(searchField); + searchField.addActionListener(this); + + JPanel box = new JPanel(); + box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS)); + box.add(search); + box.add(searchField); + + index.add("North", box); + + tree = new JTree(topNode); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.addTreeSelectionListener(this); + // tsm.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + + tree.setShowsRootHandles(true); + tree.setRootVisible(false); + + setCellRenderer(index.getNavigatorView(), tree); + + sp = new JScrollPane(); + sp.getViewport().add(tree); + + index.add("Center", sp); + reloadData(); + } + + /** + * Sets the desired cell renderer on this tree. This is exposed for redefinition + * by subclases. + */ + protected void setCellRenderer(NavigatorView view, JTree tree) { + tree.setCellRenderer(new BasicIndexCellRenderer()); + //in case you can use ToolTips for nodes + //ToolTipManager.sharedInstance().registerComponent(tree); + } + + public void uninstallUI(JComponent c) { + debug ("uninstallUI"); + HelpModel model = index.getModel(); + + index.removeComponentListener(this); + index.removePropertyChangeListener(this); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.removeTreeSelectionListener(this); + index.setLayout(null); + index.removeAll(); + + if (model != null) { + model.removeHelpModelListener(this); + } + + index = null; + } + + public Dimension getPreferredSize(JComponent c) { + /* + if (sp != null) { + return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp); + } else { + return new Dimension(200,100); + } + */ + return new Dimension(200,100); + + } + + public Dimension getMinimumSize(JComponent c) { + return new Dimension(100,100); + } + + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + private void reloadData() { + debug("reloadData"); + + // parse the Index data into topNode + IndexView view = (IndexView) index.getNavigatorView(); + if (worker != null) { + // Something is still going on. Stop it and start over + worker.interrupt(); + } + worker = new NavSwingWorker(view); + worker.start(Thread.MIN_PRIORITY); + } + + /** + * load the data for the navigator. Will be run on a separate + * thread. + */ + private synchronized Object loadData(IndexView view) { + if (view == null) { + return Boolean.FALSE; + } + + // remove all children + topNode.removeAllChildren(); + + String mergeType = view.getMergeType(); + + Locale locale = view.getHelpSet().getLocale(); + + DefaultMutableTreeNode node = view.getDataAsTree(); + + // Make sure the children are all handled correctly + MergeHelpUtilities.mergeNodeChildren(mergeType, node); + + // This is a tricky one. As you remove the entries from one node to + // another the list shrinks. So you can't use an Enumated list to do + // the move. + while (node.getChildCount() > 0) { + topNode.add((DefaultMutableTreeNode) node.getFirstChild()); + } + + // Add all of the subhelpset's data + addSubHelpSets(view.getHelpSet()); + return Boolean.TRUE; + } + + + /* + * Presents the data loaded in loadData. Will be run on the + * Swing event thread. + */ + private void presentData() { + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + + setVisibility(topNode); + + + if (index.getModel() != null) { + ID id = index.getModel().getCurrentID(); + if (id != null) { + DefaultMutableTreeNode selectedNode = findID(topNode, id); + selectNode(selectedNode); + } + } + } + + private class NavSwingWorker extends SwingWorker { + IndexView view; + + public NavSwingWorker (IndexView view) { + super(); + this.view = view; + } + + public Object construct() { + return loadData(view); + } + + public void finished() { + if ((Boolean)get() == Boolean.TRUE) { + presentData(); + } + } + } + + /** + * Reloads the presentation data using new help model. Changes the navigator if new model contains + * view with the same name as former view + **/ + private void reloadData(HelpModel model) { + debug("reloadData in using new model"); + + IndexView indexView = null; + + HelpSet newHelpSet = model.getHelpSet(); + IndexView oldView = (IndexView) index.getNavigatorView(); + String oldName = oldView.getName(); + NavigatorView[] navViews = newHelpSet.getNavigatorViews(); + for(int i = 0 ; i < navViews.length; i++){ + if((navViews[i].getName()).equals(oldName)){ + NavigatorView tempView = navViews[i]; + if(tempView instanceof IndexView){ + indexView = (IndexView) tempView; + break; + } + } + } + + if (worker != null) { + // Something is still going on. Stop it and start over + worker.interrupt(); + } + worker = new NavSwingWorker(indexView); + worker.start(Thread.MIN_PRIORITY); + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + protected void addSubHelpSets(HelpSet hs){ + debug ("addSubHelpSets"); + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if(index.canMerge(views[i])) + doMerge(views[i]); + } + addSubHelpSets( ehs ); + } + } + + /** + * Expands entry path and entry itself( when entry is not empty) for specific id + * + * @param target The target of entry + */ + + private void expand(String target){ + debug("expand called"); + //find all nodes with certain id + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug("expandPath :"+node); + if(node.getChildCount() > 0){ + DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild(); + TreePath path = new TreePath(child.getPath()); + tree.makeVisible(path); + } + else{ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + //tree.scrollPathToVisible(path); + tree.makeVisible(path); + } + } + } + + /** + * Returns all nodes with certain id + * + * @param target The target of entry + * + */ + private Vector findNodes(String target){ + Enumeration nodes = topNode.preorderEnumeration(); + DefaultMutableTreeNode node = null; + Vector nodeFound = new Vector(); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug(" node :"+ node.toString()); + if(node != null){ + IndexItem indexItem = (IndexItem)node.getUserObject(); + if(indexItem == null) + debug("indexItem is null"); + else{ + Map.ID id = indexItem.getID(); + if(id != null){ + debug("id name :"+id.id); + debug("target :"+target); + Map.ID itemID = null; + try{ + itemID = Map.ID.create(target,index.getModel().getHelpSet()); + } + catch(BadIDException exp){ + System.err.println("Not valid ID :"+target ); + break; + } + if(id.equals(itemID)) + nodeFound.addElement(node); + } + } + } + } + + return nodeFound; + } + + /** + * Collapses entry specified by id. If entry is empty collapses it's parent. + * + * @param target The target of entry + */ + + private void collapse(String target){ + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + debug("collapse called"); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + if(node.getChildCount() > 0){ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + tree.collapsePath(path); + tree.collapseRow(tree.getRowForPath(path)); + } + else{ + DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent(); + TreePath path = new TreePath(parent.getPath()); + tree.collapseRow(tree.getRowForPath(path)); + } + } + } + + + /** + * Merges in the navigational data from another IndexView. + */ + + public void doMerge(NavigatorView view) { + debug("merging data"); + + Merge mergeObject = Merge.DefaultMergeFactory.getMerge(index.getNavigatorView(),view); + if(mergeObject != null) { + mergeObject.processMerge(topNode); + } + + } + + /** + * Merges in the navigational data from another IndexView. + * + * @param view A IndexView. Note the actual argument is a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void merge(NavigatorView view) { + debug("merge"); + doMerge(view); + + //reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Removes the navigational data from another IndexView. + * + * @param view An IndexView. Note the actual argument is a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void remove(NavigatorView view) { + debug("removing "+view); + + remove(topNode, view.getHelpSet()); + + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Recursively removes all children of the node that have either hs or a HelpSet that + * is included in hs as their HelpSet data. + * + * Recursion is stopped when a node is removed. This is because of the + * property of the merge mechanism. + * + * @param node The node from which to remove children. + * @param hs The non-null HelpSet to use. + */ + + private void remove(DefaultMutableTreeNode node, + HelpSet hs) { + debug("remove("+node+", "+hs+")"); + + // a simple node.children() does not work because the + // enumeration is voided when a child is removed + + // getNextSibling() has a linear search, so we won't do that either + + // Collect all to be removed + Vector toRemove = new Vector(); + + for (Enumeration e = node.children(); + e.hasMoreElements(); ) { + DefaultMutableTreeNode child + = (DefaultMutableTreeNode) e.nextElement(); + debug(" considering "+child); + IndexItem item = (IndexItem) child.getUserObject(); + HelpSet chs = item.getHelpSet(); + debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs)); + if (chs != null && + hs.contains(chs)) { + if (child.isLeaf()) { + // if the child has no children then just remove it + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // be carefull here. While the child hs is one to be + // removed it is possible that there are children that + // are not of this hs. Attempt to remove the + // child's children first. If they're are any children left + // the change the hs to be the hs of the first child + remove(child, hs); + if (child.isLeaf()) { + // no more children remove the child as well + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // nuts! There are children from different hs + // change the hs of the IndexItem to be the hs of the + // first child + DefaultMutableTreeNode childOne = + (DefaultMutableTreeNode) child.getFirstChild(); + IndexItem itemOne = (IndexItem) childOne.getUserObject(); + item.setHelpSet(itemOne.getHelpSet()); + debug(" orphaned children - changing hs: "+child); + } + } + } else { + // the child doesn't need to be removed but possibly it's + // children will + remove(child, hs); + } + } + + // Now remove them + for (int i=0; i<toRemove.size(); i++) { + debug(" removing "+toRemove.elementAt(i)); + node.remove((DefaultMutableTreeNode) toRemove.elementAt(i)); + } + } + + // Make all nodes visible + + private void setVisibility (DefaultMutableTreeNode node) { + IndexItem item = (IndexItem)node.getUserObject(); + if (node == topNode || + (item != null && item.getExpansionType() != TreeItem.COLLAPSE)) { + tree.expandPath(new TreePath(node.getPath())); + if (! node.isLeaf()) { + int max = node.getChildCount(); + for (int i=0; i<max; i++) { + setVisibility((DefaultMutableTreeNode)node.getChildAt(i)); + } + } + } + } + + // Process and idChanged event + + public synchronized void idChanged(HelpModelEvent e) { + ID id = e.getID(); + HelpModel helpModel = index.getModel(); + debug("idChanged("+e+")"); + + if (e.getSource() != helpModel) { + debug("Internal inconsistency!"); + debug(" "+e.getSource()+" != "+helpModel); + throw new Error("Internal error"); + } + + if (id == null) { + id = helpModel.getHelpSet().getCombinedMap().getClosestID(e.getURL()); + } + TreePath s = tree.getSelectionPath(); + if (s != null) { + Object o = s.getLastPathComponent(); + // should require only a TreeNode + if (o instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o; + IndexItem item = (IndexItem) tn.getUserObject(); + if (item != null) { + ID nId = item.getID(); + if (nId != null && nId.equals(id)) { + return; + } + } + } + } + + DefaultMutableTreeNode node = findID(topNode, id); + selectNode(node); + } + + // Note - this recursive implementation may need tuning for very large Index - epll + + private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) { + debug("findID: ("+id+")"); + debug(" node: "+node); + + // check on the id + if (id == null) { + return null; + } + IndexItem item = (IndexItem) node.getUserObject(); + if (item != null) { + ID testID = item.getID(); + debug(" testID: "+testID); + if (testID != null && testID.equals(id)) { + return node; + } + } + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = findID(tmp, id); + if (test != null) { + return test; + } + } + return null; + } + + /** + * Select a certian node + */ + private void selectNode(DefaultMutableTreeNode node) { + if (node == null) { + // node doesn't exist. Need to clear the selection. + tree.clearSelection(); + return; + } + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + } + + protected JHelpNavigator getHelpNavigator() { + return index; + } + + public void valueChanged(TreeSelectionEvent e) { + + JHelpNavigator navigator = getHelpNavigator(); + HelpModel helpmodel = navigator.getModel(); + + debug("ValueChanged: "+e); + debug(" model: "+helpmodel); + + // send selected items into navigator + TreeItem[] items = null; + TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + items = new TreeItem[paths.length]; + for (int i = 0; i < paths.length; i++) { + if (paths[i] != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + items[i] = (TreeItem) node.getUserObject(); + } + } + } + navigator.setSelectedItems(items); + + // change current id only if one items is selected + if (items != null && items.length == 1) { + IndexItem item = (IndexItem) items[0]; + if (item != null && item.getID() != null) { + String presentation = item.getPresentation(); + if (presentation == null) { + // This is the old way of doing things + // set the currentID in the helpModel + try { + helpmodel.setCurrentID(item.getID(), item.getName(), navigator); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + } else { + // using a Presentation + // Get a Presentation + Presentation pres; + HelpSet hs = helpmodel.getHelpSet(); + ClassLoader loader; + Class klass; + Class types[] = { HelpSet.class, + String.class}; + Object args[] = { hs, + item.getPresentationName()}; + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + Method m = klass.getMethod("getPresentation", types); + pres = (Presentation)m.invoke(null, args); + } catch (Exception ex) { + throw new RuntimeException("error invoking presentation" ); + } + + if (pres == null) { + return; + } + + // Minor adjustments for Windows and Popups + if (pres instanceof WindowPresentation) { + ((WindowPresentation)pres).setActivationObject(tree); + } + if (pres instanceof Popup) { + ((Popup)pres).setInvokerInternalBounds(tree.getPathBounds(paths[0])); + ((Popup)pres).setInvoker((Component)tree); + } + + // set the id to be displayed + try { + pres.setCurrentID(item.getID()); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + + // diplay the presentation + pres.setDisplayed(true); + } + } + } + } + + public void propertyChange(PropertyChangeEvent event) { + debug("propertyChange: " + event.getSource() + " " + + event.getPropertyName()); + + if (event.getSource() == index) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + debug("model changed"); + reloadData((HelpModel)event.getNewValue()); + } else if (changeName.equals("font")) { + debug ("Font change"); + Font newFont = (Font)event.getNewValue(); + searchField.setFont(newFont); + RepaintManager.currentManager(searchField).markCompletelyDirty(searchField); + tree.setFont(newFont); + RepaintManager.currentManager(tree).markCompletelyDirty(tree); + } else if(changeName.equals("expand")){ + debug("Expand change"); + expand((String)event.getNewValue()); + } else if(changeName.equals("collapse")){ + debug("Collapse change"); + collapse((String)event.getNewValue()); + } + // changes to UI property? + } + } + + /** + * Invoked when the component's size changes. + */ + public void componentResized(ComponentEvent e) { + } + + /** + * Invoked when the component's position changes. + */ + public void componentMoved(ComponentEvent e) { + } + + /** + * Invoked when the component has been made visible. + */ + public void componentShown(ComponentEvent e) { + searchField.selectAll(); + searchField.requestFocus(); + } + + /** + * Invoked when the component has been made invisible. + */ + public void componentHidden(ComponentEvent e) { + } + /** + * Handles Action from the JTextField component for searching. + */ + public void actionPerformed(ActionEvent evt) { + if (evt.getSource()==searchField) { + + // get a Collator based on the component locale + rbc = (RuleBasedCollator) Collator.getInstance(index.getLocale()); + + String text = searchField.getText(); + if (text != null) { + text = text.toLowerCase(); + } + if (oldText != null && text.compareTo(oldText) != 0) { + currentFindNode = null; + } + oldText = text; + + // find the node in the tree + DefaultMutableTreeNode node = searchName(topNode, text); + if (node == null) { + currentFindNode = null; + index.getToolkit().beep(); + return; + } + currentFindNode = node; + + //display it + TreePath path = new TreePath(node.getPath()); + tree.scrollPathToVisible(path); + tree.expandPath(path); + tree.setSelectionPath(path); + + } + } + + /** + * Searches in the tree for an index item with a name that starts with String name. + * Returns the node that contains the name, + * returns null if no node is found. + */ + private DefaultMutableTreeNode searchName(DefaultMutableTreeNode node, + String name) { + if (currentFindNode == null) { + IndexItem item = (IndexItem) node.getUserObject(); + if (item!=null) { + String itemName = item.getName(); + if (itemName !=null) { + itemName = itemName.toLowerCase(); + // compare the Node with the Name + if (HelpUtilities.isStringInString(rbc, name, itemName)) { + return node; + } + } + } + } else { + if (currentFindNode == node) { + currentFindNode = null; + } + } + + // travel the the rest of the tree + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = searchName(tmp, name); + if (test != null) { + return test; + } + } + return null; + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicIndexNavigatorUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java new file mode 100644 index 0000000000000000000000000000000000000000..2abf301349257900f38c882463a76be1d67d561f --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java @@ -0,0 +1,266 @@ +/* + * @(#)BasicNativeContentViewerUI.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicNativeContentViewerUI.java 1.2 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpContentViewerUI; +import javax.help.event.*; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Hashtable; +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TextUI; +import javax.swing.border.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.*; +import javax.help.Map.ID; +import org.jdesktop.jdic.browser.WebBrowser; + +/** + * A native UI for JHelpContentViewer using the native browser. + * + * @author Roger Brinkley + * @version 1.2 10/30/06 + */ + +public class BasicNativeContentViewerUI extends HelpContentViewerUI +implements HelpModelListener, TextHelpModelListener, PropertyChangeListener, Serializable { + protected JHelpContentViewer theViewer; + + private static Dimension PREF_SIZE = new Dimension(200, 300); + private static Dimension MIN_SIZE = new Dimension(80, 80); + + private WebBrowser html; + private JViewport vp; + + public static ComponentUI createUI(JComponent x) { + debug("createUI"); + return new BasicNativeContentViewerUI((JHelpContentViewer) x); + } + + public BasicNativeContentViewerUI(JHelpContentViewer b) { + debug("createUI - sort of"); + } + + public void installUI(JComponent c) { + debug("installUI"); + theViewer = (JHelpContentViewer)c; + theViewer.setLayout(new BorderLayout()); + + // listen to property changes... + theViewer.addPropertyChangeListener(this); + + TextHelpModel model = theViewer.getModel(); + if (model != null) { + // listen to id changes... + model.addHelpModelListener(this); + // listen to highlight changes... + model.addTextHelpModelListener(this); + } + + html = new WebBrowser(); + html.getAccessibleContext().setAccessibleName(HelpUtilities.getString(HelpUtilities.getLocale(html), "access.contentViewer")); + if (debug) { + html.setDebug(true); + } + /** + * html future additions + * add any listeners here + */ + + // if the model has a current URL then set it + if (model != null) { + URL url = model.getCurrentURL(); + if (url != null) { + html.setURL(url); + } + } + + JScrollPane scroller = new JScrollPane(); + scroller.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.white, + Color.gray)); + vp = scroller.getViewport(); + vp.add(html); + vp.setBackingStoreEnabled(true); + + theViewer.add("Center", scroller); + } + + public void uninstallUI(JComponent c) { + debug("uninstallUI"); + JHelpContentViewer viewer = (JHelpContentViewer) c; + viewer.removePropertyChangeListener(this); + /** + * html future additions + * remove all html listeners here - if we add any + */ + TextHelpModel model = viewer.getModel(); + if (model != null) { + model.removeHelpModelListener(this); + model.removeTextHelpModelListener(this); + } + viewer.setLayout(null); + viewer.removeAll(); + } + + public Dimension getPreferredSize(JComponent c) { + return PREF_SIZE; + } + + public Dimension getMinimumSize(JComponent c) { + return MIN_SIZE; + } + + public Dimension getMaximumSize(JComponent c) { + // This doesn't seem right. But I'm not sure what to do for now + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public void idChanged(HelpModelEvent e) { + ID id = e.getID(); + URL url = e.getURL(); + TextHelpModel model = theViewer.getModel(); + debug("idChanged("+e+")"); + debug(" = " + id + " " + url); + debug(" my helpModel: "+model); + + model.setDocumentTitle(null); + + /** + * html future additions + * if we were doing any highlighting of the search text + * code would be needed here remove all the highlights before + * the new page is displayed + */ + + html.setURL(url); + + debug("done with idChanged"); + } + + private void rebuild() { + debug("rebuild"); + TextHelpModel model = theViewer.getModel(); + if (model == null) { + debug("rebuild-end: model is null"); + return; + } + + /** + * html future additions + * if we were doing any highlighting the highlights would need + * to be removed here + */ + + HelpSet hs = model.getHelpSet(); + // for glossary - not set homeID page - glossary is not synchronized + if(theViewer.getSynch()){ + try { + Map.ID homeID = hs.getHomeID(); + Locale locale = hs.getLocale(); + String name = HelpUtilities.getString(locale, "history.homePage"); + model.setCurrentID(homeID, name, (JHelpNavigator)null); + html.setURL(model.getCurrentURL()); + } catch (Exception e) { + // ignore + } + } + debug("rebuild-end"); + } + + public void propertyChange(PropertyChangeEvent event) { + debug("propertyChange: " + event.getPropertyName() + "\n\toldValue:" + event.getOldValue() + "\n\tnewValue:" + event.getNewValue()); + + if (event.getSource() == theViewer) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + TextHelpModel oldModel = (TextHelpModel) event.getOldValue(); + TextHelpModel newModel = (TextHelpModel) event.getNewValue(); + if (oldModel != null) { + oldModel.removeHelpModelListener(this); + oldModel.removeTextHelpModelListener(this); + } + if (newModel != null) { + newModel.addHelpModelListener(this); + newModel.addTextHelpModelListener(this); + } + rebuild(); + } else if (changeName.equals("font")) { + debug("font changed"); + Font newFont = (Font)event.getNewValue(); + /** + * ~~ + * Put font change handling code here + */ + }else if (changeName.equals("clear")) { + /** + * html future additions + * do not know how to do this at the current time + */ + // a~~ html.setText(""); + }else if (changeName.equals("reload")) { + html.refresh(); + } + } + } + + /** + * Determines if highlights have changed. + * Collects all the highlights and marks the presentation. + * + * @param e The TextHelpModelEvent. + */ + public void highlightsChanged(TextHelpModelEvent e) { + debug("highlightsChanged "+e); + + // if we do anything with highlighting it would need to + // be handled here. + } + + /** + * For printf debugging. + */ + private final static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("NativeContentViewerUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..7edfa638e05f40bf067bd1df5cd238a2a8e53ee2 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java @@ -0,0 +1,526 @@ +/* + * @(#)BasicSearchCellRenderer.java 1.15 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicSearchCellRenderer.java 1.15 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +/** + * TreeCellRender for JSearchNavigator. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.15 10/30/06 + */ + +import java.awt.*; +import java.net.URL; +import java.util.Locale; +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.help.Map; +import javax.help.Map.ID; +import javax.help.SearchTOCItem; +import javax.help.SearchHit; +import javax.help.HelpUtilities; +import javax.accessibility.AccessibleValue; +import javax.accessibility.AccessibleContext; + +/** + * Displays an search entry in a tree. + * + * @author Roger D. Brinkley + * @version 1.15 10/30/06 + */ +public class BasicSearchCellRenderer extends JPanel implements TreeCellRenderer +{ + /** Is the value currently selected. */ + protected boolean selected; + // These two ivars will be made protected later. + /** True if has focus. */ + private boolean hasFocus; + /** True if draws focus border around icon as well. */ + private boolean drawsFocusBorderAroundIcon; + + // Colors + /** Color to use for the foreground for selected nodes. */ + protected Color textSelectionColor; + + /** Color to use for the foreground for non-selected nodes. */ + protected Color textNonSelectionColor; + + /** Color to use for the background when a node is selected. */ + protected Color backgroundSelectionColor; + + /** Color to use for the background when the node is not selected. */ + protected Color backgroundNonSelectionColor; + + /** Color to use for the background when the node is not selected. */ + protected Color borderSelectionColor; + + /** Map to use for rendering included images. */ + protected Map map; + + /** Hits */ + protected ValueJLabel hits; + + /** Quality */ + protected ValueJLabel quality; + + /** Title */ + protected JLabel title; + + /** + * Returns a new instance of BasicSearchCellRender. Left alignment is + * set. Icons and text color are determined from the + * UIManager. + */ + public BasicSearchCellRenderer(Map map) { + super(); + this.map = map; + + setTextSelectionColor(UIManager.getColor("Tree.selectionForeground")); + setTextNonSelectionColor(UIManager.getColor("Tree.textForeground")); + setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground")); + setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground")); + setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor")); + Object value = UIManager.get("Tree.drawsFocusBorderAroundIcon"); + drawsFocusBorderAroundIcon = (value != null && ((Boolean)value). + booleanValue()); + + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + hits = new ValueJLabel(); + hits.setHorizontalAlignment(JLabel.LEFT); + quality = new ValueJLabel(); + title = new JLabel(); + title.setFont(getFont()); + title.setHorizontalAlignment(JLabel.LEFT); + add(Box.createRigidArea(new Dimension(4,0))); + add(quality); + add(Box.createRigidArea(new Dimension(4,0))); + add(hits); + add(Box.createRigidArea(new Dimension(4,0))); + add(title); + + } + + + /** + * Sets the color the text is drawn with when the node is selected. + */ + public void setTextSelectionColor(Color newColor) { + textSelectionColor = newColor; + } + + /** + * Returns the color the text is drawn with when the node is selected. + */ + public Color getTextSelectionColor() { + return textSelectionColor; + } + + /** + * Sets the color the text is drawn with when the node is not selected. + */ + public void setTextNonSelectionColor(Color newColor) { + textNonSelectionColor = newColor; + } + + /** + * Returns the color the text is drawn with when the node is not selected. + */ + public Color getTextNonSelectionColor() { + return textNonSelectionColor; + } + + /** + * Sets the color to use for the background if the node is selected. + */ + public void setBackgroundSelectionColor(Color newColor) { + backgroundSelectionColor = newColor; + } + + + /** + * Returns the color to use for the background if the node is selected. + */ + public Color getBackgroundSelectionColor() { + return backgroundSelectionColor; + } + + /** + * Sets the background color to be used for unselected nodes. + */ + public void setBackgroundNonSelectionColor(Color newColor) { + backgroundNonSelectionColor = newColor; + } + + /** + * Returns the background color to be used for unselected nodes. + */ + public Color getBackgroundNonSelectionColor() { + return backgroundNonSelectionColor; + } + + /** + * Sets the color to use for the border. + */ + public void setBorderSelectionColor(Color newColor) { + borderSelectionColor = newColor; + } + + /** + * Returns the the border color. + */ + public Color getBorderSelectionColor() { + return borderSelectionColor; + } + + /** + * Subclassed to only accept the font if it is not a FontUIResource. + */ + public void setFont(Font font) { + if(font instanceof FontUIResource) { + font = null; + } + if (font != null) { + if (title != null) { + title.setFont(font); + } + } + super.setFont(font); + } + + /** + * Subclassed to only accept the color if it is not a ColorUIResource. + */ + public void setBackground(Color color) { + if(color instanceof ColorUIResource) + color = null; + super.setBackground(color); + } + + /** + * Configures the renderer based on the components passed in. + * Sets the value from messaging value with toString(). + * The foreground color is set based on the selection and the icon + * is set based on on leaf and expanded. + */ + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + SearchTOCItem item = + (SearchTOCItem) ((DefaultMutableTreeNode) value).getUserObject(); + + String stringValue = ""; + + if (item != null) { + stringValue = item.getName(); + } + + if (sel) { + hits.setForeground(getTextNonSelectionColor()); + title.setForeground(getTextSelectionColor()); + title.setBackground(getBackgroundSelectionColor()); + } else { + Color bColor = getBackgroundNonSelectionColor(); + if(bColor == null) + bColor = getBackground(); + hits.setForeground(getTextNonSelectionColor()); + title.setForeground(getTextNonSelectionColor()); + title.setBackground(bColor); + } + + Locale locale = Locale.getDefault(); + + // Set the locale of this if there is a lang value + if (item != null) { + locale = item.getLocale(); + if (locale != null) { + setLocale(locale); + } + } + + if (item != null) { + // Set the hit count + int hitCount = item.hitCount(); + hits.setText(String.valueOf(hitCount)); + hits.setAccessibility(null, + HelpUtilities.getString(locale, "search.hitDesc"), + new Integer(hitCount), + new Integer(hitCount), + new Integer(hitCount)); + + String qualityLevel=null; + // Set the quality index + double penalty = item.getConfidence(); + if (penalty < 1) { + quality.setIcon(high); + qualityLevel = HelpUtilities.getString(locale, "search.high"); + } else if (penalty < 5) { + quality.setIcon(medhigh); + qualityLevel = HelpUtilities.getString(locale, "search.midhigh"); + } else if (penalty < 12.5) { + quality.setIcon(med); + qualityLevel = HelpUtilities.getString(locale, "search.mid"); + } else if (penalty < 25) { + quality.setIcon(medlow); + qualityLevel = HelpUtilities.getString(locale, "search.midlow"); + } else { + quality.setIcon(low); + qualityLevel = HelpUtilities.getString(locale, "search.low"); + } + + quality.setAccessibility(qualityLevel, + HelpUtilities.getString(locale, "search.qualityDesc"), + new Double(penalty), + new Double(penalty), + new Double(penalty)); + + // Finally set the title + title.setText(stringValue); + } + + selected = sel; + this.hasFocus = hasFocus; + return this; + } + + /** + * Paints the value. The background is filled based on selected color. + */ + public void paint(Graphics g) { + Color bColor; + + if(selected) { + bColor = getBackgroundSelectionColor(); + } else { + bColor = getBackgroundNonSelectionColor(); + if(bColor == null) + bColor = getBackground(); + } + int imageOffset = -1; + if(bColor != null) { + + imageOffset = getLabelStart(); + g.setColor(bColor); + Dimension size = getSize(); + g.fillRect(imageOffset, 0, size.width - 1 - imageOffset, + size.height); + } + if (hasFocus) { + if (drawsFocusBorderAroundIcon) { + imageOffset = 0; + } + else if (imageOffset == -1) { + imageOffset = getLabelStart(); + } + g.setColor(getBorderSelectionColor()); + g.drawRect(imageOffset, 0, getWidth() - 1 - imageOffset, + getHeight() - 1); + } + // call paintChildren and not paint so we don't + // erase everyting we've already done. + super.paintChildren(g); + + } + + private int getLabelStart() { + return title.getX() - 1; + } + + /** + * Overrides <code>JComponent.getPreferredSize</code> to + * return slightly taller preferred size value. + */ + public Dimension getPreferredSize() { + Dimension retDimension = super.getPreferredSize(); + int width = 0; + int height = 0; + + // Set the initial height; + if (retDimension != null) { + height = retDimension.height; + } + + // The the insets + Insets insets = getInsets(); + width += insets.left + insets.right; + + // Add the width of the quality + width += 4; + Dimension size; + size = quality.getPreferredSize(); + width += size.width; + height = Math.max(height, size.height + insets.top + insets.bottom); + + // Add the width of quantity + width += 4; + size = hits.getPreferredSize(); + width += size.width; + height = Math.max(height, size.height + insets.top + insets.bottom); + + // Add the width of titl + width += 4; + size = title.getPreferredSize(); + width += size.width; + height = Math.max(height, size.height + insets.top + insets.bottom); + + // Add 3 to the width for good measure + width += 3; + + if(retDimension != null) + retDimension = new Dimension(retDimension.width + 3, + retDimension.height); + retDimension.setSize(width, height); + return retDimension; + } + + // icons used for the BasicSearchCellRender + private static Icon high = UIManager.getIcon("SearchHigh.icon"); + private static Icon medhigh = UIManager.getIcon("SearchMedHigh.icon"); + private static Icon med = UIManager.getIcon("SearchMed.icon"); + private static Icon medlow = UIManager.getIcon("SearchMedLow.icon"); + private static Icon low = UIManager.getIcon("SearchLow.icon"); + + private class ValueJLabel extends JLabel { + + String accessName; + String accessDesc; + Number accessValue; + Number minValue; + Number maxValue; + + public void setAccessibility (String accessName, String accessDesc, + Number accessValue, Number minValue, + Number maxValue) { + this.accessName = accessName; + this.accessDesc = accessDesc; + this.accessValue = accessValue; + this.minValue = minValue; + this.maxValue = maxValue; + } + + + ///////////////// + // Accessibility support + //////////////// + + /** + * Get the AccessibleContext associated with this JComponent + * + * @return the AccessibleContext of this JComponent + */ + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleValueJLabel(); + } + accessibleContext.setAccessibleDescription(accessDesc); + accessibleContext.setAccessibleName(accessName); + return accessibleContext; + } + + /** + * The class used to obtain the accessible role for this object. + * <p> + * <strong>Warning:</strong> + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is appropriate + * for short term storage or RMI between applications running the same + * version of Swing. A future release of Swing will provide support for + * long term persistence. + */ + protected class AccessibleValueJLabel extends AccessibleJLabel implements AccessibleValue { + + + public AccessibleValue getAccessibleValue() { + return this; + } + + /** + * Get the value of this object as a Number. + * If the value has not been + * set, the return value will be null. + * + * @return value of the object + * @see #setCurrentAccessibleValue + */ + public Number getCurrentAccessibleValue() { + return accessValue; + } + + /** + * Set the value of this object as a Number. + * + * @return True if the value was set; else False + * @see #getCurrentAccessibleValue + */ + public boolean setCurrentAccessibleValue(Number n) { + return false; // I assume the value can't be set + } + + /** + * Get the minimum value of this object as a Number. + * + * @return Minimum value of the object; null if this object does not + * have a minimum value + * @see #getMaximumAccessibleValue + */ + public Number getMinimumAccessibleValue() { + return minValue; + } + + /** + * Get the maximum value of this object as a Number. + * + * @return Maximum value of the object; null if this object does not + * have a maximum value + * @see #getMinimumAccessibleValue + */ + public Number getMaximumAccessibleValue() { + return maxValue; + } + } + } + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicSearchCellRenderer: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..0293d3f6378027aecfc0057fae65d21f8adfb0fa --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java @@ -0,0 +1,768 @@ +/* + * @(#)BasicSearchNavigatorUI.java 1.86 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicSearchNavigatorUI.java 1.86 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +/** + * UI for Search Navigator of type JHelpListNavigator. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @author Richard Gregor + * @version 1.86 10/30/06 + */ +import javax.help.*; +import javax.help.search.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import javax.help.search.SearchListener; +import javax.help.search.SearchEvent; +import java.util.EventObject; +import java.util.Vector; +import java.util.Enumeration; +import java.net.URL; +import javax.swing.*; +import javax.swing.tree.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.net.MalformedURLException; +import javax.help.DefaultHelpModel.DefaultHighlight; +import javax.help.Map.ID; + +public class BasicSearchNavigatorUI extends HelpNavigatorUI + implements HelpModelListener, SearchListener, + PropertyChangeListener, TreeSelectionListener, + ComponentListener +{ + protected JHelpSearchNavigator searchnav; + protected JScrollPane sp; + protected JTree tree; + protected DefaultMutableTreeNode topNode; + protected JTextField searchparams; + protected boolean displayOptions; + protected SearchEngine helpsearch; + protected SearchQuery searchquery; + protected DefaultMutableTreeNode lastTOCnode; + private HelpSet newHelpSet; + + public static ComponentUI createUI(JComponent x) { + return new BasicSearchNavigatorUI((JHelpSearchNavigator) x); + } + + public BasicSearchNavigatorUI(JHelpSearchNavigator b) { + ImageIcon icon = getImageIcon(b.getNavigatorView()); + if (icon != null) { + setIcon(icon); + } else { + setIcon(UIManager.getIcon("SearchNav.icon")); + } + } + + ActionListener searchAction = new SearchActionListener(); + private Cursor paramCursor; + private Cursor treeCursor; + private Cursor waitCursor=null; + + class SearchActionListener implements ActionListener { + public synchronized void actionPerformed(ActionEvent e) { + HelpModel helpmodel = searchnav.getModel(); + try { + if (paramCursor == null) { + paramCursor = searchparams.getCursor(); + } + if (treeCursor == null) { + treeCursor = tree.getCursor(); + } + if (waitCursor == null) { + waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + } + searchparams.setCursor(waitCursor); + tree.setCursor(waitCursor); + + if (helpsearch == null) { + debug("helpsearch is null"); + helpsearch = searchnav.getSearchEngine(); + searchquery = helpsearch.createQuery(); + searchquery.addSearchListener(BasicSearchNavigatorUI.this); + } + debug("click on search w/: "+searchparams.getText()); + if (searchquery.isActive()) { + searchquery.stop(); + } + searchquery.start(searchparams.getText(),searchnav.getLocale()); + } catch (Exception e2) { + searchparams.setCursor(paramCursor); + tree.setCursor(treeCursor); + // more work needed here + e2.printStackTrace(); + // 2 beeps + searchnav.getToolkit().beep(); + searchnav.getToolkit().beep(); + } + } + } + + public void installUI(JComponent c) { + searchnav = (JHelpSearchNavigator)c; + HelpModel helpmodel = searchnav.getModel(); + + searchnav.setLayout(new BorderLayout()); + searchnav.addPropertyChangeListener(this); + searchnav.addComponentListener(this); + if (helpmodel != null) { + helpmodel.addHelpModelListener(this); + } + + JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c), + "search.findLabel")); + searchparams = new JTextField ("", 20); + search.setLabelFor(searchparams); + searchparams.addActionListener(searchAction); + + JPanel box = new JPanel(); + box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS)); + box.add(search); + box.add(searchparams); + + searchnav.add ("North", box); + topNode = new DefaultMutableTreeNode(); + lastTOCnode = null; + tree = new JTree(topNode); + // public String convertValueToText(Object val + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.addTreeSelectionListener(this); + tree.setShowsRootHandles(false); + tree.setRootVisible(false); + sp = new JScrollPane(); + sp.getViewport().add(tree); + searchnav.add("Center", sp); + reloadData(); + } + + public void uninstallUI(JComponent c) { + HelpModel helpmodel = searchnav.getModel(); + + searchnav.removeComponentListener(this); + searchnav.removePropertyChangeListener(this); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.removeTreeSelectionListener(this); + searchnav.setLayout(null); + searchnav.removeAll(); + + if (helpmodel != null) { + helpmodel.removeHelpModelListener(this); + } + searchnav = null; + } + + public Dimension getPreferredSize(JComponent c) { + /* + if (sp != null) { + return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp); + } else { + return new Dimension(200,100); + } + */ + return new Dimension(200,100); + } + + public Dimension getMinimumSize(JComponent c) { + if (sp != null) { + return ((ScrollPaneLayout)sp.getLayout()).minimumLayoutSize(sp); + } else { + return new Dimension(100,100); + } + } + + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + /** + * Indicates that there is new search data to use. + */ + private void reloadData() { + helpsearch = null; + setCellRenderer(searchnav.getNavigatorView(), tree); + // add all subhelpsets + HelpModel model = searchnav.getModel(); + if (model != null) { + addSubHelpSets(model.getHelpSet()); + } + } + + /** + * Reloads data from new model, creates new search engine to search in new model if model + * contains view with the same name + **/ + private void reloadData(HelpModel model) { + debug("reloadData using new model"); + helpsearch = null; + SearchView view = null; + + newHelpSet = model.getHelpSet(); + SearchView oldView = (SearchView) searchnav.getNavigatorView(); + String oldName = oldView.getName(); + NavigatorView[] navViews = newHelpSet.getNavigatorViews(); + for(int i = 0 ; i < navViews.length; i++){ + if((navViews[i].getName()).equals(oldName)){ + NavigatorView tempView = navViews[i]; + if(tempView instanceof SearchView){ + view = (SearchView) tempView; + break; + } + } + } + + if(view == null) + return; + + topNode.removeAllChildren(); + searchnav.setSearchEngine(new MergingSearchEngine(view)); + + + setCellRenderer(view, tree); + // add all subhelpsets + addSubHelpSets(newHelpSet); + + } + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + protected void addSubHelpSets(HelpSet hs){ + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if(searchnav.canMerge(views[i])) + searchnav.merge(views[i]); + } + addSubHelpSets( ehs ); + } + } + + /** + * Merges in the navigational data from another NavigatorView. + */ + + public void merge(NavigatorView view) { + debug("merging "+view); + + // redo the search if necessary + String text = searchparams.getText(); + if (text != null && text.length() != 0) { + searchAction.actionPerformed(new ActionEvent(searchparams, + ActionEvent.ACTION_PERFORMED, + "")); + } + } + + /** + * Removes the navigational data from another NavigatorView. + */ + + public void remove(NavigatorView view) { + debug("removing "+view); + + // redo the search if necessary + if (searchparams.getText() != null) { + searchAction.actionPerformed(new ActionEvent(searchparams, + ActionEvent.ACTION_PERFORMED, + "")); + } + } + + /** + * Setd the desired cell renderer on this tree. This is exposed for redefinition + * by subclases. + */ + protected void setCellRenderer(NavigatorView view, JTree tree) { + if (view == null) { + return; + } + Map map = view.getHelpSet().getCombinedMap(); + tree.setCellRenderer(new BasicSearchCellRenderer(map)); + } + + /** + * Processes an idChanged event. Search is different from all other + * navigators in that you while search tree is synchronized + * the highlighting doesn't occur unless selected from the search + * navigator. + */ + + public void idChanged(HelpModelEvent e) { + ID id = e.getID(); + URL url = e.getURL(); + HelpModel helpModel = searchnav.getModel(); + debug("idChanged("+e+")"); + + if (e.getSource() != helpModel) { + debug("Internal inconsistency!"); + debug(" "+e.getSource()+" != "+helpModel); + throw new Error("Internal error"); + } + + TreePath s = tree.getSelectionPath(); + if (s != null) { + Object o = s.getLastPathComponent(); + // should require only a TreeNode + if (o instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o; + SearchTOCItem item = (SearchTOCItem) tn.getUserObject(); + if (item != null) { + ID nId = item.getID(); + if (nId != null && nId.equals(id)) { + return; + } + } + } + } + + DefaultMutableTreeNode node = findIDorURL(topNode, id, url); + if (node == null) { + // node doesn't exist. Need to clear the selection. + debug ("node didn't exist"); + tree.clearSelection(); + return; + } + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + } + + protected JHelpNavigator getHelpNavigator() { + return searchnav; + } + + /** + * A value has changed. This is used as a TreeSelectionListener. + */ + public void valueChanged(TreeSelectionEvent e) { + + JHelpNavigator navigator = getHelpNavigator(); + HelpModel helpmodel = navigator.getModel(); + + debug("ValueChanged: "+e); + debug(" model: "+helpmodel); + + // send selected items into navigator + TreeItem[] items = null; + TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + items = new TreeItem[paths.length]; + for (int i = 0; i < paths.length; i++) { + if (paths[i] != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + items[i] = (TreeItem) node.getUserObject(); + } + } + } + navigator.setSelectedItems(items); + + // change current id only if one items is selected + if (items != null && items.length == 1) { + SearchTOCItem item = (SearchTOCItem)items[0]; + if (item != null) { + if (item.getID() != null) { + try { + // navigator.setCurrentID(item.getID()); + helpmodel.setCurrentID(item.getID(), item.getName(), navigator); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + } else if (item.getURL() != null) { + // navigator.setCurrentURL(item.getURL()); + helpmodel.setCurrentURL(item.getURL(), item.getName(), navigator); + } else { + // no ID, no URL + return; + } + if (helpmodel instanceof TextHelpModel) { + DefaultHighlight h[] = new DefaultHighlight[item.hitCount()]; + int i = 0; + Enumeration enum1 = item.getSearchHits(); + while (enum1.hasMoreElements()) { + SearchHit info = (SearchHit) enum1.nextElement(); + h[i] = new DefaultHighlight(info.getBegin(), info.getEnd()); + i++; + } + // using setHighlights() instead of removeAll + add + // avoids one highlighting event + ((TextHelpModel)helpmodel).setHighlights(h); + } + } + } + } + + public void propertyChange(PropertyChangeEvent event) { + debug(this + " " + "propertyChange: " + event.getSource() + " " + + event.getPropertyName()); + + if (event.getSource() == searchnav) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + + reloadData((HelpModel)event.getNewValue()); + + } else if (changeName.equals("font")) { + debug ("Font change"); + Font newFont = (Font)event.getNewValue(); + searchparams.setFont(newFont); + RepaintManager.currentManager(searchparams).markCompletelyDirty(searchparams); + tree.setFont(newFont); + RepaintManager.currentManager(tree).markCompletelyDirty(tree); + } + // changes to UI property? + } + } + + /** + * Invoked when the component's size changes. + */ + public void componentResized(ComponentEvent e) { + } + + /** + * Invoked when the component's position changes. + */ + public void componentMoved(ComponentEvent e) { + } + + /** + * Invoked when the component has been made visible. + */ + public void componentShown(ComponentEvent e) { + searchparams.selectAll(); + searchparams.requestFocus(); + } + + /** + * Invoked when the component has been made invisible. + */ + public void componentHidden(ComponentEvent e) { + } + + // Note - this recursive implementation may need tuning for very large TOC - epll + + private DefaultMutableTreeNode findIDorURL(DefaultMutableTreeNode node, + ID id, URL url) { + SearchTOCItem item = (SearchTOCItem) node.getUserObject(); + if (item != null) { + ID testID = item.getID(); + if (testID != null && id != null && testID.equals(id)) { + return node; + } else { + URL testURL = item.getURL(); + if (testURL != null && url != null && url.sameFile(testURL)) { + return node; + } + } + } + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = findIDorURL(tmp, id, url); + if (test != null) { + return test; + } + } + return null; + } + + // reorder the nodes + private void reorder (Vector nodes) { + + debug ("reorder nodes"); + + // remove all the children of topNode (they'll be added back later) + topNode.removeAllChildren(); + + // Create an array of the elements for sorting & copy the elements + // into the array. + DefaultMutableTreeNode[] array = new DefaultMutableTreeNode[nodes.size()]; + nodes.copyInto(array); + + // Sort the array (Quick Sort) + quickSort(array, 0, array.length - 1); + + // Reload the topNode. Everthing is in order now. + for (int i=0; i < array.length ; i++) { + topNode.add((DefaultMutableTreeNode)array[i]); + } + + // Tell the tree to repaint itself + ((DefaultTreeModel)tree.getModel()).reload(); + tree.invalidate(); + tree.repaint(); + } + + /** This is a version of C.A.R Hoare's Quick Sort + * algorithm. This will handle arrays that are already + * sorted, and arrays with duplicate keys.<BR> + * + * If you think of a one dimensional array as going from + * the lowest index on the left to the highest index on the right + * then the parameters to this function are lowest index or + * left and highest index or right. The first time you call + * this function it will be with the parameters 0, a.length - 1. + * + * @param a a DefaultMutableTreeNode array + * @param lo0 left boundary of array partition + * @param hi0 right boundary of array partition + */ + void quickSort(DefaultMutableTreeNode a[], int lo0, int hi0) { + int lo = lo0; + int hi = hi0; + int mid; + + if ( hi0 > lo0) + { + + /* Arbitrarily establishing partition element as the midpoint of + * the array. + */ + mid = ( lo0 + hi0 ) / 2; + + // loop through the array until indices cross + while( lo <= hi ) + { + /* find the first element that is greater than or equal to + * the partition element starting from the left Index. + */ + + while( ( lo < hi0 ) && ( compare(a[lo],a[mid]) > 0 )) + ++lo; + + /* find an element that is smaller than or equal to + * the partition element starting from the right Index. + */ + while( ( hi > lo0 ) && ( compare(a[hi],a[mid]) < 0 )) + --hi; + + // if the indexes have not crossed, swap + if( lo <= hi ) + { + swap(a, lo, hi); + ++lo; + --hi; + } + } + + /* If the right index has not reached the left side of array + * must now sort the left partition. + */ + if( lo0 < hi ) + quickSort( a, lo0, hi ); + + /* If the left index has not reached the right side of array + * must now sort the right partition. + */ + if( lo < hi0 ) + quickSort( a, lo, hi0 ); + + } + } + + private void swap(DefaultMutableTreeNode a[], int i, int j) + { + DefaultMutableTreeNode T; + T = a[i]; + a[i] = a[j]; + a[j] = T; + + } + + private int compare (DefaultMutableTreeNode node1, + DefaultMutableTreeNode node2) { + SearchTOCItem item1, item2; + double confidence1, confidence2; + int hits1, hits2; + + item1 = (SearchTOCItem) node1.getUserObject(); + confidence1 = item1.getConfidence(); + hits1 = item1.hitCount(); + + item2 = (SearchTOCItem) node2.getUserObject(); + confidence2 = item2.getConfidence(); + hits2 = item2.hitCount(); + + // confidence is a penality. The lower the better + if (confidence1 > confidence2) { + // node1 is less than node2 + return -1; + } else if (confidence1 < confidence2) { + // node1 is greater than node2 + return 1; + } else { + // confidences are the same check the hits + if (hits1 < hits2) { + // node1 is less than node2 + return -1; + } else if (hits1 > hits2) { + // node2 is greater than node2 + return 1; + } + } + // nodes1 and nodes2 are equivalent + return 0; + + } + + public synchronized void itemsFound(SearchEvent e) { + SwingUtilities.invokeLater(new SearchItemsFound(e)); + } + + class SearchItemsFound implements Runnable { + + SearchEvent e; + + SearchItemsFound (SearchEvent e) { + this.e = e; + } + + public void run() { + SearchTOCItem tocitem; + Vector nodes = new Vector(); + + // Add all the children of the topnode to the Vector of nodes. + Enumeration children = topNode.children(); + while (children.hasMoreElements()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement(); + nodes.addElement(node); + } + + debug ("items found"); + HelpModel helpmodel = searchnav.getModel(); + HelpSet hs = helpmodel.getHelpSet(); + debug("hs:"+hs.toString()); + Map map = hs.getCombinedMap(); + Enumeration itemEnum = e.getSearchItems(); + while (itemEnum.hasMoreElements()) { + SearchItem item = (SearchItem) itemEnum.nextElement(); + debug(" item: "+item); + URL url; + try { + url = new URL(item.getBase(), item.getFilename()); + } catch (MalformedURLException me) { + System.err.println ("Failed to create URL from " + item.getBase() + "|" + + item.getFilename()); + continue; + } + boolean foundNode = false; + DefaultMutableTreeNode node = null; + Enumeration nodesEnum = nodes.elements(); + while (nodesEnum.hasMoreElements()) { + node = (DefaultMutableTreeNode)nodesEnum.nextElement(); + tocitem = (SearchTOCItem) node.getUserObject(); + URL testURL = tocitem.getURL(); + if (testURL != null && url != null && url.sameFile(testURL)) { + tocitem = (SearchTOCItem) node.getUserObject(); + tocitem.addSearchHit(new SearchHit(item.getConfidence(), + item.getBegin(), + item.getEnd())); + foundNode = true; + break; + } + } + if (!foundNode) { + tocitem = new SearchTOCItem(item); + node = new DefaultMutableTreeNode(tocitem); + nodes.addElement(node); + } + } + reorder(nodes); + ((DefaultTreeModel)tree.getModel()).reload(); + } + } + + public synchronized void searchStarted(SearchEvent e) { + debug ("search Started"); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.clearSelection(); + topNode.removeAllChildren(); + ((DefaultTreeModel)tree.getModel()).reload(); + tree.invalidate(); + tree.repaint(); + } + }); + } + + public synchronized void searchFinished(SearchEvent e) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + TreeSelectionModel tsm = tree.getSelectionModel(); + if (lastTOCnode == null && topNode.getChildCount() > 0) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) topNode.getFirstChild(); + if (node != null) { + tsm.clearSelection(); + tsm.setSelectionPath(new TreePath(node.getPath())); + } + } else { + // beep + searchnav.getToolkit().beep(); + } + searchparams.setCursor(paramCursor); + tree.setCursor(treeCursor); + } + }); + return; + } + + + /** + * For printf debugging. + */ + private static boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("BasicSearchNavigatorUI: " + str); + } + } +} + + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..1350ac713948fd9581d0122efdf5022704da3f40 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java @@ -0,0 +1,188 @@ +/* + * @(#)BasicTOCCellRenderer.java 1.25 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicTOCCellRenderer.java 1.25 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.swing.*; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import java.awt.*; +import java.net.URL; +import java.util.Locale; +import javax.help.TOCItem; +import javax.help.TOCView; +import javax.help.Map; +import javax.help.HelpUtilities; +import javax.help.Map.ID; + +/** + * Basic cell renderer for TOC UI. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @version 1.25 10/30/06 + */ + +public class BasicTOCCellRenderer extends DefaultTreeCellRenderer +{ + protected Map map; + protected TOCView view; + + public BasicTOCCellRenderer(Map map) { + this(map, null); + } + + public BasicTOCCellRenderer(Map map, TOCView view) { + super(); + this.map = map; + this.view = view; + } + + /** + * Configures the renderer based on the components passed in. + * Sets the value from messaging value with toString(). + * The foreground color is set based on the selection and the icon + * is set based on on leaf and expanded. + */ + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) + { + + String stringValue = ""; + + // variable hasFocus was private to DefaultTreeCellRenderer since jdk1.3 + try { + this.hasFocus = hasFocus; + } catch (IllegalAccessError e) { + } + + TOCItem item + = (TOCItem) ((DefaultMutableTreeNode) value).getUserObject(); + + if (item != null) { + stringValue = item.getName(); + } + + setText(stringValue); + if (sel) { + setForeground(getTextSelectionColor()); + } else { + setForeground(getTextNonSelectionColor()); + } + + ImageIcon icon = null; + if (item != null) { + ID id = item.getImageID(); + if (id != null) { + try { + URL url = map.getURLFromID(id); + icon = new ImageIcon(url); + } catch (Exception e) { + } + } + } + + // Set the locale of this if there is a lang value + if (item != null) { + Locale locale = item.getLocale(); + if (locale != null) { + setLocale(locale); + } + } + + // determine which icon to display + if (icon != null) { + setIcon(icon); + } else if (leaf) { + setIcon(getLeafIcon()); + } else if (expanded) { + setIcon(getOpenIcon()); + } else { + setIcon(getClosedIcon()); + } + + selected = sel; + + return this; + } + + public Icon getLeafIcon() { + Icon icon = null; + if (view != null) { + ID id = view.getTopicImageID(); + if (id != null) { + try { + URL url = map.getURLFromID(id); + icon = new ImageIcon(url); + return icon; + } catch (Exception e) { + } + } + } + return super.getLeafIcon(); + } + + public Icon getOpenIcon() { + Icon icon = null; + if (view != null) { + ID id = view.getCategoryOpenImageID(); + if (id != null) { + try { + URL url = map.getURLFromID(id); + icon = new ImageIcon(url); + return icon; + } catch (Exception e) { + } + } + } + return super.getOpenIcon(); + } + + public Icon getClosedIcon() { + Icon icon = null; + if (view != null) { + ID id = view.getCategoryClosedImageID(); + if (id != null) { + try { + URL url = map.getURLFromID(id); + icon = new ImageIcon(url); + return icon; + } catch (Exception e) { + } + } + } + return super.getClosedIcon(); + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java new file mode 100644 index 0000000000000000000000000000000000000000..e57c3e91aac63fe3218d7e9f1145e44e8446219b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java @@ -0,0 +1,807 @@ +/* + * @(#)BasicTOCNavigatorUI.java 1.99 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) BasicTOCNavigatorUI.java 1.99 - last change made 10/30/06 + */ + +package javax.help.plaf.basic; + +import javax.help.*; +import javax.help.plaf.HelpNavigatorUI; +import javax.help.plaf.HelpUI; +import javax.help.event.HelpModelListener; +import javax.help.event.HelpModelEvent; +import com.sun.java.help.impl.SwingWorker; +import java.util.EventObject; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.RepaintManager; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; +import javax.swing.plaf.ComponentUI; +import javax.swing.tree.*; +import javax.swing.event.*; +import java.awt.*; +import java.io.Reader; +import java.io.Serializable; +import java.net.URL; +import java.net.URLConnection; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import javax.help.Map.ID; +import java.util.Locale; +import java.lang.reflect.Method; + +/** + * The default UI for JHelpNavigator of type TOC. + * + * @author Roger D. Brinkley + * @author Eduardo Pelegri-Llopart + * @author Stepan Marek + * @author Richard Gregor + * @version 1.99 10/30/06 + */ +public class BasicTOCNavigatorUI extends HelpNavigatorUI + implements HelpModelListener, TreeSelectionListener, + PropertyChangeListener, ComponentListener, + Serializable +{ + protected JHelpTOCNavigator toc; + protected JScrollPane sp; + protected DefaultMutableTreeNode topNode; + protected JTree tree; + private boolean inInstallUI = false; + private SwingWorker worker = null; + + public static ComponentUI createUI(JComponent x) { + return new BasicTOCNavigatorUI((JHelpTOCNavigator) x); + } + + public BasicTOCNavigatorUI(JHelpTOCNavigator b) { + debug (this + " " + "CreateUI - sort of"); + ImageIcon icon = getImageIcon(b.getNavigatorView()); + if (icon != null) { + setIcon(icon); + } else { + setIcon(UIManager.getIcon("TOCNav.icon")); + } + } + + public void installUI(JComponent c) { + debug (this + " " + "installUI"); + + inInstallUI = true; + toc = (JHelpTOCNavigator)c; + HelpModel model = toc.getModel(); + + toc.setLayout(new BorderLayout()); + toc.addPropertyChangeListener(this); + toc.addComponentListener(this); + if (model != null) { + model.addHelpModelListener(this); // for our own changes + } + + topNode = new DefaultMutableTreeNode(); + + tree = new JTree(topNode); + TreeSelectionModel tsm = tree.getSelectionModel(); + // tsm.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + tsm.addTreeSelectionListener(this); + + tree.setShowsRootHandles(false); + tree.setRootVisible(false); + + setCellRenderer(toc.getNavigatorView(), tree); + + sp = new JScrollPane(); + sp.getViewport().add(tree); + + toc.add("Center", sp); + reloadData(); + inInstallUI = false; + } + + /** + * Sets the desired cell renderer on this tree. This is exposed for redefinition + * by subclases. + */ + protected void setCellRenderer(NavigatorView view, JTree tree) { + // Use the combined map to drive the TOC tree actions + Map map = view.getHelpSet().getCombinedMap(); + tree.setCellRenderer(new BasicTOCCellRenderer(map, (TOCView)view)); + } + + public void uninstallUI(JComponent c) { + debug (this + " " + "unistallUI"); + HelpModel model = toc.getModel(); + + toc.removeComponentListener(this); + toc.removePropertyChangeListener(this); + TreeSelectionModel tsm = tree.getSelectionModel(); + tsm.removeTreeSelectionListener(this); + toc.setLayout(null); + toc.removeAll(); + + if (model != null) { + model.removeHelpModelListener(this); + } + + toc = null; + } + + public Dimension getPreferredSize(JComponent c) { + /* + if (sp != null) { + return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp); + } else { + return new Dimension(200,100); + } + */ + return new Dimension (200,100); + } + + public Dimension getMinimumSize(JComponent c) { + return new Dimension(100,100); + } + + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + /** + * Reloads the presentation data. + */ + private void reloadData() { + debug("reloadData"); + + // parse the TOC data into topNode + TOCView view = (TOCView) toc.getNavigatorView(); + + if (worker != null) { + // Something is still going on. Stop it and start over + worker.interrupt(); + } + worker = new NavSwingWorker(view); + worker.start(Thread.MIN_PRIORITY); + } + + /** + * load the data for the navigator. Will be run on a separate + * thread. + */ + private synchronized Object loadData(TOCView view) { + if (view == null) { + return Boolean.FALSE; + } + + // remove all children + topNode.removeAllChildren(); + + String mergeType = view.getMergeType(); + + Locale locale = view.getHelpSet().getLocale(); + + DefaultMutableTreeNode node = view.getDataAsTree(); + + // Make sure the children are all handled correctly + MergeHelpUtilities.mergeNodeChildren(mergeType, node); + + // This is a tricky one. As you remove the entries from one node to + // another the list shrinks. So you can't use an Enumated list to do + // the move. + while (node.getChildCount() > 0) { + topNode.add((DefaultMutableTreeNode) node.getFirstChild()); + } + + // Add all of the subhelpset's data + addSubHelpSets(view.getHelpSet()); + return Boolean.TRUE; + } + + + /* + * Presents the data loaded in loadData. Will be run on the + * Swing event thread. + */ + private void presentData() { + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + + setVisibility(topNode); + + + if (toc.getModel() != null) { + ID id = toc.getModel().getCurrentID(); + if (id != null) { + DefaultMutableTreeNode selectedNode = findID(topNode, id); + selectNode(selectedNode); + } + } + } + + private class NavSwingWorker extends SwingWorker { + TOCView view; + + public NavSwingWorker (TOCView view) { + super(); + this.view = view; + } + + public Object construct() { + return loadData(view); + } + + public void finished() { + if ((Boolean)get() == Boolean.TRUE) { + presentData(); + } + } + } + + + /** + * Reloads the presentation data using new help model. Changes the navigator if new model contains + * view with the same name as former view + **/ + private void reloadData(HelpModel model) { + debug("reloadData using new model"); + + TOCView view = null; + + HelpSet newHelpSet = model.getHelpSet(); + TOCView oldView = (TOCView) toc.getNavigatorView(); + String oldName = oldView.getName(); + NavigatorView[] navViews = newHelpSet.getNavigatorViews(); + for(int i = 0 ; i < navViews.length; i++){ + if((navViews[i].getName()).equals(oldName)){ + NavigatorView tempView = navViews[i]; + if(tempView instanceof TOCView){ + view = (TOCView) tempView; + break; + } + } + } + + if (worker != null) { + // Something is still going on. Stop it and start over + worker.interrupt(); + } + worker = new NavSwingWorker(view); + worker.start(Thread.MIN_PRIORITY); + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + protected void addSubHelpSets(HelpSet hs){ + debug("addSubHelpSets"); + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if(toc.canMerge(views[i])) + doMerge(views[i]); + } + addSubHelpSets( ehs ); + } + } + + /** + * Expands entry path and entry itself( when entry is not empty) for specific id + * + * @param target The target of entry + */ + + private void expand(String target){ + debug("expand called"); + //find all nodes with certain id + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug("expandPath :"+node); + if(node.getChildCount() > 0){ + DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild(); + TreePath path = new TreePath(child.getPath()); + tree.makeVisible(path); + } + else{ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + //tree.scrollPathToVisible(path); + tree.makeVisible(path); + } + } + } + + /** + * Returns all nodes with certain id + * + * @param target The target of entry + * + */ + private Vector findNodes(String target){ + Enumeration nodes = topNode.preorderEnumeration(); + DefaultMutableTreeNode node = null; + Vector nodeFound = new Vector(); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + debug(" node :"+ node.toString()); + if(node != null){ + TOCItem tocItem = (TOCItem)node.getUserObject(); + if(tocItem == null) + debug("tocItem is null"); + else{ + Map.ID id = tocItem.getID(); + if(id != null){ + debug("id name :"+id.id); + debug("target :"+target); + Map.ID itemID = null; + try{ + itemID = Map.ID.create(target,toc.getModel().getHelpSet()); + } + catch(BadIDException exp){ + System.err.println("Not valid ID :"+target ); + break; + } + if(id.equals(itemID)) + nodeFound.addElement(node); + } + } + } + } + + return nodeFound; + } + + /** + * Collapses entry specified by id. If entry is empty collapses its parent. + * + * @param target The target of entry + */ + + private void collapse(String target){ + Enumeration nodes = findNodes(target).elements(); + DefaultMutableTreeNode node = null; + debug("collapse called"); + + while(nodes.hasMoreElements()){ + node = (DefaultMutableTreeNode)nodes.nextElement(); + if(node.getChildCount() > 0){ + TreeNode[] treeNode = node.getPath(); + TreePath path = new TreePath(treeNode); + tree.collapsePath(path); + tree.collapseRow(tree.getRowForPath(path)); + } + else{ + DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent(); + TreePath path = new TreePath(parent.getPath()); + tree.collapseRow(tree.getRowForPath(path)); + } + } + } + + + /** + * Merges in the navigational data from another IndexView. + */ + + public void doMerge(NavigatorView view) { + debug("merging data"); + + Merge mergeObject = Merge.DefaultMergeFactory.getMerge(toc.getNavigatorView(),view); + if(mergeObject != null) { + mergeObject.processMerge(topNode); + } + + } + + /** + * Merges in the navigational data from another TOCView. + * + * @param view A TOCView. Note the actual argument is of a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void merge(NavigatorView view) { + debug("merging "+view); + doMerge(view); + + //reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Removes the navigational data. + * + * @param view A TOCView. Note the actual argument is of a NavigatorView type + * so it replaces the correct NavigatorUI method. + */ + + public void remove(NavigatorView view) { + debug("removing "+view); + + remove(topNode, view.getHelpSet()); + + // reload the tree data + ((DefaultTreeModel)tree.getModel()).reload(); + setVisibility(topNode); + } + + /** + * Recursively removes all children of the node that have either hs or a HelpSet that + * is included in hs as their HelpSet data. + * + * Recursion is stopped when a node is removed. This is because of the + * property of the merge mechanism. + * + * @param node The node from where to remove its children + * @param hs The non-null helpset to use + */ + + private void remove(DefaultMutableTreeNode node, + HelpSet hs) { + debug("remove("+node+", "+hs+")"); + + // a simple node.children() does not work because the + // enumeration is voided when a child is removed + + // getNextSibling() has a linear search, so we won't do that either + + // Collect all to be removed + Vector toRemove = new Vector(); + + for (Enumeration e = node.children(); + e.hasMoreElements(); ) { + DefaultMutableTreeNode child + = (DefaultMutableTreeNode) e.nextElement(); + debug(" considering "+child); + TOCItem item = (TOCItem) child.getUserObject(); + HelpSet chs = item.getHelpSet(); + debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs)); + if (chs != null && + hs.contains(chs)) { + if (child.isLeaf()) { + // if the child has no children then just remove it + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // be carefull here. While the child hs is one to be + // removed it is possible that there are children that + // are not of this hs. Attempt to remove the + // child's children first. If they're are any children left + // the change the hs to be the hs of the first child + remove(child, hs); + if (child.isLeaf()) { + // no more children remove the child as well + debug(" tagging for removal: "+child); + toRemove.addElement(child); // tag to be removed... + } else { + // nuts! There are children from different hs + // change the hs of the TOCItem to be the hs of the + // first child + DefaultMutableTreeNode childOne = + (DefaultMutableTreeNode) child.getFirstChild(); + TOCItem itemOne = (TOCItem) childOne.getUserObject(); + item.setHelpSet(itemOne.getHelpSet()); + debug(" orphaned children - changing hs: "+child); + } + } + } else { + // the child doesn't need to be removed but possibly it's + // children will + remove(child, hs); + } + } + + // Now remove them + for (int i=0; i<toRemove.size(); i++) { + debug(" removing "+toRemove.elementAt(i)); + node.remove((DefaultMutableTreeNode) toRemove.elementAt(i)); + } + } + + + // In the TOC only set the visibility at the next to the top node + // unless the node is set for expansion. Always expand the first row + private void setVisibility (DefaultMutableTreeNode node) { + TOCItem item = (TOCItem)node.getUserObject(); + int expandType = TreeItem.DEFAULT_EXPANSION; + if (item != null) { + expandType = item.getExpansionType(); + } + TreePath path = new TreePath(node.getPath()); + int pathcount = path.getPathCount(); + if (node == topNode || + (pathcount <= 2 && expandType == TreeItem.DEFAULT_EXPANSION) || + (expandType == TreeItem.EXPAND)) { + tree.expandPath(new TreePath(node.getPath())); + if (! node.isLeaf()) { + int max = node.getChildCount(); + for (int i=0; i<max; i++) { + setVisibility((DefaultMutableTreeNode)node.getChildAt(i)); + } + } + } + } + + /** + * Processes an idChanged event. + */ + + public synchronized void idChanged(HelpModelEvent e) { + ID id = e.getID(); + HelpModel helpModel = toc.getModel(); + debug("idChanged("+e+")"); + + if (e.getSource() != helpModel) { + debug("Internal inconsistency!"); + debug(" "+e.getSource()+" != "+helpModel); + throw new Error("Internal error"); + } + + if (id == null) { + id = helpModel.getHelpSet().getCombinedMap().getClosestID(e.getURL()); + } + TreePath s = tree.getSelectionPath(); + if (s != null) { + Object o = s.getLastPathComponent(); + // should require only a TreeNode + if (o instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o; + TOCItem item = (TOCItem) tn.getUserObject(); + if (item != null) { + ID nId = item.getID(); + if (nId != null && nId.equals(id)) { + return; + } + } + } + } + + DefaultMutableTreeNode node = findID(topNode, id); + selectNode(node); + } + + // Note - this recursive implementation may need tuning for very large TOC - epll + + private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) { + debug("findID: ("+id+")"); + debug(" node: "+node); + + // check on the ID + if (id == null) { + return null; + } + TOCItem item = (TOCItem) node.getUserObject(); + if (item != null) { + ID testID = item.getID(); + debug(" testID: "+testID); + if (testID != null && testID.equals(id)) { + return node; + } + } + int size = node.getChildCount(); + for (int i=0; i<size ; i++) { + DefaultMutableTreeNode tmp = + (DefaultMutableTreeNode) node.getChildAt(i); + DefaultMutableTreeNode test = findID(tmp, id); + if (test != null) { + return test; + } + } + return null; + } + + /** + * Select a certian node + */ + private void selectNode(DefaultMutableTreeNode node) { + if (node == null) { + // node doesn't exist. Need to clear the selection. + tree.clearSelection(); + return; + } + TreePath path = new TreePath(node.getPath()); + tree.expandPath(path); + tree.setSelectionPath(path); + tree.scrollPathToVisible(path); + } + + protected JHelpNavigator getHelpNavigator() { + return toc; + } + + public void valueChanged(TreeSelectionEvent e) { + + JHelpNavigator navigator = getHelpNavigator(); + HelpModel helpmodel = navigator.getModel(); + + debug("ValueChanged: "+e); + debug(" model: "+helpmodel); + + // send selected items into navigator + TreeItem[] items = null; + TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + items = new TreeItem[paths.length]; + for (int i = 0; i < paths.length; i++) { + if (paths[i] != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + items[i] = (TreeItem) node.getUserObject(); + } + } + } + navigator.setSelectedItems(items); + + // change current id only if one items is selected + if (items != null && items.length == 1) { + TOCItem item = (TOCItem) items[0]; + if (item != null && item.getID() != null) { + String presentation = item.getPresentation(); + if (presentation == null) { + // This is the old way of doing things + // set the currentID in the helpModel + try { + helpmodel.setCurrentID(item.getID(), item.getName(), navigator); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + } else { + // Tricky situation here + // Don't select a Tree item if we're installing + // and that TreeItem displays in different presentation + // This can lead to infinate loops + if (inInstallUI) { + tree.clearSelection(); + return; + } + + // using a Presentation + // Get a Presentation + Presentation pres; + HelpSet hs = helpmodel.getHelpSet(); + ClassLoader loader; + Class klass; + Class types[] = { HelpSet.class, + String.class}; + Object args[] = { hs, + item.getPresentationName()}; + try { + loader = hs.getLoader(); + if (loader == null) { + klass = Class.forName(presentation); + } else { + klass = loader.loadClass(presentation); + } + Method m = klass.getMethod("getPresentation", types); + pres = (Presentation)m.invoke(null, args); + } catch (Exception ex) { + throw new RuntimeException("error invoking presentation" ); + } + + if (pres == null) { + return; + } + + // Minor adjustments for Windows and Popups + if (pres instanceof WindowPresentation) { + ((WindowPresentation)pres).setActivationObject(tree); + } + if (pres instanceof Popup) { + ((Popup)pres).setInvokerInternalBounds(tree.getPathBounds(paths[0])); + ((Popup)pres).setInvoker((Component)tree); + } + + // set the id to be displayed + try { + pres.setCurrentID(item.getID()); + } catch (InvalidHelpSetContextException ex) { + System.err.println("BadID: "+item.getID()); + return; + } + + // diplay the presentation + pres.setDisplayed(true); + } + } + } + } + + public void propertyChange(PropertyChangeEvent event) { + debug(this + " " + "propertyChange: " + event.getSource() + " " + + event.getPropertyName()); + + if (event.getSource() == toc) { + String changeName = event.getPropertyName(); + if (changeName.equals("helpModel")) { + reloadData((HelpModel)event.getNewValue()); + } else if (changeName.equals("font")) { + debug ("Font change"); + Font newFont = (Font)event.getNewValue(); + tree.setFont(newFont); + RepaintManager.currentManager(tree).markCompletelyDirty(tree); + } else if(changeName.equals("expand")){ + debug("Expand change"); + expand((String)event.getNewValue()); + } else if(changeName.equals("collapse")){ + debug("Collapse change"); + collapse((String)event.getNewValue()); + } + // changes to UI property? + } + + } + + /** + * Invoked when the component's size changes. + */ + public void componentResized(ComponentEvent e) { + } + + /** + * Invoked when the component's position changes. + */ + public void componentMoved(ComponentEvent e) { + } + + /** + * Invoked when the component has been made visible. + */ + public void componentShown(ComponentEvent e) { + tree.requestFocus(); + } + + /** + * Invoked when the component has been made invisible. + */ + public void componentHidden(ComponentEvent e) { + } + + /** + * For printf debugging. + */ + protected static final boolean debug = false; + protected static void debug(String str) { + if (debug) { + System.out.println("BasicTOCNavigatorUI: " + str); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9d2397eea3b79f2598e44b683fd48e63eb812256 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java @@ -0,0 +1,195 @@ +/* + * @(#)GTKCursorFactory.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.plaf.gtk; + +import java.io.*; +import javax.swing.ImageIcon; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.util.ResourceBundle; +import java.util.MissingResourceException; +import java.util.PropertyResourceBundle; + +/** + * Factory object that can vend cursors appropriate for the GTK L & F. + * <p> + * + * @version 1.2 10/30/06 + * @author Roger D. Brinkley + */ +public class GTKCursorFactory { + private static Cursor onItemCursor; + private static Cursor dndCursor; + private static GTKCursorFactory theFactory; + + /** + * Returns the OnItem cursor. + */ + public static Cursor getOnItemCursor() { + debug ("getOnItemCursor"); + if (theFactory == null) { + theFactory = new GTKCursorFactory(); + } + if (onItemCursor == null) { + onItemCursor = theFactory.createCursor("OnItemCursor"); + } + return onItemCursor; + } + + /** + * Returns the DnDCursor. + */ + public static Cursor getDnDCursor(){ + debug("getDnDCursor"); + if (theFactory == null) { + theFactory = new GTKCursorFactory(); + } + if (dndCursor == null) { + dndCursor = theFactory.createCursor("DnDCursor"); + } + return dndCursor; + } + + private Cursor createCursor(String name) { + String gifFile = null; + String hotspot = null; + ImageIcon icon; + Point point; + + debug("CreateCursor for " + name); + + // Get the Property file + InputStream is = getClass().getResourceAsStream("images/" + name + ".properties"); + if (is == null) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " not found."); + return null; + } + try { + ResourceBundle resource = new PropertyResourceBundle(is); + gifFile = resource.getString("Cursor.File"); + hotspot = resource.getString("Cursor.HotSpot"); + } catch (MissingResourceException e) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " invalid."); + return null; + } catch (IOException e2) { + debug(getClass().getName() + "/" + + "images/" + name + ".properties" + " invalid."); + return null; + } + + // Create the icon + byte[] buffer = null; + try { + /* Copies resource into a byte array. This is + * necessary because several browsers consider + * Class.getResource a security risk because it + * can be used to load additional classes. + * Class.getResourceAsStream returns raw + * bytes, which JH can convert to an image. + */ + InputStream resource = + getClass().getResourceAsStream(gifFile); + if (resource == null) { + debug(getClass().getName() + "/" + + gifFile + " not found."); + return null; + } + BufferedInputStream in = + new BufferedInputStream(resource); + ByteArrayOutputStream out = + new ByteArrayOutputStream(1024); + buffer = new byte[1024]; + int n; + while ((n = in.read(buffer)) > 0) { + out.write(buffer, 0, n); + } + in.close(); + out.flush(); + + buffer = out.toByteArray(); + if (buffer.length == 0) { + debug("warning: " + gifFile + + " is zero-length"); + return null; + } + } catch (IOException ioe) { + debug(ioe.toString()); + return null; + } + + icon = new ImageIcon(buffer); + + // create the point + int k = hotspot.indexOf(','); + point = new Point(Integer.parseInt(hotspot.substring(0,k)), + Integer.parseInt(hotspot.substring(k+1))); + + debug ("Toolkit fetching cursor"); + try { + + Image image = icon.getImage(); + int width = icon.getIconWidth(); + int height = icon.getIconHeight(); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + Dimension d = toolkit.getBestCursorSize(width, height); + + if ((d.width > width) || (d.height > height)) { + try { + Image bimage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB); + bimage.getGraphics().drawImage(icon.getImage(), 0, 0, icon.getImageObserver()); + image = bimage; + } catch (Exception ex) { + } + } + + return toolkit.createCustomCursor(image, point, name); + + } catch (NoSuchMethodError err) { + // return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + return null; + } + } + + /** + * For printf debugging. + */ + private static final boolean debug = false; + private static void debug(String str) { + if (debug) { + System.out.println("GTKCursorFactory: " + str); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html b/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html new file mode 100644 index 0000000000000000000000000000000000000000..060ede57db8cad7b7196e6e874caa42a38c93202 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.2 99/03/19 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Supports access to Component UI classes. <code>HelpUI</code> is for +the JHelp component, <code>HelpContentViewerUI</code> is for the +JHelpContentViewer component, and <code>HelpNavigatorUI</code> is for +the JHelp components. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see the <em>JavaHelp System User's Guide</em>. + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..c0c9f28e6dfdd49723ab3ce7958122143fb39262 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java @@ -0,0 +1,149 @@ +/* + * @(#)Constants.java 1.22 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants.java 1.22 - last change made 10/30/06 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "Unknown PublicID {0}"}, + { "helpset.wrongTitle", + "Attempting to set title to {0} but already has value {1}."}, + { "helpset.wrongHomeID", + "Attempting to set homeID to {0} but already has value {1}."}, + { "helpset.subHelpSetTrouble", + "Trouble creating subhelpset: {0}."}, + { "helpset.malformedURL", + "Malformed URL: {0}."}, + { "helpset.incorrectURL", + "Incorrect URL: {0}."}, + { "helpset.wrongText", + "{0} cannot contain text {1}."}, + { "helpset.wrongTopLevel", + "{0} cannot be a top level tag."}, + { "helpset.wrongParent", + "The parent tag for {0} cannot be {1}."}, + { "helpset.unbalanced", + "Unbalanced tag {0}."}, + { "helpset.wrongLocale", + "Warning: xml:lang attribute {0} conflicts with default {1} and with default {2}"}, + { "helpset.unknownVersion", + "Unknown Version {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "Warning: Invalid Index format"}, + { "index.unknownVersion", + "Unknown Version {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "Unknown PublicID {0}"}, + { "toc.invalidTOCFormat", + "Warning: Invalid TOC format"}, + { "toc.unknownVersion", + "Unknown Version {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Warning: Invalid Favorites format"}, + { "favorites.unknownVersion", + "Unknown Version {0}."}, + + // Map messages + { "map.wrongPublicID", + "Unknown PublicID {0}"}, + { "map.invalidMapFormat", + "Warning: Invalid Map format"}, + { "map.unknownVersion", + "Unknown Version {0}."}, + + // GUI components + // Labels + { "index.findLabel", "Find: "}, + + { "search.findLabel", "Find: "}, + { "search.hitDesc", "Number of occurances in document"}, + { "search.qualityDesc", "Lowest penality value in document" }, + { "search.high", "High"}, + { "search.midhigh", "Medium high"}, + { "search.mid", "Medium"}, + { "search.midlow", "Medium low"}, + { "search.low", "Low"}, + + { "favorites.add", "Add"}, + { "favorites.remove", "Remove"}, + { "favorites.folder", "New Folder"}, + { "favorites.name", "Name"}, + { "favorites.cut", "Cut"}, + { "favorites.paste", "Paste"}, + { "favorites.copy" , "Copy"}, + + { "history.homePage", "Home page"}, + { "history.unknownTitle", "<unknown page title>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "Previous Page"}, + { "tooltip.ForwardAction", "Next Page"}, + { "tooltip.PrintAction", "Print"}, + { "tooltip.PrintSetupAction", "Page Setup"}, + { "tooltip.ReloadAction", "Reload"}, + { "tooltip.FavoritesAction", "Add to Favorites"}, + { "tooltip.HomeAction", "Go to home page"}, + + // Accessibility names + { "access.BackAction", "Previous Button"}, + { "access.ForwardAction", "Next Button"}, + { "access.HistoryAction", "History Button"}, + { "access.PrintAction", "Print Button"}, + { "access.PrintSetupAction", "Page Setup Button"}, + { "access.ReloadAction", "Reload Button"}, + { "access.HomeAction", "Home Button"}, + { "access.FavoritesAction", "Add to Favorites Button"}, + { "access.contentViewer", "Content Viewer"} + + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java new file mode 100644 index 0000000000000000000000000000000000000000..b61be368ded1a5d66e2633b2c559d6323277b9e1 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java @@ -0,0 +1,149 @@ +/* + * @(#)Constants_ar.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_ar.java 1.19 - last change made 10/19/01 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_ar extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "PublicID {0} \u0645\u062c\u0647\u0648\u0644"}, + { "helpset.wrongTitle", + "\u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0639\u0637\u0627\u0621 \u0639\u0646\u0648\u0627\u0646 \u0644 {0} \u0644\u0643\u0646 \u0647\u0646\u0627\u0643 \u0639\u0646\u0648\u0627\u0646 {1}."}, + { "helpset.wrongHomeID", + ".homeID \u0642\u064a\u0645\u0629{\u0660} \u0644 {\u0660} \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0639\u0637\u0627\u0621 \u0644\u0643\u0646 \u0647\u0646\u0627\u0643"}, + { "helpset.subHelpSetTrouble", + "\u0647\u0646\u0627\u0643 \u0645\u0634\u0643\u0644\u0629 \u0627\u0646\u0634\u0627\u0621 subhelpset:{0}."}, + { "helpset.malformedURL", + "\u0645\u0648\u0642\u0639 URL {0). \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"}, + { "helpset.incorrectURL", + "\u0645\u0648\u0642\u0639 URL {0). \u063a\u064a\u0631 \u0635\u062d\u064a\u062d"}, + { "helpset.wrongText", + "{0} \u064a\u062a\u0639\u0630\u0631 \u0627\u062f\u062e\u0627\u0644 \u0646\u0635\u0648\u0635 {1}."}, + { "helpset.wrongTopLevel", + "{0} TAG \u0645\u0646 \u0627\u0644\u0645\u0633\u062a\u0648\u0649 \u0627\u0644\u0623\u0639\u0644\u0649 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646."}, + { "helpset.wrongParent", + "TAG \u0631\u0626\u064a\u0633\u064a \u0645\u0646 {0} \u0644\u0627 \u064a\u0645\u0643\u0646 \u0623\u0646 \u064a\u0643\u0648\u0646 . {1}."}, + { "helpset.unbalanced", + "tag {0} \u063a\u064a\u0631 \u0645\u0648\u0632\u0648\u0646"}, + { "helpset.wrongLocale", + "\u062a\u0646\u0628\u064a\u0647: \u0633\u0645\u0629 xml:lang {0} \u062a\u062a\u0639\u0627\u0631\u0636 \u0645\u0639 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629 {1} \u0648\u0645\u0639 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629 {2}."}, + { "helpset.unknownVersion", + "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644\u0641\u0647\u0631\u0633 \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"}, + { "index.unknownVersion", + "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "PublicID {0} \u0645\u062c\u0647\u0648\u0644"}, + { "toc.invalidTOCFormat", + "\u062a\u0646\u0628\u064a\u0647: \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u064a\u0627\u062a \u063a\u064a\u0631 \u0635\u0627\u0644\u062d\u0629"}, + { "toc.unknownVersion", + "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"}, + { "favorites.unknownVersion", + "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."}, + + // Map messages + { "map.wrongPublicID", + "PublicID {0} \u0645\u062c\u0647\u0648\u0644"}, + { "map.invalidMapFormat", + "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644 Map \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"}, + { "map.unknownVersion", + "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."}, + + // GUI components + // Labels + { "index.findLabel", "\u0628\u062d\u062b: "}, + + { "search.findLabel", "\u0628\u062d\u062b: "}, + { "search.hitDesc", "\u0639\u062f\u062f \u0645\u0631\u0627\u062a \u0627\u0644\u0638\u0647\u0648\u0631 \u0641\u064a \u0627\u0644\u0645\u0633\u062a\u0646\u062f"}, + { "search.qualityDesc", "" }, + { "search.high", "\u0639\u0627\u0644\u064a"}, + { "search.midhigh", "\u0648\u0633\u0637 \u0627\u0644\u0639\u0627\u0644\u064a"}, + { "search.mid", "\u0648\u0633\u0637"}, + { "search.midlow", "\u0648\u0633\u0637 \u0627\u0644\u0645\u0646\u062e\u0641\u0636"}, + { "search.low", "\u0645\u0646\u062e\u0641\u0636"}, + + { "favorites.add", "\u0627\u0636\u0627\u0641\u0629"}, + { "favorites.remove", "\u0627\u0632\u0627\u0644\u0629"}, + { "favorites.folder", "\u0645\u062c\u0644\u062f \u062c\u062f\u064a\u062f"}, + { "favorites.name", "\u0627\u0633\u0645"}, + { "favorites.cut", "\u0642\u0635"}, + { "favorites.paste", "\u0644\u0635\u0642"}, + { "favorites.copy" , "\u0646\u0633\u062e"}, + + { "history.homePage", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629"}, + { "history.unknownTitle", "<\u0639\u0646\u0648\u0627\u0646 \u0635\u0641\u062d\u0629 \u0645\u062c\u0647\u0648\u0644>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629"}, + { "tooltip.ForwardAction", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u062a\u0627\u0644\u064a\u0629"}, + { "tooltip.PrintAction", "\u0637\u0628\u0627\u0639\u0629"}, + { "tooltip.PrintSetupAction", "\u0627\u0639\u062f\u0627\u062f \u0627\u0644\u0635\u0641\u062d\u0629"}, + { "tooltip.ReloadAction", "\u0627\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644"}, + { "tooltip.FavoritesAction", "\u0623\u0636\u0641 \u0644\u0644\u0645\u0641\u0636\u0644\u0629"}, + { "tooltip.HomeAction", "\u0631\u062c\u0648\u0639 \u0644\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629"}, + + // Accessibility names + { "access.BackAction", "\u0627\u0644\u0632\u0631 \u0633\u0627\u0628\u0642"}, + { "access.ForwardAction", "\u0627\u0644\u0632\u0631 \u0627\u0644\u0627\u062a\u064a"}, + { "access.HistoryAction", "\u0627\u0644\u0632\u0631 \u0645\u062d\u0641\u0648\u0638\u0627\u062a"}, + { "access.PrintAction", "\u0627\u0644\u0632\u0631 \u0637\u0628\u0627\u0639\u0629"}, + { "access.PrintSetupAction", "\u0627\u0644\u0632\u0631 \u0627\u0639\u062f\u0627\u062f \u0627\u0644\u0635\u0641\u062d\u0629"}, + { "access.ReloadAction", "\u0627\u0644\u0632\u0631 \u0627\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644"}, + { "access.HomeAction", "\u0627\u0644\u0632\u0631 \u0628\u062f\u0627\u064a\u0629"}, + { "access.FavoritesAction", "\u0627\u0644\u0632\u0631 \u0623\u0636\u0641 \u0644\u0644\u0645\u0641\u0636\u0644\u0629"}, + { "access.contentViewer", "\u0639\u0627\u0631\u0636 \u0627\u0644\u0645\u062d\u062a\u0648\u064a\u0627\u062a"} + + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java new file mode 100644 index 0000000000000000000000000000000000000000..7638eb43e90d23e34d89dcc2d74f75fe2d11f5ab --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java @@ -0,0 +1,149 @@ +/* + * @(#)Constants_cs.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + * + * @author Stepan Marek + * @version 1.9 10/30/06 + * + */ + +public class Constants_cs extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "Nezn\u00e1m\u00e9 PublicID {0}"}, + { "helpset.wrongTitle", + "Zkou\u0161\u00edm nastavit nadpis na {0}, ale nadpis m\u00e1 ji\u017e hodnotu {1}."}, + { "helpset.wrongHomeID", + "Zkou\u0161\u00edm nastavit homeID na {0}, ale homeID ma ji\u017e hodnotu {1}."}, + { "helpset.subHelpSetTrouble", + "Nelze vytvo\u0159it subhelpset: {0}"}, + { "helpset.malformedURL", + "Chybn\u00fd form\u00e1t URL: {0}"}, + { "helpset.incorrectURL", + "Chybn\u00e9 URL: {0}"}, + { "helpset.wrongText", + "{0} nem\u016f\u017ee obsahovat text {1}."}, + { "helpset.wrongTopLevel", + "{0} nem\u016f\u017ee b\u00fdt top level tag."}, + { "helpset.wrongParent", + "P\u0159edch\u016fdce tagu {0} nem\u016f\u017ee b\u00fdt {1}."}, + { "helpset.unbalanced", + "Nesoum\u011brn\u00fd tag {0}"}, + { "helpset.wrongLocale", + "Upozorn\u011bn\u00ed: xml:lang atribut {0} je v konfliktu s implicitn\u00edmi hodnotami {1} a {2}"}, + { "helpset.unknownVersion", + "Nezn\u00e1m\u00e1 verze {0}"}, + + // IndexView messages + { "index.invalidIndexFormat", + "Upozorn\u011bn\u00ed: Index m\u00e1 chybn\u00fd form\u00e1t"}, + { "index.unknownVersion", + "Nezn\u00e1m\u00e1 verze {0}"}, + + // TOCView messages + { "toc.wrongPublicID", + "Nezn\u00e1m\u00e9 PublicID {0}"}, + { "toc.invalidTOCFormat", + "Upozorn\u011bn\u00ed: TOC m\u00e1 chybn\u00fd form\u00e1t TOC"}, + { "toc.unknownVersion", + "Nezn\u00e1m\u00e1 verze {0}"}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Upozorn\u011bn\u00ed: Nespr\u00e1vn\u00fd form\u00e1t souboru Favorites.xml"}, + { "favorites.unknownVersion", + "Nespr\u00e1vn\u00e1 verze {0}."}, + + // Map messages + { "map.wrongPublicID", + "Nezn\u00e1m\u00e9 PublicID {0}"}, + { "map.invalidMapFormat", + "Upozorn\u011bn\u00ed: Map m\u00e1 chybn\u00fd form\u00e1t"}, + { "map.unknownVersion", + "Nezn\u00e1m\u00e1 verze {0}"}, + + // GUI components + // Labels + { "index.findLabel", "Vyhledat: "}, + + { "search.findLabel", "Vyhledat: "}, + { "search.hitDesc", "Po\u010det v\u00fdskyt\u016f v dokumentu"}, + { "search.qualityDesc", "Nejni\u017e\u0161\u00ed chybovost v dokumentu" }, + { "search.high", "Velmi vysok\u00e1"}, + { "search.midhigh", "Vysok\u00e1"}, + { "search.mid", "St\u0159edn\u00ed"}, + { "search.midlow", "N\u00edzk\u00e1"}, + { "search.low", "Velmi n\u00edzk\u00e1"}, + + { "favorites.add", "P\u0159idej"}, + { "favorites.remove", "Sma\u017e"}, + { "favorites.folder", "Slo\u017eka"}, + { "favorites.name", "N\u00e1zev"}, + { "favorites.cut", "Vyst\u0159ihni"}, + { "favorites.paste", "Vlo\u017e"}, + { "favorites.copy" ,"Kop\u00edruj" }, + + { "history.homePage", "Domovsk\u00e1 Str\u00e1nka"}, + { "history.unknownTitle", "<nezn\u00e1m\u00fd titulek>"}, + + // ToolTips + { "tooltip.BackAction", "P\u0159edchoz\u00ed"}, + { "tooltip.ForwardAction", "N\u00e1sleduj\u00edc\u00ed"}, + { "tooltip.PrintAction", "Tisk"}, + { "tooltip.PrintSetupAction", "Nastaven\u00ed str\u00e1nky"}, + { "tooltip.ReloadAction", "Obnovit"}, + { "tooltip.FavoritesAction", "P\u0159idej k obl\u00edben\u00fdm polo\u017ek\u00e1m"}, + { "tooltip.HomeAction", "Go to home page"}, + + // Accessibility names + { "access.BackAction", "Sp\u00e1tky"}, + { "access.ForwardAction", "Vp\u0159ed"}, + { "access.HistoryAction", "Historie"}, + { "access.PrintAction", "Tisk"}, + { "access.PrintSetupAction", "Nastaven\u00ed Tisku"}, + { "access.ReloadAction", "Obnoven\u00ed"}, + { "access.HomeAction", "Domovsk\u00e1 Str\u00e1nka"}, + { "access.FavoritesAction", "P\u0159idej k obl\u00edben\u00fdm"}, + { "access.contentViewer", "Prohl\u00ed\u017ee\u010d obsahu"} + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java new file mode 100644 index 0000000000000000000000000000000000000000..6578ef769ce1ae12364588c6ab7356b52600a6fc --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java @@ -0,0 +1,150 @@ +/* + * @(#)Constants_de.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * Constants_de.java + * + * Originaly: Constants.java 1.8 - last change made 01/29/99 + * Translated to German by iXOS Software AG, 03/03/1999, Martin Balin + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_de extends ListResourceBundle { + /** + * Overrides ListResourceBundle + */ + public Object[][] getContents() { + return new Object[][] { + // Constant strings and patterns + { "helpset.wrongPublicID", + "Unbekannte PublicID {0}"}, + { "helpset.wrongTitle", + "Versuche, Titel auf {0} zu setzen, aber Wert {1} ist schon gesetzt."}, + { "helpset.wrongHomeID", + "Versuche HomeID auf {0} zu setzen, aber Wert {1} ist schon gesetzt."}, + { "helpset.subHelpSetTrouble", + "Probleme beim Erzeugen des Subhelpset: {0}."}, + { "helpset.malformedURL", + "Formfehler in URL: {0}."}, + { "helpset.incorrectURL", + "Fehlerhafte URL: {0}."}, + { "helpset.wrongText", + "{0} darf nicht den Text {1} enthalten."}, + { "helpset.wrongTopLevel", + "{0} darf kein Top Level Tag sein."}, + { "helpset.wrongParent", + "Parent Tag f\u00fcr {0} darf nicht {1} sein."}, + { "helpset.unbalanced", + "Einseitiger Tag {0}."}, + { "helpset.wrongLocale", + "Warning: xml:lang-Attribut {0} widerspricht Voreinstellung {1} und Voreinstellung {2}"}, + { "helpset.unknownVersion", + "Unbekannte Version {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "Warnung: Ung\u00fcltiges Index-Format"}, + { "index.unknownVersion", + "Unbekannte Version {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "Unbekannte PublicID {0}"}, + { "toc.invalidTOCFormat", + "Warnung: Ung\u00fcltiges Format f\u00fcr Inhaltsverzeichnis"}, + { "toc.unknownVersion", + "Unbekannte Version {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Warnung: Ung\u00fcltiges Favorites-Format"}, + { "favorites.unknownVersion", + "Unbekannte Version {0}."}, + + // Map messages + { "map.wrongPublicID", + "Unbekannte PublicID {0}"}, + { "map.invalidMapFormat", + "Warnung: Ung\u00fcltiges Map-Format"}, + { "map.unknownVersion", + "Unbekannte Version {0}."}, + + + // GUI components + // Labels + { "index.findLabel", "Suche: "}, + + { "search.findLabel", "Suche: "}, + { "search.hitDesc", "Number of occurances in document"}, + { "search.qualityDesc", "Lowest penality value in document" }, + { "search.high", "High"}, + { "search.midhigh", "Medium high"}, + { "search.mid", "Medium"}, + { "search.midlow", "Medium low"}, + { "search.low", "Low"}, + + { "favorites.add", "Hinzuf\u00fcgen"}, + { "favorites.remove", "Entfernem"}, + { "favorites.folder", "Neuer Ordner"}, + { "favorites.name", "Name"}, + { "favorites.cut", "Ausschneiden"}, + { "favorites.paste", "Einf\u00fcgen"}, + { "favorites.copy" , "Kopieren"}, + + { "history.homePage", "Startseite"}, + { "history.unknownTitle", "<Unbekannter Titel>"}, + + // ToolTips + { "tooltip.BackAction", "Voriger"}, + { "tooltip.ForwardAction", "N\u00e4chster"}, + { "tooltip.PrintAction", "Drucken"}, + { "tooltip.PrintSetupAction", "Seite einrichten"}, + { "tooltip.ReloadAction", "Neu laden"}, + { "tooltip.HomeAction", "Go to home page"}, + + // Accessibility names + { "access.BackAction", "Previous Button"}, + { "access.ForwardAction", "Next Button"}, + { "access.HistoryAction", "History Button"}, + { "access.PrintAction", "Print Button"}, + { "access.PrintSetupAction", "Page Setup Button"}, + { "access.ReloadAction", "Reload Button"}, + { "access.HomeAction", "Home Button"}, + { "access.FavoritesAction", "Add to Favorites Button"}, + { "access.contentViewer", "Content Viewer"} + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java new file mode 100644 index 0000000000000000000000000000000000000000..297991e206586743fd077b4793e207e5f356317e --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java @@ -0,0 +1,153 @@ +/* + * @(#)Constants_es.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_es.java 1.3 - last change made 10/30/06 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_es extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "PublicID {0} desconocido"}, + { "helpset.wrongTitle", + "Intentando asignar el t\u00EDtulo a {0} pero ya tiene el valor {1}."}, + { "helpset.wrongHomeID", + "Intentando asignar homeID a {0} pero ya tiene el valor {1}."}, + { "helpset.subHelpSetTrouble", + "Problemas creando subhelpset: {0}."}, + { "helpset.malformedURL", + "URL mal formada: {0}."}, + { "helpset.incorrectURL", + "URL incorrecta: {0}."}, + { "helpset.wrongText", + "{0} no puede contener el texto {1}."}, + { "helpset.wrongTopLevel", + "{0} no puede ser una etiqueta del nivel superior."}, + { "helpset.wrongParent", + "La etiqueta padre de {0} no puede ser {1}."}, + { "helpset.unbalanced", + "Etiqueta sin cerrar {0}."}, + { "helpset.wrongLocale", + "Aviso: atributo xml:lang {0} est\u00E1 en conflicto con el por defecto{1} y con {2}"}, + { "helpset.unknownVersion", + "Versi\u00F3n desconocida {0}."}, + + { "index.invalidIndexFormat", + "Aviso: Formato de \u00EDndice incorrecto"}, + { "index.unknownVersion", + "Versi\u00F3n desconocida {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "PublicID {0} desconocido"}, + { "toc.invalidTOCFormat", + "Aviso: Formato de TOC incorrecto"}, + { "toc.unknownVersion", + "Versi\u00F3n desconocida {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Aviso: Formato de Favoritos incorrecto"}, + { "favorites.unknownVersion", + "Versi\u00F3n desconocida {0}."}, + + // Map messages + { "map.wrongPublicID", + "PublicID {0} desconocido"}, + { "map.invalidMapFormat", + "Aviso: Formato de Map incorrecto"}, + { "map.unknownVersion", + "Versi\u00F3n desconocida {0}."}, + + // GUI components + // Labels + { "index.findLabel", "Buscar: "}, + { "search.findLabel", "Buscar: "}, + { "search.hitDesc", + "N\u00FAmero de apariciones en el documento"}, + { "search.qualityDesc", + "El m\u00E1s bajo valor de penalizaci\u00F3n en el documento" }, + { "search.high", "Alto"}, + { "search.midhigh", "Medio alto"}, + { "search.mid", "Medio"}, + { "search.midlow", "Medio bajo"}, + { "search.low", "Bajo"}, + + { "favorites.add", "Anadir"}, + { "favorites.remove", "Quitar"}, + { "favorites.folder", "Nueva carpeta"}, + { "favorites.name", "Nombre"}, + { "favorites.cut", "Cortar"}, + { "favorites.paste", "Pegar"}, + { "favorites.copy", "Copiar"}, + + { "history.homePage", "P\u00E1gina de inicio"}, + { "history.unknownTitle", + "<T\u00EDtulo de p\u00E1gina desconocido>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "P\u00E1gina anterior"}, + { "tooltip.ForwardAction", "P\u00E1gina siguiente"}, + { "tooltip.PrintAction", "Imprimir"}, + { "tooltip.PrintSetupAction", + "Configuraci\u00F3n de p\u00E1gina"}, + { "tooltip.ReloadAction", "Recargar"}, + { "tooltip.FavoritesAction", "Anadir a favoritos"}, + { "tooltip.HomeAction", "Ir a la p\u00E1gina de inicio"}, + + // Accessibility names + { "access.BackAction", "Bot\u00F3n de anterior"}, + { "access.ForwardAction", "Bot\u00F3n de siguiente"}, + { "access.HistoryAction", "Bot\u00F3n de historia"}, + { "access.PrintAction", "Bot\u00F3n de imprimir"}, + { "access.PrintSetupAction", + "Bot\u00F3n de configuraci\u00F3n de p\u00E1gina"}, + { "access.ReloadAction", "Bot\u00F3n de recarga"}, + { "access.HomeAction", "Bot\u00F3n de inicio"}, + { "access.FavoritesAction", "Bot\u00F3n de anadir a favoritos"}, + { "access.contentViewer", "Visualizador del contenido"} + + }; + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java new file mode 100644 index 0000000000000000000000000000000000000000..6463413a5916fd5d51e860356f9b198922a88b5d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java @@ -0,0 +1,148 @@ +/* + * @(#)Constants_fr.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants.java 1.11 - last change made 08/25/99 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_fr extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "ID Publique inconnue {0}"}, + { "helpset.wrongTitle", + "Essai de r\u00e9glage du titre sur {0} mais valeur {1} existe d\u00e9j\u00e0."}, + { "helpset.wrongHomeID", + "Essai de r\u00e9glage de l''ID domestique sur {0} mais valeur {1} existe d\u00e9j\u00e0."}, + { "helpset.subHelpSetTrouble", + "Probl\u00e8me lors de la cr\u00e9ation de l''ensemble de sous-aide : {0}."}, + { "helpset.malformedURL", + "URL mal form\u00e9 : {0}."}, + { "helpset.incorrectURL", + "URL incorrect : {0}."}, + { "helpset.wrongText", + "{0} ne peut contenir de texte {1}."}, + { "helpset.wrongTopLevel", + "{0} ne peut pas \u00eatre une \u00e9tiquette de haut niveau."}, + { "helpset.wrongParent", + "L''\u00e9tiquette parent pour {0} ne peut pas \u00eatre {1}."}, + { "helpset.unbalanced", + "\u00c9tiquette non \u00e9quilibr\u00e9e {0}."}, + { "helpset.wrongLocale", + "Attention : xml:lang attribue {0} des conflits avec d\u00e9faut {1} et avec d\u00e9faut {2}"}, + { "helpset.unknownVersion", + "Version inconnue {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "Attention : format d'Index invalide"}, + { "index.unknownVersion", + "Version inconnue {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "ID Publique inconnue {0}"}, + { "toc.invalidTOCFormat", + "Attention : Format TOC invalide"}, + { "toc.unknownVersion", + "Version inconnue {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Attention : Format Favorites invalide"}, + { "favorites.unknownVersion", + "Version inconnue {0}."}, + + // Map messages + { "map.wrongPublicID", + "ID Publique inconnue {0}"}, + { "map.invalidMapFormat", + "Attention : Format Map inconnu"}, + { "map.unknownVersion", + "Version inconnue {0}."}, + + // GUI components + // Labels + { "index.findLabel", "Trouver : "}, + + { "search.findLabel", "Trouver : "}, + { "search.hitDesc", "Nombre d'apparitions dans le document"}, + { "search.qualityDesc", "Valeur de p\u00e9nalit\u00e9 la plus basse du document" +}, + { "search.high", "Haut"}, + { "search.midhigh", "Moyen haut"}, + { "search.mid", "Moyen"}, + { "search.midlow", "Moyen bas"}, + { "search.low", "Bas"}, + + { "favorites.add", "Ajouter"}, + { "favorites.remove", "Supprimer"}, + { "favorites.folder", "Nouveau dossier"}, + { "favorites.name", "Nom"}, + { "favorites.cut", "Couper"}, + { "favorites.paste", "Coller"}, + { "favorites.copy" , "Copier"}, + + { "history.homePage", "Page de d\u00e9marrage"}, + { "history.unknownTitle", "Page inconnue>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "Pr\u00e9c\u00e9dent"}, + { "tooltip.ForwardAction", "Suivant"}, + { "tooltip.PrintAction", "Imprimer"}, + { "tooltip.PrintSetupAction", "Mise en page"}, + { "tooltip.ReloadAction", "Recharger"}, + { "tooltip.HomeAction", "Vers page ded\u00e9marrage"}, + + // Accessibility names + { "access.BackAction", "Bouton Pr\00e9c\00e9dent"}, + { "access.ForwardAction", "Bouton Suivant"}, + { "access.HistoryAction", "Bouton Historique"}, + { "access.PrintAction", "Bouton Impression"}, + { "access.PrintSetupAction", "Bouton Mise en page"}, + { "access.ReloadAction", " Bouton Actualiser"}, + { "access.HomeAction", "Bouton Page de d\u00e9marrage"}, + { "access.FavoritesAction", "Bouton Ajouter aux favoris"}, + { "access.contentViewer", "Visualiser le contenu"} + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java new file mode 100644 index 0000000000000000000000000000000000000000..585e0b5bb66199b6d54feeccd10c64a82cfeaf0b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java @@ -0,0 +1,149 @@ +/* + * @(#)Constants_he.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_he.java 1.19 - last change made 10/19/01 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_he extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "PublicID {0} \u05dc\u05d0 \u05d9\u05d3\u05d5\u05e2"}, + { "helpset.wrongTitle", + "\u05de\u05e0\u05e1\u05d4 \u05dc\u05d4\u05d2\u05d3\u05d9\u05e8 \u05d0\u05ea \u05d4\u05db\u05d5\u05ea\u05e8\u05ea \u05db {0} \u05d0\u05da \u05db\u05d1\u05e8 \u05d4\u05d5\u05d2\u05d3\u05e8\u05d4 \u05db {1}."}, + { "helpset.wrongHomeID", + " homeID \u05db {0} \u05d0\u05da \u05db\u05d1\u05e8 \u05d4\u05d5\u05d2\u05d3\u05e8 \u05db {1}."}, + { "helpset.subHelpSetTrouble", + "\u05d1\u05e2\u05d9\u05d5\u05ea \u05d1\u05d9\u05e6\u05d9\u05e8\u05ea \u05ea\u05ea-\u05e2\u05e8\u05db\u05ea \u05e2\u05d6\u05e8\u05d4:{0}.-"}, + { "helpset.malformedURL", + "\u05db\u05ea\u05d5\u05d1\u05ea URL \u05d0\u05d9\u05e0\u05d4 \u05de\u05e2\u05d5\u05e6\u05d1\u05ea \u05db\u05e8\u05d0\u05d5\u05d9:{0}."}, + { "helpset.incorrectURL", + "\u05db\u05ea\u05d5\u05d1\u05ea URL \u05e9\u05d2\u05d5\u05d9\u05d4"}, + { "helpset.wrongText", + "{0} \u05d0\u05d9\u05e0\u05d4 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05db\u05d9\u05dc \u05db\u05d9\u05ea\u05d5\u05d1 {1}."}, + { "helpset.wrongTopLevel", + "{0} \u05d0\u05d9\u05e0\u05d4 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05d9\u05d5\u05ea \u05ea\u05d2\u05d9\u05ea \u05d1\u05e8\u05de\u05d4 \u05e2\u05dc\u05d9\u05d5\u05e0\u05d4."}, + { "helpset.wrongParent", + "\u05ea\u05d2\u05d9\u05ea \u05d4\u05d0\u05dd \u05e9\u05dc {0} \u05dc\u05d0 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05d9\u05d5\u05ea {1}."}, + { "helpset.unbalanced", + "\u05ea\u05d2\u05d9\u05ea \u05d1\u05dc\u05ea\u05d9 \u05de\u05d0\u05d5\u05d6\u05e0\u05ea {0}."}, + { "helpset.wrongLocale", + "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05de\u05d0\u05e4\u05d9\u05d9\u05df xml:lang {0} \u05de\u05ea\u05e0\u05d2\u05e9 \u05e2\u05dd \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc {1} \u05d5\u05e2\u05dd \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc {2}."}, + { "helpset.unknownVersion", + " \u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05d0\u05d9\u05e0\u05d3\u05e7\u05e1 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"}, + { "index.unknownVersion", + "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "PublicID {0} \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4"}, + { "toc.invalidTOCFormat", + "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05ea\u05d5\u05db\u05df \u05e2\u05e0\u05d9\u05e0\u05d9\u05dd \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"}, + { "toc.unknownVersion", + "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"}, + { "favorites.unknownVersion", + "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."}, + + // Map messages + { "map.wrongPublicID", + "PublicID {0} \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4"}, + { "map.invalidMapFormat", + "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05de\u05e4\u05ea \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"}, + { "map.unknownVersion", + "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."}, + + // GUI components + // Labels + { "index.findLabel", "\u05d7\u05e4\u05e9: "}, + + { "search.findLabel", "\u05d7\u05e4\u05e9: "}, + { "search.hitDesc", "\u05de\u05e1\u05e4\u05e8 \u05de\u05d5\u05e4\u05e2\u05d9\u05dd \u05d1\u05de\u05e1\u05de\u05da"}, + { "search.qualityDesc", "\u05e2\u05e8\u05da \u05d4\u05e7\u05e0\u05e1 \u05d4\u05e0\u05de\u05d5\u05da \u05d1\u05d9\u05d5\u05ea\u05e8 \u05d1\u05de\u05e1\u05de\u05da" }, + { "search.high", "\u05d2\u05d1\u05d5\u05d4"}, + { "search.midhigh", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9 \u05d2\u05d1\u05d5\u05d4"}, + { "search.mid", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9"}, + { "search.midlow", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9 \u05e0\u05de\u05d5\u05da"}, + { "search.low", "\u05e0\u05de\u05d5\u05da"}, + + { "favorites.add", "\u05d4\u05d5\u05e1\u05e4\u05d4"}, + { "favorites.remove", "\u05d4\u05e1\u05e8\u05d4"}, + { "favorites.folder", "\u05ea\u05d9\u05e7\u05d9\u05d4 \u05d7\u05d3\u05e9\u05d4"}, + { "favorites.name", "\u05e9\u05dd/\u05de\u05ea\u05df \u05e9\u05dd"}, + { "favorites.cut", "\u05d2\u05d6\u05d9\u05e8\u05d4"}, + { "favorites.paste", "\u05d4\u05d3\u05d1\u05e7\u05d4"}, + { "favorites.copy" , "\u05d4\u05e2\u05ea\u05e7\u05d4"}, + + { "history.homePage", "\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea"}, + { "history.unknownTitle", "<\u05db\u05d5\u05ea\u05e8\u05ea \u05d3\u05e3 \u05d0\u05d9\u05e0\u05d4 \u05d9\u05d3\u05d5\u05e2\u05d4>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "\u05d4\u05d3\u05e3 \u05d4\u05e7\u05d5\u05d3\u05dd"}, + { "tooltip.ForwardAction", "\u05d4\u05d3\u05e3 \u05d4\u05d1\u05d0"}, + { "tooltip.PrintAction", "\u05d4\u05d3\u05e4\u05e1\u05d4"}, + { "tooltip.PrintSetupAction", "\u05d4\u05d2\u05d3\u05e8\u05ea \u05e2\u05de\u05d5\u05d3"}, + { "tooltip.ReloadAction", "\u05d8\u05e2\u05d9\u05e0\u05d4 \u05de\u05d7\u05d3\u05e9"}, + { "tooltip.FavoritesAction", "\u05d4\u05d5\u05e1\u05e4\u05d4 \u05dc\u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd"}, + { "tooltip.HomeAction", "\u05e2\u05d1\u05d5\u05e8 \u05dc\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea"}, + + // Accessibility names + { "access.BackAction", "\u05d4\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05e7\u05d5\u05d3\u05dd"}, + { "access.ForwardAction", "\u05d4\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d1\u05d0"}, + { "access.HistoryAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05e1\u05d8\u05d5\u05e8\u05d9\u05d4"}, + { "access.PrintAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d3\u05e4\u05e1\u05d4"}, + { "access.PrintSetupAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d2\u05d3\u05e8\u05ea \u05e2\u05de\u05d5\u05d3"}, + { "access.ReloadAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d8\u05e2\u05d9\u05e0\u05d4 \u05de\u05d7\u05d3\u05e9"}, + { "access.HomeAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d1\u05d9\u05ea"}, + { "access.FavoritesAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d5\u05e1\u05e4\u05d4 \u05dc\u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd"}, + { "access.contentViewer", "\u05ea\u05d5\u05db\u05e0\u05ea \u05e6\u05e4\u05d9\u05d9\u05d4 \u05d1\u05ea\u05d5\u05db\u05df"} + + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java new file mode 100644 index 0000000000000000000000000000000000000000..07c516a820176657578b9a856d6f238c80d971bf --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java @@ -0,0 +1,119 @@ +/* + * @(#)Constants_ja.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_ja.java 1.10 - last change made 10/30/06 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * \u5b9a\u6570\u306f\u3001JavaHelp \u3092\u30ed\u30fc\u30ab\u30e9\u30a4\u30ba\u3059\u308b\u306e\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002 + * + * \u5b9a\u6570\u306f\u3001\u30ad\u30fc\u3001\u5024\u306e\u5f62\u3067\u793a\u3055\u308c\u307e\u3059\u3002 + * \u5024\u3060\u3051\u3092\u7ffb\u8a33\u3057\u307e\u3059\u3002 + */ + +public class Constants_ja extends ListResourceBundle { + /** + * ListResourceBundle \u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059\u3002 + */ + public Object[][] getContents() { + return new Object[][] { + + // \u5b9a\u6570\u6587\u5b57\u5217\u3068\u30d1\u30bf\u30fc\u30f3 + { "helpset.wrongTitle", + "\u30bf\u30a4\u30c8\u30eb\u3092 {0} \u306b\u8a2d\u5b9a\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001\u3059\u3067\u306b\u5024 {1} \u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002"}, + { "helpset.wrongHomeID", + "homeID \u3092 {0} \u306b\u8a2d\u5b9a\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001\u3059\u3067\u306b\u5024 {1} \u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002"}, + { "helpset.subHelpSetTrouble", + "\u30b5\u30d6\u30d8\u30eb\u30d7\u30bb\u30c3\u30c8: {0} \u306e\u4f5c\u6210\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002"}, + { "helpset.malformedURL", + "URL: {0} \u306e\u5f62\u5f0f\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"}, + { "helpset.incorrectURL", + "URL: {0} \u306f\u9593\u9055\u3063\u3066\u3044\u307e\u3059\u3002"}, + { "helpset.wrongText", + "{0} \u306b\u306f\u30c6\u30ad\u30b9\u30c8 {1} \u3092\u542b\u3080\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002"}, + { "helpset.wrongTopLevel", + "{0} \u306f\u6700\u4e0a\u4f4d\u30ec\u30d9\u30eb\u306e\u30bf\u30b0\u306b\u306f\u306a\u308c\u307e\u305b\u3093\u3002"}, + { "helpset.wrongParent", + "{0} \u306e\u89aa\u30bf\u30b0\u306f {1} \u306b\u306f\u306a\u308c\u307e\u305b\u3093\u3002"}, + { "helpset.unbalanced", + "\u30bf\u30b0 {0} \u306f\u9589\u3058\u3066\u3044\u307e\u305b\u3093\u3002"}, + { "helpset.wrongLocale", + "\u8b66\u544a: xml: \u8a00\u8a9e\u5c5e\u6027 {0} \u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u306e {1} \u304a\u3088\u3073 {2} \u3068\u91cd\u8907\u3057\u307e\u3059\u3002"}, + + { "index.invalidIndexFormat", + "\u8b66\u544a: \u7d22\u5f15\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"}, + + { "toc.invalidTOCFormat", + "\u8b66\u544a: \u76ee\u6b21\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u304c\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"}, + + // GUI \u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8 + // \u30e9\u30d9\u30eb + { "index.findLabel", "\u691c\u7d22 : "}, + + { "search.findLabel", "\u691c\u7d22 : "}, + { "search.hitDesc", "Number of occurances in document"}, + { "search.qualityDesc", "Lowest penality value in document" }, + { "search.high", "High"}, + { "search.midhigh", "Medium high"}, + { "search.mid", "Medium"}, + { "search.midlow", "Medium low"}, + { "search.low", "Low"}, + + { "favorites.add", "\u8ffd\u52a0"}, + { "favorites.remove", "\u524a\u9664"}, + { "favorites.folder", "\u65b0\u898f\u30df=u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210"}, + { "favorites.name", "\u540d]u524d"}, + { "favorites.cut", "u5207\u308a\u53d6\u308a"}, + { "favorites.paste", "\u8cbc\u308a\u4ed8\u3051"}, + { "favorites.copy" , "u30b3\u30d4\u30fc"}, + + // ToolTips for Action + { "tooltip.BactionAction", "\u524d\u306e\u30da\u30fc\u30b8"}, + { "tooltip.ForwardAction", "\u6b21\u306e\u30da\u30fc\u30b8"}, + { "tooltip.PrintAction", "\u5370\u5237"}, + { "tooltip.PrintSetupAction", "\u30da\u30fc\u30b8\u8a2d\u5b9a"}, + { "tooltip.ReloadAction", "\u518d\u8aad\u307f\u8fbc\u307f"}, + { "tooltip.FavoritesAction", "\u304a\u6c17\u306b\u5165\u308a\u306b\u8ffd\u52a0"}, + { "tooltip.HomeAction", "\u30db\u30fc\u30e0\u30da\u30fc\u30b8\u3078\u79fb\u52d5"}, + + // Accessibility names + { "access.BackAction", "Previous Button"}, + { "access.ForwardAction", "Next Button"}, + { "access.HistoryAction", "History Button"}, + { "access.PrintAction", "Print Button"}, + { "access.PrintSetupAction", "Page Setup Button"}, + { "access.ReloadAction", "Reload Button"}, + { "access.HomeAction", "Home Button"}, + { "access.FavoritesAction", "Add to Favorites Button"}, + { "access.contentViewer", "Content Viewer"} + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java new file mode 100644 index 0000000000000000000000000000000000000000..97024c5f8d77eaf7e5100d51db963e461b9e076d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java @@ -0,0 +1,173 @@ +/* + * @(#)Constants_pl.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + * + * @author Krystian Nowak + * @author krystian (at) man (dot) poznan (dot) pl + * + */ + +// +// Polish diacritical characters in Unicode +// +// A - 0104 a - 0105 +// C - 0106 c - 0107 +// E - 0118 e - 0119 +// L - 0141 l - 0142 +// N - 0143 n - 0144 +// O - 00D3 o - 00F3 +// S - 015A s - 015B +// X - 0179 x - 017A +// Z - 017B z - 017C + +public class Constants_pl extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "Nieznane PublicID {0}"}, + { "helpset.wrongTitle", + "Pr\u00F3ba ustawienia tytu\u0142u na {0} mimo, \u017Ce ma ju \u017C warto\u015B\u0107 {1}."}, + { "helpset.wrongHomeID", + "Pr\u00F3ba ustawienia homeID na {0} mimo, \u017Ce ma ju \u017C warto\u015B\u0107 {1}."}, + { "helpset.subHelpSetTrouble", + "B\u0142\u0105d w trakcie tworzenia podpomocy: {0}."}, + { "helpset.malformedURL", + "\u0179le sformu\u0142owany URL: {0}."}, + { "helpset.incorrectURL", + "Niepoprawny URL: {0}."}, + { "helpset.wrongText", + "{0} nie mo\u017Ce zawiera\u0107 tekstu {1}."}, + { "helpset.wrongTopLevel", + "{0} nie mo\u017Ce by\u0107 znacznikiem najwy\u017Cszego poziomu."}, + { "helpset.wrongParent", + "{1} nie mo\u017Ce by\u0107 nadznacznikiem dla {0}."}, + { "helpset.unbalanced", + "Niezbalansowany znacznik {0}."}, + { "helpset.wrongLocale", + "Uwaga: atrybut xml:lang {0} jest w konflikcie z domy\u015Blnym {1} i domy\u015Blnym {2}"}, + { "helpset.unknownVersion", + "Nieznana wersja {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "Uwaga: Index ma nieprawid\u0142owy format"}, + { "index.unknownVersion", + "Nieznana wersja {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "Nieznany PublicID {0}"}, + { "toc.invalidTOCFormat", + "Uwaga: TOC ma nieprawid\u0142owy format"}, + { "toc.unknownVersion", + "Nieznana wersja {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Uwaga: Plik Favorites.xml ma nieprawid\u0142owy format"}, + { "favorites.unknownVersion", + "Nieznana wersja {0}."}, + + // Map messages + { "map.wrongPublicID", + "Nieznane PublicID {0}"}, + { "map.invalidMapFormat", + "Uwaga: Map ma nieprawid\u0142owy format"}, + { "map.unknownVersion", + "Nieznana wersja {0}."}, + + + // GUI components + // Labels + { "index.findLabel", "Znajd\u017A: "}, + + { "search.findLabel", "Znajd\u017A: "}, + { "search.hitDesc", "Liczba wyst\u0105pie\u0144 w dokumencie"}, + { "search.qualityDesc", "Miara niedok\u0142adno\u015Bci" }, + { "search.high", "Najwy\u017Csza"}, + { "search.midhigh", "Wysoka"}, + { "search.mid", "\u015Arednia"}, + { "search.midlow", "Niska"}, + { "search.low", "Najni\u017Csza"}, + + { "favorites.add", "Dodaj"}, + { "favorites.remove", "Usu\u0144"}, + { "favorites.folder", "Nowy folder"}, + { "favorites.name", "Nazwa"}, + { "favorites.cut", "Wytnij"}, + { "favorites.paste", "Wklej"}, + { "favorites.copy" , "Kopiuj"}, + + { "history.homePage", "Strona domowa"}, + { "history.unknownTitle", "<nieznany tytu\u0142 strony>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "Poprzednia strona"}, + { "tooltip.ForwardAction", "Nast\u0119pna strona"}, + { "tooltip.PrintAction", "Drukuj"}, + { "tooltip.PrintSetupAction", "Ustawienia strony"}, + { "tooltip.ReloadAction", "Prze\u0142aduj"}, + { "tooltip.FavoritesAction", "Dodaj do ulubionych"}, + { "tooltip.HomeAction", "Id\u017A do strony domowej"}, + + // Accessibility names + { "access.BackAction", "Do ty\u0142u"}, + { "access.ForwardAction", "Nast\u0119pny"}, + { "access.HistoryAction", "Historia"}, + { "access.PrintAction", "Drukuj"}, + { "access.PrintSetupAction", "Ustawienia stron"}, + { "access.ReloadAction", "Prze\u0142aduj"}, + { "access.HomeAction", "Strona domowa"}, + { "access.FavoritesAction", "Dodaj do ulubionych"}, + { "access.contentViewer", "Przegl\u0105darka zawarto\u015Bci"} + + }; + } +} + + + + + + + + diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java new file mode 100644 index 0000000000000000000000000000000000000000..1f6c9763deac536e6c3657f9fb7ae0c06624bd8d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java @@ -0,0 +1,148 @@ +/* + * @(#)Constants_ru.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_ru.java 1.8 - last change made 10/30/06 + * @(#) Constants.java 1.8 - last change made 01/29/99 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp + * + * These are in the form of key, value. + * Translators take care to only translate the values + */ + +public class Constants_ru extends ListResourceBundle { + /** + * Overrides ListResourceBundle + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 PublicID {0}"}, + { "helpset.wrongTitle", + "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 title \u043d\u0430 {0} \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 {1}."}, + { "helpset.wrongHomeID", + "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 homeID \u043d\u0430 {0} \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 {1}."}, + { "helpset.subHelpSetTrouble", + "\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f subhelpset: {0}."}, + { "helpset.malformedURL", + "\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 URL: {0}."}, + { "helpset.incorrectURL", + "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 URL: {0}."}, + { "helpset.wrongText", + "{0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 {1}."}, + { "helpset.wrongTopLevel", + "{0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u0435\u0433\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f."}, + { "helpset.wrongParent", + "\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0442\u0435\u0433 {0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c {1}."}, + { "helpset.unbalanced", + "\u041d\u0435\u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u0433 {0}."}, + { "helpset.wrongLocale", + "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: xml: \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u0443\u0435\u0442\u0441\u044f \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e {1} \u0438 {2}"}, + { "helpset.unknownVersion", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u0430"}, + { "index.unknownVersion", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 PublicID {0}"}, + { "toc.invalidTOCFormat", + "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f"}, + { "toc.unknownVersion", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Warning: Invalid Favorites format"}, + { "favorites.unknownVersion", + "Unknown Version {0}."}, + + // Map messages + { "map.wrongPublicID", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 PublicID {0}"}, + { "map.invalidMapFormat", + "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043a\u0430\u0440\u0442\u044b"}, + { "map.unknownVersion", + "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."}, + + // GUI components + // Labels + { "index.findLabel", "\u041d\u0430\u0439\u0442\u0438: "}, + + { "search.findLabel", "\u041d\u0430\u0439\u0442\u0438: "}, + { "search.hitDesc", "Number of occurances in document"}, + { "search.qualityDesc", "Lowest penality value in document" }, + { "search.high", "High"}, + { "search.midhigh", "Medium high"}, + { "search.mid", "Medium"}, + { "search.midlow", "Medium low"}, + { "search.low", "Low"}, + + { "favorites.add", "Add"}, + { "favorites.remove", "Remove"}, + { "favorites.folder", "New Folder"}, + { "favorites.name", "Name"}, + { "favorites.cut", "Cut"}, + { "favorites.paste", "Paste"}, + { "favorites.copy" , "Copy"}, + + { "history.homePage", "Home page"}, + { "history.unknownTitle", "<unknown page title>"}, + + // ToolTips + { "tooltip.BackAction", "\u043d\u0430\u0437\u0430\u0434"}, + { "tooltip.ForwardAction", "\u0432\u043f\u0435\u0440\u0435\u0434"}, + { "tooltip.PrintAction", "\u043f\u0435\u0447\u0430\u0442\u044c"}, + { "tooltip.PrintSetupAction", "\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b"}, + { "tooltip.ReloadAction", "\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c"}, + { "tooltip.HomeAction", "Go to home page"}, + + // Accessibility names + { "access.BackAction", "Previous Button"}, + { "access.ForwardAction", "Next Button"}, + { "access.HistoryAction", "History Button"}, + { "access.PrintAction", "Print Button"}, + { "access.PrintSetupAction", "Page Setup Button"}, + { "access.ReloadAction", "Reload Button"}, + { "access.HomeAction", "Home Button"}, + { "access.FavoritesAction", "Add to Favorites Button"}, + { "access.contentViewer", "Content Viewer"} + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java new file mode 100644 index 0000000000000000000000000000000000000000..53b9f1cfd6ab4f03ff489f880975d6508ace0e2b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java @@ -0,0 +1,153 @@ +/* + * @(#)Constants_sk.java 1.10 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + * + * @author Richard Gregor + * @version 1.10 10/30/06 + * + */ + +public class Constants_sk extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "Nezn\u00e1me PublicID {0}"}, + { "helpset.wrongTitle", + "Pokus o nastavenie Title na {0} Title u\u017E m\u00e1 hodnotu {1}."}, + { "helpset.wrongHomeID", + "Pokus o nastavenie homeID na {0} homeID u\u017E m\u00e1 hodnotu {1}."}, + { "helpset.subHelpSetTrouble", + "Probl\u00e9m pri vytv\u00e1ran\u00ed subhelpsetu: {0}."}, + { "helpset.malformedURL", + "Chybn\u00fd form\u00e1t URL: {0}."}, + { "helpset.incorrectURL", + "Nespr\u00e1vne URL: {0}."}, + { "helpset.wrongText", + "{0} nem\u00f4\u017Ee obsahova\u0165 text {1}."}, + { "helpset.wrongTopLevel", + "{0} Nespr\u00e1vny top level tag."}, + { "helpset.wrongParent", + "Rodi\u010Dovsk\u00fd tag {0} nem\u00f4\u017Ee by\u0165 {1}."}, + { "helpset.unbalanced", + "Neukon\u010Den\u00fd tag {0}."}, + { "helpset.wrongLocale", + "Pozor!: xml:lang atrib\u00fat {0} je v konflikte s {1} a s {2}"}, + { "helpset.unknownVersion", + "Nezn\u00e1ma verzia {0}."}, + + // IndexView messages + { "index.invalidIndexFormat", + "Pozor!: Index m\u00e1 chybn\u00fd form\u00e1t"}, + { "index.unknownVersion", + "Nezn\u00e1ma verzia {0}."}, + + // TOCView messages + { "toc.wrongPublicID", + "Nezn\u00e1me PublicID {0}"}, + { "toc.invalidTOCFormat", + "Pozor!: TOC m\u00e1 chybn\u00fd form\u00e1t"}, + { "toc.unknownVersion", + "Nezn\u00e1ma verzia {0}."}, + + //FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Pozor!: Nespr\u00e1vny form\u00e1t s\u00faboru Favorites.xml"}, + { "favorites.unknownVersion", + "Nespr\u00e1vna verzia {0}."}, + + // Map messages + { "map.wrongPublicID", + "Nezn\u00e1me PublicID {0}"}, + { "map.invalidMapFormat", + "Pozor!: Map m\u00e1 nespr\u00e1vny form\u00e1t"}, + { "map.unknownVersion", + "Nezn\u00e1ma verzia {0}."}, + + // GUI components + // Labels + { "index.findLabel", "Vyh\u013Eada\u0165 : "}, + + { "search.findLabel", "Vyh\u013Eada\u0165 : "}, + { "search.hitDesc", "Po\u010Det v\u00fdskytov v dokumente"}, + { "search.qualityDesc", "Miera nepresnosti" }, + { "search.high", "Najvy\u0161\u0161ia"}, + { "search.midhigh", "Vysok\u00e1"}, + { "search.mid", "Stredn\u00e1"}, + { "search.midlow", "N\u00edzka"}, + { "search.low", "Najni\u0161\u0161ia"}, + + { "favorites.add", "Pridaj"}, + { "favorites.remove", "Zma\u017e"}, + { "favorites.folder", "Zlo\u017eka"}, + { "favorites.name", "N\u00e1zov"}, + { "favorites.cut", "Vystrihni"}, + { "favorites.paste", "Vlo\u017e"}, + { "favorites.copy" ,"Kop\u00edruj" }, + + { "history.homePage", "Domovsk\u00e1 str\u00e1nka"}, + { "history.unknownTitle", "<nezn\u00e1my titul str\u00e1nky>"}, + + // ToolTips for Actions + { "tooltip.BackAction", "Predch\u00e1dzaj\u00face"}, + { "tooltip.ForwardAction", "\u010Eal\u0161ie"}, + { "tooltip.PrintAction", "Tla\u010D"}, + { "tooltip.PrintSetupAction", "Nastavenie str\u00e1nky"}, + { "tooltip.ReloadAction", "Obnovi\u0165"}, + { "tooltip.FavoritesAction", "Pridaj k ob\u013E\u00faben\u00fdm polo\u017Ek\u00e1m"}, + { "tooltip.HomeAction", "Zobraz domovsk\u00fa str\u00e1nku"}, + + // Accessibility names + { "access.BackAction", "Spiatky"}, + { "access.ForwardAction", "Vpred"}, + { "access.HistoryAction", "Hist\u00f3ria"}, + { "access.PrintAction", "Tla\u010D"}, + { "access.PrintSetupAction", "Nastavenie Tla\u010De"}, + { "access.ReloadAction", "Obnovenie"}, + { "access.HomeAction", "Domovsk\u00e1 Str\u00e1nka"}, + { "access.FavoritesAction", "Pridaj k ob\u013E\u00faben\u00fdm polo\u017ek\u00e1m"}, + { "access.contentViewer", "Prehliada\u010D obsahu"} + + }; + + } + + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java new file mode 100644 index 0000000000000000000000000000000000000000..33c9ca85bfa7f8e7b30f75a2b5a6b883c449a965 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java @@ -0,0 +1,148 @@ +/* + * @(#)Constants_zh.java 1.6 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#) Constants_zh.java 1.6 - last change made 10/30/06 + */ + +package javax.help.resources; + +import java.util.ListResourceBundle; + +/** + * Constants used for localizing JavaHelp. + * + * These are in the form of key, value. + * Translators take care to only translate the values. + */ + +public class Constants_zh extends ListResourceBundle { + /** + * Overrides ListResourceBundle. + */ + public Object[][] getContents() { + return new Object[][] { + + // Constant strings and patterns + { "helpset.wrongPublicID", + "\u672a\u77e5\u7684 PublicID {0}"}, + { "helpset.wrongTitle", + "\u8bd5\u56fe\u5c06\u6807\u9898\u8bbe\u7f6e\u4e3a {0}\uff0c\u4f46\u6807\u9898\u5df2\u8d4b\u503c\u4e3a {1}\u3002"}, + { "helpset.wrongHomeID", + "\u8bd5\u56fe\u5c06 homeID \u8bbe\u7f6e\u4e3a {0} \u4f46 homeID \u5df2\u8d4b\u503c\u4e3a {1}\u3002"}, + { "helpset.subHelpSetTrouble", + "\u521b\u5efa subhelpset \u65f6\u51fa\u9519\uff1a{0}\u3002"}, + { "helpset.malformedURL", + "\u683c\u5f0f\u9519\u8bef\u7684 URL\uff1a{0}\u3002"}, + { "helpset.incorrectURL", + "\u9519\u8bef\u7684 URL\uff1a{0}\u3002"}, + { "helpset.wrongText", + "{0} \u4e0d\u80fd\u5305\u542b\u6587\u672c {1}\u3002"}, + { "helpset.wrongTopLevel", + "{0} \u4e0d\u80fd\u4e3a\u9876\u7ea7\u6807\u8bb0\u3002"}, + { "helpset.wrongParent", + "{0} \u7684\u7236\u6807\u8bb0\u4e0d\u80fd\u4e3a {1}\u3002"}, + { "helpset.unbalanced", + "\u4e0d\u5747\u8861\u7684\u6807\u8bb0 {0}\u3002"}, + { "helpset.wrongLocale", + "\u8b66\u544a\uff1axml:lang \u7279\u6027 {0} \u4e0e\u7f3a\u7701\u503c {1} \u53ca\u7f3a\u7701\u503c {2} \u51b2\u7a81\u3002"}, + { "helpset.unknownVersion", + "\u672a\u77e5\u7248\u672c {0}\u3002"}, + + // IndexView messages + { "index.invalidIndexFormat", + "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u7d22\u5f15\u683c\u5f0f"}, + { "index.unknownVersion", + "\u672a\u77e5\u7248\u672c {0}\u3002"}, + + // TOCView messages + { "toc.wrongPublicID", + "\u672a\u77e5 PublicID {0}"}, + { "toc.invalidTOCFormat", + "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u76ee\u5f55\u683c\u5f0f"}, + { "toc.unknownVersion", + "\u672a\u77e5\u7248\u672c {0}\u3002"}, + + // FavoritesView messages + { "favorites.invalidFavoritesFormat", + "Warning: Invalid Favorites format"}, + { "favorites.unknownVersion", + "Unknown Version {0}."}, + + // Map messages + { "map.wrongPublicID", + "\u672a\u77e5 PublicID {0}"}, + { "map.invalidMapFormat", + "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u6620\u5c04\u683c\u5f0f"}, + { "map.unknownVersion", + "\u672a\u77e5\u7248\u672c {0}\u3002"}, + + // GUI components + // Labels + { "index.findLabel", "\u67e5\u627e\uff1a"}, + + { "search.findLabel", "\u67e5\u627e\uff1a"}, + { "search.hitDesc", "\u6587\u6863\u4e2d\u51fa\u73b0\u7684\u6b21\u6570"}, + { "search.qualityDesc", "\u6587\u6863\u7684\u6700\u4f4e\u8865\u507f\u503c" }, + { "search.high", "\u9ad8"}, + { "search.midhigh", "\u8f83\u9ad8"}, + { "search.mid", "\u4e2d\u7b49"}, + { "search.midlow", "\u8f83\u4f4e"}, + { "search.low", "\u4f4e"}, + + { "favorites.add", "Add"}, + { "favorites.remove", "Remove"}, + { "favorites.folder", "New Folder"}, + { "favorites.name", "Name"}, + { "favorites.cut", "Cut"}, + { "favorites.paste", "Paste"}, + { "favorites.copy" , "Copy"}, + + { "history.homePage", "Home page"}, + { "history.unknownTitle", "<unknown page title>"}, + + // ToolTips for Action + { "tooltip.BackAction", "\u4e0a\u4e00\u9875"}, + { "tooltip.NextAction", "\u4e0b\u4e00\u9875"}, + { "tooltip.PrintAction", "\u6253\u5370"}, + { "tooltip.PrintSetupAction", "\u9875\u8bbe\u7f6e"}, + { "tooltip.ReloadAction", "\u91cd\u65b0\u88c5\u8f7d"}, + { "tooltip.HomeAction", "Go to home page"}, + + // Accessibility names + { "access.BackAction", "Previous Button"}, + { "access.ForwardAction", "Next Button"}, + { "access.HistoryAction", "History Button"}, + { "access.PrintAction", "Print Button"}, + { "access.PrintSetupAction", "Page Setup Button"}, + { "access.ReloadAction", "Reload Button"}, + { "access.HomeAction", "Home Button"}, + { "access.FavoritesAction", "Add to Favorites Button"}, + { "access.contentViewer", "Content Viewer"} + }; + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/package.html b/jhMaster/JavaHelp/src/new/javax/help/resources/package.html new file mode 100644 index 0000000000000000000000000000000000000000..1033ce9e5372fdf0efdc547e377763b4a2d378a5 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/resources/package.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.2 99/03/19 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Supports localization of JavaHelp. +The class <code>Constants</code> provides +all the needed values. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see the <em>JavaHelp System User's Guide</em>. + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java b/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java new file mode 100644 index 0000000000000000000000000000000000000000..2a723264950ffd4cb7b659cd3329d1888734e220 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java @@ -0,0 +1,200 @@ +/* + * @(#)ConfigFile.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) ConfigFile.java 1.8 - last change made 10/30/06 + */ + +package javax.help.search; + +import java.io.*; +import java.text.*; +import java.util.Vector; +import java.util.Hashtable; +import java.util.Enumeration; + +/** + * Describes and parses the configuration file for + * the full-text search indexer. + * + * @see Indexer + * @version 1.8 10/30/06 + * @author Roger D. Brinkley + */ + +public class ConfigFile { + + private String remove; + + private String prepend; + + private Hashtable stopWords; + + private String defStopWords[] = { + "a", "all", "am", "an", "and", "any", "are", "as", "at", "be", "but", + "by", "can", "could", "did", "do", "does", "etc", "for", "from", + "goes", "got", "had", "has", "have", "he", "her", "him", "his", + "how", "if", "in", "is", "it", "let", "me", "more", "much", "must", + "my", "nor", "not", "now", "of", "off", "on", "or", "our", "own", + "see", "set", "shall", "she", "should", "so", "some", "than", "that", + "the", "them", "then", "there", "these", "this", "those", "though", + "to", "too", "us", "was", "way", "we", "what", "when", "where", + "which", "who", "why", "will", "would", "yes", "yet", "you"}; + + private Vector files; + + /** + * Creates a configuration file. + * @params configFile The config file. + * @params files A list of files to process in addition to any files in the config file. + * @params noStopWords If true do not allow stopwords, if false allow the stopwords + * defined in the config file or the default stop words. + */ + public ConfigFile (String configFile, Vector files, boolean noStopWords) { + this.files = files; + LineNumberReader in; + String line; + String removeText = new String ("IndexRemove "); + String prependText = new String ("IndexPrepend "); + String fileText = new String ("File "); + String stopWordsText = new String ("StopWords "); + String stopWordsFileText = new String ("StopWordsFile "); + BreakIterator boundary; + int start; + String url; + + stopWords = new Hashtable(); + + if (configFile == null) { + if (!noStopWords) { + useDefaultStopWords(); + } + return; + } + try { + in = new LineNumberReader(new BufferedReader + (new FileReader(configFile))); + while ((line = in.readLine()) != null) { + if (line.startsWith(removeText)) { + remove = line.substring (removeText.length(), + line.length()); + } else if (line.startsWith(prependText)) { + prepend = line.substring (prependText.length(), + line.length()); + } else if (line.startsWith(fileText)) { + String file = line.substring (fileText.length(), + line.length()); + files.addElement(file); + } else if (line.startsWith(stopWordsFileText)) { + String file = line.substring (stopWordsFileText.length(), + line.length()); + addStopWordsFile(file); + } else if (line.startsWith(stopWordsText)) { + if (noStopWords) { + continue; + } + String words = line.substring (stopWordsText.length(), + line.length()); + boundary = BreakIterator.getWordInstance(); + boundary.setText(words); + start = boundary.first(); + for (int end = boundary.next(); + end != BreakIterator.DONE; + start = end, end = boundary.next()) { + String word = words.substring(start,end).trim().toLowerCase(); + if (word.equals(",") || word.equals("")) { + continue; + } + stopWords.put(word, word); + } + } else { + System.out.println ("Unknown Config Keyword at line " + + in.getLineNumber()); + } + } + // If there aren't any stopwords then add the default stopwords + if (stopWords.isEmpty() && !noStopWords) { + useDefaultStopWords(); + } + } catch (IOException e) {} + } + + /** + * Returns the URL filename of a file in String format. + */ + public String getURLString (String file) { + String url; + + if (remove != null && (file.startsWith(remove))) { + url = file.substring(remove.length(), file.length()); + } else { + url = file; + } + if (prepend != null) { + url = prepend + url; + } + if (File.separatorChar != '/') { + url = url.replace(File.separatorChar, '/'); + } + return url; + } + + /** + * Returns the list of stopwords from a config file. + */ + public Enumeration getStopWords() { return stopWords.elements(); } + + /** + * Gets the list of files from a config file. + */ + public Vector getFiles () { return files; } + + private void useDefaultStopWords() { + for (int i=0; i < defStopWords.length; i++) { + stopWords.put(defStopWords[i], defStopWords[i]); + } + } + + // Add stopwords from a file + // A single stop words exist per line in the file + private void addStopWordsFile(String swfile) { + String word; + LineNumberReader in; + + if (swfile == null) { + return; + } + try { + in = new LineNumberReader(new BufferedReader + (new FileReader(swfile))); + while ((word = in.readLine()) != null) { + word = word.trim(); + stopWords.put(word, word); + } + } catch (IOException e) {} + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java b/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..13cdff52298e071ed5a891920ef505507ec668cd --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java @@ -0,0 +1,115 @@ +/* + * @(#)IndexBuilder.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) IndexBuilder.java 1.8 - last change made 10/30/06 + */ + +package javax.help.search; + +import java.io.*; +import java.util.Enumeration; + +/** + * Abstract base class that builds an index for a search database. + * + * @author Roger D. Brinkley + * @version 1.8 10/30/06 + */ + +public abstract class IndexBuilder +{ + + protected String indexDir; + + /** + * Builds an index at indexDir. If indexDir already exists + * the index is opened and the new doucments are merged into + * the existing document. + */ + public IndexBuilder(String indexDir) throws Exception + { + debug("indexDir=" + indexDir); + this.indexDir = indexDir; + File test = new File(indexDir); + try { + if (!test.exists()) { + debug ("file " + indexDir + " didn't exist - creating"); + test.mkdirs(); + } + } catch (java.lang.SecurityException e) { + } + } + + /** + * Closes the index. + */ + public abstract void close() throws Exception; + + /** + * Sets the stopwords in an index. If the stopwords are already + * defined for an index, the stop words are merged with the existing + * set of stopwords. + * @params stopWords An Enumeration of Strings. + */ + public abstract void storeStopWords(Enumeration stopWords); + + /** + * Returns the list of stopwords for an index. + * @returns Enumeration An enumeration of Strings. Returns null if there are no stopwords. + */ + public abstract Enumeration getStopWords(); + + /** + * Opens a document to store information. + */ + public abstract void openDocument(String name) throws Exception; + + /** + * Closes the document. This prevents any additional information from being + * stored. + */ + public abstract void closeDocument() throws Exception; + + /** + * Stores a concept at a given position. + */ + public abstract void storeLocation(String text, int position) throws Exception; + + /** + * Stores the title for the document. + */ + public abstract void storeTitle(String title) throws Exception; + + private boolean debug=false; + private void debug(String msg) { + if (debug) { + System.err.println("IndexBuilder: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java b/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java new file mode 100644 index 0000000000000000000000000000000000000000..5749860482cd1a77c272e1561552ec7f3ebf9635 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java @@ -0,0 +1,181 @@ +/* + * @(#)IndexerKit.java 1.13 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @(#) IndexerKit.java 1.13 - last change made 10/30/06 + */ + +package javax.help.search; + +import java.io.*; +import java.util.Locale; + +/** + * Establishes the requirements of an indexing object for a <em>type</em> + * of text content. The DefaultKit acts as a factory for policy. + * For example, an implementation + * for HTML and RTF can be provided that is replaceable + * with other implementations. + * <p> + * New kits are normally created by cloning a + * prototype kit. + * + * @author Roger D. Brinkley + * @version %I %G + */ +public abstract class IndexerKit implements Cloneable { + + protected IndexBuilder builder; + protected ConfigFile config; + protected String file; + protected Locale locale; + + /** + * Creates a copy of the indexer kit. This + * allows an implementation to serve as a prototype + * for others, so that they can be quickly created. + * + * @return the copy + */ + public abstract Object clone(); + + /** + * Gets the MIME type of the data that this + * kit represents support for. + * + * @return the type + */ + public abstract String getContentType(); + + /** + * Sets the locale for string tokenizing. A null locale value is valid and means + * that no locale has been set for this IndexerKit. + */ + public void setLocale (Locale locale) { + this.locale = locale; + } + + /** + * Convenience method for setting the locale from a lang string + * Takes the lang string in the form of "language_country_variant". + * Parses the string and creates an appropriate locale. + * @param lang A string representation of a locale. If lang is null it is the + * same as setting the locale to null. + */ + public void setLocale(String lang) { + if (lang == null) { + setLocale((Locale)null); + return; + } + String language; + String country; + String variant=null; + Locale newlocale; + int lpt = lang.indexOf("_"); + if (lpt == -1) { + language = lang; + country = ""; + newlocale = new Locale(language, country); + } else { + language = lang.substring(0, lpt); + int cpt = lang.indexOf("_", lpt+1); + if (cpt == -1) { + country = lang.substring(lpt+1); + newlocale = new Locale(language, country); + } else { + country = lang.substring(lpt+1, cpt); + variant = lang.substring(cpt+1); + newlocale = new Locale(language, country, variant); + } + } + setLocale(newlocale); + } + + /** + * Gets the Locale. + */ + public Locale getLocale() { + return locale; + } + + /** + * Parses content from the given stream. The stream is expected + * to be in a format appropriate for this content + * handler to parse into tokens according to the locale of the class. + * In the absense of a locale, the default locale tokenizer + * is used. + * + * @param in The stream to read from. + * @param file The file name being parsed. + * @param builder The IndexBuilder for the full text insertion. + * @param config The indexer configuration information. + * @exception IOException on any I/O error. + */ + public abstract void parse(Reader in, String file, boolean ignoreCharset, + IndexBuilder builder, + ConfigFile config) + throws IOException; + + /** + * Parses a string into tokens and stores the tokens. + */ + public abstract int parseIntoTokens (String source, int pos); + + /** + * Starts the storing of the dcoument. + */ + protected abstract void startStoreDocument (String file) + throws Exception; + + /** + * Ends the storing of the document. + */ + protected abstract void endStoreDocument () + throws Exception; + + /** + * Stores a token in the IndexBuilder. + */ + protected abstract void storeToken (String token, int pos) + throws Exception; + + /** + * Stores a title in the IndexBuilder. + */ + protected abstract void storeTitle (String title) throws Exception; + + /** + * Debug code + */ + + private boolean debugFlag=false; + private void debug(String msg) { + if (debugFlag) { + System.err.println("IndexerKit: "+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java b/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..3c4b684fb9b14f64194493c7d0db285a22dd8df8 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java @@ -0,0 +1,350 @@ +/* + * @(#)MergingSearchEngine.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Locale; +import java.net.URL; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import javax.help.HelpSet; +import javax.help.HelpUtilities; +import javax.help.NavigatorView; +import javax.help.search.SearchListener; +import javax.help.search.SearchEvent; +import javax.help.search.SearchEngine; +import javax.help.search.SearchQuery; + +/* + * A class that provides a merging/removing layer for the search. + */ +public class MergingSearchEngine extends SearchEngine { + + private Vector engines; + private Hashtable enginePerView = new Hashtable(); + private boolean stopQuery = false; + + public MergingSearchEngine(NavigatorView view) { + if (view == null) { + throw new IllegalArgumentException("view must not be null"); + } + engines = new Vector(); + // HERE - the makeEngine() should be delayed until the actual query + SearchEngine engine = makeEngine(view); + engines.addElement(engine); + } + + public MergingSearchEngine(SearchEngine engine) { + if (engine == null) { + throw new IllegalArgumentException("engine must not be null"); + } + engines = new Vector(); + engines.addElement(engine); + } + + /** + * Creates the query for this helpset. + */ + public SearchQuery createQuery() { + return new MergingSearchQuery(this); + } + + /** + * Adds/Removes a Search Engine to/from list. + * + * Possibly the makeEngine should be delayed until the actual query. + */ + + public void merge(NavigatorView view) { + if (view == null) { + throw new IllegalArgumentException("view must not be null"); + } + SearchEngine engine = makeEngine(view); + if (engine == null) { + throw new IllegalArgumentException("view is invalid"); + } + engines.addElement(engine); + enginePerView.put(view, engine); + } + + /* + * Remove a Navigator View + * Throws an IllegalArgumentException if view is null or if there + * is no search engine for a view. + */ + public void remove(NavigatorView view) { + if (view == null) { + throw new IllegalArgumentException("view is either null or invalid"); + } + SearchEngine engine = (SearchEngine) enginePerView.get(view); + if (engine != null) { + engines.removeElement(engine); + enginePerView.remove(engine); + } else { + throw new IllegalArgumentException("view is either null or invalid"); + } + + } + + public Enumeration getEngines() { + return engines.elements(); + } + + private SearchEngine makeEngine(NavigatorView view) { + Hashtable params = view.getParameters(); + + // if there were no parameters or there were parameters but + // no data then return a null SearchEngine + if (params == null || + (params != null && !params.containsKey("data"))) { + return null; + } + String engineName = (String) params.get("engine"); + HelpSet hs = view.getHelpSet(); + URL base = hs.getHelpSetURL(); + ClassLoader loader = hs.getLoader(); + + if (engineName == null) { + engineName = HelpUtilities.getDefaultQueryEngine(); + params.put("engine", engineName); + } + + SearchEngine back = null; + + Constructor konstructor; + Class types[] = {URL.class, Hashtable.class}; + Object args[] = {base, params}; + Class klass; + + debug("makeEngine"); + debug(" base: "+base); + debug(" params: "+params); + + try { + if (loader == null) { + klass = Class.forName(engineName); + } else { + klass = loader.loadClass(engineName); + } + } catch (Throwable t) { + throw new Error("Could not load engine named "+engineName+" for view: "+view); + } + + try { + konstructor = klass.getConstructor(types); + } catch (Throwable t) { + throw new Error("Could not find constructor for "+engineName+". For view: "+view); + } + try { + back = (SearchEngine) konstructor.newInstance(args); + } catch (InvocationTargetException e) { + System.err.println("Exception while creating engine named "+engineName+" for view: "+view); + e.printStackTrace(); + } catch (Throwable t) { + throw new Error("Could not create engine named "+engineName+" for view: "+view); + } + return back; + } + + private class MergingSearchQuery extends SearchQuery implements SearchListener { + + private MergingSearchEngine mhs; + private Vector queries; + private String searchparams; + + public MergingSearchQuery(SearchEngine hs) { + super(hs); + if (hs instanceof MergingSearchEngine) { + this.mhs = (MergingSearchEngine) hs; + } + } + + // Start all the search engines + public synchronized void start(String searchparams, Locale l) + throws IllegalArgumentException, IllegalStateException + { + MergingSearchEngine.this.debug("startSearch()"); + + // if we're already alive you can't start again + if (isActive()) { + throw new IllegalStateException(); + } + + stopQuery = false; + + // setup everthing to get started + super.start(searchparams, l); + queries = new Vector(); + + // Get a query for each engine + for (Enumeration e = mhs.getEngines(); + e.hasMoreElements(); ) { + SearchEngine engine = (SearchEngine) e.nextElement(); + if (engine != null) { + queries.addElement(engine.createQuery()); + } + } + + // Set the listener to this class and start the query + for (Enumeration e = queries.elements(); e.hasMoreElements(); ) { + SearchQuery query = (SearchQuery) e.nextElement(); + query.addSearchListener(this); + query.start(searchparams, l); + } + } + + // Stop all the search engines + // This is an override of the SearchQuery.stop + // Donnot call super.stop in this method as an + // extra fireSearchStopped will be genertated + public synchronized void stop() throws IllegalStateException { + // Can't stop what is already stopped silly + if (queries == null) { + return; + } + + stopQuery = true; + + // Loop through all the queries and and make sure they have + // all inActive. If any query is active wait a small period of + // time + boolean queriesActive = true; + while (queriesActive) { + queriesActive = false; + + // Throughout this process the queries will disappear so + // protect against a null pointer + if (queries == null) { + continue; + } + for (Enumeration e = queries.elements(); + e.hasMoreElements(); ) { + SearchQuery query = (SearchQuery) e.nextElement(); + if (query.isActive()) { + debug ("queries are active waiting to stop"); + queriesActive = true; + } + } + if (queriesActive) { + try { + wait(250); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + queries = null; + } + + public boolean isActive() { + + // if there aren't any queries we aren't alive + if (queries == null) { + return false; + } + + // Loop through all the queries and see if anyone is alive + for (Enumeration e = queries.elements(); + e.hasMoreElements(); ) { + SearchQuery query = (SearchQuery) e.nextElement(); + if (query.isActive()) { + return true; + } + } + + // Didn't find anyone alive so we're not alive + return false; + } + + public SearchEngine getSearchEngine() { + return mhs; + } + + public synchronized void itemsFound(SearchEvent e) { + SearchQuery queryin = (SearchQuery) e.getSource(); + + if (stopQuery) { + return; + } + + // Loop through all the queries and match this one + if (queries != null) { + Enumeration enum1 = queries.elements(); + while (enum1.hasMoreElements()) { + SearchQuery query = (SearchQuery) enum1.nextElement(); + if (query == queryin) { + // Redirect any Events as if they were from me + fireItemsFound(e); + } + } + } + } + + public void searchStarted(SearchEvent e) { + // Ignore these events as this class already informed + // the listeners the search was started so we don't have + // to do anything else + } + + public synchronized void searchFinished(SearchEvent e) { + SearchQuery queryin = (SearchQuery) e.getSource(); + + // Loop through all the queries and match this one + if (queries != null) { + Enumeration enum1 = queries.elements(); + while (enum1.hasMoreElements()) { + SearchQuery query = (SearchQuery) enum1.nextElement(); + if (query == queryin) { + queryin.removeSearchListener(this); + queries.removeElement(query); + } + } + // If all the queries are done then send a searchFinished + if (queries.isEmpty()) { + queries = null; + if (!stopQuery) { + fireSearchFinished(); + } + } + } + + } + + } // This needs to be public to deal with inner classes... + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("MergineSearchEngine: "+msg); + } + } + +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..98b86e6ff5467ac2fceedd4880541f89ce1db22b --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java @@ -0,0 +1,95 @@ +/* + * @(#)SearchEngine.java 1.8 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +import javax.help.event.EventListenerList; +import javax.help.search.SearchEvent; +import javax.help.search.SearchListener; +import java.net.URL; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Locale; +import java.security.InvalidParameterException; + +/** + * Defines the methods used to access a search engine. + * Each instance is created by a engine factory. + * + * Extensions of SearchEngine can perform the search or negotiate the search + * results with an outside agent. A server search engine is an an example + * of an outside agent. + * + * Search results are returned through SearchEvents to listeners that + * register with a SearchQuery instance. The SearchQuery + * is returned from the method createQuery. + * + * @author Roger D. Brinkley + * @version 1.6 03/19/99 + * + * @see javax.help.search.SearchEvent + * @see javax.help.search.SearchListener + */ + +public abstract class SearchEngine { + + protected URL base; // the base for resolving URLs against + protected Hashtable params; // other parameters to the engine + + /** + * Creates a SearchEngine using the standard JavaHelp SearchEngine + * parameters. Only this constructor is used to create a SearchEngine + * from within a search view. + * + * @param base The base address of the data. + * @param params A hashtable of parameters from the search view. + */ + public SearchEngine(URL base, Hashtable params) + throws InvalidParameterException + { + this.base = base; + this.params = params; + } + + /** + * Creates a SearchEngine. + */ + public SearchEngine() { + } + + /** + * Creates a new search query. + */ + public abstract SearchQuery createQuery() throws IllegalStateException; + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("SearchEngine: "+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..80c00edd84e0aa40886eab1280b1267c1acc57b8 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java @@ -0,0 +1,116 @@ +/* + * @(#)SearchEvent.java 1.22 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +import java.util.Vector; +import java.util.Enumeration; + +/** + * Encapsulates information that describes changes to a SearchQuery. It is used + * to notify listeners of the change. + * + * @author Roger D. Brinkley + * @version 1.16 03/19/99 + */ + +public class SearchEvent extends java.util.EventObject +{ + private String params; + private boolean searching; + private Vector items; + + /** + * Represents a change in the SearchEngine. Used for starting the search + * or ending the search. + * + * @param source The source of this event. + * @param params The search parameters. + * @param searching A boolean operator that indicates if searching is + * executing (true) or stopped (false). + * @throws IllegalArgumentException if source, or params is NULL. + */ + public SearchEvent(Object source, String params, boolean searching) { + super (source); + if (params == null) { + throw new IllegalArgumentException("null params"); + } + this.params = params; + this.searching = searching; + } + + /** + * Represents a change in the SearchEngine. Used to indicate that either a single + * item or a group of items have matched the params. + * + * @param source The source of this event. + * @param params The search parameters. + * @param searching A boolean operator that indicates if a search is + * executing (true) or stopped (false). + * @param items A Vector of SearchItems matching the the search params. + * + * @throws IllegalArgumentException if source, params, or items is NULL. + * @see java.javahelp.SearchItems + */ + public SearchEvent(Object source, String params, boolean searching, Vector items) { + super(source); + if (params == null) { + throw new IllegalArgumentException("null params"); + } + this.params = params; + this.searching = searching; + if (items == null) { + throw new IllegalArgumentException("null items"); + } + this.items = items; + } + + + /** + * Returns the parameters to the query. + */ + public String getParams() { + return params; + } + + /** + * A boolean value that indicates if the search is completed. + */ + public boolean isSearchCompleted() { + return searching; + } + + /** + * An enumerated list of SearchItems that match parameters of the query. + */ + public Enumeration getSearchItems() { + if (items == null) { + return null; + } + return items.elements(); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java new file mode 100644 index 0000000000000000000000000000000000000000..aef5e667a7942f4d5408a5821901822705011af0 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java @@ -0,0 +1,190 @@ +/* + * @(#)SearchItem.java 1.21 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +import java.util.Vector; +import java.util.Enumeration; +import java.net.URL; + +/** + * A SearchItem corresponds to one specific item found in a search query. + * SearchItems are used in the default Search navigator. + * + * @see javax.help.SearchTOCItem + * @see javax.help.search.SearchEvent + * @see javax.help.search.SearchListener + * + * @author Roger D. Brinkley + * @version 1.21 10/30/06 + */ + +public class SearchItem { + private URL base; + private String title; + private String lang; + private String filename; + private double confidence; + private int begin; + private int end; + private Vector concepts; + + /** + * Constructs a SearchItem + * + * @param base The URL to the base from which file is a spec. + * @param title Title of the item + * @param lang A string representation of the locale. A null lang is valid + * and represents the default locale. + * @param filename FileName for the item. + * @param confidence How closely this matches the params. + * @param begin Starting position where the (requested) match has been found. + * @param end Ending position. + * @param concepts A vector of concepts. + */ + public SearchItem(URL base, + String title, String lang, String filename, + double confidence, + int begin, int end, Vector concepts) { + if (base == null) { + throw new NullPointerException("base"); + } + this.base = base; + if (title == null) { + throw new NullPointerException("title"); + } + this.title = title; + this.lang = lang; + if (filename == null) { + throw new NullPointerException("fileName"); + } + this.filename = filename; + this.confidence = confidence; + this.begin = begin; + this.end = end; + if (concepts == null) { + throw new NullPointerException("concepts"); + } + this.concepts = concepts; + } + + /** + * Gets the base of the SearchItem. + * + * @return The base for this SearchItem. Should be used with filename to + * obtain a URL to the desired hit. + */ + public URL getBase() { + return base; + } + + /** + * Gets the title of the SearchItem. + * + * @return The title of the document. Used to present the hit in the navigator. + */ + public String getTitle() { + return title; + } + + /** + * Gets the lang of the SearchItem. + * + * @return The title of the document. Used to present the hit in the navigator. + */ + public String getLang() { + return lang; + } + + /** + * Gets the spec (as a URL relative to getBase() ) to the document. + * + * @return The spec, relative to getBase(), to the document containing the hit. + */ + public String getFilename() { + return filename; + } + + /** + * Gets the confidence value for the hit. + * + * @return The confidence value for the hit. + * This measures how "good" the hit is. The lower the value the better. + */ + public double getConfidence() { + return confidence; + } + + /** + * Gets the begin pointer position for the hit. + * + * @return The starting position for the area in the document where a hit is found. + */ + public int getBegin() { + return begin; + } + + /** + * Gets the ending pointer position. + * + * @return The ending position for the area in the document where a hit is found. + */ + public int getEnd() { + return end; + } + + /** + * If there are "concepts" against which the query is made, this is an enumeration + * of the concepts. Otherwise null. + * + * @return An enumeration of the concepts found in this query. + */ + public Enumeration getConcepts() { + return concepts.elements(); + } + + public String toString() { + StringBuffer result; + result = new StringBuffer(confidence + " " + title + ":" + + base + filename + " [" + begin + "," + end + + "], {"); + if (concepts == null) { + result.append("}"); + return result.toString(); + } + Enumeration enum1 = concepts.elements(); + while(enum1.hasMoreElements()) { + String concept = (String)enum1.nextElement(); + result.append(concept); + if (enum1.hasMoreElements()) { + result.append(","); + } + } + result.append("}"); + return result.toString(); + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java new file mode 100644 index 0000000000000000000000000000000000000000..5baf297e2064ea5cb9e9eefb0f9e1560eb50e1b1 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java @@ -0,0 +1,56 @@ +/* + * @(#)SearchListener.java 1.11 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +/** + * Defines the interface for an object that listens to + * changes from a SearchQuery instance. + * + * @author Roger D. Brinkley + * @version 1.11 10/30/06 + */ + +public interface SearchListener extends java.util.EventListener +{ + /** + * Tells the listener that matching SearchItems have been found. + */ + void itemsFound(SearchEvent e); + + /** + * Tells the listener that the search has started. + */ + void searchStarted(SearchEvent e); + + + /** + * Tells the listener that the search has finished + */ + void searchFinished(SearchEvent e); +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..273150b72cefb80a526b413ea3f981ece621efbe --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java @@ -0,0 +1,247 @@ +/* + * @(#)SearchQuery.java 1.9 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.search; + +import javax.help.event.EventListenerList; +import javax.help.search.SearchEvent; +import javax.help.search.SearchListener; +import java.net.URL; +import java.util.Vector; +import java.util.Locale; +import java.util.Enumeration; + +/** + * The instance of a query on a search database. It is + * instantiated by SearchEngine.startQuery. + * + * Subclasses of SearchQuery can perform the search or negotiate the search + * results with an outside agent as setup in the SearchEngine class. A server + * search engine is an an example of an outside agent. + * + * Search results are returned through SearchEvents to listeners that + * register with a SearchEngine instance. + * + * @author Roger D. Brinkley + * @version 1.22 09/16/98 + * + * @see javax.help.search.SearchEvent + * @see javax.help.search.SearchListener + */ + +public abstract class SearchQuery { + + protected EventListenerList listenerList = new EventListenerList(); + protected SearchEngine hs; + protected String searchparams; + protected Locale l; + + /** + * Creates a SearchQuery. + */ + public SearchQuery(SearchEngine hs) { + this.hs = hs; + } + + /** + * Adds a listener for the SearchEngine posted after the search has + * started, stopped, or search parameters have been defined. + * + * @param l The listener to add. + * @see java.javahelp.SearchEngine#removeSearchListener + */ + public void addSearchListener(SearchListener l) { + listenerList.add(SearchListener.class, l); + } + + /** + * Removes a listener previously added with <tt>addSearchListener</tt>. + * + * @param l The listener to remove. + * @see java.javahelp.SearchEngine#addSearchListener + */ + public void removeSearchListener(SearchListener l) { + listenerList.remove(SearchListener.class, l); + } + + /** + * Starts the search. This method invokes searchStarted on + * SearchListeners and stores the searchparams. Extensions + * of SearchQuery should fully implement this method according + * to the needs of the SearchQuery and its corresponding SearchEngine. + * + * + * @param searchparams The search string. + * @param locale The locale of the search string. + * @exception IllegalArgumentException The parameters are not + * understood by this engine. + * @exception IllegalStateException There is an active search in + * progress in this instance. + */ + public void start(String searchparams, Locale l) + throws IllegalArgumentException, IllegalStateException + { + this.searchparams = searchparams; + this.l = l; + fireSearchStarted(); + } + + /** + * Stops the search. This method invokes searchStopped on + * SearchListeners. Extensions of + * SearchQuery should fully implement this method according to needs + * of the SearchQuery and its corresponding SearchEngine. + * + * @exception IllegalStateException The search engine is not in a state in which it can be started. + */ + public void stop() throws IllegalStateException { + fireSearchFinished(); + } + + /** + * Returns the SearchEngine associated with this SearchQuery. + */ + public SearchEngine getSearchEngine() { + return hs; + } + + /** + * Determines if this SearchQuery is active. + * + * @returns True if active, false otherwise + */ + public abstract boolean isActive(); + + /** + * Notifies that query of items is found in the search. + * + * @param docs A vector of SearchItem. + * @param inSearch Is the search completed? + */ + public void itemsFound(boolean inSearch, Vector docs) { + fireItemsFound(inSearch, docs); + } + + /** + * Notifies that a SearchItem has been found. + * + * @param params The parameters to the search. + * @param inSearch Is the search completed? + * @param docs A vector of SearchItem. + * @see javax.help.search.SearchItem + */ + protected void fireItemsFound(boolean inSearch, Vector docs) { + debug("fireItemsFound"); + debug(" params: " + searchparams); + debug(" insearch: " + inSearch); + debug(" docs: " + docs); + Object[] listeners = listenerList.getListenerList(); + SearchEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == SearchListener.class) { + if (e == null) { + e = new SearchEvent(this, searchparams, + inSearch, docs); + } + ((SearchListener)listeners[i+1]).itemsFound(e); + } + } + } + + /** + * Passs through that a SearchEvent has happened. + * This is useful for SearchEngine engines that encapsulate others. + * + * @param e The SearchEvent to pass through. + */ + protected void fireItemsFound(SearchEvent e) { + Object[] listeners = listenerList.getListenerList(); + + Vector newItems = new Vector(); + for (Enumeration enum1 = e.getSearchItems(); + enum1.hasMoreElements(); ) { + newItems.addElement((SearchItem) enum1.nextElement()); + } + + SearchEvent e2 = new SearchEvent(this, e.getParams(), + e.isSearchCompleted(), + newItems); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == SearchListener.class) { + ((SearchListener)listeners[i+1]).itemsFound(e2); + } + } + } + + /** + * Notifies that a search has started. + * + * @param params The parameters to the search. + */ + protected void fireSearchStarted() { + debug("fireSearchStarted"); + Object[] listeners = listenerList.getListenerList(); + SearchEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == SearchListener.class) { + if (e == null) { + e = new SearchEvent(this, searchparams, true); + } + ((SearchListener)listeners[i+1]).searchStarted(e); + } + } + } + + /** + * Notifies that a search has completed. + * + * @param params The parameters to the search. + */ + protected void fireSearchFinished() { + debug("fireSearchFinished"); + Object[] listeners = listenerList.getListenerList(); + SearchEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == SearchListener.class) { + if (e == null) { + e = new SearchEvent(this, searchparams, false); + } + ((SearchListener)listeners[i+1]).searchFinished(e); + } + } + } + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("SearchQuery: "+msg); + } + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/package.html b/jhMaster/JavaHelp/src/new/javax/help/search/package.html new file mode 100644 index 0000000000000000000000000000000000000000..5040eefbee21c8b10b5fda1bd17ce2e7cbfff51a --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/search/package.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<!-- + + @(#)package.html 1.3 99/04/07 + + Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Sun designates this + particular file as subject to the "Classpath" exception as provided + by Sun in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + CA 95054 USA or visit www.sun.com if you need additional information or + have any questions. + +--> + +</head> +<body bgcolor="white"> + +Supports simple access to search engines. JavaHelp supports a +standard full-text search view and navigator. The view interacts +with a search engine through this package. The reference +implementation provides a search engine that implements these +interfaces, but others can also be used--the specific search engine +is part of the information specified in the search view. This separation +provides full-text search functionality while not imposing specific +formats. These details are encapsulated in a search engine type. + +<p> +<code>HelpSearch</code> is an abstract base class for the search +engines, <code>SearchQuery</code> obtained from it can be used to +perform the actual queries. Individual items found by a search are +<code>SearchItem</code>s which can be fired as +<code>HelpEvent</code>s. + +<p> +The creation of search databases is done by subclasses of the +abstract class <code>IndexBuilder</code> based on the MIME type of +each document being indexed. Details of the index building process +can be given through instances of <code>ConfigFile</code>. + +<p> +<em>Note:</em> Registration of IndexerKits should probably be visible +in this package. + +<!-- +<H2>Package Specification</H2> +Link to updated API specification to be added here. +--> + +<H2>Related Documentation</H2> + +<P> +For overviews, tutorials, examples, guides, tool support, +and other documentation, +please see the <em>JavaHelp System User's Guide</em>. + + </body> +</html> diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java new file mode 100644 index 0000000000000000000000000000000000000000..78f5e7e180fbf472636d6249b719a2b175a9261d --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java @@ -0,0 +1,66 @@ +/* + * @(#)IndexItemTEI.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.tagext.*; + +/** + * The JSP tag extra info class for an IndexItem + * + * @author Roger D. Brinkley + * @version 1.2 10/30/06 + * @see javax.help.IndexItem + */ + +public class IndexItemTEI extends TagExtraInfo { + + public IndexItemTEI() { + super(); + } + + public VariableInfo[] getVariableInfo(TagData data) { + return new VariableInfo[] { + new VariableInfo("name", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("helpID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("parent", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("parentID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("node", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("nodeID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("contentURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("expansionType", "java.lang.String", true, + VariableInfo.NESTED) + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java new file mode 100644 index 0000000000000000000000000000000000000000..420744ed835f58c328eab84e7ace21aa4790aeb4 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java @@ -0,0 +1,217 @@ +/* + * @(#)IndexItemTag.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.*; +import javax.servlet.jsp.tagext.*; +import java.util.*; +import java.io.*; +import java.net.URL; +import java.net.MalformedURLException; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.Map; +import javax.help.Map.ID; +import javax.help.Merge; +import javax.help.MergeHelpUtilities; +import javax.help.NavigatorView; +import javax.help.IndexItem; +import javax.help.IndexView; +import javax.help.SortMerge; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; + +/** + * The JSP tag class for an IndexItem + * + * @author Roger D. Brinkley + * @version 1.4 10/30/06 + * @see javax.help.IndexItem + */ + +public class IndexItemTag extends BodyTagSupport { + private Enumeration treeEnum; + private DefaultMutableTreeNode topNode; + private String baseID="root"; + private HelpBroker hb; + private IndexView view=null; + + public void setIndexView(IndexView view) { + this.view = view; + } + + public void setBaseID(String baseID) { + this.baseID = baseID; + } + + public void setHelpBroker(HelpBroker hb) { + this.hb = hb; + } + + private void initialize() { + if (view == null) { + return; + } + topNode = view.getDataAsTree(); + treeEnum = topNode.preorderEnumeration(); + + String mergeType = view.getMergeType(); + HelpSet hs = view.getHelpSet(); + Locale locale = hs.getLocale(); + + + // Make sure the children are all handled correctly + MergeHelpUtilities.mergeNodeChildren(mergeType, topNode); + + // add all the subhelpsets + addSubHelpSets(hs); + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + private void addSubHelpSets(HelpSet hs){ + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + if (ehs == null) { + continue; + } + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if (views[i] instanceof IndexView) { + Merge mergeObject = + Merge.DefaultMergeFactory.getMerge(view, views[i]); + if (mergeObject != null) { + mergeObject.processMerge(topNode); + } + } + } + addSubHelpSets( ehs ); + } + } + + public int doStartTag() { + initialize(); + if(treeEnum.hasMoreElements()) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) treeEnum.nextElement(); + // never use the top node. It is just the container node + if (node == topNode) { + try { + node = (DefaultMutableTreeNode) treeEnum.nextElement(); + } catch (NoSuchElementException e) { + return SKIP_BODY; + } + } + setNodeAttributes(node); + return EVAL_BODY_TAG; + } + else { + return SKIP_BODY; + } + } + + public int doAfterBody() throws JspException { + BodyContent body = getBodyContent(); + try { + body.writeOut(getPreviousOut()); + } catch (IOException e) { + throw new JspTagException("IndexItemTag: " + e.getMessage()); + } + // clear up so the next time the body content is empty + body.clearBody(); + if (treeEnum.hasMoreElements()) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) treeEnum.nextElement(); + setNodeAttributes(node); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + private void setNodeAttributes(DefaultMutableTreeNode node) { + IndexItem item = (IndexItem) node.getUserObject(); + pageContext.setAttribute("name", item.getName()); + String helpID = ""; + if (item.getID() != null) { + helpID = item.getID().id; + } + pageContext.setAttribute("helpID", helpID); + pageContext.setAttribute("parent", Integer.toHexString(node.getParent().hashCode())); + String id = getID(node.getParent()); + pageContext.setAttribute("parentID", id); + pageContext.setAttribute("node", Integer.toHexString(node.hashCode())); + id = getID(node); + pageContext.setAttribute("nodeID", id); + String content = getContentURL(item); + pageContext.setAttribute("contentURL", content); + String expansionType = Integer.toString(item.getExpansionType()); + pageContext.setAttribute("expansionType", expansionType); + } + + private String getID(TreeNode node) { + if (node == topNode) { + return baseID; + } + TreeNode parent = node.getParent(); + if (parent == null) { + return ""; + } + String id = getID(parent); + id = id.concat("." + Integer.toString(parent.getIndex(node))); + return id; + } + + /** + * return the content URL in String form for a given IndexItem + * + * returns an empty String if no content exists. + */ + private String getContentURL(IndexItem item) { + URL url = null; + ID id = item.getID(); + if (id != null) { + HelpSet hs = id.hs; + Map map = hs.getLocalMap(); + try { + url = map.getURLFromID(id); + } catch (MalformedURLException e) { + // just ignore + } + } + if (url == null) { + return ""; + } + return url.toExternalForm(); + } + +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java new file mode 100644 index 0000000000000000000000000000000000000000..bd610904c665fae13297719a23700fabf56b6b5a --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java @@ -0,0 +1,61 @@ +/* + * @(#)NavigatorsTEI.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.tagext.*; + +/** + * The JSP tag extra info class for navigators + * + * @author Roger D. Brinkley + * @version 1.3 10/30/06 + * @see javax.help.HelpSet.getNavigatorView() + * @see javax.help.NavigatorView + */ + +public class NavigatorsTEI extends TagExtraInfo { + + public NavigatorsTEI() { + super(); + } + + public VariableInfo[] getVariableInfo(TagData data) { + return new VariableInfo[] { + new VariableInfo("className", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("name", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("tip", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("iconURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("isCurrentNav", "java.lang.Boolean", true, + VariableInfo.NESTED), + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java new file mode 100644 index 0000000000000000000000000000000000000000..b5f35ab7f7820c76c8ff97b5666b39da673251d7 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java @@ -0,0 +1,158 @@ +/* + * @(#)NavigatorsTag.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.*; +import javax.servlet.jsp.tagext.*; +import javax.servlet.ServletRequest; +import java.util.*; +import java.io.*; +import java.net.URL; +import java.net.MalformedURLException; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.Map; +import javax.help.Map.ID; +import javax.help.NavigatorView; + +/** + * The JSP tag class for a Navigators + * + * @author Roger D. Brinkley + * @version 1.4 10/30/06 + * @see javax.help.HelpSet.getNavigatorView() + * @see javax.help.NavigatorView + */ + +public class NavigatorsTag extends BodyTagSupport { + private HelpBroker hb; + private HelpSet hs; + private String curNav = null; + private NavigatorView[] views; + private int i; + + public void setHelpBroker(HelpBroker hb) { + this.hb = hb; + hs = hb.getHelpSet(); + } + + public void setCurrentNav(String nav) { + curNav = nav; + } + + public void initialize() { + checkRequestParams(); + initCurNav(); + views = hs.getNavigatorViews(); + } + + public int doStartTag() { + initialize(); + if(views.length > 0) { + i = 0; + setNavigatorAttributes(views[i++]); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + private void checkRequestParams() { + ServletRequest request = pageContext.getRequest(); + + String nav = request.getParameter("nav"); + if (nav != null) { + curNav = nav; + } + + } + + private void initCurNav() { + if (curNav != null) { + try { + hb.setCurrentView(curNav); + } catch (IllegalArgumentException e) { + // Ignore + } + } else { + curNav = hb.getCurrentView(); + } + } + + + public int doAfterBody() throws JspException { + BodyContent body = getBodyContent(); + try { + body.writeOut(getPreviousOut()); + } catch (IOException e) { + throw new JspTagException("NavigatorsTag: " + e.getMessage()); + } + + // clear up so the next time the body content is empty + body.clearBody(); + if (i < views.length) { + setNavigatorAttributes(views[i++]); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + private void setNavigatorAttributes(NavigatorView view) { + pageContext.setAttribute("className", view.getClass().getName()); + pageContext.setAttribute("name", view.getName()); + pageContext.setAttribute("tip", view.getLabel()); + String icon = getIconURL(view); + pageContext.setAttribute("iconURL", icon); + pageContext.setAttribute("isCurrentNav", new Boolean(curNav.compareTo(view.getName()) == 0)); + } + + /** + * return the icon URL in String form for a given TOCItem + * + * returns empty String if no content exists. + */ + private String getIconURL(NavigatorView view) { + URL url = null; + ID id = view.getImageID(); + if (id != null) { + HelpSet hs = id.hs; + Map map = hs.getLocalMap(); + try { + url = map.getURLFromID(id); + } catch (MalformedURLException e) { + // just ignore + } + } + if (url == null) { + return ""; + } + return url.toExternalForm(); + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java new file mode 100644 index 0000000000000000000000000000000000000000..b0d19e8a9d25308ed9f5104f5be8a7c77db75a23 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java @@ -0,0 +1,62 @@ +/* + * @(#)SearchTOCItemTEI.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.tagext.*; + +/** + * The JSP tag extra info class for an SearchTOCItem + * + * @author Roger D. Brinkley + * @version 1.2 10/30/06 + * @see javax.help.SearchTOCItem + */ + +public class SearchTOCItemTEI extends TagExtraInfo { + + public SearchTOCItemTEI() { + super(); + } + + public VariableInfo[] getVariableInfo(TagData data) { + return new VariableInfo[] { + new VariableInfo("name", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("helpID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("confidence", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("hits", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("contentURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("hitBoundries", "java.lang.String", true, + VariableInfo.NESTED) + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java new file mode 100644 index 0000000000000000000000000000000000000000..d837adeb4dae941ced643de025e12e6fa8cf6612 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java @@ -0,0 +1,262 @@ +/* + * @(#)SearchTOCItemTag.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.*; +import javax.servlet.jsp.tagext.*; +import java.util.*; +import java.io.*; +import java.net.URL; +import java.net.MalformedURLException; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.Map; +import javax.help.Map.ID; +import javax.help.NavigatorView; +import javax.help.SearchTOCItem; +import javax.help.SearchView; +import javax.help.SearchHit; +import javax.help.search.MergingSearchEngine; +import javax.help.search.SearchQuery; +import javax.help.search.SearchListener; +import javax.help.search.SearchEvent; +import javax.help.search.SearchItem; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; + +/** + * The JSP tag extra info class for an SearchTOCItem + * + * @author Roger D. Brinkley + * @version 1.3 10/30/06 + * @see javax.help.SearchTOCItem + */ + +public class SearchTOCItemTag extends BodyTagSupport implements SearchListener{ + private Enumeration treeEnum; + private Vector nodes; + private SearchView view; + private HelpBroker hb; + private String query; + private MergingSearchEngine helpsearch; + private SearchQuery searchquery; + private boolean searchFinished; + + public void setSearchView(SearchView view) { + this.view = view; + } + + public void setHelpBroker(HelpBroker hb) { + this.hb = hb; + } + + public void setQuery(String query) { + this.query = query; + } + + + public synchronized int doStartTag() { + if (helpsearch == null) { + helpsearch = new MergingSearchEngine(view); + searchquery = helpsearch.createQuery(); + searchquery.addSearchListener(this); + + // Make sure all the subhelpsets have a search engine + addSubHelpSets(view.getHelpSet()); + } + + if (searchquery.isActive()) { + searchquery.stop(); + } + + searchquery.start(query, Locale.getDefault()); + + if (!searchFinished) { + try { + wait(); + } catch (InterruptedException e) { + // ignore + } + } + + + if(treeEnum.hasMoreElements()) { + SearchTOCItem item = (SearchTOCItem) treeEnum.nextElement(); + setNodeAttributes(item); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + private void addSubHelpSets(HelpSet hs){ + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + if (ehs == null) { + continue; + } + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if (views[i] instanceof SearchView) { + helpsearch.merge(views[i]); + } + } + addSubHelpSets( ehs ); + } + } + + public int doAfterBody() throws JspException { + BodyContent body = getBodyContent(); + try { + body.writeOut(getPreviousOut()); + } catch (IOException e) { + throw new JspTagException("SearchTOCItemTag: " + e.getMessage()); + } + + // clear up so the next time the body content is empty + body.clearBody(); + if(treeEnum.hasMoreElements()) { + SearchTOCItem item = (SearchTOCItem) treeEnum.nextElement(); + setNodeAttributes(item); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + private void setNodeAttributes(SearchTOCItem item) { + pageContext.setAttribute("name", item.getName()); + pageContext.setAttribute("helpID", getMapID(item)); + pageContext.setAttribute("confidence", Double.toString(item.getConfidence())); + pageContext.setAttribute("hits", Integer.toString(item.hitCount())); + pageContext.setAttribute("contentURL", item.getURL().toExternalForm()); + pageContext.setAttribute("hitBoundries", getSearchHits(item)); + } + + /** + * return an Map.ID if one exists for the content URL for a given SearchTOCItem + * + * returns an empty String if no content exists. + */ + private String getMapID(SearchTOCItem item) { + URL url = item.getURL(); + HelpSet hs = hb.getHelpSet(); + Map map = hs.getCombinedMap(); + ID id = map.getIDFromURL(url); + if (id == null) { + return ""; + } + return id.id; + } + + /** + * Get a string representing the array of SearchHit's begin and end locations + * for each hit + * + * @return String a sring representation of the values + */ + private String getSearchHits(SearchTOCItem item) { + String retval = "{ "; + for (Enumeration enum1 = item.getSearchHits(); + enum1.hasMoreElements();) { + SearchHit info = (SearchHit) enum1.nextElement(); + retval = retval + "{" + info.getBegin() + "," + info.getEnd() + + "}"; + if (enum1.hasMoreElements()) { + retval = retval + ", "; + } + } + retval = retval + " }"; + return retval; + } + + + public synchronized void itemsFound(SearchEvent e) { + SearchTOCItem tocitem; + Enumeration itemEnum = e.getSearchItems(); + // Iterate through each search item in the searchEvent + while (itemEnum.hasMoreElements()) { + SearchItem item = (SearchItem) itemEnum.nextElement(); + URL url; + try { + url = new URL(item.getBase(), item.getFilename()); + } catch (MalformedURLException me) { + debug ("Failed to create URL from " + item.getBase() + "|" + + item.getFilename()); + continue; + } + boolean foundNode = false; + + // see if this search item matches that of one we currently have + // if so just do an update + Enumeration nodesEnum = nodes.elements(); + while (nodesEnum.hasMoreElements()) { + tocitem = (SearchTOCItem) nodesEnum.nextElement(); + URL testURL = tocitem.getURL(); + if (testURL != null && url != null && url.sameFile(testURL)) { + tocitem.addSearchHit(new SearchHit(item.getConfidence(), + item.getBegin(), + item.getEnd())); + foundNode = true; + break; + } + } + + // No match. + // OK then add a new one. + if (!foundNode) { + tocitem = new SearchTOCItem(item); + nodes.addElement(tocitem); + } + } + } + + public synchronized void searchStarted(SearchEvent e) { + nodes = new Vector(); + searchFinished = false; + } + + public synchronized void searchFinished(SearchEvent e) { + searchFinished = true; + treeEnum = nodes.elements(); + notifyAll(); + } + + private static final boolean debug = false; + private static void debug(String msg) { + if (debug) { + System.err.println("SearchTOCItemTag: "+msg); + } + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java new file mode 100644 index 0000000000000000000000000000000000000000..adeebaf4d1e5eab9458ec839ca4f6945bfa9b0d4 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java @@ -0,0 +1,70 @@ +/* + * @(#)TOCItemTEI.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.tagext.*; + +/** + * The JSP tag extra info class for an TOCItem + * + * @author Roger D. Brinkley + * @version 1.3 10/30/06 + * @see javax.help.TOCItem + */ + +public class TOCItemTEI extends TagExtraInfo { + + public TOCItemTEI() { + super(); + } + + public VariableInfo[] getVariableInfo(TagData data) { + return new VariableInfo[] { + new VariableInfo("name", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("helpID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("parent", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("parentID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("node", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("nodeID", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("iconURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("iconOpenURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("contentURL", "java.lang.String", true, + VariableInfo.NESTED), + new VariableInfo("expansionType", "java.lang.String", true, + VariableInfo.NESTED) + }; + } +} diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java new file mode 100644 index 0000000000000000000000000000000000000000..7350bd932a50d755ea18c51b55e086621fdd71d6 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java @@ -0,0 +1,258 @@ +/* + * @(#)TOCItemTag.java 1.5 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import javax.servlet.jsp.*; +import javax.servlet.jsp.tagext.*; +import java.util.*; +import java.io.*; +import java.net.URL; +import java.net.MalformedURLException; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.Map; +import javax.help.Map.ID; +import javax.help.Merge; +import javax.help.MergeHelpUtilities; +import javax.help.NavigatorView; +import javax.help.TOCItem; +import javax.help.TOCView; +import javax.help.SortMerge; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; + +/** + * The JSP tag extra info class for an TocItem + * + * @author Roger D. Brinkley + * @version 1.5 10/30/06 + * @see javax.help.TOCItem + */ + +public class TOCItemTag extends BodyTagSupport { + private Enumeration treeEnum; + private DefaultMutableTreeNode topNode; + private String baseID="root"; + private HelpBroker hb; + private TOCView view=null; + + public void setTocView(TOCView view) { + this.view = view; + } + + public void setBaseID(String baseID) { + this.baseID = baseID; + } + + public void setHelpBroker(HelpBroker hb) { + this.hb = hb; + } + + private void initialize() { + if (view == null) { + return; + } + topNode = view.getDataAsTree(); + + String mergeType = view.getMergeType(); + HelpSet hs = view.getHelpSet(); + Locale locale = hs.getLocale(); + + + // Make sure the children are all handled correctly + MergeHelpUtilities.mergeNodeChildren(mergeType, topNode); + + // add all the subhelpsets + addSubHelpSets(hs); + + treeEnum = topNode.preorderEnumeration(); + } + + /** Adds subhelpsets + * + * @param hs The HelpSet which subhelpsets will be added + */ + private void addSubHelpSets(HelpSet hs){ + for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) { + HelpSet ehs = (HelpSet) e.nextElement(); + if (ehs == null) { + continue; + } + // merge views + NavigatorView[] views = ehs.getNavigatorViews(); + for(int i = 0; i < views.length; i++){ + if (views[i] instanceof TOCView) { + Merge mergeObject = + Merge.DefaultMergeFactory.getMerge(view, views[i]); + if (mergeObject != null) { + mergeObject.processMerge(topNode); + } + } + } + addSubHelpSets( ehs ); + } + } + + public int doStartTag() { + initialize(); + if(treeEnum.hasMoreElements()) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) treeEnum.nextElement(); + // never use the top node. It is just the container node + if (node == topNode) { + try { + node = (DefaultMutableTreeNode) treeEnum.nextElement(); + } catch (NoSuchElementException e) { + return SKIP_BODY; + } + } + setNodeAttributes(node); + return EVAL_BODY_TAG; + } + else { + return SKIP_BODY; + } + } + + public int doAfterBody() throws JspException { + BodyContent body = getBodyContent(); + try { + body.writeOut(getPreviousOut()); + } catch (IOException e) { + throw new JspTagException("TOCItemTag: " + e.getMessage()); + } + + // clear up so the next time the body content is empty + body.clearBody(); + if (treeEnum.hasMoreElements()) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) treeEnum.nextElement(); + setNodeAttributes(node); + return EVAL_BODY_TAG; + } else { + return SKIP_BODY; + } + } + + private void setNodeAttributes(DefaultMutableTreeNode node) { + TOCItem item = (TOCItem) node.getUserObject(); + pageContext.setAttribute("name", item.getName()); + String helpID = ""; + if (item.getID() != null) { + helpID = item.getID().id; + } + pageContext.setAttribute("helpID", helpID); + pageContext.setAttribute("parent", Integer.toHexString(node.getParent().hashCode())); + String id = getID(node.getParent()); + pageContext.setAttribute("parentID", id); + pageContext.setAttribute("node", Integer.toHexString(node.hashCode())); + id = getID(node); + pageContext.setAttribute("nodeID", id); + String content = getContentURL(item); + pageContext.setAttribute("contentURL", content); + String icon = getIconURL(node, item, true); + pageContext.setAttribute("iconURL", icon); + String iconOpen = getIconURL(node, item, false); + pageContext.setAttribute("iconOpenURL", iconOpen); + String expansionType = Integer.toString(item.getExpansionType()); + pageContext.setAttribute("expansionType", expansionType); + } + + private String getID(TreeNode node) { + if (node == topNode) { + return baseID; + } + TreeNode parent = node.getParent(); + if (parent == null) { + return ""; + } + String id = getID(parent); + id = id.concat("_" + Integer.toString(parent.getIndex(node))); + return id; + } + + /** + * return the content URL in String form for a given TOCItem + * + * returns an empty String if no content exists. + */ + private String getContentURL(TOCItem item) { + URL url = null; + ID id = item.getID(); + if (id != null) { + HelpSet hs = id.hs; + Map map = hs.getLocalMap(); + try { + url = map.getURLFromID(id); + } catch (MalformedURLException e) { + // just ignore + } + } + if (url == null) { + return ""; + } + return url.toExternalForm(); + } + + /** + * return the icon URL in String form for a given TOCItem + * + * returns empty String if no content exists. + */ + private String getIconURL(DefaultMutableTreeNode node, + TOCItem item, + boolean closedIcon) { + URL url = null; + ID id = item.getImageID(); + if (id == null) { + if (node.isLeaf()) { + id = view.getTopicImageID(); + } else { + if (closedIcon) { + id = view.getCategoryClosedImageID(); + } else { + id = view.getCategoryOpenImageID(); + } + } + } + if (id != null) { + HelpSet hs = id.hs; + Map map = hs.getLocalMap(); + try { + url = map.getURLFromID(id); + } catch (MalformedURLException e) { + // just ignore + } + } + if (url == null) { + return ""; + } + return url.toExternalForm(); + } +} + diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java new file mode 100644 index 0000000000000000000000000000000000000000..6debf6c61f7887560287100f1d739983337edaa6 --- /dev/null +++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java @@ -0,0 +1,173 @@ +/* + * @(#)ValidateTag.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.help.tagext; + +import java.net.MalformedURLException; +import java.net.URL; +import javax.servlet.ServletRequest; +import javax.servlet.ServletException; +import javax.servlet.jsp.tagext.TagSupport; +import javax.servlet.jsp.tagext.Tag; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.HelpSetException; +import javax.help.InvalidHelpSetContextException; + +/** + * Validates a HelpSet file and an Map.ID thourgh either a Request Parameter + * or passed as a JSP argument and sets the state in a HelpBroker. Additionally + * allows a HelpSet to be merged with the current HelpSet in the HelpBroker. + * + * @author Roger D. BRinkley + * @version 1.3 10/30/06 + * @see javax.help.HelpSet + * @see javax.help.Map.ID + * @see javax.help.HelpBroker + */ + +public class ValidateTag extends TagSupport { + private HelpBroker helpBroker; + private String invalidURLPath = "invalidhelp.html"; + private String hsName = null; + private String id = null; + private boolean merge = false; + + public void setHelpBroker(HelpBroker helpBroker) { + this.helpBroker = helpBroker; + } + + public void setInvalidURL(String relativeURLPath) { + this.invalidURLPath = relativeURLPath; + } + + public void setHelpSetName(String hsName) { + this.hsName = hsName; + } + + public void setCurrentID(String id) { + this.id = id; + } + + public void setMerge(boolean merge) { + this.merge = merge; + } + + public int doStartTag() { + checkRequestParams(); + validateHelpSet(); + validateID(); + return SKIP_BODY; + } + + private void checkRequestParams() { + ServletRequest request = pageContext.getRequest(); + + if (hsName == null) { + hsName = request.getParameter("helpset"); + } + + if (id == null) { + id = request.getParameter("id"); + } + } + + private void validateHelpSet() { + HelpSet tesths = helpBroker.getHelpSet(); + + // If there is already a HelpSet and there isn't a hsName + // return. Nothing to do + if (tesths != null && hsName == null) { + return; + } + + // If there isn't a HelpSet and there isn't a hsName + // then forward to the invalid page + if (tesths == null && hsName == null) { + try { + pageContext.forward(invalidURLPath); + } catch (Exception e) { + // ignore it + return; + } + } + + + // If we don't have a helpset and there is a hsName + // the create one and set the HelpBroker to this page + if (tesths == null && hsName != null) { + helpBroker.setHelpSet(createHelpSet()); + return; + } + + // If we have a helpset and there is a hsname + // and merging is turned on, merge the helpset + if (tesths != null && hsName != null && merge) { + tesths.add(createHelpSet()); + } + } + + private HelpSet createHelpSet() { + HelpSet hs = null; + ServletRequest request = pageContext.getRequest(); + if (!hsName.startsWith("/")) { + hsName = "/" + hsName; + } + URL url = null; + try { + if (hsName.startsWith("http")) { + url = new URL (hsName); + } else { + url = new URL(request.getScheme(), + request.getServerName(), + request.getServerPort(), + hsName); + } + hs = new HelpSet(null, url); + } catch (MalformedURLException e) { + // ignore + } catch (HelpSetException hse) { + // this is a serious error + throw new RuntimeException(hse.getMessage()); + } + return hs; + } + + private void validateID() { + if (id != null) { + helpBroker.setCurrentID(id); + } else if (helpBroker.getCurrentID() == null && + helpBroker.getCurrentURL() == null) { + try { + helpBroker.setCurrentID(helpBroker.getHelpSet().getHomeID()); + } catch (InvalidHelpSetContextException e) { + // ignore + } + } + } +} + diff --git a/jhMaster/JavaHelp/test/editorKit/HtmlTest.java b/jhMaster/JavaHelp/test/editorKit/HtmlTest.java new file mode 100644 index 0000000000000000000000000000000000000000..db1104c1452af38203bfe93a2affcdf1d9982bcf --- /dev/null +++ b/jhMaster/JavaHelp/test/editorKit/HtmlTest.java @@ -0,0 +1,349 @@ +/* + * @(#)HtmlTest.java 1.2 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.text.html.*; +import javax.swing.tree.*; +import javax.swing.undo.*; +import java.awt.*; +import java.util.*; +import java.net.URL; +import java.net.MalformedURLException; +import java.io.IOException; + +/** + * Simple wrapper around JEditorPane to browse html. + * Useful to browse the javadoc for swing... + * java HtmlTest file:/path-to-swing-docs/packages.html + */ +public class HtmlTest { + + public static void main(String[] args) { + Properties props = System.getProperties(); + props.put("http.proxyHost", "webcache1.eng"); + props.put("http.proxyPort", "8080"); + + if (args.length != 1) { + System.err.println("need URL argument"); + System.exit(1); + } + try { + URL u = new URL(args[0]); + JEditorPane html = new JEditorPane(u); + html.setEditable(false); + html.addHyperlinkListener(new Hyperactive()); + html.setBackground(Color.white); + JScrollPane scroller = new JScrollPane(); + JViewport vp = scroller.getViewport(); + vp.add(html); + vp.setBackingStoreEnabled(true); + + JFrame f = new JFrame("testing"); + f.getContentPane().setLayout(new BorderLayout()); + f.getContentPane().add("Center", scroller); + f.pack(); + f.setSize(600, 600); + f.setVisible(true); + + JFrame elems = new JFrame("elements"); + Container fContentPane = elems.getContentPane(); + fContentPane.setLayout(new BorderLayout()); + fContentPane.add(new ElementTreePanel(html)); + elems.pack(); + elems.show(); + } catch (MalformedURLException e) { + System.err.println("Bad url"); + System.exit(1); + } catch (IOException ioe) { + System.err.println("IOException: " + ioe.getMessage()); + System.exit(1); + } + } + + static class Hyperactive implements HyperlinkListener { + + /** + * Notification of a change relative to a + * hyperlink. + */ + public void hyperlinkUpdate(HyperlinkEvent e) { + System.err.println("link event: " + e); + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + JEditorPane html = (JEditorPane) e.getSource(); + if (e instanceof HTMLFrameHyperlinkEvent) { + HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e; + HTMLDocument doc = (HTMLDocument)html.getDocument(); + doc.processHTMLFrameHyperlinkEvent(evt); + } else { + try { + html.setPage(e.getURL()); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + } + } + +/** + * Displays a tree showing all the elements in a text Document. Selecting + * a node will result in reseting the selection of the JTextComponent. + * + * @author Scott Violet + * @version 1.1 04/28/98 + */ +static class ElementTreePanel extends JPanel implements DocumentListener, TreeSelectionListener { + /** Tree showing the documents element structure. */ + protected JTree tree; + /** Text component showing elemenst for. */ + protected JTextComponent editor; + /** Model for the tree. */ + protected DefaultTreeModel treeModel; + + public ElementTreePanel(JTextComponent editor) { + this.editor = editor; + + Document document = editor.getDocument(); + + // Create the tree. + treeModel = new DefaultTreeModel((TreeNode)document. + getDefaultRootElement()); + tree = new JTree(treeModel) { + public String convertValueToText(Object value, boolean selected, + boolean expanded, boolean leaf, + int row, boolean hasFocus) { + Element e = (Element)value; + AttributeSet as = e.getAttributes().copyAttributes(); + String asString; + + if(as != null) { + StringBuffer retBuffer = new StringBuffer("["); + Enumeration names = as.getAttributeNames(); + + while(names.hasMoreElements()) { + Object nextName = names.nextElement(); + + if(nextName != StyleConstants.ResolveAttribute) { + retBuffer.append(" "); + retBuffer.append(nextName); + retBuffer.append("="); + retBuffer.append(as.getAttribute(nextName)); + } + } + retBuffer.append(" ]"); + asString = retBuffer.toString(); + } + else + asString = "[ ]"; + + if(e.isLeaf()) + return "LEAF: " + e.getName() + " Attributes: " + asString; + return "Branch: " + e.getName() + " Attributes: " + + asString; + } + }; + tree.addTreeSelectionListener(this); + // become a listener on the document to update the tree. + document.addDocumentListener(this); + + // configure the panel and frame containing it. + setLayout(new BorderLayout()); + add(new JScrollPane(tree), BorderLayout.CENTER); + + // Add a label above tree to describe what is being shown + JLabel label = new JLabel("Elements that make up the current document", SwingConstants.CENTER); + + label.setFont(new Font("Dialog", Font.BOLD, 14)); + add(label, BorderLayout.NORTH); + + setPreferredSize(new Dimension(400, 400)); + } + + + // DocumentListener + + /** + * Gives notification that there was an insert into the document. The + * given range bounds the freshly inserted region. + * + * @param e the document event + */ + public void insertUpdate(DocumentEvent e) { + updateTree(e); + } + + /** + * Gives notification that a portion of the document has been + * removed. The range is given in terms of what the view last + * saw (that is, before updating sticky positions). + * + * @param e the document event + */ + public void removeUpdate(DocumentEvent e) { + updateTree(e); + } + + /** + * Gives notification that an attribute or set of attributes changed. + * + * @param e the document event + */ + public void changedUpdate(DocumentEvent e) { + updateTree(e); + } + + // TreeSelectionListener + + /** + * Called whenever the value of the selection changes. + * @param e the event that characterizes the change. + */ + public void valueChanged(TreeSelectionEvent e) { + JTree tree = getTree(); + + if(tree.getSelectionCount() == 1) { + TreePath selPath = tree.getSelectionPath(); + Element selElement = (Element)selPath.getLastPathComponent(); + + getEditor().select(selElement.getStartOffset(), + selElement.getEndOffset()); + } + } + + // Local methods + + /** + * @return tree showing elements. + */ + protected JTree getTree() { + return tree; + } + + /** + * @return JTextComponent showing elements for. + */ + protected JTextComponent getEditor() { + return editor; + } + + /** + * @return root element of editor. + */ + protected Element getRootElement() { + return getEditor().getDocument().getDefaultRootElement(); + } + + /** + * @return TreeModel implementation used to represent the elements. + */ + public DefaultTreeModel getTreeModel() { + return treeModel; + } + + /** + * Updates the tree based on the event type. This will invoke either + * updateTree with the root element, or handleChange. + */ + protected void updateTree(DocumentEvent event) { + updateTree(event, getRootElement()); + } + + /** + * Creates TreeModelEvents based on the DocumentEvent and messages + * the treemodel. This recursively invokes this method with children + * elements. + * @param event indicates what elements in the tree hierarchy have + * changed. + * @param element Current element to check for changes against. + */ + protected void updateTree(DocumentEvent event, Element element) { + DocumentEvent.ElementChange ec = event.getChange(element); + + if (ec != null) { + Element[] removed = ec.getChildrenRemoved(); + Element[] added = ec.getChildrenAdded(); + int startIndex = ec.getIndex(); + + // Check for removed. + if(removed != null && removed.length > 0) { + int[] indices = new int[removed.length]; + + for(int counter = 0; counter < removed.length; counter++) { + indices[counter] = startIndex + counter; + } + getTreeModel().nodesWereRemoved((TreeNode)element, indices, + removed); + } + // check for added + if(added != null && added.length > 0) { + int[] indices = new int[added.length]; + + for(int counter = 0; counter < added.length; counter++) { + indices[counter] = startIndex + counter; + } + getTreeModel().nodesWereInserted((TreeNode)element, indices); + } + } + else if(!element.isLeaf()) { + // If the event is a CHANGE, then need to forward to all + // elements in effected range. + // Otherwise, only forward to element at the offset of the + // event. + if(event.getType() == DocumentEvent.EventType.CHANGE) { + int startIndex = element.getElementIndex + (event.getOffset()); + int endIndex = Math.min(element.getElementCount() - 1, + element.getElementIndex + (event.getOffset() + event.getLength())); + + if(startIndex != -1 && endIndex != -1) { + for(int counter = startIndex; counter <= endIndex; + counter++) { + updateTree(event, element.getElement(counter)); + } + } + } + else { + // Element hasn't changed, find the child in the effected + // region and forward. + int childIndex = element.getElementIndex + (event.getOffset()); + + if(childIndex >= 0 && childIndex < element.getElementCount()) + updateTree(event, element.getElement(childIndex)); + } + } + else { + // Element is a leaf, assume it changed + getTreeModel().nodeChanged((TreeNode)element); + } + } +} + +} diff --git a/jhMaster/JavaHelp/test/i18n/GNUmakefile b/jhMaster/JavaHelp/test/i18n/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..1fce85a9bbfd70159f760ff48836a9c78436aa83 --- /dev/null +++ b/jhMaster/JavaHelp/test/i18n/GNUmakefile @@ -0,0 +1,45 @@ +# +# @(#)GNUmakefile 1.3 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +CLASSPATH = ../../build/jdk12/lib/jh.jar + +SRC= GetLocalizedResource.java + +TESTS=$(SRC:.java=.class) +RUNS=$(SRC:.java=.run) + +all: $(TESTS) + +run: $(TESTS) $(RUNS) + +%.class: %.java + export CLASSPATH; CLASSPATH=$(CLASSPATH) ;\ + javac $< + +%.run: %.java + export CLASSPATH; CLASSPATH=.:$(CLASSPATH) ;\ + java $* diff --git a/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java b/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java new file mode 100644 index 0000000000000000000000000000000000000000..1fc30c9aa7a6e001ff91d0d3cc7e8dc4b07e553a --- /dev/null +++ b/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java @@ -0,0 +1,71 @@ +/* + * @(#)GetLocalizedResource.java 1.3 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import javax.javahelp.*; +import java.net.URL; +import java.util.Locale; + +public class GetLocalizedResource { + private static ClassLoader loader = GetLocalizedResource.class.getClassLoader(); + + private static int count = 0; + + private static void error(String msg) { + count += 1; + System.err.println(msg); + } + + private static void exists(String front, String back, Locale locale) { + URL url; + url = HelpUtilities.getLocalizedResource(loader, + front, back, + locale); + if (url == null) { + error("Could not find resource.\n"+ + " front: "+front+"\n"+ + " back: "+back+"\n"+ + " locale: "+locale); + } else { + System.err.println("Found "+url+" for\n"+ + " front: "+front+"\n"+ + " back: "+back+"\n"+ + " locale: "+locale); + } + } + + public static void main(String args[]) { + exists("foo", ".hs", Locale.getDefault()); + exists("foo", ".hs", Locale.getDefault()); + exists("foo", ".hs", Locale.JAPANESE); + exists("foo", ".hs", Locale.CANADA_FRENCH); + exists("foo", ".hs", Locale.TAIWAN); + exists("foo", ".hs", Locale.JAPANESE); + if (count != 0) { + throw new Error("Errors found"); + } + } +} diff --git a/jhMaster/JavaHelp/test/misc/GNUmakefile b/jhMaster/JavaHelp/test/misc/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..653ddecb783f0407fef5464602e13ae06ff30f15 --- /dev/null +++ b/jhMaster/JavaHelp/test/misc/GNUmakefile @@ -0,0 +1,46 @@ +# +# @(#)GNUmakefile 1.2 06/10/30 +# +# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +CLASSPATH = ../../build/lib/jh.jar + +SRC= JHOptionTest.java + +TESTS=$(SRC:.java=.class) +RUNS=$(SRC:.java=.run) + +all: $(TESTS) + +run: $(TESTS) $(RUNS) + +%.class: %.java + export CLASSPATH; CLASSPATH=$(CLASSPATH) ;\ + javac $< + +%.run: %.java + export CLASSPATH; CLASSPATH=.:$(CLASSPATH) ;\ + java $* + diff --git a/jhMaster/JavaHelp/test/misc/JHOptionTest.java b/jhMaster/JavaHelp/test/misc/JHOptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..640d72d80397a8edbf1ad4e283bb768d41903fc0 --- /dev/null +++ b/jhMaster/JavaHelp/test/misc/JHOptionTest.java @@ -0,0 +1,306 @@ +/* + * @(#)JHOptionTest.java 1.4 06/10/30 + * + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * JHOptionTest.java + */ + +import javax.javahelp.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.border.*; +import javax.accessibility.*; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import java.util.*; +import java.io.*; +import java.applet.*; +import java.net.*; + +/** + * A demo that tests the JOptionPane optiontypes + * + */ +public class JHOptionTest extends JPanel +{ + // This + JHOptionTest opttest; + + // The Frame + public static JFrame frame; + + // The width and height of the frame + public static int WIDTH = 790; + public static int HEIGHT = 550; + public static int INITIAL_WIDTH = 400; + public static int INITIAL_HEIGHT = 200; + + public Font defaultFont = new Font("Dialog", Font.PLAIN, 12); + + public JHOptionTest() { + super(true); // double buffer + + opttest = this; + setName("Main JHOptionTest Panel"); + setFont(defaultFont); + setLayout(new BorderLayout()); + + // Add a MenuBar + add(createMenuBar(), BorderLayout.NORTH); + + } + + /*******************************************/ + /************ create components ************/ + /*******************************************/ + + /** + * MenuBar + */ + Dialog aboutBox; + JCheckBoxMenuItem cb; + JRadioButtonMenuItem rb; + + JMenuBar createMenuBar() { + // MenuBar + JMenuBar menuBar = new JMenuBar(); + menuBar.getAccessibleContext().setAccessibleName("Swing menus"); + + JMenuItem mi; + + // File Menu + JMenu file = (JMenu) menuBar.add(new JMenu("File")); + file.setMnemonic('F'); + mi = (JMenuItem) file.add(new JMenuItem("Exit")); + mi.setMnemonic('x'); + mi.getAccessibleContext().setAccessibleDescription("Exit the JHOptionTest application"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + } + ); + + createOptionsMenu(menuBar); + return menuBar; + } + + void createOptionsMenu(JMenuBar menuBar) { + JMenu optionMenu = (JMenu)menuBar.add(new JMenu("Dialogs")); + optionMenu.setMnemonic('D'); + JMenuItem item; + item = new JMenuItem("Message Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog(JHOptionTest.this, "Plain message"); + } + }); + optionMenu.add(item); + + item = new JMenuItem("Warning Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog(JHOptionTest.this, "Example Warning", + "Warning", JOptionPane.WARNING_MESSAGE); + } + }); + optionMenu.add(item); + + item = new JMenuItem("Confirmation Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int result; + result = JOptionPane.showConfirmDialog(JHOptionTest.this, "Is SWING cool?"); + if(result == JOptionPane.YES_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "All right!"); + else if(result == JOptionPane.NO_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it."); + } + }); + optionMenu.add(item); + + item = new JMenuItem("Input Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String result; + + result = JOptionPane.showInputDialog(JHOptionTest.this, "Please enter your name:"); + if(result != null) { + Object[] message = new Object[2]; + message[0] = "Thank you for using SWING "; + message[1] = result; + JOptionPane.showMessageDialog(JHOptionTest.this, message); + } + } + }); + optionMenu.add(item); + + item = new JMenuItem("Message Help Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int result; + result = HelpUtilities.showMessageDialog(JHOptionTest.this, + "Plain message", + "Message", + HelpUtilities.DEFAULT_HELP_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null); + if (result == HelpUtilities.HELP_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI"); + } + }); + optionMenu.add(item); + + item = new JMenuItem("Confirmaion YES_NO_HELP Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int result; + result = HelpUtilities.showConfirmDialog(JHOptionTest.this, + "Is SWING cool?", + "Swing Confirmation", + HelpUtilities.YES_NO_HELP_OPTION); + if(result == HelpUtilities.YES_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "All right!"); + else if(result == HelpUtilities.NO_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it."); + else if (result == HelpUtilities.HELP_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI"); + + } + }); + optionMenu.add(item); + + item = new JMenuItem("Confirmaion YES_NO_CANCEL_HELP Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int result; + result = HelpUtilities.showConfirmDialog(JHOptionTest.this, + "Is SWING cool?", + "Swing Confirmation", + HelpUtilities.YES_NO_CANCEL_HELP_OPTION); + if(result == HelpUtilities.YES_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "All right!"); + else if(result == HelpUtilities.NO_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it."); + else if (result == HelpUtilities.HELP_OPTION) + JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI"); + + } + }); + optionMenu.add(item); + + + /* later when working + item = new JMenuItem("Input Help Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Object result; + + result = HelpUtilities.showInputDialog(JHOptionTest.this, + "Please enter your name:", + "Input", + HelpUtilities.OK_CANCEL_HELP_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, null, null); + if (result instanceof Integer) { + JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI"); + } else { + if(result != null) { + Object[] message = new Object[2]; + message[0] = "Thank you for using SWING "; + message[1] = (String) result; + JOptionPane.showMessageDialog(JHOptionTest.this, message); + } + } + } + }); + optionMenu.add(item); + */ + + item = new JMenuItem("Component Dialog"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Object[] message = new Object[4]; + JComboBox cb = new JComboBox(); + cb.addItem("One"); + cb.addItem("Two"); + cb.addItem("Three"); + message[0] = "JOptionPane can contain any number of components, and any number options."; + message[1] = new JButton("a button"); + message[2] = new JTextField("a text field"); + message[3] = cb; + + + String[] options = { "Option 1", "Option 2", "Option 3", + "Option 4" }; + JOptionPane.showOptionDialog(JHOptionTest.this, message, "Example", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[1]); + } + }); + optionMenu.add(item); + } + + + public static void main(String[] args) { + + WindowListener l = new WindowAdapter() { + public void windowClosing(WindowEvent e) {System.exit(0);} + }; + + frame = new JFrame("JHOptionTest"); + frame.addWindowListener(l); + + JOptionPane.setRootFrame(frame); + + // show the frame + frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setLocation(screenSize.width/2 - INITIAL_WIDTH/2, + screenSize.height/2 - INITIAL_HEIGHT/2); + frame.show(); + + frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + JHOptionTest sw = new JHOptionTest(); + frame.getContentPane().removeAll(); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(sw, BorderLayout.CENTER); + frame.setLocation(screenSize.width/2 - WIDTH/2, + screenSize.height/2 - HEIGHT/2); + + frame.setSize(WIDTH, HEIGHT); + frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + + frame.validate(); + frame.repaint(); + } + + +} +