// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

[[_ugr.tools.uimafit.gettingstarted]]
= Getting Started

This quick start tutorial demonstrates how to use uimaFIT to define and set a configuration parameter in an analysis engine, run it, and generate a descriptor file for it.
The complete code for this example can be found in the _uimaFIT-examples_ module.

== Adding uimaFIT to your project

The following instructions describe how to add uimaFIT to your project's classpath.

=== Maven users

If you use Maven, then uimaFIT can be added to your project by simply adding uimaFIT as a project dependency by adding the following snippet of XML to your pom.xml file:

[source,xml,subs="+attributes"]
----
<dependency>
  <groupId>org.apache.uima</groupId>
  <artifactId>uimafit-core</artifactId>
  <version>{revnumber}</version>
</dependency>
----

uimaFIT distributions are hosted by Maven Central and so no repository needs to be added to your pom.xml file. 

=== Non-Maven users

If you do not build with Maven, then download uimaFIT from the http://uima.apache.org/downloads.cgi[Apache UIMA downloads page].
The file name should be uimafit--bin.zip.
Download and unpack this file.
The contents of the resulting upacked directory will contain a directory called [path]_lib_.
Add all of the files in this directory to your classpath.

== A simple analysis engine implementation

Here is the complete analysis engine implementation for this example.

[source,java]
----
public class GetStartedQuickAE 
    extends org.apache.uima.fit.component.JCasAnnotator_ImplBase {
  
  public static final String PARAM_STRING = "stringParam";
  @ConfigurationParameter(name = PARAM_STRING)
  private String stringParam;
  
  @Override
  public void process(JCas jCas) throws AnalysisEngineProcessException {
    System.out.println("Hello world!  Say 'hi' to " + stringParam);
  }
}
----

The first thing to note is that the member variable [var]``stringParam`` is annotated with [class]``@ConfigurationParameter`` which tells uimaFIT that this is an analysis engine configuration parameter.
It is best practice to create a public constant for the parameter name, here `PARAM_STRING` The second thing to note is that we extend uimaFIT's version of the [class]``JCasAnnotator_ImplBase``.
The initialize method of this super class calls:

[source,java]
----
ConfigurationParameterInitializer.initializeConfigurationParameters(
  Object, UimaContext)
----

which populates the configuration parameters with the appropriate contents of the [interface]``UimaContext``.
If you do not want to extend uimaFIT's [class]``JCasAnnotator_ImplBase``, then you can call this method directly in the [method]``initialize`` method of your analysis engine or any class that implements [interface]``Initializable``.
You can call this method for an instance of any class that has configuration parameters.

== Running the analysis engine

The following lines of code demonstrate how to instantiate and run the analysis engine from a main method:

[source,java]
----
JCas jCas = JCasFactory.createJCas();
  
AnalysisEngine analysisEngine = AnalysisEngineFactory.createEngine(
  GetStartedQuickAE.class,
  GetStartedQuickAE.PARAM_STRING, "uimaFIT");
  
analysisEngine.process(jCas);
----

In a more involved example, we would probably instantiate a collection reader and run this analysis engine over a collection of documents.
Here, it suffices to simply create a [interface]``JCas``.
Line 3 instantiates the analysis engine using [class]``AnalysisEngineFactory`` and sets the string parameter named [parameter]``stringParam`` to the value ``uimaFIT``.
Running this simple program sends the following output to the console: 

[source]
----
Hello world!  Say 'hi' to uimaFIT
----

Normally you would be using a type system with your analysis components.
When using uimaFIT, it is easiest to keep your type system descriptors in your source folders and make them known to uimaFIT.
To do so, create a file [path]_META-INF/org.apache.uima.fit/types.txt_ in a source folder and add references to all your type descriptors to the file, one per line.
You can also use wildcards.
For example: 

[source]
----
classpath*:org/apache/uima/fit/examples/type/Token.xml
classpath*:org/apache/uima/fit/examples/type/Sentence.xml
classpath*:org/apache/uima/fit/examples/tutorial/type/*.xml
----

== Generate a descriptor file

The following lines of code demonstrate how a descriptor file can be generated using the class definition:

[source,java]
----
AnalysisEngine analysisEngine = AnalysisEngineFactory.createEngine(
  GetStartedQuickAE.class,
  GetStartedQuickAE.PARAM_STRING, "uimaFIT");

analysisEngineDescription.toXML(
  new FileOutputStream("GetStartedQuickAE.xml"));
----

If you open the resulting descriptor file you will see that the configuration parameter [parameter]``stringParam`` is defined with the value set to ``uimaFIT``.
We could now instantiate an analysis engine using this descriptor file with a line of code like this:

[source,java]
----
AnalysisEngineFactory.createEngine("GetStartedQuickAE");
----

But, of course, we really wouldn't want to do that now that we can instantiate analysis engines using the class definition as was done above!

This chapter, of course, did not demonstrate every feature of uimaFIT which provides support for annotating external resources, creating aggregate engines, running pipelines, testing components, among others.