Skip to content

Commit

Permalink
Merge pull request #935 from jplag/develop
Browse files Browse the repository at this point in the history
Merge develop into main
  • Loading branch information
tsaglam authored Feb 15, 2023
2 parents 1a7ca3c + 5534af2 commit 0c56723
Show file tree
Hide file tree
Showing 132 changed files with 25,674 additions and 15,271 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/report-viewer-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Report Viewer Deployment Workflow (Dev)

on:
workflow_dispatch: # Use this to dispatch from the Actions Tab
push:
branches:
- develop

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v3

- uses: actions/setup-node@v3
with:
node-version: "16"

- name: Set version of Report Viewer
shell: bash
run: |
VERSION=$(grep "<revision>" pom.xml | grep -oPm1 "(?<=<revision>)[^-|<]+")
MAJOR=$(echo $VERSION | cut -d '.' -f 1)
MINOR=$(echo $VERSION | cut -d '.' -f 2)
PATCH=$(echo $VERSION | cut -d '.' -f 3)
sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json
sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json
sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json
echo "Version of Report Viewer:"
cat report-viewer/src/version.json
- name: Install and Build 🔧
working-directory: report-viewer
run: |
npm install
npm run build
- name: Deploy 🚀
uses: JamesIves/[email protected]
with:
branch: gh-pages
folder: report-viewer/dist
repository-name: JPlag/JPlag-Dev
token: ${{ secrets.SDQ_DEV_DEPLOY_TOKEN }}
clean: true
single-commit: true
15 changes: 14 additions & 1 deletion .github/workflows/report-viewer-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,20 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: "16"


- name: Set version of Report Viewer
shell: bash
run: |
VERSION=$(grep "<revision>" pom.xml | grep -oPm1 "(?<=<revision>)[^-|<]+")
MAJOR=$(echo $VERSION | cut -d '.' -f 1)
MINOR=$(echo $VERSION | cut -d '.' -f 2)
PATCH=$(echo $VERSION | cut -d '.' -f 3)
sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json
sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json
sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json
echo "Version of Report Viewer:"
cat report-viewer/src/version.json
- name: Install and Build 🔧
working-directory: report-viewer
run: |
Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/report-viewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: "16"


- name: Set version of Report Viewer
shell: bash
run: |
VERSION=$(grep "<revision>" pom.xml | grep -oPm1 "(?<=<revision>)[^-|<]+")
MAJOR=$(echo $VERSION | cut -d '.' -f 1)
MINOR=$(echo $VERSION | cut -d '.' -f 2)
PATCH=$(echo $VERSION | cut -d '.' -f 3)
sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json
sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json
sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json
echo "Version of Report Viewer:"
cat report-viewer/src/version.json
- name: Install and Build 🔧
working-directory: report-viewer
run: |
Expand Down
35 changes: 19 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,33 @@
[![License](https://img.shields.io/github/license/jplag/jplag.svg)](https://github.com/jplag/jplag/blob/main/LICENSE)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/jplag/JPlag)](https://github.com/jplag/JPlag/pulse)
[![Report Viewer](https://img.shields.io/badge/report%20viewer-online-b80025)](https://jplag.github.io/JPlag/)
[![Java Version](https://img.shields.io/badge/java-SE%2017-yellowgreen)](#download-and-installation)


JPlag is a system that finds similarities among multiple sets of source code files. This way it can detect software plagiarism and collusion in software development. JPlag currently supports various programming languages, EMF metamodels, and natural language text.

## Supported Languages

In the following, a list of all supported languages with their supported language version is provided. A language can be selected from the command line using the `-l <cli argument name>` argument.

| Language | Version | CLI Argument Name | [state](https://github.com/jplag/JPlag/wiki/3.-Language-Modules) | parser |
|------------------------------------------------------------------|--------:|-----------------------| :---: | :---: |
| [Java](https://www.java.com) | 17 | java | mature | JavaC |
| [C++](https://isocpp.org) | 11 | cpp | legacy | JavaCC |
| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) | 8 | csharp | beta | ANTLR 4 |
| [Go](https://go.dev) | 1.17 | golang | beta | ANTLR 4 |
| [Kotlin](https://kotlinlang.org) | 1.3 | kotlin | beta | ANTLR 4 |
| [Python](https://www.python.org) | 3.6 | python3 | legacy | ANTLR 4 |
| [R](https://www.r-project.org/) | 3.5.0 | rlang | beta | ANTLR 4 |
| [Rust](https://www.rust-lang.org/) | 1.60.0 | rust | beta | ANTLR 4 |
| [Scala](https://www.scala-lang.org) | 2.13.8 | scala | beta | Scalameta |
| [Scheme](http://www.scheme-reports.org) | ? | scheme | unknown | JavaCC |
| [Swift](https://www.swift.org) | 5.4 | swift | beta | ANTLR 4 |
| [EMF Metamodel](https://www.eclipse.org/modeling/emf/) | 2.25.0 | emf | alpha | EMF |
| Text (naive) | - | text | legacy | CoreNLP |
| Language | Version | CLI Argument Name | [state](https://github.com/jplag/JPlag/wiki/3.-Language-Modules) | parser |
|--------------------------------------------------------|--------:|-------------------|:----------------------------------------------------------------:|:---------:|
| [Java](https://www.java.com) | 17 | java | mature | JavaC |
| [C++](https://isocpp.org) | 11 | cpp | legacy | JavaCC |
| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) | 8 | csharp | beta | ANTLR 4 |
| [Go](https://go.dev) | 1.17 | golang | beta | ANTLR 4 |
| [Kotlin](https://kotlinlang.org) | 1.3 | kotlin | beta | ANTLR 4 |
| [Python](https://www.python.org) | 3.6 | python3 | legacy | ANTLR 4 |
| [R](https://www.r-project.org/) | 3.5.0 | rlang | beta | ANTLR 4 |
| [Rust](https://www.rust-lang.org/) | 1.60.0 | rust | beta | ANTLR 4 |
| [Scala](https://www.scala-lang.org) | 2.13.8 | scala | beta | Scalameta |
| [Scheme](http://www.scheme-reports.org) | ? | scheme | unknown | JavaCC |
| [Swift](https://www.swift.org) | 5.4 | swift | beta | ANTLR 4 |
| [EMF Metamodel](https://www.eclipse.org/modeling/emf/) | 2.25.0 | emf | alpha | EMF |
| Text (naive) | - | text | legacy | CoreNLP |

## Download and Installation
You need Java SE 17 to run or build JPlag.

### Downloading a release
* Download a [released version](https://github.com/jplag/jplag/releases).
Expand All @@ -51,7 +54,7 @@ JPlag is released on [Maven Central](https://search.maven.org/search?q=de.jplag)
1. Download or clone the code from this repository.
2. Run `mvn clean package` from the root of the repository to compile and build all submodules.
Run `mvn clean package assembly:single` instead if you need the full jar which includes all dependencies.
5. You will find the generated JARs in the subdirectory `jplag.cli/target`.
5. You will find the generated JARs in the subdirectory `cli/target`.

## Usage
JPlag can either be used via the CLI or directly via its Java API. For more information, see the [usage information in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). If you are using the CLI, you can display your results via [jplag.github.io](https://jplag.github.io/JPlag/). No data will leave your computer!
Expand Down
11 changes: 6 additions & 5 deletions cli/src/main/java/de/jplag/cli/CLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@
import java.util.Random;
import java.util.stream.Collectors;

import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -54,6 +49,11 @@
import de.jplag.options.JPlagOptions;
import de.jplag.reporting.reportobject.ReportObjectFactory;

import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

/**
* Command line interface class, allows using via command line.
* @see CLI#main(String[])
Expand Down Expand Up @@ -82,6 +82,7 @@ public final class CLI {
*/
public static void main(String[] args) {
try {
logger.debug("Your version of JPlag is {}", JPlag.JPLAG_VERSION);
CLI cli = new CLI();
Namespace arguments = cli.parseArguments(args);
JPlagOptions options = cli.buildOptionsFromArguments(arguments);
Expand Down
16 changes: 8 additions & 8 deletions cli/src/main/java/de/jplag/cli/CommandLineArgument.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@
import java.util.List;
import java.util.Optional;

import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Argument;
import net.sourceforge.argparse4j.inf.ArgumentAction;
import net.sourceforge.argparse4j.inf.ArgumentContainer;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.FeatureControl;
import net.sourceforge.argparse4j.inf.Namespace;

import de.jplag.Language;
import de.jplag.Messages;
import de.jplag.NumberOfArgumentValues;
Expand All @@ -28,6 +20,14 @@
import de.jplag.clustering.algorithm.InterClusterSimilarity;
import de.jplag.options.SimilarityMetric;

import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Argument;
import net.sourceforge.argparse4j.inf.ArgumentAction;
import net.sourceforge.argparse4j.inf.ArgumentContainer;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.FeatureControl;
import net.sourceforge.argparse4j.inf.Namespace;

/**
* Command line arguments for the JPlag CLI. Each argument is defined through an enumeral.
* @author Timur Saglam
Expand Down
4 changes: 2 additions & 2 deletions cli/src/test/java/de/jplag/cli/CommandLineInterfaceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import java.util.Arrays;

import net.sourceforge.argparse4j.inf.Namespace;

import de.jplag.options.JPlagOptions;

import net.sourceforge.argparse4j.inf.Namespace;

/**
* Test base for tests regarding the {@link CLI} and any {@link CommandLineArgument}. Solely tests if the arguments set
* via the command line interface are propagated correctly into options. JPlag is not executed for the different command
Expand Down
9 changes: 9 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,13 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
12 changes: 12 additions & 0 deletions core/src/main/java/de/jplag/JPlag.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package de.jplag;

import java.util.ResourceBundle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.clustering.ClusteringFactory;
import de.jplag.exceptions.ExitException;
import de.jplag.exceptions.SubmissionException;
import de.jplag.options.JPlagOptions;
import de.jplag.reporting.reportobject.model.Version;
import de.jplag.strategy.ComparisonStrategy;
import de.jplag.strategy.ParallelComparisonStrategy;

Expand All @@ -16,6 +19,15 @@
public class JPlag {
private static final Logger logger = LoggerFactory.getLogger(JPlag.class);

public static final Version JPLAG_VERSION = loadVersion();

private static Version loadVersion() {
ResourceBundle versionProperties = ResourceBundle.getBundle("de.jplag.version");
String versionString = versionProperties.getString("version");
Version currentVersion = Version.parseVersion(versionString);
return currentVersion == null ? Version.DEVELOPMENT : currentVersion;
}

private final JPlagOptions options;

private final Language language;
Expand Down
27 changes: 24 additions & 3 deletions core/src/main/java/de/jplag/clustering/ClusteringFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@
* Runs the clustering according to an options object.
*/
public class ClusteringFactory {
private static final String CLUSTER_PATTERN = " cluster strength: {}, avg similarity: {}%, members: {}";
private static final int MAX_LOGGED_MEMBERS = 5;
private static final String STRENGTH_FORMAT = "%,.5f";
private static final String SIMILARITY_FORMAT = "%,.1f%%";
private static final String CLOSING_BRACKET = "]";
private static final String DOTS = "...";

private static final String CLUSTER_PATTERN = "avg similarity: {}, strength: {}, {} members: {}";
private static final String CLUSTERING_RESULT = "{} clusters were found:";
private static final String CLUSTERING_PARAMETERS = "Calculating clusters via {} clustering with {} pre-processing...";
private static final String CLUSTERING_DISABLED = "Cluster calculation disabled (as requested)!";

private static final Logger logger = LoggerFactory.getLogger(ClusteringFactory.class);

public static List<ClusteringResult<Submission>> getClusterings(Collection<JPlagComparison> comparisons, ClusteringOptions options) {
Expand Down Expand Up @@ -62,8 +69,22 @@ private static ClusteringResult<Submission> removeBadClusters(final ClusteringRe

private static void logClusters(ClusteringResult<Submission> result) {
var clusters = new ArrayList<>(result.getClusters());
clusters.sort((first, second) -> Double.compare(second.getCommunityStrength(), first.getCommunityStrength()));
clusters.sort((first, second) -> Double.compare(second.getAverageSimilarity(), first.getAverageSimilarity()));
logger.info(CLUSTERING_RESULT, clusters.size());
clusters.forEach(it -> logger.info(CLUSTER_PATTERN, it.getCommunityStrength(), it.getAverageSimilarity(), it.getMembers()));
clusters.forEach(ClusteringFactory::logCluster);
}

private static void logCluster(Cluster<Submission> cluster) {
String members = membersToString(cluster.getMembers());
String similarity = String.format(SIMILARITY_FORMAT, cluster.getAverageSimilarity() * 100);
String strength = String.format(STRENGTH_FORMAT, cluster.getCommunityStrength());
logger.info(CLUSTER_PATTERN, similarity, strength, cluster.getMembers().size(), members);
}

private static String membersToString(Collection<Submission> members) {
if (members.size() > MAX_LOGGED_MEMBERS) {
return List.copyOf(members).subList(0, MAX_LOGGED_MEMBERS).toString().replace(CLOSING_BRACKET, DOTS);
}
return members.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public ClusteringOptions(SimilarityMetric similarityMetric, double spectralKerne
}

public ClusteringOptions() {
this(SimilarityMetric.MAX, 20.f, 0.05 * 0.05, 5, 50, 200, 0.2, Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION, true,
this(SimilarityMetric.AVG, 20.f, 0.05 * 0.05, 5, 50, 200, 0.2, Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION, true,
ClusteringAlgorithm.SPECTRAL, InterClusterSimilarity.AVERAGE, 0.2, 0.5);
}

Expand Down
17 changes: 12 additions & 5 deletions core/src/main/java/de/jplag/options/SimilarityMetric.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import de.jplag.JPlagComparison;

public enum SimilarityMetric implements ToDoubleFunction<JPlagComparison> {
AVG(JPlagComparison::similarity),
MIN(JPlagComparison::minimalSimilarity),
MAX(JPlagComparison::maximalSimilarity),
INTERSECTION(it -> (double) it.getNumberOfMatchedTokens());
AVG("average similarity", JPlagComparison::similarity),
MIN("minimum similarity", JPlagComparison::minimalSimilarity),
MAX("maximal similarity", JPlagComparison::maximalSimilarity),
INTERSECTION("matched tokens", it -> (double) it.getNumberOfMatchedTokens());

private final ToDoubleFunction<JPlagComparison> similarityFunction;
private final String description;

SimilarityMetric(ToDoubleFunction<JPlagComparison> similarityFunction) {
SimilarityMetric(String description, ToDoubleFunction<JPlagComparison> similarityFunction) {
this.description = description;
this.similarityFunction = similarityFunction;
}

Expand All @@ -24,4 +26,9 @@ public boolean isAboveThreshold(JPlagComparison comparison, double similarityThr
public double applyAsDouble(JPlagComparison comparison) {
return similarityFunction.applyAsDouble(comparison);
}

@Override
public String toString() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.jplag.reporting.jsonfactory;

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -104,7 +105,10 @@ private Match convertMatchToReportMatch(JPlagComparison comparison, de.jplag.Mat
}

private String relativizedFilePath(File file, Submission submission) {
return submission.getRoot().toPath().relativize(file.toPath()).toString();
if (file.toPath().equals(submission.getRoot().toPath())) {
return Path.of(submissionToIdFunction.apply(submission), submission.getName()).toString();
}
return Path.of(submissionToIdFunction.apply(submission), submission.getRoot().toPath().relativize(file.toPath()).toString()).toString();
}

}
Loading

0 comments on commit 0c56723

Please sign in to comment.