mirror of https://github.com/apache/archiva.git
upgrade lucene to 2.0.0
git-svn-id: https://svn.apache.org/repos/asf/maven/repository-manager/trunk@425600 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
206cdfc17f
commit
0f715e2904
|
@ -37,11 +37,10 @@
|
||||||
<groupId>org.apache.maven</groupId>
|
<groupId>org.apache.maven</groupId>
|
||||||
<artifactId>maven-model</artifactId>
|
<artifactId>maven-model</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- TODO! upgrade to lucene 2.0.0 -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>lucene</groupId>
|
<groupId>org.apache.lucene</groupId>
|
||||||
<artifactId>lucene</artifactId>
|
<artifactId>lucene-core</artifactId>
|
||||||
<version>1.4.3</version>
|
<version>2.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
|
|
@ -159,7 +159,7 @@ public abstract class AbstractRepositoryIndex
|
||||||
{
|
{
|
||||||
if ( indexReader.numDocs() > 0 )
|
if ( indexReader.numDocs() > 0 )
|
||||||
{
|
{
|
||||||
Collection fields = indexReader.getFieldNames();
|
Collection fields = indexReader.getFieldNames( IndexReader.FieldOption.ALL );
|
||||||
for ( int idx = 0; idx < FIELDS.length; idx++ )
|
for ( int idx = 0; idx < FIELDS.length; idx++ )
|
||||||
{
|
{
|
||||||
if ( !fields.contains( FIELDS[idx] ) )
|
if ( !fields.contains( FIELDS[idx] ) )
|
||||||
|
@ -218,7 +218,7 @@ public abstract class AbstractRepositoryIndex
|
||||||
{
|
{
|
||||||
Term term = (Term) terms.next();
|
Term term = (Term) terms.next();
|
||||||
|
|
||||||
indexReader.delete( term );
|
indexReader.deleteDocuments( term );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
@ -239,30 +239,44 @@ public class ArtifactRepositoryIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
Document doc = new Document();
|
Document doc = new Document();
|
||||||
doc.add( Field.Keyword( FLD_ID, ARTIFACT + ":" + artifact.getId() ) );
|
doc.add( createKeywordField( FLD_ID, ARTIFACT + ":" + artifact.getId() ) );
|
||||||
doc.add( Field.Text( FLD_NAME, artifact.getFile().getName() ) );
|
doc.add( createTextField( FLD_NAME, artifact.getFile().getName() ) );
|
||||||
doc.add( Field.Text( FLD_GROUPID, artifact.getGroupId() ) );
|
doc.add( createTextField( FLD_GROUPID, artifact.getGroupId() ) );
|
||||||
doc.add( Field.Text( FLD_ARTIFACTID, artifact.getArtifactId() ) );
|
doc.add( createTextField( FLD_ARTIFACTID, artifact.getArtifactId() ) );
|
||||||
doc.add( Field.Text( FLD_VERSION, artifact.getVersion() ) );
|
doc.add( createTextField( FLD_VERSION, artifact.getVersion() ) );
|
||||||
doc.add( Field.Text( FLD_SHA1, sha1sum ) );
|
doc.add( createTextField( FLD_SHA1, sha1sum ) );
|
||||||
doc.add( Field.Text( FLD_MD5, md5sum ) );
|
doc.add( createTextField( FLD_MD5, md5sum ) );
|
||||||
doc.add( Field.Text( FLD_CLASSES, classes.toString() ) );
|
doc.add( createTextField( FLD_CLASSES, classes.toString() ) );
|
||||||
doc.add( Field.Text( FLD_PACKAGES, packages.toString() ) );
|
doc.add( createTextField( FLD_PACKAGES, packages.toString() ) );
|
||||||
doc.add( Field.Text( FLD_FILES, files.toString() ) );
|
doc.add( createTextField( FLD_FILES, files.toString() ) );
|
||||||
doc.add( Field.UnIndexed( FLD_DOCTYPE, ARTIFACT ) );
|
doc.add( createUnindexedField( FLD_DOCTYPE, ARTIFACT ) );
|
||||||
doc.add( Field.Text( FLD_LASTUPDATE, "" ) );
|
doc.add( createTextField( FLD_LASTUPDATE, "" ) );
|
||||||
doc.add( Field.Text( FLD_PLUGINPREFIX, "" ) );
|
doc.add( createTextField( FLD_PLUGINPREFIX, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_LICENSE_URLS, "" ) );
|
doc.add( createKeywordField( FLD_LICENSE_URLS, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_DEPENDENCIES, "" ) );
|
doc.add( createKeywordField( FLD_DEPENDENCIES, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_REPORT, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_REPORT, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_BUILD, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_BUILD, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_ALL, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_ALL, "" ) );
|
||||||
int i = artifact.getFile().getName().lastIndexOf( '.' );
|
int i = artifact.getFile().getName().lastIndexOf( '.' );
|
||||||
doc.add( Field.Text( FLD_PACKAGING, artifact.getFile().getName().substring( i + 1 ) ) );
|
doc.add( createTextField( FLD_PACKAGING, artifact.getFile().getName().substring( i + 1 ) ) );
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Field createUnindexedField( String name, String value )
|
||||||
|
{
|
||||||
|
return new Field( name, value, Field.Store.YES, Field.Index.NO );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Field createTextField( String name, String value )
|
||||||
|
{
|
||||||
|
return new Field( name, value, Field.Store.YES, Field.Index.TOKENIZED );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Field createKeywordField( String name, String value )
|
||||||
|
{
|
||||||
|
return new Field( name, value, Field.Store.YES, Field.Index.UN_TOKENIZED );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to add a class package to the buffer of packages
|
* Method to add a class package to the buffer of packages
|
||||||
|
@ -413,15 +427,15 @@ public class ArtifactRepositoryIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
Document doc = new Document();
|
Document doc = new Document();
|
||||||
doc.add( Field.Keyword( FLD_ID, POM + ":" + artifact.getId() ) );
|
doc.add( createKeywordField( FLD_ID, POM + ":" + artifact.getId() ) );
|
||||||
doc.add( Field.Text( FLD_GROUPID, groupId ) );
|
doc.add( createTextField( FLD_GROUPID, groupId ) );
|
||||||
doc.add( Field.Text( FLD_ARTIFACTID, pom.getArtifactId() ) );
|
doc.add( createTextField( FLD_ARTIFACTID, pom.getArtifactId() ) );
|
||||||
doc.add( Field.Text( FLD_VERSION, version ) );
|
doc.add( createTextField( FLD_VERSION, version ) );
|
||||||
doc.add( Field.Keyword( FLD_PACKAGING, pom.getPackaging() ) );
|
doc.add( createKeywordField( FLD_PACKAGING, pom.getPackaging() ) );
|
||||||
|
|
||||||
File pomFile = new File( repository.getBasedir(), repository.pathOf( artifact ) );
|
File pomFile = new File( repository.getBasedir(), repository.pathOf( artifact ) );
|
||||||
doc.add( Field.Text( FLD_SHA1, getChecksum( Digester.SHA1, pomFile.getAbsolutePath() ) ) );
|
doc.add( createTextField( FLD_SHA1, getChecksum( Digester.SHA1, pomFile.getAbsolutePath() ) ) );
|
||||||
doc.add( Field.Text( FLD_MD5, getChecksum( Digester.MD5, pomFile.getAbsolutePath() ) ) );
|
doc.add( createTextField( FLD_MD5, getChecksum( Digester.MD5, pomFile.getAbsolutePath() ) ) );
|
||||||
|
|
||||||
indexLicenseUrls( doc, pom );
|
indexLicenseUrls( doc, pom );
|
||||||
indexDependencies( doc, pom );
|
indexDependencies( doc, pom );
|
||||||
|
@ -435,7 +449,7 @@ public class ArtifactRepositoryIndex
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_PLUGINS_BUILD, "" ) );
|
doc.add( createTextField( FLD_PLUGINS_BUILD, "" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pom.getReporting() != null && pom.getReporting().getPlugins() != null &&
|
if ( pom.getReporting() != null && pom.getReporting().getPlugins() != null &&
|
||||||
|
@ -447,21 +461,21 @@ public class ArtifactRepositoryIndex
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_PLUGINS_REPORT, "" ) );
|
doc.add( createTextField( FLD_PLUGINS_REPORT, "" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !hasPlugins )
|
if ( !hasPlugins )
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_PLUGINS_ALL, "" ) );
|
doc.add( createTextField( FLD_PLUGINS_ALL, "" ) );
|
||||||
}
|
}
|
||||||
doc.add( Field.UnIndexed( FLD_DOCTYPE, POM ) );
|
doc.add( createUnindexedField( FLD_DOCTYPE, POM ) );
|
||||||
// TODO: do we need to add all these empty fields?
|
// TODO: do we need to add all these empty fields?
|
||||||
doc.add( Field.Text( FLD_PLUGINPREFIX, "" ) );
|
doc.add( createTextField( FLD_PLUGINPREFIX, "" ) );
|
||||||
doc.add( Field.Text( FLD_LASTUPDATE, "" ) );
|
doc.add( createTextField( FLD_LASTUPDATE, "" ) );
|
||||||
doc.add( Field.Text( FLD_NAME, "" ) );
|
doc.add( createTextField( FLD_NAME, "" ) );
|
||||||
doc.add( Field.Text( FLD_CLASSES, "" ) );
|
doc.add( createTextField( FLD_CLASSES, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PACKAGES, "" ) );
|
doc.add( createKeywordField( FLD_PACKAGES, "" ) );
|
||||||
doc.add( Field.Text( FLD_FILES, "" ) );
|
doc.add( createTextField( FLD_FILES, "" ) );
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,13 +497,13 @@ public class ArtifactRepositoryIndex
|
||||||
String url = license.getUrl();
|
String url = license.getUrl();
|
||||||
if ( StringUtils.isNotEmpty( url ) )
|
if ( StringUtils.isNotEmpty( url ) )
|
||||||
{
|
{
|
||||||
doc.add( Field.Keyword( FLD_LICENSE_URLS, url ) );
|
doc.add( createKeywordField( FLD_LICENSE_URLS, url ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Keyword( FLD_LICENSE_URLS, "" ) );
|
doc.add( createKeywordField( FLD_LICENSE_URLS, "" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,12 +523,12 @@ public class ArtifactRepositoryIndex
|
||||||
{
|
{
|
||||||
Dependency dep = (Dependency) dependencies.next();
|
Dependency dep = (Dependency) dependencies.next();
|
||||||
String id = getId( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
|
String id = getId( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
|
||||||
doc.add( Field.Keyword( FLD_DEPENDENCIES, id ) );
|
doc.add( createKeywordField( FLD_DEPENDENCIES, id ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Keyword( FLD_DEPENDENCIES, "" ) );
|
doc.add( createKeywordField( FLD_DEPENDENCIES, "" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +545,7 @@ public class ArtifactRepositoryIndex
|
||||||
{
|
{
|
||||||
Plugin plugin = (Plugin) plugins.next();
|
Plugin plugin = (Plugin) plugins.next();
|
||||||
String id = getId( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
|
String id = getId( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
|
||||||
doc.add( Field.Keyword( field, id ) );
|
doc.add( createKeywordField( field, id ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +562,7 @@ public class ArtifactRepositoryIndex
|
||||||
{
|
{
|
||||||
ReportPlugin plugin = (ReportPlugin) plugins.next();
|
ReportPlugin plugin = (ReportPlugin) plugins.next();
|
||||||
String id = getId( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
|
String id = getId( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
|
||||||
doc.add( Field.Keyword( field, id ) );
|
doc.add( createKeywordField( field, id ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,11 +196,13 @@ public class EclipseRepositoryIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
doc = new Document();
|
doc = new Document();
|
||||||
doc.add( Field.Text( MD5, md5 ) );
|
doc.add( new Field( MD5, md5, Field.Store.YES, Field.Index.UN_TOKENIZED ) );
|
||||||
doc.add( Field.Text( JAR_NAME, artifactFile.getName() ) );
|
doc.add( new Field( JAR_NAME, artifactFile.getName(), Field.Store.YES, Field.Index.TOKENIZED ) );
|
||||||
doc.add( Field.Text( JAR_DATE, DateField.timeToString( artifactFile.lastModified() ) ) );
|
doc.add( new Field( JAR_DATE, DateField.timeToString( artifactFile.lastModified() ), Field.Store.YES,
|
||||||
doc.add( Field.Text( JAR_SIZE, Long.toString( artifactFile.length() ) ) );
|
Field.Index.UN_TOKENIZED ) );
|
||||||
doc.add( Field.Text( NAMES, classes.toString() ) );
|
doc.add( new Field( JAR_SIZE, Long.toString( artifactFile.length() ), Field.Store.YES,
|
||||||
|
Field.Index.UN_TOKENIZED ) );
|
||||||
|
doc.add( new Field( NAMES, classes.toString(), Field.Store.YES, Field.Index.TOKENIZED ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
|
|
|
@ -137,19 +137,19 @@ public class MetadataRepositoryIndex
|
||||||
//get the metadatapath: check where metadata is located, then concatenate the groupId,
|
//get the metadatapath: check where metadata is located, then concatenate the groupId,
|
||||||
// artifactId, version based on its location
|
// artifactId, version based on its location
|
||||||
Document doc = new Document();
|
Document doc = new Document();
|
||||||
doc.add( Field.Keyword( FLD_ID, (String) repoMetadata.getKey() ) );
|
doc.add( createKeywordField( FLD_ID, (String) repoMetadata.getKey() ) );
|
||||||
Metadata metadata = repoMetadata.getMetadata();
|
Metadata metadata = repoMetadata.getMetadata();
|
||||||
|
|
||||||
doc.add( Field.Text( FLD_NAME, repository.pathOfRemoteRepositoryMetadata( repoMetadata ) ) );
|
doc.add( createTextField( FLD_NAME, repository.pathOfRemoteRepositoryMetadata( repoMetadata ) ) );
|
||||||
|
|
||||||
Versioning versioning = metadata.getVersioning();
|
Versioning versioning = metadata.getVersioning();
|
||||||
if ( versioning != null )
|
if ( versioning != null )
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_LASTUPDATE, versioning.getLastUpdated() ) );
|
doc.add( createTextField( FLD_LASTUPDATE, versioning.getLastUpdated() ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_LASTUPDATE, "" ) );
|
doc.add( createTextField( FLD_LASTUPDATE, "" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
List plugins = metadata.getPlugins();
|
List plugins = metadata.getPlugins();
|
||||||
|
@ -162,47 +162,57 @@ public class MetadataRepositoryIndex
|
||||||
pluginAppended = plugin.getPrefix() + "\n";
|
pluginAppended = plugin.getPrefix() + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doc.add( Field.Text( FLD_PLUGINPREFIX, pluginAppended ) );
|
doc.add( createTextField( FLD_PLUGINPREFIX, pluginAppended ) );
|
||||||
|
|
||||||
if ( metadata.getGroupId() != null )
|
if ( metadata.getGroupId() != null )
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_GROUPID, metadata.getGroupId() ) );
|
doc.add( createTextField( FLD_GROUPID, metadata.getGroupId() ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_GROUPID, "" ) );
|
doc.add( createTextField( FLD_GROUPID, "" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( metadata.getArtifactId() != null )
|
if ( metadata.getArtifactId() != null )
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_ARTIFACTID, metadata.getArtifactId() ) );
|
doc.add( createTextField( FLD_ARTIFACTID, metadata.getArtifactId() ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_ARTIFACTID, "" ) );
|
doc.add( createTextField( FLD_ARTIFACTID, "" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( metadata.getVersion() != null )
|
if ( metadata.getVersion() != null )
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_VERSION, metadata.getVersion() ) );
|
doc.add( createTextField( FLD_VERSION, metadata.getVersion() ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doc.add( Field.Text( FLD_VERSION, "" ) );
|
doc.add( createTextField( FLD_VERSION, "" ) );
|
||||||
}
|
}
|
||||||
// TODO: do we need to add all these empty fields?
|
// TODO: do we need to add all these empty fields?
|
||||||
doc.add( Field.Text( FLD_DOCTYPE, METADATA ) );
|
doc.add( createTextField( FLD_DOCTYPE, METADATA ) );
|
||||||
doc.add( Field.Keyword( FLD_PACKAGING, "" ) );
|
doc.add( createKeywordField( FLD_PACKAGING, "" ) );
|
||||||
doc.add( Field.Text( FLD_SHA1, "" ) );
|
doc.add( createTextField( FLD_SHA1, "" ) );
|
||||||
doc.add( Field.Text( FLD_MD5, "" ) );
|
doc.add( createTextField( FLD_MD5, "" ) );
|
||||||
doc.add( Field.Text( FLD_CLASSES, "" ) );
|
doc.add( createTextField( FLD_CLASSES, "" ) );
|
||||||
doc.add( Field.Text( FLD_PACKAGES, "" ) );
|
doc.add( createTextField( FLD_PACKAGES, "" ) );
|
||||||
doc.add( Field.Text( FLD_FILES, "" ) );
|
doc.add( createTextField( FLD_FILES, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_LICENSE_URLS, "" ) );
|
doc.add( createKeywordField( FLD_LICENSE_URLS, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_DEPENDENCIES, "" ) );
|
doc.add( createKeywordField( FLD_DEPENDENCIES, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_BUILD, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_BUILD, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_REPORT, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_REPORT, "" ) );
|
||||||
doc.add( Field.Keyword( FLD_PLUGINS_ALL, "" ) );
|
doc.add( createKeywordField( FLD_PLUGINS_ALL, "" ) );
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Field createTextField( String name, String value )
|
||||||
|
{
|
||||||
|
return new Field( name, value, Field.Store.YES, Field.Index.TOKENIZED );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Field createKeywordField( String name, String value )
|
||||||
|
{
|
||||||
|
return new Field( name, value, Field.Store.YES, Field.Index.UN_TOKENIZED );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.maven.repository.indexing.query;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.queryParser.ParseException;
|
import org.apache.lucene.queryParser.ParseException;
|
||||||
|
import org.apache.lucene.search.BooleanClause;
|
||||||
import org.apache.lucene.search.BooleanQuery;
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.maven.repository.indexing.RepositoryIndex;
|
import org.apache.maven.repository.indexing.RepositoryIndex;
|
||||||
|
|
||||||
|
@ -117,8 +118,9 @@ public class CompoundQuery
|
||||||
{
|
{
|
||||||
CompoundQueryTerm queryTerm = (CompoundQueryTerm) i.next();
|
CompoundQueryTerm queryTerm = (CompoundQueryTerm) i.next();
|
||||||
|
|
||||||
booleanQuery.add( queryTerm.getQuery().createLuceneQuery( index ), queryTerm.isRequired(),
|
booleanQuery.add( queryTerm.getQuery().createLuceneQuery( index ), queryTerm.isRequired()
|
||||||
queryTerm.isProhibited() );
|
? BooleanClause.Occur.MUST
|
||||||
|
: queryTerm.isProhibited() ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.SHOULD );
|
||||||
}
|
}
|
||||||
return booleanQuery;
|
return booleanQuery;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue