diff options
author | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-02-01 19:07:25 +0400 |
---|---|---|
committer | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-02-01 19:07:25 +0400 |
commit | c155a98dd4c7ee990cf1fecd3b8eb0c99e70a699 (patch) | |
tree | ab375d8730b52aaac52b89c135584a379490dc48 | |
parent | e7ae25e69208c7428f237b138906b0b139e177f9 (diff) |
Added Java code.
76 files changed, 4903 insertions, 0 deletions
@@ -4,3 +4,11 @@ *.jar *.war *.ear + +# Maven and Eclipse directories +/target +/.settings + +# Eclipse files +.classpath +.project @@ -5,4 +5,6 @@ This is a reference implementation of OMTC, an open API Standard for Machine Tra It is a Java implementation that is Java v1.5 compliant. +Use Maven v3.x to build. + Documentation coming soon. @@ -0,0 +1,81 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.capitati.omtc</groupId> + <artifactId>omtc-core</artifactId> + <version>1.0</version> + <packaging>jar</packaging> + + <name>omtc</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + <version>20040616</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.1</version> + <scope>compile</scope> + </dependency> + + <!-- Guava, formerly Google Collections --> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>13.0.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.10</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.jmock</groupId> + <artifactId>jmock-junit4</artifactId> + <version>2.5.1</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.12</version> + <executions> + <execution> + <id>default-test</id> + <phase>test</phase> + <goals> + <goal>test</goal> + </goals> + <configuration> + <includes> + <include>**/*Tests.class</include> + <include>**/*Test.class</include> + </includes> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> + diff --git a/src/main/java/com/capitati/omtc/core/commons/IDisposable.java b/src/main/java/com/capitati/omtc/core/commons/IDisposable.java new file mode 100644 index 0000000..e4bf66e --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/commons/IDisposable.java @@ -0,0 +1,23 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.commons; + +public interface IDisposable { + void dispose(); +} diff --git a/src/main/java/com/capitati/omtc/core/commons/IStoppable.java b/src/main/java/com/capitati/omtc/core/commons/IStoppable.java new file mode 100644 index 0000000..3e1b1f1 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/commons/IStoppable.java @@ -0,0 +1,23 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.commons; + +public interface IStoppable { + void stop(); +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IComposableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IComposableEngine.java new file mode 100644 index 0000000..a4cba1b --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IComposableEngine.java @@ -0,0 +1,61 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import com.capitati.omtc.core.integration.data.IDataExchangeFormatSpecification; +import com.capitati.omtc.core.scheduling.CompositionTicket; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin for composing two engines. Implementers are to mixin this + * interface with their {@link com.capitati.omtc.core.engine.IEngine} + * implementation. + * + * @author ian + * + * @param <V> - the priority's type. + */ +public interface IComposableEngine<V> extends ITicketableEngine<V> { + /** + * Compose two engines. Suppose two engines E<sub>1</sub> and E<sub>2</sub>, + * this composition shall produce an engine that is + * E<sub>resultant</sub> = E<sub>2</sub>(E<sub>1</sub>(s)). + * + * @param session - the invoking session. + * @param engine - the other engine to compose, i.e., E<sub>2</sub>. + * @param exchangeFormat - the exchange data format that the engines will use + * to communicate. + * @param resultantEngine - the engine that the composition operation + * shall create if successful. + * @param priority - the priority of this task. + * @param engineObserver - the observer that will be notified on completion + * of the task. + * @return A {@link com.capitati.omtc.core.scheduling.CompositionTicket} object. + * @throws Exception On an error. + */ + CompositionTicket<V> compose( + ISession session, + IEngine engine, + IDataExchangeFormatSpecification exchangeFormat, + IEngine resultantEngine, + IPriority<V> priority, + ITicketObserver<CompositionTicket<V>, V> engineObserver) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IEngine.java b/src/main/java/com/capitati/omtc/core/engine/IEngine.java new file mode 100644 index 0000000..485cb52 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IEngine.java @@ -0,0 +1,42 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import com.capitati.omtc.core.resources.IDerivedResource; + +/** + * A translation engine. + * + * @author ian + */ +public interface IEngine extends IDerivedResource { + /** + * Retrieve the assigned name for the engine. + * + * @return The engine's name. + */ + String getName(); + + /** + * Retrieve some descriptive free text about the engine. + * + * @return The engine's descriptive text. + */ + String getDescription(); +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IEvaluatableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IEvaluatableEngine.java new file mode 100644 index 0000000..d1f7452 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IEvaluatableEngine.java @@ -0,0 +1,73 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.resources.IPrimaryResource; +import com.capitati.omtc.core.scheduling.EvaluationTicket; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin to provide support for evaluating an engine. Implementers are to + * mixin this interface with their implementation of + * {@link com.capitati.omtc.core.engine.IEngine}. + * + * @author ian + * + * @param <V> - the task's priority type. + */ +public interface IEvaluatableEngine<V> extends ITicketableEngine<V> { + /** + * Evaluate an engine. On completion of this the evaluation task the + * implementation should store the scores calculated so that + * {@link com.capitati.omtc.core.engine.IEvaluatableEngine#getScores} can + * return appropriate data. + * + * @param session - the invoking session. + * @param evaluationResources - the primary resources to use for evaluation. + * @param priority - the priority of the task. + * @param engineObserver - the observer to listen for evaluation completion. + * @return An evaluation ticket. + * @throws Exception On an error. + */ + EvaluationTicket<V> evaluate( + ISession session, + Set<IPrimaryResource> evaluationResources, + IPriority<V> priority, + ITicketObserver<EvaluationTicket<V>, V> engineObserver) throws Exception; + + /** + * Retrieve any scores associated with an engine. The method + * {@link com.capitati.omtc.core.engine.IEvaluatableEngine#evaluate} + * should provided information, internally, to enable this method to + * return the scores calculated during a call, and subsequent calls, to + * {@link com.capitati.omtc.core.engine.IEvaluatableEngine#evaluate}. + * Without running an evaluation, it is implementation defined whether,this + * method returns an empty set. + * + * @param session - the invoking session. + * @return A {@link java.util.Set} of + * {@link com.capitati.omtc.core.engine.IScore} objects the represent the + * scores from an evaluation. + */ + Set<IScore> getScores(ISession session) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IParameterisableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IParameterisableEngine.java new file mode 100644 index 0000000..a412a74 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IParameterisableEngine.java @@ -0,0 +1,54 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Map; + +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin to provide support for a parameterisable engine. Parameters are keyed + * with a type K whose type shall be P. Methods are to be implemented that + * fetch engine parameters and allow updating of parameters. + * + * @author ian + * + * @param <K> - the type of the parameter key. + * @param <P> - the type of the parameter value. + */ +public interface IParameterisableEngine<K, P> { + /** + * Return the current parameters for an engine. + * + * @param session - the invoking session. + * + * @return A map of parameters. + * @throws Exception On an error. + */ + Map<K, P> getParamters(ISession session) throws Exception; + + /** + * Update the current parameters with the parameters provided. + * + * @param session - the invoking session. + * @param newParameters - the parameters used to update the current ones. + * @throws Exception On an error. + */ + void updateParameters(ISession session, Map<K, P> newParameters) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IQueryableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IQueryableEngine.java new file mode 100644 index 0000000..f2ec9ab --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IQueryableEngine.java @@ -0,0 +1,51 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.QueryTicket; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin to add support to querying an engine. A single source sentence + * is sent to an engine which can be used, amongst other things, for testing. + * Implementers should mixin this interface with their + * {@link com.capitati.omtc.core.engine.IEngine} implementations. + * + * @author ian + * + * @param <V> - the type of the task's priority value. + */ +public interface IQueryableEngine<V> extends ITicketableEngine<V> { + /** + * Send a source sentence to an engine. + * + * @param session - the invoking session. + * @param sourceSentence - the source sentence to send to the engine + * @param engineObserver - an observer to be notified of completion. + * @return A query ticket object. + * @throws Exception On an error. + */ + QueryTicket<V> query( + ISession session, + String sourceSentence, + IPriority<V> priority, + ITicketObserver<QueryTicket<V>, V> ticketObserver) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IRetrainableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IRetrainableEngine.java new file mode 100644 index 0000000..7202cf9 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IRetrainableEngine.java @@ -0,0 +1,55 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.resources.IPrimaryResource; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.TrainingTicket; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin to provide retraining capability if the engine implementation + * can support it. + * + * @author ian + * + * @param <V> - the type of the priority value. + */ +public interface IRetrainableEngine<V> extends ITicketableEngine<V> { + /** + * Retain an engine using a set of primary resources. + * + * @param session - the invoking session. + * @param retrainingResources - a {@link java.util.Set} of + * {@link com.capitati.omtc.core.resources.IPrimaryResource} objects that + * shall be used to retain the engine. + * @param priority - the priority of the retraining task. + * @param engineObserver - the observer listening for the retrain to complete. + * @return A training ticket. + * @throws Exception On an error. + */ + TrainingTicket<V> retrain( + ISession session, + Set<IPrimaryResource> retrainingResources, + IPriority<V> priority, + ITicketObserver<TrainingTicket<V>, V> engineObserver) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IScore.java b/src/main/java/com/capitati/omtc/core/engine/IScore.java new file mode 100644 index 0000000..e9a6868 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IScore.java @@ -0,0 +1,52 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.resources.IPrimaryResource; + +/** + * A representation of a single evaluation score. + * + * @author ian + */ +public interface IScore { + /** + * Retrieve the score scheme. Or, which algorithm was used to generate the + * score. + * + * @return A scoring scheme description object. + */ + IScoreScheme getScheme(); + + /** + * The evaluated score. + * + * @return The score for the scheme used. + */ + double getScore(); + + /** + * Retrieve the resources that generated the score. + * + * @return A {@link java.util.Set} of primary resource objects. + */ + Set<IPrimaryResource> getResources(); +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IScoreScheme.java b/src/main/java/com/capitati/omtc/core/engine/IScoreScheme.java new file mode 100644 index 0000000..5f6ec6a --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IScoreScheme.java @@ -0,0 +1,40 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +/** + * The name and descriptive text for a scoring scheme. + * + * @author ian + */ +public interface IScoreScheme { + /** + * Retrieve the name of a scoring scheme. + * + * @return The name of the scheme. + */ + String getName(); + + /** + * Retrieve the descriptive text for a scoring scheme. + * + * @return The descriptive free text. + */ + String getDescription(); +} diff --git a/src/main/java/com/capitati/omtc/core/engine/ITestableEngine.java b/src/main/java/com/capitati/omtc/core/engine/ITestableEngine.java new file mode 100644 index 0000000..7d488e8 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/ITestableEngine.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.resources.IPrimaryResource; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.TestingTicket; +import com.capitati.omtc.core.session.ISession; + +/** + * + * @author ian + * + * @param <P> + */ +public interface ITestableEngine<V> extends ITicketableEngine<V> { + TestingTicket<V> test( + ISession session, + Set<IPrimaryResource> testingResources, + IPriority<V> priority, + ITicketObserver<TestingTicket<V>, V> engineObserver) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/ITicketableEngine.java b/src/main/java/com/capitati/omtc/core/engine/ITicketableEngine.java new file mode 100644 index 0000000..1001a2b --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/ITicketableEngine.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.scheduling.EngineTicket; +import com.capitati.omtc.core.session.ISession; +import com.google.common.base.Predicate; + +/** + * A mixin that provides support for engines that, on submiting tasks, return + * task tickets. This inferface should be used with the implementer's + * {@link com.capitati.omtc.core.engine.IEngine} concrete classes to + * provide a mechanism to return <em>running</em> tickets. It is the + * responsibility of the concrete class to manage the appropriate collection + * of dispensed tickets. + * + * @author ian + * + * @param <V> - the type of the priority's value. + */ +public interface ITicketableEngine<V> { + Set<EngineTicket<V>> retrieveTickets( + ISession session, Predicate<EngineTicket<V>> filter) + throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/ITrainableEngine.java b/src/main/java/com/capitati/omtc/core/engine/ITrainableEngine.java new file mode 100644 index 0000000..199ae41 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/ITrainableEngine.java @@ -0,0 +1,55 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import java.util.Set; + +import com.capitati.omtc.core.resources.IPrimaryResource; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.TrainingTicket; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin to offer support for training engines. Implementers of the + * {@link com.capitati.omtc.core.engine.IEngine} interface should mixin this + * interface to their concrete classes. + * + * @author ian + * + * @param <V> - the type of the priority's value. + */ +public interface ITrainableEngine<V> extends ITicketableEngine<V> { + /** + * Train an engine. + * + * @param session - the invoking session. + * @param trainingResources - a {@link java.util.Set} of primary resources + * used to train the engine. + * @param priority - the priority of the train task. + * @param engineObserver - the observer that listens for task completion. + * @return A training ticket. + * @throws Exception On an error. + */ + TrainingTicket<V> train( + ISession session, + Set<IPrimaryResource> trainingResources, + IPriority<V> priority, + ITicketObserver<TrainingTicket<V>, V> engineObserver) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/engine/IUpdatableEngine.java b/src/main/java/com/capitati/omtc/core/engine/IUpdatableEngine.java new file mode 100644 index 0000000..dd111ee --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/engine/IUpdatableEngine.java @@ -0,0 +1,63 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.engine; + +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.UpdateTicket; +import com.capitati.omtc.core.session.ISession; + +/** + * A mixin for engines that support updating. The update operation is ticketed + * since the operation be computationally expensive. The update operation + * shall typically mutate the engine. It is recommended that the engine, + * during an update operation, is mutually excluded. + * + * @author ian + * + * @param <V> - the type of the priority's value. + */ +public interface IUpdatableEngine<V, P> extends ITicketableEngine<V> { + /** + * Update an engine's parameters using key-value pairs specified in a + * {@link java.util.Map} object. + * + * @param session - the invoking session. + * @param parameters - the update parameters for the engine. + * @param priority - the task's priority. + * @param engineObserver - the observer listening for the starting and + * completion of the task. + * @return An updating ticket. + * @throws Exception On an error. + */ + UpdateTicket<V> updateParameters( + ISession session, + P parameters, + IPriority<V> priority, + ITicketObserver<UpdateTicket<V>, V> engineObserver) throws Exception; + + /** + * Retrieve the current parameters of the engine. + * + * @param - the invoking session. + * @return An object that holds the engine's current parameters. + * @throws Exception On an error. + */ + P getParameters(ISession session) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/integration/data/IDataExchangeFormatSpecification.java b/src/main/java/com/capitati/omtc/core/integration/data/IDataExchangeFormatSpecification.java new file mode 100644 index 0000000..9d8c43a --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/integration/data/IDataExchangeFormatSpecification.java @@ -0,0 +1,60 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.integration.data; + +import com.capitati.omtc.core.negotiation.IVersion; + +/** + * A description of a data exchange format, specification or standard. + * Implementers of this interface shall decide on a unique identifier for + * the data exchange format. + * + * @author ian + */ +public interface IDataExchangeFormatSpecification +extends Comparable<IDataExchangeFormatSpecification> { + /** + * The short name, probably and acronym, for the format, specification, or + * standard. + * + * @return The short name of the data exchange format. + */ + String getShortName(); + + /** + * The long name for the format, specification standard. + * + * @return The long name of the data exchange format. + */ + String getLongName(); + + /** + * The lowest version of the data exchange format at which the client supports. + * + * @return The lowest supported version. + */ + IVersion getLowestVersion(); + + /** + * The highest version of the data exchange format the client supports. + * + * @return The highest supported version. + */ + IVersion getHighestVersion(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/Capability.java b/src/main/java/com/capitati/omtc/core/negotiation/Capability.java new file mode 100644 index 0000000..6d4aeb9 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/Capability.java @@ -0,0 +1,48 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +public enum Capability { + INVALID(CapabilityGroup.INVALID), + + API_VERSION(CapabilityGroup.API), + + RES_FILE_TMX(CapabilityGroup.RESOURCE), + RES_FILE_TBX(CapabilityGroup.RESOURCE), + RES_FILE_UTX(CapabilityGroup.RESOURCE), + RES_FILE_SRX(CapabilityGroup.RESOURCE), + RES_FILE_ITS(CapabilityGroup.RESOURCE), + RES_FILE_XLIFF(CapabilityGroup.RESOURCE), + RES_FILE_TTX(CapabilityGroup.RESOURCE), + + FET_RES_UPLOAD(CapabilityGroup.FEATURE), + FET_RES_DOWNLOAD(CapabilityGroup.FEATURE), + + PRE_REQ_PAYMENT(CapabilityGroup.PREREQUISITE); + + private CapabilityGroup group; + + private Capability(final CapabilityGroup theGroup) { + group = theGroup; + } + + public CapabilityGroup getGroup() { + return group; + } +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/CapabilityGroup.java b/src/main/java/com/capitati/omtc/core/negotiation/CapabilityGroup.java new file mode 100644 index 0000000..22c9eb1 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/CapabilityGroup.java @@ -0,0 +1,37 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +public enum CapabilityGroup { + INVALID("INVALID"), + API("API"), + RESOURCE("Resource"), + FEATURE("Feature"), + PREREQUISITE("Prerequisite"); + + final private String name; + + private CapabilityGroup(final String theName) { + name = theName; + } + + public String toString() { + return name; + } +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IAPICapability.java b/src/main/java/com/capitati/omtc/core/negotiation/IAPICapability.java new file mode 100644 index 0000000..0c9a41b --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IAPICapability.java @@ -0,0 +1,34 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * The semantic version capability of the API. + * + * @author ian + */ +public interface IAPICapability extends ICapability { + /** + * Retrieve the semantic version of the API. + * + * @return An instance of {@link com.capitati.omtc.core.negotiation.ISemanticVersion} + * which represents the semantic version of the API. + */ + ISemanticVersion getVersion(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/ICapability.java b/src/main/java/com/capitati/omtc/core/negotiation/ICapability.java new file mode 100644 index 0000000..0f1c6ab --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/ICapability.java @@ -0,0 +1,34 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * The base capability interface. Specifies only the unique aspect of a + * capability. + * + * @author ian + */ +public interface ICapability { + /** + * Get the unique capability + * + * @return the capability's unique name + */ + Capability getName(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityRequest.java b/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityRequest.java new file mode 100644 index 0000000..2e834be --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityRequest.java @@ -0,0 +1,48 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.Set; + + +/** + * A description of the client's capabilities. + * + * @author ian + */ +public interface IClientCapabilityRequest { + /** + * Implementers shall return the client's supported API version capability. + * + * @return A {@link com.capitati.omtc.core.negotiation.IAPICapability} + * objects which represent the client's supported API version. + */ + IAPICapability getVersionCapability(); + + /** + * Implementers shall return a set of the + * {@link com.capitati.omtc.core.negotiation.IResourceCapability} objects + * which shall represent the resource kinds which it expects the service + * to support. + * + * @return A set of {@link com.capitati.omtc.core.negotiation.IResourceCapability} + * objects. + */ + Set<IResourceCapability> getResourceCapabilities(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityResponse.java b/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityResponse.java new file mode 100644 index 0000000..0bb74c5 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IClientCapabilityResponse.java @@ -0,0 +1,63 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.Set; + +/** + * The response to a client negotiation. + * + * @author ian + */ +public interface IClientCapabilityResponse { + /** + * Does the service support the client's API revision. If this method returns + * false then the service should send the response back to the client and + * disconnect the session. + * + * @return True if the client's API is supported. Otherwise, returns false. + */ + boolean isClientAPISupported(); + + /** + * The collection of data exchange formats that the service does not support + * but the client does. If the set of service supported data exchange formats + * is <em>S</em>, and the client supported data exchange formats is <em>C</em> + * then the returned collection shall be <em>C - S</em>. This is based, firstly, + * on the capability, and then the resource capability's version range. + * <p> + * When the client receives this set it needs to make a decision whether to + * continue with its session. For example, if all of the client's supported + * exchange formats are returned here then it is pointless continuing with + * the session. The service does not "talk" any of client's supported formats. + * + * @return A set of + * {@link com.capitati.omtc.core.negotiation.IResourceCapability} + * objects that the client supports but the service does not. + */ + Set<IResourceCapability> getUnsupportedResourceCapabilities(); + + /** + * The supported feature capabilities of the service. + * + * @return A set of {@link com.capitati.omtc.core.negotiation.IFeatureCapability} + * objects. + */ + Set<IFeatureCapability> getFeatureCapabilities(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IFeatureCapability.java b/src/main/java/com/capitati/omtc/core/negotiation/IFeatureCapability.java new file mode 100644 index 0000000..25f3916 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IFeatureCapability.java @@ -0,0 +1,36 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.Set; + +/** + * Implementations of this interface specify a feature capability. + * + * @author ian + */ +public interface IFeatureCapability extends ICapability { + /** + * Implementers shall return the set of prerequisites for this feature. + * + * @return A set of {@link com.capitati.omtc.core.negotiation.IPrerequisiteCapability} + * objects. + */ + Set<IPrerequisiteCapability> getPrerequisiteCapabilities(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/INegotiator.java b/src/main/java/com/capitati/omtc/core/negotiation/INegotiator.java new file mode 100644 index 0000000..6bd42d1 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/INegotiator.java @@ -0,0 +1,38 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * The negotiator that determines whether a client's capabilities are + * matched with the server's. + * + * @author ian + * + */ +public interface INegotiator { + /** + * Negotiate a client's capabilities. This method accepts a negotiation request + * and constructs a response. + * + * @param negotiationRequest - the client's negotiation request. + * @return A {@link com.capitati.omtc.core.negotiation.IClientCapabilityResponse} + * object that holds the server's response to the client request. + */ + IClientCapabilityResponse negotiate(IClientCapabilityRequest negotiationRequest); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IPrerequisiteCapability.java b/src/main/java/com/capitati/omtc/core/negotiation/IPrerequisiteCapability.java new file mode 100644 index 0000000..b0903b6 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IPrerequisiteCapability.java @@ -0,0 +1,28 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * Implementations of this interface specify a prerequisite capability. + * + * @author ian + */ +public interface IPrerequisiteCapability extends ICapability { + +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IResourceCapability.java b/src/main/java/com/capitati/omtc/core/negotiation/IResourceCapability.java new file mode 100644 index 0000000..b1f1714 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IResourceCapability.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * Implementations of this interface shall specify the version range + * of a specific resource kind, e.g., XLIFF. + * + * @author ian + */ +public interface IResourceCapability extends ICapability { + /** + * The lowest version of the resource that is supported. + * + * @return A string that represents the resource kind's lower supported + * version. + */ + String getLowerVersion(); + + /** + * The highest version of the resource that is supported. + * + * @return A string that represents the resource kind's highest supported + * version. + */ + String getHigherVersion(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/ISemanticVersion.java b/src/main/java/com/capitati/omtc/core/negotiation/ISemanticVersion.java new file mode 100644 index 0000000..9147aec --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/ISemanticVersion.java @@ -0,0 +1,62 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * Semantic versioning. + * + * @author ian + * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a> + */ +public interface ISemanticVersion extends Comparable<ISemanticVersion> { + /** + * Returns the major version number. + * + * @return The major version number. + */ + int getMajor(); + + /** + * Returns the minor version number. + * + * @return The minor version number. + */ + int getMinor(); + + /** + * Return the patch number of the semantic version. + * + * @return The patch version number. + */ + int getPatch(); + + /** + * Returns the parsed pre-release information from the version. + * + * @return A string array containing the dot delimited pre-release components. + */ + String[] getPreRelease(); + + /** + * Returns the parsed build information from the version. + * + * @return A string array containing the dot delimited build components. + */ + String[] getBuild(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IServiceResourceCapability.java b/src/main/java/com/capitati/omtc/core/negotiation/IServiceResourceCapability.java new file mode 100644 index 0000000..1796878 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IServiceResourceCapability.java @@ -0,0 +1,35 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * Extends the {@link com.capitati.omtc.core.negotiation.IResourceCapability} + * to allow resource capability versions to be compared. + * + * @author ian + */ +public interface IServiceResourceCapability extends IResourceCapability { + /** + * Comparator method to compare resource kind versions. + * + * @param otherResourceCapability + * @return + */ + int compareVersion(IResourceCapability otherResourceCapability); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/IVersion.java b/src/main/java/com/capitati/omtc/core/negotiation/IVersion.java new file mode 100644 index 0000000..7af1de5 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/IVersion.java @@ -0,0 +1,40 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +/** + * A base version interface. Major and minor versions. + * + * @author ian + */ +public interface IVersion extends Comparable<IVersion> { + /** + * Returns the major version number. + * + * @return The major version number. + */ + int getMajor(); + + /** + * Returns the minor version number. + * + * @return The minor version number. + */ + int getMinor(); +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/Negotiator.java b/src/main/java/com/capitati/omtc/core/negotiation/Negotiator.java new file mode 100644 index 0000000..9086fb7 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/Negotiator.java @@ -0,0 +1,141 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.tuple.ImmutablePair; + +public class Negotiator implements INegotiator { + private final ISemanticVersion apiVersion; + private final Map<Capability, List<IServiceResourceCapability>> supportedResources; + private final Set<IFeatureCapability> featureCapabilities; + + public Negotiator( + final String theApiVersion, + final Collection<IServiceResourceCapability> theResourceCapabilities, + final Collection<IFeatureCapability> theFeatureCapabilities) + throws SemanticVersionParseException { + super(); + apiVersion = SemanticVersion.parseVersion(theApiVersion); + + featureCapabilities = (theFeatureCapabilities == null) ? + new HashSet<IFeatureCapability>() : + new HashSet<IFeatureCapability>(theFeatureCapabilities); + + /* + * Group resource capabilities by their unique identifier for possibly + * different version of the resource revision. + */ + supportedResources = new HashMap<Capability, List<IServiceResourceCapability>>(); + if(theResourceCapabilities != null) { + for(IServiceResourceCapability resourceCap : theResourceCapabilities) { + final Capability capabilityName = resourceCap.getName(); + + if(supportedResources.containsKey(capabilityName) == true) { + final List<IServiceResourceCapability> yeah = + supportedResources.get(capabilityName); + yeah.add(resourceCap); + } else { + final List<IServiceResourceCapability> yeah = + new ArrayList<IServiceResourceCapability>(); + yeah.add(resourceCap); + supportedResources.put(capabilityName, yeah); + } + } + } + } + + public final IClientCapabilityResponse negotiate( + final IClientCapabilityRequest negotiationRequest) { + final ISemanticVersion clientAPIVersion = + negotiationRequest.getVersionCapability().getVersion(); + final boolean isClientAPISupported = isClientAPISupported(clientAPIVersion); + final Set<IResourceCapability> unsupportedResources = + new HashSet<IResourceCapability>(); + + /* + * Work out which of the clients resource kinds are supported by the + * service. + */ + for(IResourceCapability resourceCap : + negotiationRequest.getResourceCapabilities()) { + final Capability capabilityName = resourceCap.getName(); + + /* + * First check if the resource kind is supported. + */ + if(supportedResources.containsKey(capabilityName) == true) { + boolean supported = false; + + for(IServiceResourceCapability svcResourceCap : + supportedResources.get(capabilityName)) { + if(svcResourceCap.compareVersion(resourceCap) == 0) { + supported = true; + } + } + + if(supported == false) { + unsupportedResources.add(resourceCap); + } + } else { + unsupportedResources.add(resourceCap); + } + } + + return new IClientCapabilityResponse() { + public boolean isClientAPISupported() { + return isClientAPISupported; + } + public Set<IResourceCapability> getUnsupportedResourceCapabilities() { + return unsupportedResources; + } + public Set<IFeatureCapability> getFeatureCapabilities() { + return featureCapabilities; + } + }; + } + + private boolean isClientAPISupported(ISemanticVersion version) { + final ImmutablePair<Integer, SemanticVersionComponent> versionComp = + SemanticVersionComparator.compare(apiVersion, version); + boolean isApiSupported = false; + + switch(versionComp.getRight()) { + case PRE_RELEASE_AND_BUILD_VERSION: + case PATCH_VERSION: + case MINOR_VERSION: + isApiSupported = true; + break; + + case MAJOR_VERSION: + case INVALID: + isApiSupported = (versionComp.getLeft() == 0) ? true : false; + break; + } + + return isApiSupported; + } +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersion.java b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersion.java new file mode 100644 index 0000000..998f604 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersion.java @@ -0,0 +1,196 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +/** + * Implementation of semantic versioning. + * + * @author ian + * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a> + */ +public class SemanticVersion implements ISemanticVersion { + public static final String IDENTIFIER_SEPARATOR = "."; + private static final String PRE_RELEASE_SEPARATOR = "-"; + private static final String BUILD_SEPARATOR = "+"; + private static final String GROUP_NAME_MAJOR = "major"; + private static final String GROUP_NAME_MINOR = "minor"; + private static final String GROUP_NAME_PATCH = "patch"; + private static final String GROUP_NAME_PRERELEASE = "prerelease"; + private static final String GROUP_NAME_BUILD = "build"; + private static final Pattern versionPattern = + Pattern.compile( + "(?<" + GROUP_NAME_MAJOR + ">\\d+)\\." + + "(?<" + GROUP_NAME_MINOR + ">\\d+)\\." + + "(?<" + GROUP_NAME_PATCH + ">\\d+)" + + "(([" + PRE_RELEASE_SEPARATOR + "](?<" + GROUP_NAME_PRERELEASE + ">[0-9A-Z-.]+))?" + + "([" + BUILD_SEPARATOR + "](?<" + GROUP_NAME_BUILD + ">[0-9A-Z-.]+))?)?", + Pattern.CASE_INSENSITIVE); + + public static ISemanticVersion parseVersion(final String version) + throws SemanticVersionParseException { + final Matcher matcher = versionPattern.matcher(version); + + if(matcher.matches() == false) { + throw new SemanticVersionParseException(version); + } + + final int theMajor = Integer.parseInt(matcher.group(GROUP_NAME_MAJOR)); + final int theMinor = Integer.parseInt(matcher.group(GROUP_NAME_MINOR)); + final int thePatch = Integer.parseInt(matcher.group(GROUP_NAME_PATCH)); + final String thePreRelease = matcher.group(GROUP_NAME_PRERELEASE); + final String theBuild = matcher.group(GROUP_NAME_BUILD); + + return new SemanticVersion( + theMajor, + theMinor, + thePatch, + thePreRelease, + theBuild); + } + + private final int major; + private final int minor; + private final int patch; + private final String[] preRelease; + private final String[] build; + + public SemanticVersion( + final int theMajorVersion, + final int theMinorVersion, + final int thePatchVersion) { + super(); + if((theMajorVersion < 0) || + (theMinorVersion < 0) || + (thePatchVersion <0)) { + throw new IllegalArgumentException( + "Major, minor, or patch version cannot be negative."); + } + major = theMajorVersion; + minor = theMinorVersion; + patch = thePatchVersion; + preRelease = null; + build = null; + } + + public SemanticVersion( + final int theMajorVersion, + final int theMinorVersion, + final int thePatchVersion, + final String thePreRelease, + final String theBuild) { + super(); + if((theMajorVersion < 0) || + (theMinorVersion < 0) || + (thePatchVersion <0)) { + throw new IllegalArgumentException( + "Major, minor, or patch version cannot be negative."); + } + major = theMajorVersion; + minor = theMinorVersion; + patch = thePatchVersion; + preRelease = (thePreRelease != null) ? + thePreRelease.split("[" + IDENTIFIER_SEPARATOR + "]") : + null; + build = (theBuild != null) ? + theBuild.split("[" + IDENTIFIER_SEPARATOR + "]") : + null; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getPatch() { + return patch; + } + + public String[] getPreRelease() { + return preRelease; + } + + public String[] getBuild() { + return build; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(build); + result = prime * result + major; + result = prime * result + minor; + result = prime * result + patch; + result = prime * result + Arrays.hashCode(preRelease); + return result; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) + return true; + if(obj == null) + return false; + if(getClass() != obj.getClass()) + return false; + SemanticVersion other = (SemanticVersion) obj; + if(!Arrays.equals(build, other.build)) + return false; + if(major != other.major) + return false; + if(minor != other.minor) + return false; + if(patch != other.patch) + return false; + if(!Arrays.equals(preRelease, other.preRelease)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuffer repr = + new StringBuffer(String.format("%d.%d.%d", major, minor, patch)); + + if(preRelease != null) { + repr.append(PRE_RELEASE_SEPARATOR); + repr.append(StringUtils.join(preRelease, IDENTIFIER_SEPARATOR)); + } + + if(build != null) { + repr.append(BUILD_SEPARATOR); + repr.append(StringUtils.join(build, IDENTIFIER_SEPARATOR)); + } + + return repr.toString(); + } + + public int compareTo(final ISemanticVersion theOtherVersion) { + return SemanticVersionComparator.compare(this, theOtherVersion).getLeft(); + } +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java new file mode 100644 index 0000000..017d675 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java @@ -0,0 +1,223 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.apache.commons.collections.iterators.ArrayIterator; +import org.apache.commons.lang3.tuple.ImmutablePair; + +/** + * A comparator for two semantic versions. + * + * @author ian + * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a> for + * the specification on how this comparator operates. + */ +public class SemanticVersionComparator { + public static final ImmutablePair<Integer, SemanticVersionComponent> compare( + final ISemanticVersion verOne, + final ISemanticVersion verTwo) { + if(verOne.equals(verTwo) == true) { + return new ImmutablePair<Integer, SemanticVersionComponent>( + 0, SemanticVersionComponent.INVALID); + } + + if(verOne.getMajor() == verTwo.getMajor()) { + if(verOne.getMinor() == verTwo.getMinor()) { + if(verOne.getPatch() == verTwo.getPatch()) { + /* + * Compare the pre-release components. + */ + final ImmutablePair<Integer, Boolean> preReleaseCompResult = + compareArray(verOne.getPreRelease(), verTwo.getPreRelease()); + /* + * Compare the build components. + */ + final ImmutablePair<Integer, Boolean> buildCompResult = + compareArray(verOne.getBuild(), verTwo.getBuild()); + + /* + * Unpack the comparison values. + */ + final int prc = preReleaseCompResult.getLeft(); + final int bc = buildCompResult.getLeft(); + + if((preReleaseCompResult.getRight() == true) && + (buildCompResult.getRight() == true)) { + /* + * There was at most one pre-release component, and at most one + * build component in both versions. + */ + if((Math.abs(prc) == 1) && (Math.abs(bc) == 1)) { + return new ImmutablePair<Integer, SemanticVersionComponent>( + (Math.signum((float )prc) == 1.0) ? -1 : 1, + SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION); + } else if((Math.abs(prc) == 1) && (bc == 0)) { + return new ImmutablePair<Integer, SemanticVersionComponent>( + (Math.signum((float )prc) == 1.0) ? -1 : 1, + SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION); + } + + return new ImmutablePair<Integer, SemanticVersionComponent>( + bc, SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION); + } else if((preReleaseCompResult.getRight() == true) && + (buildCompResult.getRight() == false)) { + /* + * One of the versions had a null pre-release. + */ + return new ImmutablePair<Integer, SemanticVersionComponent>( + bc, SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION); + } + + /* + * Either one of the version has a null build or both versions where + * fully specified. + */ + return new ImmutablePair<Integer, SemanticVersionComponent>( + (Math.abs(prc) == 1) ? prc : bc, + SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION); + } else { + return new ImmutablePair<Integer, SemanticVersionComponent>( + verOne.getPatch() - verTwo.getPatch(), + SemanticVersionComponent.PATCH_VERSION); + } + } else { + return new ImmutablePair<Integer, SemanticVersionComponent>( + verOne.getMinor() - verTwo.getMinor(), + SemanticVersionComponent.MINOR_VERSION); + } + } + + return new ImmutablePair<Integer, SemanticVersionComponent>( + verOne.getMajor() - verTwo.getMajor(), + SemanticVersionComponent.MAJOR_VERSION); + } + + /** + * Lexically compare the components of two string arrays. + * + * @param one - First string array. + * @param two - The array that is compared to one. + * @return If one array is determined to be lexically less than two then + * -1 is returned. If one is determined to be lexically greater then two then + * 1 is returned. Otherwise, 0 is returned. + */ + private static ImmutablePair<Integer, Boolean> compareArray( + final String[] one, + final String[] two) { + if((one == null) && (two == null)) { + return new ImmutablePair<Integer, Boolean>(0, true); + } + + if((one == null) && (two != null)) { + return new ImmutablePair<Integer, Boolean>(-1, true); + } + + if((one != null) && (two == null)) { + return new ImmutablePair<Integer, Boolean>(1, true); + } + + @SuppressWarnings("unchecked") + final Iterator<String> oneIterator = new ArrayIterator(one); + @SuppressWarnings("unchecked") + final Iterator<String> twoIterator = new ArrayIterator(two); + String oneComp = null; + String twoComp = null; + int comp = 0; + + while(true) { + try { + oneComp = oneIterator.next(); + } catch(final NoSuchElementException ex) { + oneComp = null; + } + + try { + twoComp = twoIterator.next(); + } catch(final NoSuchElementException ex) { + twoComp = null; + } + + if((oneComp == null) && (twoComp == null)) { + break; + } + + comp = componentCompare(oneComp, twoComp); + if(comp != 0) { + break; + } + } + + return new ImmutablePair<Integer, Boolean>(comp, false); + } + + /** + * Compare two components from the pre-release and build string arrays as + * detailed in the Semantic Versioning 2.0.0-rc.1 specification. + * + * @param oneComp - first value. + * @param twoComp - second value. + * @return If first value is determined to be less than the second value then + * return -1. If one value is determined to be greater than the second value + * then return 1. Otherwise, 0 is returned. + * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a> + */ + private static int componentCompare( + final String oneComp, final String twoComp) { + if((oneComp == null) && (twoComp == null)) { + return 0; + } + + if((oneComp == null) && (twoComp != null)) { + return -1; + } + + if((oneComp != null) && (twoComp == null)) { + return 1; + } + + boolean isOneInt = false; + boolean isTwoInt = false; + int oneInt = 0; + int twoInt = 0; + + try { + oneInt = Integer.parseInt(oneComp); + isOneInt = true; + } catch(final NumberFormatException ex) { + isOneInt = false; + } + + try { + twoInt = Integer.parseInt(twoComp); + isTwoInt = true; + } catch(final NumberFormatException ex) { + isTwoInt = false; + } + + final int comp = ((isOneInt == true) && (isTwoInt == true)) ? + oneInt - twoInt : + oneComp.compareTo(twoComp); + final int compValue = (comp > 0) ? 1 : (comp < 0) ? -1 : 0; + + return compValue; + } +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComponent.java b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComponent.java new file mode 100644 index 0000000..306a5dd --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComponent.java @@ -0,0 +1,27 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +public enum SemanticVersionComponent { + INVALID, + PRE_RELEASE_AND_BUILD_VERSION, + PATCH_VERSION, + MINOR_VERSION, + MAJOR_VERSION +} diff --git a/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionParseException.java b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionParseException.java new file mode 100644 index 0000000..c11a013 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionParseException.java @@ -0,0 +1,53 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.negotiation; + +public class SemanticVersionParseException extends Exception { + private static final long serialVersionUID = -3118190471319312408L; + + private final String invalidVersion; + + public SemanticVersionParseException(final String theInvalidVersion) { + super(); + invalidVersion = theInvalidVersion; + } + + public SemanticVersionParseException( + final String theInvalidVersion, final Throwable theThrowable) { + super(theThrowable); + invalidVersion = theInvalidVersion; + } + + public SemanticVersionParseException( + final String theInvalidVersion, + final Throwable theThrowable, + final boolean isSuppressionEnabled, + final boolean isWritableStackTrace) { + super(null, theThrowable, isSuppressionEnabled, isWritableStackTrace); + invalidVersion = theInvalidVersion; + } + + public String getInvalidVersion() { + return invalidVersion; + } + + public String getMessage() { + return String.format("Invalid semantic version: [%s]", invalidVersion); + } +} diff --git a/src/main/java/com/capitati/omtc/core/notification/IResourceDownloadObserver.java b/src/main/java/com/capitati/omtc/core/notification/IResourceDownloadObserver.java new file mode 100644 index 0000000..ca6db59 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/notification/IResourceDownloadObserver.java @@ -0,0 +1,24 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.notification; + +public interface IResourceDownloadObserver +extends IResourceTaskObserver { + +} diff --git a/src/main/java/com/capitati/omtc/core/notification/IResourceTaskObserver.java b/src/main/java/com/capitati/omtc/core/notification/IResourceTaskObserver.java new file mode 100644 index 0000000..2dccf7e --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/notification/IResourceTaskObserver.java @@ -0,0 +1,55 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.notification; + +import com.capitati.omtc.core.resources.IResource; +import com.capitati.omtc.core.session.ISession; + +/** + * A generic resource task observer. On successful completion of a task the + * onSuccess() method shall be called. Whereas, on an error the onError() + * method shall be called. The onError() method provides an object, of type F, + * shall be provided which is the object that was used to invoke the task. + * + * @author ianjohnson + */ +public interface IResourceTaskObserver { + /** + * Called on successful completion of a resource task. + * + * @param notification + * @param resource + * @param invokingSession + */ + void onSuccess( + ISession invokingSession, + IResource resource); + + /** + * Called when a resource task has failed. + * + * @param notification + * @param invokingSession + * @param exception + */ + void onError( + ISession session, + IResource resource, + Exception exception); +} diff --git a/src/main/java/com/capitati/omtc/core/notification/IResourceUploadObserver.java b/src/main/java/com/capitati/omtc/core/notification/IResourceUploadObserver.java new file mode 100644 index 0000000..b406a7f --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/notification/IResourceUploadObserver.java @@ -0,0 +1,23 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.notification; + +public interface IResourceUploadObserver extends IResourceTaskObserver { + +} diff --git a/src/main/java/com/capitati/omtc/core/resources/IDerivedResource.java b/src/main/java/com/capitati/omtc/core/resources/IDerivedResource.java new file mode 100644 index 0000000..51ce2fa --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/resources/IDerivedResource.java @@ -0,0 +1,25 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.resources; + +import java.util.Date; + +public interface IDerivedResource extends IResource { + Date getLastChanged(); +} diff --git a/src/main/java/com/capitati/omtc/core/resources/IPrimaryResource.java b/src/main/java/com/capitati/omtc/core/resources/IPrimaryResource.java new file mode 100644 index 0000000..e62941b --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/resources/IPrimaryResource.java @@ -0,0 +1,23 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.resources; + +public interface IPrimaryResource extends IResource { + +} diff --git a/src/main/java/com/capitati/omtc/core/resources/IResource.java b/src/main/java/com/capitati/omtc/core/resources/IResource.java new file mode 100644 index 0000000..72787df --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/resources/IResource.java @@ -0,0 +1,29 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.resources; + +import java.net.URI; +import java.util.Date; +import java.util.UUID; + +public interface IResource { + UUID getIdentifier(); + URI getURI(); + Date getBirthDate(); +} diff --git a/src/main/java/com/capitati/omtc/core/resources/IResourceReader.java b/src/main/java/com/capitati/omtc/core/resources/IResourceReader.java new file mode 100644 index 0000000..c74539f --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/resources/IResourceReader.java @@ -0,0 +1,26 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.resources; + +import java.io.IOException; + +public interface IResourceReader { + int read(byte[] buffer) throws IOException; + void close() throws IOException; +} diff --git a/src/main/java/com/capitati/omtc/core/resources/IResourceWriter.java b/src/main/java/com/capitati/omtc/core/resources/IResourceWriter.java new file mode 100644 index 0000000..f605e26 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/resources/IResourceWriter.java @@ -0,0 +1,26 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.resources; + +import java.io.IOException; + +public interface IResourceWriter { + void write(byte[] chunk, int chunkLength) throws IOException; + void close() throws IOException; +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/CompositionTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/CompositionTicket.java new file mode 100644 index 0000000..b9d1535 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/CompositionTicket.java @@ -0,0 +1,49 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class CompositionTicket<V> extends EngineTicket<V> { + private final IEngine composingEngine; + + public CompositionTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine, + final IEngine theComposingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + composingEngine = theComposingEngine; + } + + public IEngine getComposingEngine() { + return composingEngine; + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/EngineTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/EngineTicket.java new file mode 100644 index 0000000..d81bda6 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/EngineTicket.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class EngineTicket<V> extends Ticket<V> { + private final IEngine participatingEngine; + + public EngineTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super(theIdentifier, theStartDate, theSession, thePriority); + participatingEngine = theParticipatingEngine; + } + + public IEngine getParticipatingEngine() { + return participatingEngine; + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/EvaluationTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/EvaluationTicket.java new file mode 100644 index 0000000..63f5423 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/EvaluationTicket.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class EvaluationTicket<V> extends EngineTicket<V> { + public EvaluationTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/IPriority.java b/src/main/java/com/capitati/omtc/core/scheduling/IPriority.java new file mode 100644 index 0000000..021cc5c --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/IPriority.java @@ -0,0 +1,36 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +/** + * This presents a priority that will be used to schedule a task in the MT API. + * + * @author ianjohnson + * + * @param <V> the type of the priority value. + */ +public interface IPriority<V> { + /** + * A getter function to provide the caller with a task's priority. This allows + * late binding of any priority parameters at call time. + * + * @return The priority's value of type V. + */ + V getPriority(); +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/IPriorityMechanism.java b/src/main/java/com/capitati/omtc/core/scheduling/IPriorityMechanism.java new file mode 100644 index 0000000..d38d1b8 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/IPriorityMechanism.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +/** + * Implementers should define the priority policy for their product. A priority + * description is used to provide the parameters that shall be used to generate + * a priority object. The description may include SLA, due date, user's price + * plan, one-off task payment details that would improve a task's priority etc. + * + * @author ianjohnson + * + * @param <V> the type of the priority value. + * @param <D> the type of the priority description. This is a type that provides + * all the parameters that will be combined to create a priority object. + */ +public interface IPriorityMechanism<V, D> { + /** + * Taking a priority description generate a priority object that is the + * combination of the description. + * + * @param priorityDescription - the parameters to use to generate the priority. + * @return A priority object. + * @throws Exception + */ + IPriority<V> getPriority(D priorityDescription) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/ITicketObserver.java b/src/main/java/com/capitati/omtc/core/scheduling/ITicketObserver.java new file mode 100644 index 0000000..7d778a1 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/ITicketObserver.java @@ -0,0 +1,58 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +/** + * An observer that watches for tickets starting and completing. + * + * @author ian + * + * @param <T> - the type of the ticket that has completed. + */ +public interface ITicketObserver<T extends Ticket<V>, V> { + /** + * Notify the observer that a ticketed task has been submitted. This method + * shall be called at post-submission and pre-starting time. + * + * @param ticket - the ticket representing the submitted task. + */ + void notifySubmitted(T ticket); + + /** + * Notify the observer that the ticketed task as begun. + * + * @param ticket - the ticket that has started. + */ + void notifyStarted(T ticket); + + /** + * Notify the observer that the ticketed task has ended successfully. + * + * @param ticket - the ticket that has completed. + */ + void notifySuccess(T ticket); + + /** + * Notify the observer that the ticketed task has generated an error. + * + * @param ticket - the ticket that has completed. + * @param exception - the exception that represents the error. + */ + void notifyError(T ticket, Exception exception); +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/QueryTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/QueryTicket.java new file mode 100644 index 0000000..3147f49 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/QueryTicket.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class QueryTicket<V> extends EngineTicket<V> { + public QueryTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/TestingTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/TestingTicket.java new file mode 100644 index 0000000..0c6735d --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/TestingTicket.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class TestingTicket<V> extends EngineTicket<V> { + public TestingTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/Ticket.java b/src/main/java/com/capitati/omtc/core/scheduling/Ticket.java new file mode 100644 index 0000000..0bd7114 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/Ticket.java @@ -0,0 +1,66 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.session.ISession; + +public abstract class Ticket<V> { + private final UUID identifier; + private final Date startDate; + private final ISession session; + private final V priority; + + protected Date endDate; + + protected Ticket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority) { + super(); + identifier = theIdentifier; + startDate = theStartDate; + session = theSession; + priority = thePriority; + endDate = null; + } + + public UUID getIdentifier() { + return identifier; + } + + public Date getStartDate() { + return startDate; + } + + public Date getEndDate() { + return endDate; + } + + public ISession getSession() { + return session; + } + + public V getPriority() { + return priority; + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/TrainingTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/TrainingTicket.java new file mode 100644 index 0000000..741311f --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/TrainingTicket.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class TrainingTicket<V> extends EngineTicket<V> { + public TrainingTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/TranslationTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/TranslationTicket.java new file mode 100644 index 0000000..aa1a5c7 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/TranslationTicket.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.session.ISession; +import com.capitati.omtc.core.translation.Translator; + +public class TranslationTicket<V> extends Ticket<V> { + private final Translator<V> translator; + + public TranslationTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final Translator<V> theTranslator) { + super(theIdentifier, theStartDate, theSession, thePriority); + translator = theTranslator; + } + + public Translator<V> getTranslator() { + return translator; + } +} diff --git a/src/main/java/com/capitati/omtc/core/scheduling/UpdateTicket.java b/src/main/java/com/capitati/omtc/core/scheduling/UpdateTicket.java new file mode 100644 index 0000000..10955c4 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/scheduling/UpdateTicket.java @@ -0,0 +1,41 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.scheduling; + +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.session.ISession; + +public class UpdateTicket<V> extends EngineTicket<V> { + public UpdateTicket( + final UUID theIdentifier, + final Date theStartDate, + final ISession theSession, + final V thePriority, + final IEngine theParticipatingEngine) { + super( + theIdentifier, + theStartDate, + theSession, + thePriority, + theParticipatingEngine); + } +} diff --git a/src/main/java/com/capitati/omtc/core/security/IUser.java b/src/main/java/com/capitati/omtc/core/security/IUser.java new file mode 100644 index 0000000..092cddd --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/security/IUser.java @@ -0,0 +1,42 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.security; + +import java.util.UUID; + +/** + * A machine translation service user. + * + * @author ian + */ +public interface IUser { + /** + * The unique identifier for the user. + * + * @return The user's unique identity. + */ + UUID getIdentifier(); + + /** + * Retrieve the user's roles. + * + * @return The roles of the user. + */ + Role[] getRoles(); +} diff --git a/src/main/java/com/capitati/omtc/core/security/Role.java b/src/main/java/com/capitati/omtc/core/security/Role.java new file mode 100644 index 0000000..bf1e3c4 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/security/Role.java @@ -0,0 +1,43 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.security; + +public enum Role { + INVALID(-1, "Invalid"), + TRANSLATOR(1, "Translator"), + ENGINE_MANAGER(3, "Engine Manager"), + ADMINISTRATOR(7, "Administrator"), + SERVICE_ADMINISTRATOR(8, "Service Administrator"); + + private final int code; + private final String name; + + private Role(final int theCode, final String theName) { + code = theCode; + name = theName; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/capitati/omtc/core/security/User.java b/src/main/java/com/capitati/omtc/core/security/User.java new file mode 100644 index 0000000..bca6e0e --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/security/User.java @@ -0,0 +1,39 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.security; + +import java.util.UUID; + +public abstract class User implements IUser { + private final UUID userId; + private final Role role; + + protected User(final UUID theUserId, final Role theRole) { + userId = theUserId; + role = theRole; + } + + public UUID getIdentifier() { + return userId; + } + + public Role getRole() { + return role; + } +} diff --git a/src/main/java/com/capitati/omtc/core/session/IEngineAssignableSession.java b/src/main/java/com/capitati/omtc/core/session/IEngineAssignableSession.java new file mode 100644 index 0000000..d838e72 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IEngineAssignableSession.java @@ -0,0 +1,60 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.security.IUser; + +/** + * A mixin to provide methods to grant and revoke users access to constructed + * engines in the machine translation service. Implementers of this interface + * should associate an engine. And optionally storing the record of a grant or + * revocation into some persistent backing store. Whether the backing store is + * a database or authorisation service is implementation defined. + * + * @author ianjohnson + */ +public interface IEngineAssignableSession +extends IEngineRetrievableSession, IUserRetrievableSession { + /** + * Associate a user with an engine. This association should allow the user + * to use the engine for a {@link com.capitati.omtc.core.translation.Translator} + * object. Optionally, the implementation should back this association to some + * persistent backing store. + * + * @param engine - the engine to grant. + * @param theUser - the grantee. + * @throws Exception Any error that is encountered. + */ + void grantEngineToUser(IEngine engine, IUser theUser) throws Exception; + + /** + * Dissociate a user from an engine. The user shall no longer be able to use + * an engine to build a {@link com.capitati.omtc.core.translation.Translator} + * object. Whether the existing translator objects, that use the engine, + * shall be destroyed immediately, or that the engine is no longer available + * for use in a translator is to implementation defined. Optionally, the + * implementation should back the dissociation to a persistent backing store. + * + * @param engine - the engine to revoke. + * @param theUser - the revokee. + * @throws Exception Any error that is encountered. + */ + void revokeEngineFromUser(IEngine engine, IUser theUser) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/session/IEngineRetrievableSession.java b/src/main/java/com/capitati/omtc/core/session/IEngineRetrievableSession.java new file mode 100644 index 0000000..d2ee5bb --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IEngineRetrievableSession.java @@ -0,0 +1,10 @@ +package com.capitati.omtc.core.session; + +import java.util.Set; + +import com.capitati.omtc.core.engine.IEngine; +import com.google.common.base.Predicate; + +public interface IEngineRetrievableSession { + Set<IEngine> retrieveEngines(Predicate<IEngine> filter) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/session/IResourceTransferDelegate.java b/src/main/java/com/capitati/omtc/core/session/IResourceTransferDelegate.java new file mode 100644 index 0000000..489bdde --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IResourceTransferDelegate.java @@ -0,0 +1,71 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import com.capitati.omtc.core.resources.IResource; +import com.capitati.omtc.core.resources.IResourceReader; +import com.capitati.omtc.core.resources.IResourceWriter; + +/** + * The delegated resource transfer mechanism. + * + * @author ianjohnson + */ +public interface IResourceTransferDelegate { + /** + * Constructs an instance of {@link com.capitati.omtc.core.resources.IResourceReader} + * which is an object that is used to read chunks of data from a source + * resource. Implementers of this method should take this opportunity to + * open a resource where ever that may be, e.g., local disk, remote client. + * + * @param theInvokingSession - the session for whom this method is being called. + * @return An implementation of the {@link com.capitati.omtc.core.resources.IResourceReader} + * interface that shall provide data for a resource. + * @throws Exception On any error encountered. + */ + IResourceReader getResourceReader(ISession theInvokingSession) throws Exception; + + /** + * Constructs an instance of {@link com.capitati.omtc.core.resources.IResourceWriter} + * which is an object that is used to write chunks of data to a destination + * resource. Implementers of this method should take this opportunity to + * open a resource where ever it may needed to be, e.g., local disk, remote client. + * + * @param theInvokingSession - the session for whom this method is being called. + * @return An implementation of the {@link com.capitati.omtc.core.resources.IResourceWriter} + * interface that is to handle the writing of resource data. + * @throws Exception On any error encountered. + */ + IResourceWriter getResourceWriter(ISession theInvokingSession) throws Exception; + + /** + * Implementers of this method should return a {@link com.capitati.omtc.core.resources.IResource} + * object that represents the resource that is begin transfered. + * Please note: for documents, translation memories, and glossaries etc instances of + * {@link com.capitati.omtc.core.resources.IPrimaryResource} should be + * constructed. However, for resources that are derived, e.g., engines, then + * instances of type {@link com.capitati.omtc.core.resources.IDerivedResource} + * should be returned. + * + * @param theInvokingSession - the session that invoked the transfer action. + * @return A {@link com.capitati.omtc.core.resources.IResource} + * object that presents the resource uploaded + */ + IResource getResource(ISession theInvokingSession); +} diff --git a/src/main/java/com/capitati/omtc/core/session/IRoleAssignableSession.java b/src/main/java/com/capitati/omtc/core/session/IRoleAssignableSession.java new file mode 100644 index 0000000..8948634 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IRoleAssignableSession.java @@ -0,0 +1,50 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import com.capitati.omtc.core.security.IUser; +import com.capitati.omtc.core.security.Role; + +/** + * A mixin for providing a session the ability to grant and revoke roles from + * users of the machine translation service. Implementers of this interface + * should integrate with any back-end authorisation service that may be used + * alongside the concrete service. + * + * @author ianjohnson + */ +public interface IRoleAssignableSession extends IUserRetrievableSession { + /** + * Grant a role to a user. + * + * @param theRole - the role to grant. + * @param theUser - the user. + * @throws Exception On any errors that occur during the granting process. + */ + void grantRoleToUser(Role theRole, IUser theUser) throws Exception; + + /** + * Revoke a role from a user. + * + * @param theRole - the role to revoke from the user. + * @param theUser - the user. + * @throws Exception On any errors that occur during the revocation process. + */ + void revokeRoleFromUser(Role theRole, IUser theUser) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/session/ISession.java b/src/main/java/com/capitati/omtc/core/session/ISession.java new file mode 100644 index 0000000..d6245ed --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/ISession.java @@ -0,0 +1,120 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Future; + +import javax.naming.OperationNotSupportedException; + +import com.capitati.omtc.core.notification.IResourceDownloadObserver; +import com.capitati.omtc.core.notification.IResourceUploadObserver; +import com.capitati.omtc.core.resources.IResource; +import com.google.common.base.Predicate; + +/** + * A machine translation service session. This session is <em>user-less</em>; + * this session is for services where user identity is not crucial for using the + * service. + * + * @author ian + */ +public interface ISession { + /** + * Get the session's unique identifier. + * + * @return The unique identifier that is of type {@link java.util.UUID}. + */ + UUID getIdentifier(); + + /** + * Upload a resource to the service. The upload delegate shall be called to + * implement the actual mechanism that shall transfer resource data. If + * specified the {@link com.capitati.omtc.core.notification.IResourceUploadObserver} + * object shall be notified when the uploading of the resource has completed: + * either on success or failure. + * + * <p>The returning {@link java.util.concurrent.Future} object, + * and the optional observer, allows callers to wait synchronously or + * asynchronously for upload completion. + * + * @param theResourceUploaderDelegate - the delegated uploader mechanism. + * @param theResourceUploadObserver - optional observer that is notified + * once the uploading task has completed, either successfully or unsuccessfully. + * @return A {@link java.util.concurrent.Future} object that waits on the + * availability of the {@link com.capitati.omtc.core.resources.IResource} object + * that represents the resource once uploaded. + * @throws OperationNotSupportedException If no executor service was specified. + * @throws IllegalArgumentException If no uploading delegate has been + * provided. + */ + Future<IResource> uploadResource( + IResourceTransferDelegate theResourceUploaderDelegate, + IResourceUploadObserver theResourceUploadObserver) + throws OperationNotSupportedException; + + /** + * Download a resource from the service. The download delegate shall be called to + * implement the actual mechanism that shall transfer resource data. If + * specified the {@link com.capitati.omtc.core.notification.IResourceDownloadObserver} + * object shall be notified when the downloading of the resource has completed: + * either on success or failure. + * + * <p>The returning {@link java.util.concurrent.Future} object, + * and the optional observer, allows callers to wait synchronously or + * asynchronously for the downloading to complete. + * + * @param theResourceDownloaderDelegate - the delegated downloading mechanism. + * @param theResourceDownloadObserver - optional observer that is notified + * once the downloading task has completed, either successfully or unsuccessfully. + * @return A {@link java.util.concurrent.Future} object that waits on the + * availability of the {@link com.capitati.omtc.core.resources.IResource} object + * that represents the resource once downloaded. + * @throws OperationNotSupportedException If no executor service was specified. + * @throws IllegalArgumentException If no uploading delegate had been + * provided. + */ + Future<IResource> downloadResource( + IResourceTransferDelegate theResourceDownloaderDelegate, + IResourceDownloadObserver theResourceDownloadObserver) + throws OperationNotSupportedException; + + /** + * Remove a resource. If the resource implements + * {@link com.capitati.omtc.core.commons.IDisposable} the the method + * {@link com.capitati.omtc.core.commons.IDisposable#dispose} should be + * called to dispose of any used system resources, e.g., disk space. + * + * @param resource - the resource to remove. + * @throws Exception On an error. + */ + void removeResource(IResource resource) throws Exception; + + /** + * This method shall return a set of resources that belong to the session. + * + * @param theFilter - the predicate that shall filter the resources returned. + * @return A {@link java.util.Set} of {@link com.capitati.omtc.core.resource.IResource} + * objects that are owned by the session and meet the predicate. + * @throws Exception on error evaluating the predicate. + */ + Set<IResource> retrieveResources(Predicate<IResource> theFilter) + throws Exception; +}
\ No newline at end of file diff --git a/src/main/java/com/capitati/omtc/core/session/IUserRetrievableSession.java b/src/main/java/com/capitati/omtc/core/session/IUserRetrievableSession.java new file mode 100644 index 0000000..6c4eb05 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IUserRetrievableSession.java @@ -0,0 +1,28 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import java.util.Set; + +import com.capitati.omtc.core.security.IUser; +import com.google.common.base.Predicate; + +public interface IUserRetrievableSession { + Set<IUser> retrieveUsers(Predicate<IUser> filter) throws Exception; +} diff --git a/src/main/java/com/capitati/omtc/core/session/IUserSession.java b/src/main/java/com/capitati/omtc/core/session/IUserSession.java new file mode 100644 index 0000000..02754af --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/IUserSession.java @@ -0,0 +1,36 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import com.capitati.omtc.core.security.IUser; + +/** + * A session that is associated with a user. This session would be used by a + * service implementation that requires user identity. + * + * @author ian + */ +public interface IUserSession extends ISession { + /** + * Retrieve the associated user object for the session. + * + * @return The session's associated user object. + */ + IUser getUser(); +} diff --git a/src/main/java/com/capitati/omtc/core/session/Session.java b/src/main/java/com/capitati/omtc/core/session/Session.java new file mode 100644 index 0000000..6731325 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/Session.java @@ -0,0 +1,232 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import javax.naming.OperationNotSupportedException; + +import com.capitati.omtc.core.notification.IResourceDownloadObserver; +import com.capitati.omtc.core.notification.IResourceUploadObserver; +import com.capitati.omtc.core.resources.IResource; +import com.capitati.omtc.core.resources.IResourceReader; +import com.capitati.omtc.core.resources.IResourceWriter; + +/** + * A machine translation service session. This session is <em>user-less</em>; + * this session is for services where user identity is not crucial for using the + * service. + * + * @author ianjohnson + */ +public abstract class Session implements ISession { + private static final int DEFAULT_BUFFER_SIZE = 1024 * 1024; // 1Mb + + private final UUID id; + private final int bufferSize; + protected final ExecutorService executor; + + /** + * Construct a session that does not support uploading or downloading of + * resources. + * + * @param theIdentifier - the unique identifier for the session. + */ + protected Session(final UUID theIdentifier) { + super(); + id = theIdentifier; + bufferSize = DEFAULT_BUFFER_SIZE; + executor = null; + } + + /** + * Construct a session that supports uploading and downloading of resources. + * + * @param theIdentifier - the unique identifier for the session. + * @param theDelegateExecutorService - the executor service in which the + * upload and download delegates shall run. + */ + protected Session( + final UUID theIdentifier, + final ExecutorService theDelegationExecutorService) { + super(); + id = theIdentifier; + executor = theDelegationExecutorService; + bufferSize = (executor != null) ? DEFAULT_BUFFER_SIZE : -1; + } + + /** + * Construct a session that supports uploading and downloading of resources. + * + * @param theIdentifier - the unique identifier for the session. + * @param theDelegateExecutorService - the executor service in which the + * upload and download delegates shall run. + * @param theTransferBufferSize - the number of bytes available to the + * upload and download transfer buffer. + */ + protected Session( + final UUID theIdentifier, + final ExecutorService theDelegationExecutorService, + final int theTransferBufferSize) { + super(); + id = theIdentifier; + bufferSize = (theTransferBufferSize > 0) ? theTransferBufferSize : DEFAULT_BUFFER_SIZE; + executor = theDelegationExecutorService; + } + + public UUID getIdentifier() { + return id; + } + + public Future<IResource> uploadResource( + final IResourceTransferDelegate theResourceUploaderDelegate, + final IResourceUploadObserver theResourceUploadObserver) + throws OperationNotSupportedException { + if(executor == null) { + throw new OperationNotSupportedException(""); + } + + if(theResourceUploaderDelegate == null) { + throw new IllegalArgumentException("No uploader delegate specified."); + } + + final ISession invokingSession = this; + final Callable<IResource> uploadTask = new Callable<IResource>() { + public IResource call() throws Exception { + final IResource resource = + theResourceUploaderDelegate.getResource(invokingSession); + + try { + upload(); + + if(theResourceUploadObserver != null) { + theResourceUploadObserver.onSuccess(invokingSession, resource); + } + } catch(final Exception ex) { + if(theResourceUploadObserver != null) { + theResourceUploadObserver.onError(invokingSession, resource, ex); + } + throw ex; + } + + return resource; + } + + private void upload() throws Exception { + final IResourceReader resourceReader = + theResourceUploaderDelegate.getResourceReader(invokingSession); + + try { + final IResourceWriter resourceWriter = + theResourceUploaderDelegate.getResourceWriter(invokingSession); + + try { + Session.copyBytes(resourceReader, resourceWriter, bufferSize); + } finally { + resourceWriter.close(); + } + } finally { + resourceReader.close(); + } + } + }; + final Future<IResource> future = executor.submit(uploadTask); + + return future; + } + + public Future<IResource> downloadResource( + final IResourceTransferDelegate theResourceDownloaderDelegate, + final IResourceDownloadObserver theResourceDownloadObserver) { + if(theResourceDownloaderDelegate == null) { + throw new IllegalArgumentException("No downloader delegate specified."); + } + + final ISession invokingSession = this; + final Callable<IResource> downloadTask = new Callable<IResource>() { + public IResource call() throws Exception { + final IResource resource = + theResourceDownloaderDelegate.getResource(invokingSession); + + try { + download(); + + if(theResourceDownloadObserver != null) { + theResourceDownloadObserver.onSuccess(invokingSession, resource); + } + } catch(final Exception ex) { + if(theResourceDownloadObserver != null) { + theResourceDownloadObserver.onError(invokingSession, resource, ex); + throw ex; + } + } + + return resource; + } + + private void download() throws Exception { + final IResourceWriter resourceWriter = + theResourceDownloaderDelegate.getResourceWriter(invokingSession); + + try { + final IResourceReader resourceReader = + theResourceDownloaderDelegate.getResourceReader(invokingSession); + + try { + Session.copyBytes(resourceReader, resourceWriter, bufferSize); + } finally { + resourceReader.close(); + } + } finally { + resourceWriter.close(); + } + } + }; + final Future<IResource> future = executor.submit(downloadTask); + + return future; + } + + /** + * Writes bytes, read from a resource reader, to a resource writer. This + * copies the bytes from a source resource to a destination resource, + * respectively. + * + * @param resourceReader - the object that shall read the source resource data. + * @param resourceWriter - the object that shall write the resource data to + * the destination resource. + * @param bufferSize - the number of bytes used to build the buffer. + * @throws Exception on an error reading from, or writing to the resources. + */ + private static void copyBytes( + final IResourceReader resourceReader, + final IResourceWriter resourceWriter, + final int bufferSize) throws Exception { + final byte[] readBuffer = new byte[bufferSize]; + int bytesRead = resourceReader.read(readBuffer); + + while(bytesRead > -1) { + resourceWriter.write(readBuffer, bytesRead); + bytesRead = resourceReader.read(readBuffer); + } + } +} diff --git a/src/main/java/com/capitati/omtc/core/session/UserSession.java b/src/main/java/com/capitati/omtc/core/session/UserSession.java new file mode 100644 index 0000000..6fa549c --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/session/UserSession.java @@ -0,0 +1,88 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.session; + +import java.util.UUID; +import java.util.concurrent.ExecutorService; + +import com.capitati.omtc.core.security.IUser; + +/** + * A session that is associated with a user. This session would be used by a + * service implementation that requires user identity. + * + * @author ianjohnson + */ +public abstract class UserSession extends Session implements IUserSession { + protected final IUser user; + + /** + * Construct a user session that does not support downloading or uploading. + * + * @param theIdentifier - the unique identifier for the session. + * @param theUser - the associated user object. + */ + protected UserSession(final UUID theIdentifier, final IUser theUser) { + super(theIdentifier); + user = theUser; + } + + /** + * Construct a user session that supports downloading and uploading. + * + * @param theIdentifier - the unique identifier for the session. + * @param theUser - the associated user object. + * @param theDelegateExecutorService - the executor service in which the + * upload and download delegates shall run. + */ + protected UserSession( + final UUID theIdentifier, + final IUser theUser, + final ExecutorService theDelegationExecutorService) { + super(theIdentifier, theDelegationExecutorService); + user = theUser; + } + + /** + * + * @param theIdentifier - the unique identifier for the session. + * @param theUser - the associated user object. + * @param theDelegationExecutorService -the executor service in which the + * upload and download delegates shall run. + * @param theTransferBufferSize - the number of bytes available to the + * upload and download transfer buffer. + */ + protected UserSession( + final UUID theIdentifier, + final IUser theUser, + final ExecutorService theDelegationExecutorService, + final int theTransferBufferSize) { + super(theIdentifier, theDelegationExecutorService, theTransferBufferSize); + user = theUser; + } + + /** + * Retrieve the associated user object for the session. + * + * @return The session's associated user object. + */ + public IUser getUser() { + return user; + } +} diff --git a/src/main/java/com/capitati/omtc/core/translation/Translator.java b/src/main/java/com/capitati/omtc/core/translation/Translator.java new file mode 100644 index 0000000..3ef63a3 --- /dev/null +++ b/src/main/java/com/capitati/omtc/core/translation/Translator.java @@ -0,0 +1,120 @@ +/* + * Copyright Capita Translation and Interpreting 2013 + * + * This file is part of OMTC. + * + * OMTC is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OMTC 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OMTC. If not, see <http://www.gnu.org/licenses/>. + */ +package com.capitati.omtc.core.translation; + +import java.util.HashSet; +import java.util.Set; + +import com.capitati.omtc.core.engine.IEngine; +import com.capitati.omtc.core.resources.IPrimaryResource; +import com.capitati.omtc.core.scheduling.IPriority; +import com.capitati.omtc.core.scheduling.ITicketObserver; +import com.capitati.omtc.core.scheduling.TranslationTicket; +import com.google.common.base.Predicate; + +/** + * An associative class that brings together an engine, glossaries and + * translation memories. These resources are to be used as a translator. + * + * @author ian + * + * @param <P> - the type of the priority's value. + */ +public abstract class Translator<V> { + private final IEngine engine; + private final Set<IPrimaryResource> glossaries = + new HashSet<IPrimaryResource>(); + private final Set<IPrimaryResource> translationMemories = + new HashSet<IPrimaryResource>(); + + protected Translator(final IEngine theEngine) { + super(); + engine = theEngine; + } + + protected Translator( + final IEngine theEngine, + final Set<IPrimaryResource> theGlossaries, + final Set<IPrimaryResource> theTranslationMemories) { + super(); + engine = theEngine; + glossaries.addAll(theGlossaries); + translationMemories.addAll(theTranslationMemories); + } + + public IEngine getEngine() { + return engine; + } + + public Set<IPrimaryResource> getGlossaries() { + return glossaries; + } + + public Set<IPrimaryResource> getTranslationMemories() { + return translationMemories; + } + + /** + * Schedule a translation for a primary resource. It is implementation + * defined which kind of primary resources shall be translated. + * + * @param session - the invoking session. + * @param resourceToTranslate - the primary resource to translate. + * @param thePriority - the requested priority. + * @param translationObserver - the observer that listens for the translation + * task to starting and complete. + * @return A translation ticket. + * @throws Exception On an error. + */ + public abstract TranslationTicket<V> scheduleTranslation( + IPrimaryResource resourceToTranslate, + IPriority<V> thePriority, + ITicketObserver<TranslationTicket<V>, V> translationObserver) + throws Exception; + + /** + * Schedule a translation for a single sentence. + * + * @param session - the invoking session. + * @param sourceSentence - the sentence to translate. + * @param thePriority - the requested priority. + * @param translationObserver - the observer that listens for the translation + * task to starting and complete. + * @return A translation ticket. + * @throws Exception On an error. + */ + public abstract TranslationTicket<V> scheduleTranslation( + String sourceSentence, + IPriority<V> thePriority, + ITicketObserver<TranslationTicket<V>, V> translationObserver) + throws Exception; + + /** + * Retrieve the dispensed translation tickets. + * + * @param filter - a predicate used to filter the translation tickets. + * @return A {@link java.util.Set} of currently scheduled translation + * tickets. It is the implementations responsibility to manage the in-flight + * collection of tickets. + * + * @throws Exception + */ + public abstract Set<TranslationTicket<V>> retrieveTranslations( + Predicate<TranslationTicket<V>> filter) throws Exception; +} diff --git a/src/test/java/com/capitati/omtc/core/negotiation/NegotiatorTests.java b/src/test/java/com/capitati/omtc/core/negotiation/NegotiatorTests.java new file mode 100644 index 0000000..2c94427 --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/negotiation/NegotiatorTests.java @@ -0,0 +1,248 @@ +package com.capitati.omtc.core.negotiation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class NegotiatorTests { + public Mockery mockery; + public IServiceResourceCapability resourceOne; + public IServiceResourceCapability resourceTwo; + public IServiceResourceCapability resourceThree; + public IServiceResourceCapability resourceFour; + public IFeatureCapability featureOne; + public IFeatureCapability featureTwo; + public IPrerequisiteCapability prereq; + public List<IServiceResourceCapability> resources; + public Set<IFeatureCapability> features; + + @Before + public void setUp() { + mockery = new JUnit4Mockery(); + resourceOne = mockery.mock(IServiceResourceCapability.class, "resourceOne"); + resourceTwo = mockery.mock(IServiceResourceCapability.class, "resourceTwo"); + resourceThree = mockery.mock(IServiceResourceCapability.class, "resourceThree"); + resourceFour = mockery.mock(IServiceResourceCapability.class, "resourceFour"); + featureOne = mockery.mock(IFeatureCapability.class, "featureOne"); + featureTwo = mockery.mock(IFeatureCapability.class, "featureTwo"); + prereq = mockery.mock(IPrerequisiteCapability.class, "prereqOne"); + + resources = + new ArrayList<IServiceResourceCapability>() { + private static final long serialVersionUID = 1L; + { + add(resourceOne); + add(resourceTwo); + add(resourceThree); + add(resourceFour); + }}; + + features = + new HashSet<IFeatureCapability>() { + private static final long serialVersionUID = 1L; + { + add(featureOne); + add(featureTwo); + }}; + } + + @Test + public void testNegotiation() throws SemanticVersionParseException { + final ISemanticVersion clientVersion = SemanticVersion.parseVersion("1.3.7"); + final IResourceCapability clientResourceCapOne = new IResourceCapability() { + public Capability getName() { + return Capability.RES_FILE_XLIFF; + } + public String getLowerVersion() { + return "1.6"; + } + public String getHigherVersion() { + return "2.0"; + } + }; + final IResourceCapability clientResourceCapTwo = new IResourceCapability() { + public Capability getName() { + return Capability.RES_FILE_XLIFF; + } + public String getLowerVersion() { + return "7.0"; + } + public String getHigherVersion() { + return "10.0"; + } + }; + final IResourceCapability clientResourceCapThree = new IResourceCapability() { + public Capability getName() { + return Capability.RES_FILE_TMX; + } + public String getLowerVersion() { + return "0.8"; + } + public String getHigherVersion() { + return "10.5"; + } + }; + final IResourceCapability clientResourceCapFour = new IResourceCapability() { + public Capability getName() { + return Capability.RES_FILE_TTX; + } + public String getLowerVersion() { + return "2.718"; + } + public String getHigherVersion() { + return "3.141"; + } + }; + final Set<IResourceCapability> clientResourceCapabilities = + new HashSet<IResourceCapability>() { + private static final long serialVersionUID = 1L; + { + add(clientResourceCapOne); + add(clientResourceCapTwo); + add(clientResourceCapThree); + add(clientResourceCapFour); + }}; + + mockery.checking(new Expectations() {{ + allowing(resourceOne).getName(); + will(returnValue(Capability.RES_FILE_XLIFF)); + allowing(resourceOne).getLowerVersion(); + will(returnValue("1.5")); + allowing(resourceOne).getHigherVersion(); + will(returnValue("2.3")); + allowing(resourceOne).compareVersion(with(clientResourceCapOne)); + will(returnValue(0)); + allowing(resourceOne).compareVersion(with(clientResourceCapTwo)); + will(returnValue(1)); + allowing(resourceOne).compareVersion(with(any(IResourceCapability.class))); + will(returnValue(-1)); + + allowing(resourceTwo).getName(); + will(returnValue(Capability.RES_FILE_XLIFF)); + allowing(resourceTwo).getLowerVersion(); + will(returnValue("3.7")); + allowing(resourceTwo).getHigherVersion(); + will(returnValue("4.2")); + allowing(resourceTwo).compareVersion(with(any(IResourceCapability.class))); + will(returnValue(-1)); + + allowing(resourceThree).getName(); + will(returnValue(Capability.RES_FILE_TMX)); + allowing(resourceThree).getLowerVersion(); + will(returnValue("0.2")); + allowing(resourceThree).getHigherVersion(); + will(returnValue("1.0")); + allowing(resourceThree).compareVersion(clientResourceCapThree); + will(returnValue(0)); + allowing(resourceThree).compareVersion(with(any(IResourceCapability.class))); + will(returnValue(-1)); + + allowing(resourceFour).getName(); + will(returnValue(Capability.RES_FILE_TBX)); + allowing(resourceFour).getLowerVersion(); + will(returnValue("0.8")); + allowing(resourceFour).getHigherVersion(); + will(returnValue("10.5")); + allowing(resourceFour).compareVersion(with(any(IResourceCapability.class))); + will(returnValue(-1)); + + allowing(featureOne).getName(); + will(returnValue(Capability.FET_RES_DOWNLOAD)); + allowing(featureOne).getPrerequisiteCapabilities(); + will(returnValue(new HashSet<IPrerequisiteCapability>())); + + allowing(featureTwo).getName(); + will(returnValue(Capability.FET_RES_UPLOAD)); + allowing(featureTwo).getPrerequisiteCapabilities(); + will(returnValue(new HashSet<IPrerequisiteCapability>() { + private static final long serialVersionUID = 1L; + { + add(new IPrerequisiteCapability() { + public Capability getName() { + return Capability.PRE_REQ_PAYMENT; + } + }); + }})); + }}); + + final INegotiator negotiator = new Negotiator("1.5.1", resources, features); + final IClientCapabilityRequest request = new IClientCapabilityRequest() { + public IAPICapability getVersionCapability() { + return new IAPICapability() { + public Capability getName() { + return Capability.API_VERSION; + } + public ISemanticVersion getVersion() { + return clientVersion; + } + }; + } + public Set<IResourceCapability> getResourceCapabilities() { + return clientResourceCapabilities; + } + }; + final IClientCapabilityResponse response = negotiator.negotiate(request); + + final Set<IResourceCapability> targetUnsupportedResources = + new HashSet<IResourceCapability>() { + private static final long serialVersionUID = 4358016718704699346L; + { + add(clientResourceCapTwo); + add(clientResourceCapFour); + }}; + + Assert.assertTrue(response.isClientAPISupported()); + Assert.assertEquals( + targetUnsupportedResources, + response.getUnsupportedResourceCapabilities()); + Assert.assertEquals(features, response.getFeatureCapabilities()); + } + + @Test + public void testAPIVersionNotSupported() throws SemanticVersionParseException { + final INegotiator negotiator = new Negotiator("1.5.1", null, null); + final IClientCapabilityRequest requestLow = new IClientCapabilityRequest() { + public IAPICapability getVersionCapability() { + return new IAPICapability() { + public Capability getName() { + return Capability.API_VERSION; + } + public ISemanticVersion getVersion() { + return new SemanticVersion(0, 9, 0, "alpha.1", "build.1234"); + } + }; + } + public Set<IResourceCapability> getResourceCapabilities() { + return new HashSet<IResourceCapability>(); + } + }; + final IClientCapabilityResponse responseLow = negotiator.negotiate(requestLow); + final IClientCapabilityRequest requestHigh = new IClientCapabilityRequest() { + public IAPICapability getVersionCapability() { + return new IAPICapability() { + public Capability getName() { + return Capability.API_VERSION; + } + public ISemanticVersion getVersion() { + return new SemanticVersion(2, 3, 7); + } + }; + } + public Set<IResourceCapability> getResourceCapabilities() { + return new HashSet<IResourceCapability>(); + } + }; + final IClientCapabilityResponse responseHigh = negotiator.negotiate(requestHigh); + + Assert.assertFalse(responseLow.isClientAPISupported()); + Assert.assertFalse(responseHigh.isClientAPISupported()); + } +} diff --git a/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionComparatorTests.java b/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionComparatorTests.java new file mode 100644 index 0000000..adff242 --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionComparatorTests.java @@ -0,0 +1,528 @@ +package com.capitati.omtc.core.negotiation; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.junit.Assert; +import org.junit.Test; + +public class SemanticVersionComparatorTests { + private interface IVersionsWithChecker { + ISemanticVersion getLeftVersion(); + ISemanticVersion getRightVersion(); + boolean forwardCheck(int comparisonValue); + boolean backwardCheck(int comparisonValue); + SemanticVersionComponent getChangedComponent(); + } + + private static final List<ISemanticVersion> orderedVersions = + new ArrayList<ISemanticVersion>() { + private static final long serialVersionUID = 1L; + { + add(new SemanticVersion(1, 0, 0, "alpha", null)); + add(new SemanticVersion(1, 0, 0, "alpha.1", null)); + add(new SemanticVersion(1, 0, 0, "beta.2", null)); + add(new SemanticVersion(1, 0, 0, "beta.11", null)); + add(new SemanticVersion(1, 0, 0, "rc.1", null)); + add(new SemanticVersion(1, 0, 0, "rc.1", "build.1")); + add(new SemanticVersion(1, 0, 0, "rc.2", null)); + add(new SemanticVersion(1, 0, 0)); + add(new SemanticVersion(1, 0, 1)); + add(new SemanticVersion(1, 1, 2)); + add(new SemanticVersion(2, 0, 0)); + add(new SemanticVersion(2, 0, 0, null, "0.3.7")); + add(new SemanticVersion(2, 3, 7, null, "build")); + add(new SemanticVersion(2, 3, 7, null, "build.2.b8f12d7")); + add(new SemanticVersion(2, 3, 7, null, "build.11.e0f985a")); + }}; + + @Test + public void testComparatorWithLexicalOrdering() { + for(int idx = 0; idx < orderedVersions.size() - 1; idx++) { + final ISemanticVersion one = orderedVersions.get(idx); + final ISemanticVersion two = orderedVersions.get(idx + 1); + + System.err.printf( + "Version [%s] and [%s]...%s", + one, + two, + System.lineSeparator()); + + Assert.assertTrue( + String.format( + "Semantic version [%s] is greater than [%s]", + one, two), + SemanticVersionComparator.compare(one, two).getLeft() < 0); + Assert.assertTrue( + String.format( + "Semantic version [%s] is less than [%s]", + two, one), + SemanticVersionComparator.compare(two, one).getLeft() > 0); + Assert.assertTrue( + String.format( + "Semantic version [%s] is not equal to itself!", one), + SemanticVersionComparator.compare(one, one).getLeft() == 0); + Assert.assertTrue( + String.format( + "Semantic version [%s] is not equal to itself!", two), + SemanticVersionComparator.compare(two, two).getLeft() == 0); + } + } + + /* + * Versions with both pre-release and build + */ + private static final List<IVersionsWithChecker> versionsWithPreReleaseAndBuild = + new ArrayList<IVersionsWithChecker>() { + private static final long serialVersionUID = 1L; + { + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + // Arrrgh, v4! + return new SemanticVersion(4, 0, 0, "rc.1", "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.MAJOR_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 5, 0, "rc.1", "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.MINOR_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 8, "rc.1", "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PATCH_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, "rc.2", "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, "rc.2", "build.1"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + }}; + + @Test + public void testPreReleaseAndBuildComponentOrdering() { + runVersionsWithCheckTest(versionsWithPreReleaseAndBuild); + } + + /* + * These versions invoke the true, true code path for pre-release and + * build comparisons. + */ + private static final List<IVersionsWithChecker> versionWithNullComponents = + new ArrayList<IVersionsWithChecker>() { + private static final long serialVersionUID = 1L; + { + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 1); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PATCH_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 2, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.MINOR_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(3, 2, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.MAJOR_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", null); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, null, "build.2"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.2"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue == 0); + } + public boolean backwardCheck(int comparisonValue) { + return forwardCheck(comparisonValue); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.INVALID; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", null); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, null, "build.2"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.2"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "beta.11", null); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, null, "build.11.e0f985a"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, null, "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, null, "build.2"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, null, "build.2"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, null, "build.1"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + + add(new IVersionsWithChecker() { + public ISemanticVersion getLeftVersion() { + return new SemanticVersion(1, 0, 0, "rc.1", "build.1"); + } + public ISemanticVersion getRightVersion() { + return new SemanticVersion(1, 0, 0, null, "build.2.b8f12d7"); + } + public boolean forwardCheck(int comparisonValue) { + return (comparisonValue < 0); + } + public boolean backwardCheck(int comparisonValue) { + return (comparisonValue > 0); + } + public SemanticVersionComponent getChangedComponent() { + return SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION; + } + }); + }}; + + @Test + public void testVersionsWithNullPreReleaseOrBuild() { + runVersionsWithCheckTest(versionWithNullComponents); + } + + @Test + public void testVersionParser() throws SemanticVersionParseException { + final List<ISemanticVersion> versions = new ArrayList<ISemanticVersion>() { + private static final long serialVersionUID = -1726840289543320508L; + { + add(new SemanticVersion(4, 5, 9)); + add(new SemanticVersion(3, 6, 2, "rc.2.deadbeef", null)); + add(new SemanticVersion(10, 0, 8, null, "build.667")); + add(new SemanticVersion(0, 5, 10, "rc.10.a4b56", "build.b39de2")); + }}; + + for(ISemanticVersion version : versions) { + Assert.assertEquals( + String.format("Failed to parse version [%s]", version), + SemanticVersion.parseVersion(version.toString()), + version); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testNegativeMajorVersionConstruction() { + @SuppressWarnings("unused") + final ISemanticVersion sv = new SemanticVersion(-1, 5, 8); + } + + @Test(expected = IllegalArgumentException.class) + public void testNegativeMinorVersionConstruction() { + @SuppressWarnings("unused") + final ISemanticVersion sv = new SemanticVersion(1, -5, 8); + } + + @Test(expected = IllegalArgumentException.class) + public void testNegativePatchVersionConstruction() { + @SuppressWarnings("unused") + final ISemanticVersion sv = new SemanticVersion(1, 5, -8); + } + + private void runVersionsWithCheckTest( + final List<IVersionsWithChecker> vwcCollection) { + for(IVersionsWithChecker vwc : vwcCollection) { + System.err.printf( + "Version [%s] and [%s]...%s", + vwc.getLeftVersion(), + vwc.getRightVersion(), + System.lineSeparator()); + + final ImmutablePair<Integer, SemanticVersionComponent> comparison = + SemanticVersionComparator.compare( + vwc.getLeftVersion(), + vwc.getRightVersion()); + + Assert.assertTrue( + String.format( + "Semantic versions [%s] and [%s] failed check.", + vwc.getLeftVersion(), vwc.getRightVersion()), + vwc.forwardCheck(comparison.getLeft())); + Assert.assertTrue( + String.format( + "Semantic versions [%s] and [%s] failed expected component change:" + + "got [%s], expected [%s]", + vwc.getLeftVersion(), + vwc.getRightVersion(), + comparison.getRight(), + vwc.getChangedComponent()), + comparison.getRight() == vwc.getChangedComponent()); + } + } +} diff --git a/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionTests.java b/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionTests.java new file mode 100644 index 0000000..1866fc3 --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/negotiation/SemanticVersionTests.java @@ -0,0 +1,37 @@ +package com.capitati.omtc.core.negotiation; + +import java.util.ArrayList; +import java.util.Collection; + +import junit.framework.Assert; + +import org.junit.Test; + +public class SemanticVersionTests { + private static final Collection<ISemanticVersion> versions = + new ArrayList<ISemanticVersion>() { + private static final long serialVersionUID = 1L; + { + add(new SemanticVersion(1, 0, 0, "alpha", null)); + add(new SemanticVersion(1, 0, 0, "alpha.1", null)); + add(new SemanticVersion(1, 0, 0, "beta.2", null)); + add(new SemanticVersion(1, 0, 0, "beta.11", null)); + add(new SemanticVersion(1, 0, 0, "rc.1", null)); + add(new SemanticVersion(1, 0, 0, "rc.1", "build.1")); + add(new SemanticVersion(1, 0, 0)); + add(new SemanticVersion(1, 0, 0, null, "0.3.7")); + add(new SemanticVersion(1, 3, 7, null, "build")); + add(new SemanticVersion(1, 3, 7, null, "build.2.b8f12d7")); + add(new SemanticVersion(1, 3, 7, null, "build.11.e0f985a")); + }}; + + @Test + public void testSemanticVersionParsing() + throws SemanticVersionParseException { + for(ISemanticVersion target : versions) { + final ISemanticVersion version = + SemanticVersion.parseVersion(target.toString()); + Assert.assertEquals(target, version); + } + } +} diff --git a/src/test/java/com/capitati/omtc/core/session/PrimaryResource.java b/src/test/java/com/capitati/omtc/core/session/PrimaryResource.java new file mode 100644 index 0000000..dedf86b --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/session/PrimaryResource.java @@ -0,0 +1,75 @@ +package com.capitati.omtc.core.session; + +import java.net.URI; +import java.util.Date; +import java.util.UUID; + +import com.capitati.omtc.core.resources.IPrimaryResource; + +public class PrimaryResource implements IPrimaryResource { + final UUID resourceId; + final URI resourceUri; + final Date resourceBirthDate; + + public PrimaryResource( + final UUID resourceId, + final URI resourceUri, + final Date resourceBirthDate) { + super(); + this.resourceId = resourceId; + this.resourceUri = resourceUri; + this.resourceBirthDate = resourceBirthDate; + } + + public UUID getIdentifier() { + return resourceId; + } + + public URI getURI() { + return resourceUri; + } + + public Date getBirthDate() { + return resourceBirthDate; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((resourceBirthDate == null) ? 0 : resourceBirthDate.hashCode()); + result = prime * result + + ((resourceId == null) ? 0 : resourceId.hashCode()); + result = prime * result + + ((resourceUri == null) ? 0 : resourceUri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) + return true; + if(obj == null) + return false; + if(getClass() != obj.getClass()) + return false; + PrimaryResource other = (PrimaryResource) obj; + if(resourceBirthDate == null) { + if(other.resourceBirthDate != null) + return false; + } else if(!resourceBirthDate.equals(other.resourceBirthDate)) + return false; + if(resourceId == null) { + if(other.resourceId != null) + return false; + } else if(!resourceId.equals(other.resourceId)) + return false; + if(resourceUri == null) { + if(other.resourceUri != null) + return false; + } else if(!resourceUri.equals(other.resourceUri)) + return false; + return true; + } +} diff --git a/src/test/java/com/capitati/omtc/core/session/ResourceUploadDelegate.java b/src/test/java/com/capitati/omtc/core/session/ResourceUploadDelegate.java new file mode 100644 index 0000000..208122f --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/session/ResourceUploadDelegate.java @@ -0,0 +1,79 @@ +package com.capitati.omtc.core.session; + +import java.io.IOException; +import java.net.URI; +import java.util.Date; +import java.util.UUID; + +import org.apache.commons.lang3.ArrayUtils; + +import com.capitati.omtc.core.resources.IResource; +import com.capitati.omtc.core.resources.IResourceReader; +import com.capitati.omtc.core.resources.IResourceWriter; + +public class ResourceUploadDelegate implements IResourceTransferDelegate { + private final IResource resource; + private final String source; + private byte[] destination; + + public ResourceUploadDelegate( + final String theSource, + final UUID theResourceId, + final URI theResourceUri, + final Date theResourceBirthDate) { + source = theSource; + resource = new PrimaryResource( + theResourceId, theResourceUri, theResourceBirthDate); + } + + public IResourceReader getResourceReader(final ISession theInvokingSession) + throws Exception { + return new IResourceReader() { + private final byte[] readerSource = source.getBytes(); + private int noBytesRead = 0; + + public int read(final byte[] buffer) throws IOException { + if(noBytesRead >= readerSource.length) { + return -1; + } + + int bytesRead = 0; + for(int idx = 0; + (idx < buffer.length) && ((noBytesRead + bytesRead) < readerSource.length); + idx++) { + buffer[idx] = readerSource[noBytesRead + idx]; + bytesRead += 1; + } + + noBytesRead += bytesRead; + + return bytesRead; + } + + public void close() throws IOException { + } + }; + } + + public IResourceWriter getResourceWriter(final ISession theInvokingSession) + throws Exception { + return new IResourceWriter() { + public void write(byte[] chunk, int chunkLength) throws IOException { + destination = ArrayUtils.addAll( + destination, + ArrayUtils.subarray(chunk, 0, chunkLength)); + } + + public void close() throws IOException { + } + }; + } + + public IResource getResource(final ISession theInvokingSession) { + return resource; + } + + public byte[] getDestination() { + return destination; + } +} diff --git a/src/test/java/com/capitati/omtc/core/session/SessionTestException.java b/src/test/java/com/capitati/omtc/core/session/SessionTestException.java new file mode 100644 index 0000000..372a8ef --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/session/SessionTestException.java @@ -0,0 +1,7 @@ +package com.capitati.omtc.core.session; + +import java.io.IOException; + +public class SessionTestException extends IOException { + private static final long serialVersionUID = 7413491732377268653L; +} diff --git a/src/test/java/com/capitati/omtc/core/session/SessionTests.java b/src/test/java/com/capitati/omtc/core/session/SessionTests.java new file mode 100644 index 0000000..986a696 --- /dev/null +++ b/src/test/java/com/capitati/omtc/core/session/SessionTests.java @@ -0,0 +1,203 @@ +package com.capitati.omtc.core.session; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Date; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.capitati.omtc.core.notification.IResourceUploadObserver; +import com.capitati.omtc.core.resources.IResource; +import com.capitati.omtc.core.resources.IResourceReader; +import com.capitati.omtc.core.resources.IResourceWriter; +import com.google.common.base.Predicate; + +public class SessionTests { + class TestSession extends Session { + protected TestSession( + final UUID theIdentifier, + final AbstractExecutorService theDelegationExecutorService, + final int bufferSize) { + super(theIdentifier, theDelegationExecutorService, bufferSize); + } + + public Set<IResource> retrieveResources(final Predicate<IResource> theFilter) + throws Exception { + return null; + } + + public void removeResource(final IResource resource) throws Exception { + } + } + + private static final String MESSAGE = + "Whose was it? His who is gone. " + + "Who shall have it? He who will come. " + + "Where was the sun? Over the oak. " + + "Where was the shadow? Under the elm. " + + "How was it stepped? North by ten and by ten, east by five and by five, " + + "south by two and by two, west by one and by one, and so under. " + + "What shall we give for it? All that is ours. " + + "Why should we give it? For the sake of the trust."; + + private final UUID resourceId = UUID.randomUUID(); + private final Date resourceBirthDate = new Date(); + + private URI resourceUri; + private Mockery mockery; + private AbstractExecutorService executor; + private Session session; + + @Before + public void setUp() throws URISyntaxException { + mockery = new JUnit4Mockery(); + resourceUri = new URI("test://some_resource_or_other"); + executor = new ThreadPoolExecutor( + 1, + 1, + 0, + TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1)); + session = new TestSession(UUID.randomUUID(), executor, MESSAGE.length() / 4); + } + + @After + public void tearDown() { + executor.shutdown(); + } + + @Test + public void testSuccessfulUpload() throws Exception { + final IResourceTransferDelegate delegate = new ResourceUploadDelegate( + MESSAGE, + resourceId, + resourceUri, + resourceBirthDate); + final IResourceUploadObserver observer = + mockery.mock(IResourceUploadObserver.class, "successUploadObserver"); + final IResource targetResource = delegate.getResource(session); + + mockery.checking(new Expectations() {{ + oneOf(observer).onSuccess( + with(equal(session)), + with(equal(targetResource))); + }}); + + final Future<IResource> futureResource = session.uploadResource(delegate, observer); + final IResource resource = futureResource.get(); + + Assert.assertSame("Wrong resource", targetResource, resource); + } + + @Test(expected = SessionTestException.class) + public void testReaderReadFailureOnUpload() throws Throwable { + final Exception targetException = new SessionTestException(); + final IResourceReader resourceReader = + mockery.mock(IResourceReader.class, "resourceReader"); + final IResourceWriter resourceWriter = + mockery.mock(IResourceWriter.class, "resourceWriter"); + final IResourceTransferDelegate delegate = + mockery.mock(IResourceTransferDelegate.class, "badUploadDelegate"); + final IResourceUploadObserver observer = + mockery.mock(IResourceUploadObserver.class, "badUploadObserver"); + final IResource resource = + mockery.mock(IResource.class, "badResource"); + + mockery.checking(new Expectations() {{ + allowing(delegate).getResource(with(equal(session))); + will(returnValue(resource)); + + oneOf(resourceReader).read(with(any(byte[].class))); + will(throwException(targetException)); + + oneOf(resourceReader).close(); + + oneOf(resourceWriter).close(); + + oneOf(delegate).getResourceReader(with(equal(session))); + will(returnValue(resourceReader)); + + oneOf(delegate).getResourceWriter(with(equal(session))); + will(returnValue(resourceWriter)); + + oneOf(observer).onError( + with(equal(session)), + with(equal(resource)), + with(equal(targetException))); + }}); + + final Future<IResource> futureResource = + session.uploadResource(delegate, observer); + + try { + @SuppressWarnings("unused") + final IResource future = futureResource.get(); + } catch(final ExecutionException ex) { + throw ex.getCause(); + } + } + + @Test(expected = SessionTestException.class) + public void testWriterWriteFailureOnUpload() throws Throwable { + final Exception targetException = new SessionTestException(); + final IResourceReader resourceReader = + mockery.mock(IResourceReader.class, "resourceReader"); + final IResourceWriter resourceWriter = + mockery.mock(IResourceWriter.class, "resourceWriter"); + final IResourceTransferDelegate delegate = + mockery.mock(IResourceTransferDelegate.class, "badUploadDelegate"); + final IResourceUploadObserver observer = + mockery.mock(IResourceUploadObserver.class, "badUploadObserver"); + final IResource resource = + mockery.mock(IResource.class, "badResource"); + + mockery.checking(new Expectations() {{ + allowing(delegate).getResource(with(equal(session))); + will(returnValue(resource)); + + oneOf(resourceReader).read(with(any(byte[].class))); + will(returnValue(7)); + + oneOf(resourceReader).close(); + + oneOf(resourceWriter).write(with(any(byte[].class)), with(any(int.class))); + will(throwException(targetException)); + + oneOf(resourceWriter).close(); + + oneOf(delegate).getResourceReader(with(equal(session))); + will(returnValue(resourceReader)); + + oneOf(delegate).getResourceWriter(with(equal(session))); + will(returnValue(resourceWriter)); + + oneOf(observer).onError( + with(equal(session)), + with(equal(resource)), + with(equal(targetException))); + }}); + + final Future<IResource> futureResource = + session.uploadResource(delegate, observer); + + try { + @SuppressWarnings("unused") + final IResource future = futureResource.get(); + } catch(final ExecutionException ex) { + throw ex.getCause(); + } + } +} |