SEARCH-2548: Upgrade license headers

This commit is contained in:
Angel Borroy
2021-04-05 16:19:06 +02:00
parent 191a8d65ee
commit 3dd88e1a04
356 changed files with 36492 additions and 36492 deletions
@@ -1,57 +1,57 @@
/*
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.search;
public class TestGroup
{
// Used for TestRail test annotation
public static final String SEARCH = "search";
public static final String REST_API = "rest-api";
public static final String PREUPGRADE = "pre-upgrade";
public static final String POSTUPGRADE = "post-upgrade";
public static final String CONFIG_MASTER_SLAVE = "CONFIG_Master_Slave"; // Alfresco Search Services using master slave configurations
public static final String CONFIG_MASTER ="CONFIG_Master"; // Alfresco search services using master/stand alone mode
public static final String CONFIG_SHARDING ="CONFIG_Sharding"; // Alfresco search services using sharded environment
public static final String CONFIG_SHARDING_EXPLICIT ="CONFIG_Sharding_EXPLICIT"; // Alfresco search services using sharded environment and explicit routing
public static final String CONFIG_SHARDING_DB_ID_RANGE = "CONFIG_Sharding_DB_ID_RANGE"; // Alfresco Search Services using Sharding with DB_ID_RANGE
public static final String CONFIG_ENABLED_CASCADE_TRACKER ="Config_Enabled_Cascade_Tracker"; // Alfresco search services does not index fields related to cascaded updates
public static final String NOT_INSIGHT_ENGINE = "Not_InsightEngine"; // When Alfresco Insight Engine 1.0 isn't running
public static final String ACS_52n = "ACS_52n"; // Alfresco Content Services 5.2.n
public static final String ACS_60n = "ACS_60n"; // Alfresco Content Services 6.0 or above
public static final String ACS_61n = "ACS_61n"; // Alfresco Content Services 6.1 or above
public static final String ACS_611n = "ACS_611n"; // Alfresco Content Services 6.1.1 or above
public static final String ACS_62n = "ACS_62n"; // Alfresco Content Services 6.2 or above
public static final String ACS_63n = "ACS_63n"; // Alfresco Content Services 6.3 or above
public static final String AGS_302 = "AGS_302"; // Alfresco governance Services 3.0.2 or above
}
/*
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.search;
public class TestGroup
{
// Used for TestRail test annotation
public static final String SEARCH = "search";
public static final String REST_API = "rest-api";
public static final String PREUPGRADE = "pre-upgrade";
public static final String POSTUPGRADE = "post-upgrade";
public static final String CONFIG_MASTER_SLAVE = "CONFIG_Master_Slave"; // Alfresco Search Services using master slave configurations
public static final String CONFIG_MASTER ="CONFIG_Master"; // Alfresco search services using master/stand alone mode
public static final String CONFIG_SHARDING ="CONFIG_Sharding"; // Alfresco search services using sharded environment
public static final String CONFIG_SHARDING_EXPLICIT ="CONFIG_Sharding_EXPLICIT"; // Alfresco search services using sharded environment and explicit routing
public static final String CONFIG_SHARDING_DB_ID_RANGE = "CONFIG_Sharding_DB_ID_RANGE"; // Alfresco Search Services using Sharding with DB_ID_RANGE
public static final String CONFIG_ENABLED_CASCADE_TRACKER ="Config_Enabled_Cascade_Tracker"; // Alfresco search services does not index fields related to cascaded updates
public static final String NOT_INSIGHT_ENGINE = "Not_InsightEngine"; // When Alfresco Insight Engine 1.0 isn't running
public static final String ACS_52n = "ACS_52n"; // Alfresco Content Services 5.2.n
public static final String ACS_60n = "ACS_60n"; // Alfresco Content Services 6.0 or above
public static final String ACS_61n = "ACS_61n"; // Alfresco Content Services 6.1 or above
public static final String ACS_611n = "ACS_611n"; // Alfresco Content Services 6.1.1 or above
public static final String ACS_62n = "ACS_62n"; // Alfresco Content Services 6.2 or above
public static final String ACS_63n = "ACS_63n"; // Alfresco Content Services 6.3 or above
public static final String AGS_302 = "AGS_302"; // Alfresco governance Services 3.0.2 or above
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -116,4 +116,4 @@ public class SetupTest extends AbstractE2EFunctionalTest
Assert.assertTrue(waitForIndexing("cm:name:" + customFile.getName(),true),"New content could not be found");
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -336,4 +336,4 @@ public class FacetRangeSearchTest extends AbstractSearchServicesE2ETest
facetRangeModel.setGap(gap);
return facetRangeModel;
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -339,4 +339,4 @@ public class FacetedSearchTest extends AbstractSearchServicesE2ETest
bucket1.assertThat().field("filterQuery").is("modifier:\"" + testUser.getUsername() + "\"");
bucket1.assertThat().field("metrics").is("[{entry=null, type=count, value={count=1}}]");
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -208,4 +208,4 @@ public class SearchAPATHTest extends AbstractSearchServicesE2ETest
return buckets;
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -509,4 +509,4 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
Assert.assertTrue(isContentInSearchResponse(response, file2.getName()), "Expected file not returned in the search results: " + file2.getName());
testSearchSpellcheckResponse(response, null, null);
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -338,4 +338,4 @@ public class StatsSearchTest extends AbstractSearchServicesE2ETest
assertEquals(metrics.size(),metricsCount);
return metrics.stream().map(RestGenericMetricModel::getType).collect(Collectors.toSet());
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -127,4 +127,4 @@ public class SearchSolrAPITest extends AbstractE2EFunctionalTest
String errorMsg = "No QueryObjectBuilder defined for node a in {q={!xmlparser";
Assert.assertTrue(restClient.onResponse().getResponse().body().xmlPath().getString("response").contains(errorMsg));
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -67,4 +67,4 @@ public abstract class AbstractUpgradeE2ETest extends AbstractTestNGSpringContext
{
serverHealth.assertServerIsOnline();
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services E2E Test
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,63 +1,63 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import org.alfresco.error.AlfrescoRuntimeException;
public class AnalysisException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = -7722380192490118459L;
public AnalysisException(String msgId)
{
super(msgId);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Throwable cause)
{
super(msgId, cause);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
// TODO Auto-generated constructor stub
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import org.alfresco.error.AlfrescoRuntimeException;
public class AnalysisException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = -7722380192490118459L;
public AnalysisException(String msgId)
{
super(msgId);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Throwable cause)
{
super(msgId, cause);
// TODO Auto-generated constructor stub
}
public AnalysisException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
// TODO Auto-generated constructor stub
}
}
@@ -1,391 +1,391 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Locale;
import org.alfresco.repo.search.MLAnalysisMode;
import org.alfresco.solr.AlfrescoAnalyzerWrapper.Mode;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.springframework.extensions.surf.util.I18NUtil;
public class MLAnalayser extends Analyzer
{
private static Log s_logger = LogFactory.getLog(MLAnalayser.class);
private MLAnalysisMode mlAnalaysisMode;
private IndexSchema schema;
private Mode mode;
public MLAnalayser(MLAnalysisMode mlAnalaysisMode, IndexSchema schema, Mode mode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.mlAnalaysisMode = mlAnalaysisMode;
this.schema = schema;
this.mode = mode;
}
public MLAnalayser(MLAnalysisMode mlAnalaysisMode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.mlAnalaysisMode = mlAnalaysisMode;
}
@Override
protected TokenStreamComponents createComponents(String fieldName)
{
MLTokenizer mltokenizer = new MLTokenizer(fieldName, schema, mlAnalaysisMode, mode);
// try
// {
// mltokenizer.setLocaleAndPositionReaderAfterLocaleEncoding(reader);
// }
// catch (IOException e)
// {
// try{mltokenizer.close();} catch(IOException ioe) {};
// throw new AnalysisException("Failed to init MLTokenizer", e);
// }
return new LocaleAwareTokenStreamComponents(mltokenizer);
}
private static class LocaleAwareTokenStreamComponents extends Analyzer.TokenStreamComponents
{
MLTokenizer mltokenizer;
/**
* @param source
*/
public LocaleAwareTokenStreamComponents(final MLTokenizer source)
{
super(source);
this.mltokenizer = source;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Analyzer.TokenStreamComponents#setReader(java.io.Reader)
*/
@Override
protected void setReader(Reader reader)
{
super.setReader(mltokenizer.setLocaleAndPositionReaderAfterLocaleEncoding(reader));
}
}
private static class MLTokenizer extends Tokenizer
{
TokenStream ts;
String fieldName;
private IndexSchema schema;
MLAnalysisMode mlAnalaysisMode;
@SuppressWarnings("unused")
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
@SuppressWarnings("unused")
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
@SuppressWarnings("unused")
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
@SuppressWarnings("unused")
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private Mode mode;
MLTokenizer(String fieldName, IndexSchema schema, MLAnalysisMode mlAnalaysisMode, Mode mode)
{
this.fieldName = fieldName;
this.schema = schema;
this.mlAnalaysisMode = mlAnalaysisMode;
this.mode = mode;
}
/**
* @param reader
* @throws IOException
*/
public Reader setLocaleAndPositionReaderAfterLocaleEncoding(Reader reader)
{
Pair<Locale, Reader> pair = getLocaleAndPositioReaderAfterLocaleEncoding(fieldName, reader);
if(s_logger.isDebugEnabled())
{
s_logger.debug("Created ML analyser token stream for "+fieldName+ " with locale "+pair.getFirst());
}
TokenStream source = getAnalyser(fieldName, pair.getFirst()).tokenStream(fieldName, pair.getSecond());
ts = new MLTokenDuplicator(source, pair.getFirst(), pair.getSecond(), mlAnalaysisMode);
return pair.getSecond();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#close()
*/
@Override
public void close() throws IOException
{
ts.close();
super.close();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void reset() throws IOException
{
ts.reset();
super.reset();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void end() throws IOException
{
ts.end();
super.end();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.TokenStream#incrementToken()
*/
@Override
public boolean incrementToken() throws IOException
{
clearAttributes();
if(ts.incrementToken())
{
ts.copyTo(this);
return true;
}
else
{
ts.end();
ts.close();
return false;
}
}
public Pair<Locale,Reader> getLocaleAndPositioReaderAfterLocaleEncoding(String fieldName, Reader reader)
{
// We use read ahead to get the language info - if this does not exist we need to restart
// an use the default - there for we need mark and restore.
BufferedReader breader;
if (reader instanceof BufferedReader)
{
breader = (BufferedReader)reader;
}
else
{
breader = new BufferedReader(reader);
}
try
{
if (!breader.markSupported())
{
throw new AnalysisException(
"Multilingual tokenisation requires a reader that supports marks and reset");
}
breader.mark(100);
StringBuilder builder = new StringBuilder();
if (breader.read() == '\u0000')
{
String language = "";
String country = "";
String varient = "";
char c;
int count = 0;
while ((c = (char) breader.read()) != '\u0000')
{
if (count++ > 99)
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
if (c == '_')
{
if (language.length() == 0)
{
language = builder.toString();
}
else if (country.length() == 0)
{
country = builder.toString();
}
else if (varient.length() == 0)
{
varient = builder.toString();
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
builder = new StringBuilder();
}
else
{
builder.append(c);
}
}
if (builder.length() > 0)
{
if (language.length() == 0)
{
language = builder.toString();
}
else if (country.length() == 0)
{
country = builder.toString();
}
else if (varient.length() == 0)
{
varient = builder.toString();
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
}
Locale locale = new Locale(language, country, varient);
// leave the reader where it is ....
return new Pair<Locale, Reader>(locale, breader);
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
}
catch (IOException io)
{
try
{
breader.reset();
}
catch (IOException e)
{
throw new AnalysisException("Failed to reset buffered reader - token stream will be invalid", e);
}
return null;
}
}
private Analyzer getAnalyser(String fieldName, Locale locale)
{
if(schema != null)
{
if(fieldName.contains("l_@{"))
{
FieldType fieldType = schema.getFieldTypeByName("identifier");
return selectAnalyzer(fieldType);
}
else if(fieldName.contains("lt@{"))
{
StringBuilder builder = new StringBuilder();
builder.append("text_");
builder.append(locale.getLanguage());
FieldType fieldType = schema.getFieldTypeByName(builder.toString());
if(fieldType == null)
{
fieldType = schema.getFieldTypeByName("text_en");
}
return selectAnalyzer(fieldType);
}
else
{
return null;
}
}
else
{
return null;
}
}
private Analyzer selectAnalyzer(FieldType fieldType) {
if(mode == Mode.INDEX)
{
return fieldType.getIndexAnalyzer();
}
else if(mode == Mode.QUERY)
{
return fieldType.getQueryAnalyzer();
}
else
{
return null;
}
}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Locale;
import org.alfresco.repo.search.MLAnalysisMode;
import org.alfresco.solr.AlfrescoAnalyzerWrapper.Mode;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.springframework.extensions.surf.util.I18NUtil;
public class MLAnalayser extends Analyzer
{
private static Log s_logger = LogFactory.getLog(MLAnalayser.class);
private MLAnalysisMode mlAnalaysisMode;
private IndexSchema schema;
private Mode mode;
public MLAnalayser(MLAnalysisMode mlAnalaysisMode, IndexSchema schema, Mode mode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.mlAnalaysisMode = mlAnalaysisMode;
this.schema = schema;
this.mode = mode;
}
public MLAnalayser(MLAnalysisMode mlAnalaysisMode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.mlAnalaysisMode = mlAnalaysisMode;
}
@Override
protected TokenStreamComponents createComponents(String fieldName)
{
MLTokenizer mltokenizer = new MLTokenizer(fieldName, schema, mlAnalaysisMode, mode);
// try
// {
// mltokenizer.setLocaleAndPositionReaderAfterLocaleEncoding(reader);
// }
// catch (IOException e)
// {
// try{mltokenizer.close();} catch(IOException ioe) {};
// throw new AnalysisException("Failed to init MLTokenizer", e);
// }
return new LocaleAwareTokenStreamComponents(mltokenizer);
}
private static class LocaleAwareTokenStreamComponents extends Analyzer.TokenStreamComponents
{
MLTokenizer mltokenizer;
/**
* @param source
*/
public LocaleAwareTokenStreamComponents(final MLTokenizer source)
{
super(source);
this.mltokenizer = source;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Analyzer.TokenStreamComponents#setReader(java.io.Reader)
*/
@Override
protected void setReader(Reader reader)
{
super.setReader(mltokenizer.setLocaleAndPositionReaderAfterLocaleEncoding(reader));
}
}
private static class MLTokenizer extends Tokenizer
{
TokenStream ts;
String fieldName;
private IndexSchema schema;
MLAnalysisMode mlAnalaysisMode;
@SuppressWarnings("unused")
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
@SuppressWarnings("unused")
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
@SuppressWarnings("unused")
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
@SuppressWarnings("unused")
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private Mode mode;
MLTokenizer(String fieldName, IndexSchema schema, MLAnalysisMode mlAnalaysisMode, Mode mode)
{
this.fieldName = fieldName;
this.schema = schema;
this.mlAnalaysisMode = mlAnalaysisMode;
this.mode = mode;
}
/**
* @param reader
* @throws IOException
*/
public Reader setLocaleAndPositionReaderAfterLocaleEncoding(Reader reader)
{
Pair<Locale, Reader> pair = getLocaleAndPositioReaderAfterLocaleEncoding(fieldName, reader);
if(s_logger.isDebugEnabled())
{
s_logger.debug("Created ML analyser token stream for "+fieldName+ " with locale "+pair.getFirst());
}
TokenStream source = getAnalyser(fieldName, pair.getFirst()).tokenStream(fieldName, pair.getSecond());
ts = new MLTokenDuplicator(source, pair.getFirst(), pair.getSecond(), mlAnalaysisMode);
return pair.getSecond();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#close()
*/
@Override
public void close() throws IOException
{
ts.close();
super.close();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void reset() throws IOException
{
ts.reset();
super.reset();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void end() throws IOException
{
ts.end();
super.end();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.TokenStream#incrementToken()
*/
@Override
public boolean incrementToken() throws IOException
{
clearAttributes();
if(ts.incrementToken())
{
ts.copyTo(this);
return true;
}
else
{
ts.end();
ts.close();
return false;
}
}
public Pair<Locale,Reader> getLocaleAndPositioReaderAfterLocaleEncoding(String fieldName, Reader reader)
{
// We use read ahead to get the language info - if this does not exist we need to restart
// an use the default - there for we need mark and restore.
BufferedReader breader;
if (reader instanceof BufferedReader)
{
breader = (BufferedReader)reader;
}
else
{
breader = new BufferedReader(reader);
}
try
{
if (!breader.markSupported())
{
throw new AnalysisException(
"Multilingual tokenisation requires a reader that supports marks and reset");
}
breader.mark(100);
StringBuilder builder = new StringBuilder();
if (breader.read() == '\u0000')
{
String language = "";
String country = "";
String varient = "";
char c;
int count = 0;
while ((c = (char) breader.read()) != '\u0000')
{
if (count++ > 99)
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
if (c == '_')
{
if (language.length() == 0)
{
language = builder.toString();
}
else if (country.length() == 0)
{
country = builder.toString();
}
else if (varient.length() == 0)
{
varient = builder.toString();
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
builder = new StringBuilder();
}
else
{
builder.append(c);
}
}
if (builder.length() > 0)
{
if (language.length() == 0)
{
language = builder.toString();
}
else if (country.length() == 0)
{
country = builder.toString();
}
else if (varient.length() == 0)
{
varient = builder.toString();
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
}
Locale locale = new Locale(language, country, varient);
// leave the reader where it is ....
return new Pair<Locale, Reader>(locale, breader);
}
else
{
breader.reset();
return new Pair<Locale, Reader>(I18NUtil.getLocale(), breader);
}
}
catch (IOException io)
{
try
{
breader.reset();
}
catch (IOException e)
{
throw new AnalysisException("Failed to reset buffered reader - token stream will be invalid", e);
}
return null;
}
}
private Analyzer getAnalyser(String fieldName, Locale locale)
{
if(schema != null)
{
if(fieldName.contains("l_@{"))
{
FieldType fieldType = schema.getFieldTypeByName("identifier");
return selectAnalyzer(fieldType);
}
else if(fieldName.contains("lt@{"))
{
StringBuilder builder = new StringBuilder();
builder.append("text_");
builder.append(locale.getLanguage());
FieldType fieldType = schema.getFieldTypeByName(builder.toString());
if(fieldType == null)
{
fieldType = schema.getFieldTypeByName("text_en");
}
return selectAnalyzer(fieldType);
}
else
{
return null;
}
}
else
{
return null;
}
}
private Analyzer selectAnalyzer(FieldType fieldType) {
if(mode == Mode.INDEX)
{
return fieldType.getIndexAnalyzer();
}
else if(mode == Mode.QUERY)
{
return fieldType.getQueryAnalyzer();
}
else
{
return null;
}
}
}
}
@@ -1,284 +1,284 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import org.alfresco.repo.search.MLAnalysisMode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
/**
* Create duplicate tokens for multilingual varients The forms are Tokens: Token - all languages {fr}Token - if a
* language is specified {fr_CA}Token - if a language and country is specified {fr_CA_Varient}Token - for all three
* {fr__Varient}Token - for a language varient with no country
*
* @author andyh
*/
public class MLTokenDuplicator extends TokenStream
{
private static Log s_logger = LogFactory.getLog(MLTokenDuplicator.class);
TokenStream source;
Locale locale;
Iterator<PackedTokenAttributeImpl> it;
HashSet<String> prefixes;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private boolean done = false;
public MLTokenDuplicator(TokenStream source, Locale locale, Reader reader, MLAnalysisMode mlAnalysisMode)
{
this.source = source;
this.locale = locale;
Collection<Locale> locales = MLAnalysisMode.getLocales(mlAnalysisMode, locale, false);
prefixes = new HashSet<String>(locales.size());
for(Locale toAdd : locales)
{
String localeString = toAdd.toString();
if(localeString.length() == 0)
{
prefixes.add("");
}
else
{
StringBuilder builder = new StringBuilder(16);
builder.append("{").append(localeString).append("}");
prefixes.add(builder.toString());
}
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Locale "+ locale +" using "+mlAnalysisMode+" is "+prefixes);
}
}
/**
*
* @param locale
* @param mlAnalysisMode
*/
public MLTokenDuplicator(Locale locale, MLAnalysisMode mlAnalysisMode)
{
this.locale = locale;
Collection<Locale> locales = MLAnalysisMode.getLocales(mlAnalysisMode, locale, false);
prefixes = new HashSet<String>(locales.size());
for(Locale toAdd : locales)
{
String localeString = toAdd.toString();
if(localeString.length() == 0)
{
prefixes.add("");
}
else
{
StringBuilder builder = new StringBuilder(16);
builder.append("{").append(localeString).append("}");
prefixes.add(builder.toString());
}
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Locale "+ locale +" using "+mlAnalysisMode+" is "+prefixes);
}
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#close()
*/
@Override
public void close() throws IOException
{
source.close();
super.close();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void reset() throws IOException
{
source.reset();
super.reset();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.TokenStream#end()
*/
@Override
public void end() throws IOException
{
source.end();
super.end();
}
private PackedTokenAttributeImpl next() throws IOException
{
PackedTokenAttributeImpl t = null;
if (it == null)
{
it = buildIterator();
}
if (it == null)
{
return null;
}
if (it.hasNext())
{
t = it.next();
return t;
}
else
{
it = null;
t = this.next();
return t;
}
}
private Iterator<PackedTokenAttributeImpl> buildIterator() throws IOException
{
// TODO: use incrementToken() somehow?
if(!done && source.incrementToken())
{
CharTermAttribute cta = source.getAttribute(CharTermAttribute.class);
OffsetAttribute offsetAtt = source.getAttribute(OffsetAttribute.class);
TypeAttribute typeAtt = null;
if(source.hasAttribute(TypeAttribute.class))
{
typeAtt = source.getAttribute(TypeAttribute.class);
}
PositionIncrementAttribute posIncAtt = null;
if(source.hasAttribute(PositionIncrementAttribute.class))
{
posIncAtt = source.getAttribute(PositionIncrementAttribute.class);
}
PackedTokenAttributeImpl token = new PackedTokenAttributeImpl();
token.setEmpty().append(new String(cta.buffer()), 0, cta.length());
token.setOffset(offsetAtt.startOffset(), offsetAtt.endOffset());
if(typeAtt != null)
{
token.setType(typeAtt.type());
}
if(posIncAtt != null)
{
token.setPositionIncrement(posIncAtt.getPositionIncrement());
}
return buildIterator(token);
}
else
{
done = true;
return buildIterator(null);
}
}
public Iterator<PackedTokenAttributeImpl> buildIterator(PackedTokenAttributeImpl token)
{
if (token == null)
{
return null;
}
ArrayList<PackedTokenAttributeImpl> tokens = new ArrayList<PackedTokenAttributeImpl>(prefixes.size());
for (String prefix : prefixes)
{
PackedTokenAttributeImpl newToken = new PackedTokenAttributeImpl();
newToken.setEmpty().append(prefix + termText(token));
newToken.setOffset(token.startOffset(), token.endOffset());
newToken.setType(token.type());
if (tokens.size() == 0)
{
newToken.setPositionIncrement(token.getPositionIncrement());
}
else
{
newToken.setPositionIncrement(0);
}
tokens.add(newToken);
}
return tokens.iterator();
}
@Override
public final boolean incrementToken() throws IOException
{
clearAttributes();
PackedTokenAttributeImpl next = next();
if (next == null)
{
return false;
}
termAtt.copyBuffer(next.buffer(), 0, next.length());
offsetAtt.setOffset(next.startOffset(), next.endOffset());
typeAtt.setType(next.type());
posIncAtt.setPositionIncrement(next.getPositionIncrement());
return true;
}
// TODO: temporary replacement for Token.termText()
private String termText(PackedTokenAttributeImpl token)
{
return new String(token.buffer(), 0, token.length());
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import org.alfresco.repo.search.MLAnalysisMode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
/**
* Create duplicate tokens for multilingual varients The forms are Tokens: Token - all languages {fr}Token - if a
* language is specified {fr_CA}Token - if a language and country is specified {fr_CA_Varient}Token - for all three
* {fr__Varient}Token - for a language varient with no country
*
* @author andyh
*/
public class MLTokenDuplicator extends TokenStream
{
private static Log s_logger = LogFactory.getLog(MLTokenDuplicator.class);
TokenStream source;
Locale locale;
Iterator<PackedTokenAttributeImpl> it;
HashSet<String> prefixes;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private boolean done = false;
public MLTokenDuplicator(TokenStream source, Locale locale, Reader reader, MLAnalysisMode mlAnalysisMode)
{
this.source = source;
this.locale = locale;
Collection<Locale> locales = MLAnalysisMode.getLocales(mlAnalysisMode, locale, false);
prefixes = new HashSet<String>(locales.size());
for(Locale toAdd : locales)
{
String localeString = toAdd.toString();
if(localeString.length() == 0)
{
prefixes.add("");
}
else
{
StringBuilder builder = new StringBuilder(16);
builder.append("{").append(localeString).append("}");
prefixes.add(builder.toString());
}
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Locale "+ locale +" using "+mlAnalysisMode+" is "+prefixes);
}
}
/**
*
* @param locale
* @param mlAnalysisMode
*/
public MLTokenDuplicator(Locale locale, MLAnalysisMode mlAnalysisMode)
{
this.locale = locale;
Collection<Locale> locales = MLAnalysisMode.getLocales(mlAnalysisMode, locale, false);
prefixes = new HashSet<String>(locales.size());
for(Locale toAdd : locales)
{
String localeString = toAdd.toString();
if(localeString.length() == 0)
{
prefixes.add("");
}
else
{
StringBuilder builder = new StringBuilder(16);
builder.append("{").append(localeString).append("}");
prefixes.add(builder.toString());
}
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Locale "+ locale +" using "+mlAnalysisMode+" is "+prefixes);
}
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#close()
*/
@Override
public void close() throws IOException
{
source.close();
super.close();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset()
*/
@Override
public void reset() throws IOException
{
source.reset();
super.reset();
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.TokenStream#end()
*/
@Override
public void end() throws IOException
{
source.end();
super.end();
}
private PackedTokenAttributeImpl next() throws IOException
{
PackedTokenAttributeImpl t = null;
if (it == null)
{
it = buildIterator();
}
if (it == null)
{
return null;
}
if (it.hasNext())
{
t = it.next();
return t;
}
else
{
it = null;
t = this.next();
return t;
}
}
private Iterator<PackedTokenAttributeImpl> buildIterator() throws IOException
{
// TODO: use incrementToken() somehow?
if(!done && source.incrementToken())
{
CharTermAttribute cta = source.getAttribute(CharTermAttribute.class);
OffsetAttribute offsetAtt = source.getAttribute(OffsetAttribute.class);
TypeAttribute typeAtt = null;
if(source.hasAttribute(TypeAttribute.class))
{
typeAtt = source.getAttribute(TypeAttribute.class);
}
PositionIncrementAttribute posIncAtt = null;
if(source.hasAttribute(PositionIncrementAttribute.class))
{
posIncAtt = source.getAttribute(PositionIncrementAttribute.class);
}
PackedTokenAttributeImpl token = new PackedTokenAttributeImpl();
token.setEmpty().append(new String(cta.buffer()), 0, cta.length());
token.setOffset(offsetAtt.startOffset(), offsetAtt.endOffset());
if(typeAtt != null)
{
token.setType(typeAtt.type());
}
if(posIncAtt != null)
{
token.setPositionIncrement(posIncAtt.getPositionIncrement());
}
return buildIterator(token);
}
else
{
done = true;
return buildIterator(null);
}
}
public Iterator<PackedTokenAttributeImpl> buildIterator(PackedTokenAttributeImpl token)
{
if (token == null)
{
return null;
}
ArrayList<PackedTokenAttributeImpl> tokens = new ArrayList<PackedTokenAttributeImpl>(prefixes.size());
for (String prefix : prefixes)
{
PackedTokenAttributeImpl newToken = new PackedTokenAttributeImpl();
newToken.setEmpty().append(prefix + termText(token));
newToken.setOffset(token.startOffset(), token.endOffset());
newToken.setType(token.type());
if (tokens.size() == 0)
{
newToken.setPositionIncrement(token.getPositionIncrement());
}
else
{
newToken.setPositionIncrement(0);
}
tokens.add(newToken);
}
return tokens.iterator();
}
@Override
public final boolean incrementToken() throws IOException
{
clearAttributes();
PackedTokenAttributeImpl next = next();
if (next == null)
{
return false;
}
termAtt.copyBuffer(next.buffer(), 0, next.length());
offsetAtt.setOffset(next.startOffset(), next.endOffset());
typeAtt.setType(next.type());
posIncAtt.setPositionIncrement(next.getPositionIncrement());
return true;
}
// TODO: temporary replacement for Token.termText()
private String termText(PackedTokenAttributeImpl token)
{
return new String(token.buffer(), 0, token.length());
}
}
@@ -1,47 +1,47 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import org.apache.lucene.analysis.Analyzer;
/**
* @author Andy
*
*/
public class PathAnalyzer extends Analyzer
{
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Analyzer#createComponents(java.lang.String, java.io.Reader)
*/
@Override
protected TokenStreamComponents createComponents(String fieldName)
{
return new TokenStreamComponents(new PathTokenFilter(PathTokenFilter.PATH_SEPARATOR, PathTokenFilter.SEPARATOR_TOKEN_TEXT, PathTokenFilter.NO_NS_TOKEN_TEXT, PathTokenFilter.NAMESPACE_START_DELIMITER, PathTokenFilter.NAMESPACE_END_DELIMITER, true));
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import org.apache.lucene.analysis.Analyzer;
/**
* @author Andy
*
*/
public class PathAnalyzer extends Analyzer
{
/* (non-Javadoc)
* @see org.apache.lucene.analysis.Analyzer#createComponents(java.lang.String, java.io.Reader)
*/
@Override
protected TokenStreamComponents createComponents(String fieldName)
{
return new TokenStreamComponents(new PathTokenFilter(PathTokenFilter.PATH_SEPARATOR, PathTokenFilter.SEPARATOR_TOKEN_TEXT, PathTokenFilter.NO_NS_TOKEN_TEXT, PathTokenFilter.NAMESPACE_START_DELIMITER, PathTokenFilter.NAMESPACE_END_DELIMITER, true));
}
}
@@ -1,396 +1,396 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
/**
* @author andyh TODO To change the template for this generated type comment go to Window - Preferences - Java - Code
* Style - Code Templates
*/
public class PathTokenFilter extends Tokenizer
{
public final static String INTEGER_FORMAT = "0000000000";
public final static char PATH_SEPARATOR = ';';
public final static char NAMESPACE_START_DELIMITER = '{';
public final static char NAMESPACE_END_DELIMITER = '}';
public final static String SEPARATOR_TOKEN_TEXT = ";";
public final static String NO_NS_TOKEN_TEXT = "<No Namespace>";
public final static String TOKEN_TYPE_PATH_SEP = "PATH_SEPARATOR";
public final static String TOKEN_TYPE_PATH_LENGTH = "PATH_LENGTH";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAME = "PATH_ELEMENT_NAME";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE = "PATH_ELEMENT_NAMESPACE";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX = "PATH_ELEMENT_NAMESPACE_PREFIX";
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
char pathSeparator;
String separatorTokenText;
String noNsTokenText;
char nsStartDelimiter;
int nsStartDelimiterLength;
char nsEndDelimiter;
int nsEndDelimiterLength;
char nsPrefixDelimiter = ':';
LinkedList<PackedTokenAttributeImpl> tokens = new LinkedList<PackedTokenAttributeImpl>();
Iterator<PackedTokenAttributeImpl> it = null;
private boolean includeNamespace;
private boolean endOfStream = false;
public PathTokenFilter(char pathSeparator, String separatorTokenText, String noNsTokenText,
char nsStartDelimiter, char nsEndDelimiter, boolean includeNameSpace)
{
this.pathSeparator = pathSeparator;
this.separatorTokenText = separatorTokenText;
this.noNsTokenText = noNsTokenText;
this.nsStartDelimiter = nsStartDelimiter;
this.nsEndDelimiter = nsEndDelimiter;
this.includeNamespace = includeNameSpace;
this.nsStartDelimiterLength = 1;
this.nsEndDelimiterLength = 1;
}
/*
* (non-Javadoc)
*
* @see org.apache.lucene.analysis.TokenStream#next()
*/
public PackedTokenAttributeImpl next() throws IOException
{
PackedTokenAttributeImpl nextToken;
if (it == null)
{
buildTokenListAndIterator();
}
if (it.hasNext())
{
nextToken = it.next();
}
else
{
nextToken = null;
}
return nextToken;
}
// TODO: temporary replacement for Token.termText()
private String termText(PackedTokenAttributeImpl token)
{
return new String(token.buffer(), 0, token.length());
}
private void buildTokenListAndIterator() throws IOException
{
NumberFormat nf = new DecimalFormat(INTEGER_FORMAT);
// Could optimise to read each path ata time - not just all paths
int insertCountAt = 0;
int lengthCounter = 0;
PackedTokenAttributeImpl t;
PackedTokenAttributeImpl pathSplitToken = null;
PackedTokenAttributeImpl nameToken = null;
PackedTokenAttributeImpl countToken = null;
PackedTokenAttributeImpl namespaceToken = null;
while ((t = nextToken()) != null)
{
String text = termText(t);
if (text.length() == 0)
{
continue; // Skip if we find // or /; or ;; etc
}
if (text.charAt(text.length() - 1) == pathSeparator)
{
text = text.substring(0, text.length() - 1);
pathSplitToken = new PackedTokenAttributeImpl();
pathSplitToken.setEmpty().append(separatorTokenText);
pathSplitToken.setOffset(t.startOffset(), t.endOffset());
pathSplitToken.setType( TOKEN_TYPE_PATH_SEP);
pathSplitToken.setPositionIncrement(1);
}
int split = -1;
boolean isPrefix = false;
if ((text.length() > 0) && (text.charAt(0) == nsStartDelimiter))
{
split = text.indexOf(nsEndDelimiter);
}
if (split == -1)
{
split = text.indexOf(nsPrefixDelimiter);
isPrefix = true;
}
if (split == -1)
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(noNsTokenText);
namespaceToken.setOffset(t.startOffset(), t.startOffset());
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text);
nameToken.setOffset(t.startOffset(), t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
else
{
if (isPrefix)
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(text.substring(0, split));
namespaceToken.setOffset(t.startOffset(), t.startOffset() + split);
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text.substring(split + 1));
nameToken.setOffset(t.startOffset() + split + 1, t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
else
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(text.substring(nsStartDelimiterLength, (split + nsEndDelimiterLength - 1)));
namespaceToken.setOffset(t.startOffset(), t.startOffset() + split);
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text.substring(split + nsEndDelimiterLength));
nameToken.setOffset(t.startOffset() + split + nsEndDelimiterLength, t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
}
namespaceToken.setPositionIncrement(1);
nameToken.setPositionIncrement(1);
if (includeNamespace)
{
if (termText(namespaceToken).equals(""))
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(noNsTokenText);
namespaceToken.setOffset(t.startOffset(), t.startOffset());
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
namespaceToken.setPositionIncrement(1);
}
tokens.add(namespaceToken);
}
tokens.add(nameToken);
lengthCounter++;
if (pathSplitToken != null)
{
String countString = nf.format(lengthCounter);
countToken = new PackedTokenAttributeImpl();
countToken.setEmpty().append(countString);
countToken.setOffset(t.startOffset(), t.endOffset());
countToken.setType(TOKEN_TYPE_PATH_SEP);
countToken.setPositionIncrement(1);
tokens.add(insertCountAt, countToken);
tokens.add(pathSplitToken);
lengthCounter = 0;
insertCountAt = tokens.size();
pathSplitToken = null;
}
}
String countString = nf.format(lengthCounter);
countToken = new PackedTokenAttributeImpl();
countToken.setEmpty().append(countString);
countToken.setOffset(0, 0);
countToken.setType(TOKEN_TYPE_PATH_SEP);
countToken.setPositionIncrement(1);
tokens.add(insertCountAt, countToken);
if ((tokens.size() == 0) || !(termText(tokens.get(tokens.size() - 1)).equals(TOKEN_TYPE_PATH_SEP)))
{
pathSplitToken = new PackedTokenAttributeImpl();
pathSplitToken.setEmpty().append(separatorTokenText);
pathSplitToken.setOffset(0, 0);
pathSplitToken.setType(TOKEN_TYPE_PATH_SEP);
pathSplitToken.setPositionIncrement(1);
tokens.add(pathSplitToken);
}
it = tokens.iterator();
}
int readerPosition = 0;
private PackedTokenAttributeImpl nextToken() throws IOException
{
if (endOfStream)
{
return null;
}
StringBuilder buffer = new StringBuilder(64);
boolean inNameSpace = false;
int start = readerPosition;
int current;
char c;
while ((current = input.read()) != -1)
{
c = (char) current;
readerPosition++;
if (c == nsStartDelimiter)
{
inNameSpace = true;
}
else if (c == nsEndDelimiter)
{
inNameSpace = false;
}
else if (!inNameSpace && (c == '/'))
{
PackedTokenAttributeImpl qNameToken = new PackedTokenAttributeImpl();
qNameToken.setEmpty().append(buffer.toString());
qNameToken.setOffset(start, readerPosition - 1);
qNameToken.setType("QNAME");
return qNameToken;
}
else if (!inNameSpace && (c == ';'))
{
buffer.append(c);
PackedTokenAttributeImpl lastQNameToken = new PackedTokenAttributeImpl();
lastQNameToken.setEmpty().append(buffer.toString());
lastQNameToken.setOffset(start, readerPosition);
lastQNameToken.setType("LASTQNAME");
return lastQNameToken;
}
buffer.append(c);
}
int end = readerPosition - 1;
// Stop the final token being returned with an end before the start.
if (start > end)
{
end = start;
}
endOfStream = true;
if (!inNameSpace)
{
PackedTokenAttributeImpl qNameToken = new PackedTokenAttributeImpl();
qNameToken.setEmpty().append(buffer.toString());
qNameToken.setOffset(start, end);
qNameToken.setType("QNAME");
return qNameToken;
}
else
{
throw new IllegalStateException("QName terminated incorrectly: " + buffer.toString());
}
}
@Override
public final boolean incrementToken() throws IOException
{
clearAttributes();
PackedTokenAttributeImpl next = next();
if (next == null)
{
return false;
}
termAtt.copyBuffer(next.buffer(), 0, next.length());
offsetAtt.setOffset(correctOffset(next.startOffset()), correctOffset(next.endOffset()));
typeAtt.setType(next.type());
posIncAtt.setPositionIncrement(next.getPositionIncrement());
return true;
}
@Override
public void reset() throws IOException
{
super.reset();
tokens.clear();
it = null;
readerPosition = 0;
endOfStream = false;
}
@Override
public void end() throws IOException
{
super.end();
int finalOffset = correctOffset(readerPosition);
offsetAtt.setOffset(finalOffset, finalOffset);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
/**
* @author andyh TODO To change the template for this generated type comment go to Window - Preferences - Java - Code
* Style - Code Templates
*/
public class PathTokenFilter extends Tokenizer
{
public final static String INTEGER_FORMAT = "0000000000";
public final static char PATH_SEPARATOR = ';';
public final static char NAMESPACE_START_DELIMITER = '{';
public final static char NAMESPACE_END_DELIMITER = '}';
public final static String SEPARATOR_TOKEN_TEXT = ";";
public final static String NO_NS_TOKEN_TEXT = "<No Namespace>";
public final static String TOKEN_TYPE_PATH_SEP = "PATH_SEPARATOR";
public final static String TOKEN_TYPE_PATH_LENGTH = "PATH_LENGTH";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAME = "PATH_ELEMENT_NAME";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE = "PATH_ELEMENT_NAMESPACE";
public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX = "PATH_ELEMENT_NAMESPACE_PREFIX";
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
char pathSeparator;
String separatorTokenText;
String noNsTokenText;
char nsStartDelimiter;
int nsStartDelimiterLength;
char nsEndDelimiter;
int nsEndDelimiterLength;
char nsPrefixDelimiter = ':';
LinkedList<PackedTokenAttributeImpl> tokens = new LinkedList<PackedTokenAttributeImpl>();
Iterator<PackedTokenAttributeImpl> it = null;
private boolean includeNamespace;
private boolean endOfStream = false;
public PathTokenFilter(char pathSeparator, String separatorTokenText, String noNsTokenText,
char nsStartDelimiter, char nsEndDelimiter, boolean includeNameSpace)
{
this.pathSeparator = pathSeparator;
this.separatorTokenText = separatorTokenText;
this.noNsTokenText = noNsTokenText;
this.nsStartDelimiter = nsStartDelimiter;
this.nsEndDelimiter = nsEndDelimiter;
this.includeNamespace = includeNameSpace;
this.nsStartDelimiterLength = 1;
this.nsEndDelimiterLength = 1;
}
/*
* (non-Javadoc)
*
* @see org.apache.lucene.analysis.TokenStream#next()
*/
public PackedTokenAttributeImpl next() throws IOException
{
PackedTokenAttributeImpl nextToken;
if (it == null)
{
buildTokenListAndIterator();
}
if (it.hasNext())
{
nextToken = it.next();
}
else
{
nextToken = null;
}
return nextToken;
}
// TODO: temporary replacement for Token.termText()
private String termText(PackedTokenAttributeImpl token)
{
return new String(token.buffer(), 0, token.length());
}
private void buildTokenListAndIterator() throws IOException
{
NumberFormat nf = new DecimalFormat(INTEGER_FORMAT);
// Could optimise to read each path ata time - not just all paths
int insertCountAt = 0;
int lengthCounter = 0;
PackedTokenAttributeImpl t;
PackedTokenAttributeImpl pathSplitToken = null;
PackedTokenAttributeImpl nameToken = null;
PackedTokenAttributeImpl countToken = null;
PackedTokenAttributeImpl namespaceToken = null;
while ((t = nextToken()) != null)
{
String text = termText(t);
if (text.length() == 0)
{
continue; // Skip if we find // or /; or ;; etc
}
if (text.charAt(text.length() - 1) == pathSeparator)
{
text = text.substring(0, text.length() - 1);
pathSplitToken = new PackedTokenAttributeImpl();
pathSplitToken.setEmpty().append(separatorTokenText);
pathSplitToken.setOffset(t.startOffset(), t.endOffset());
pathSplitToken.setType( TOKEN_TYPE_PATH_SEP);
pathSplitToken.setPositionIncrement(1);
}
int split = -1;
boolean isPrefix = false;
if ((text.length() > 0) && (text.charAt(0) == nsStartDelimiter))
{
split = text.indexOf(nsEndDelimiter);
}
if (split == -1)
{
split = text.indexOf(nsPrefixDelimiter);
isPrefix = true;
}
if (split == -1)
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(noNsTokenText);
namespaceToken.setOffset(t.startOffset(), t.startOffset());
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text);
nameToken.setOffset(t.startOffset(), t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
else
{
if (isPrefix)
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(text.substring(0, split));
namespaceToken.setOffset(t.startOffset(), t.startOffset() + split);
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text.substring(split + 1));
nameToken.setOffset(t.startOffset() + split + 1, t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
else
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(text.substring(nsStartDelimiterLength, (split + nsEndDelimiterLength - 1)));
namespaceToken.setOffset(t.startOffset(), t.startOffset() + split);
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
nameToken = new PackedTokenAttributeImpl();
nameToken.setEmpty().append(text.substring(split + nsEndDelimiterLength));
nameToken.setOffset(t.startOffset() + split + nsEndDelimiterLength, t.endOffset());
nameToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAME);
}
}
namespaceToken.setPositionIncrement(1);
nameToken.setPositionIncrement(1);
if (includeNamespace)
{
if (termText(namespaceToken).equals(""))
{
namespaceToken = new PackedTokenAttributeImpl();
namespaceToken.setEmpty().append(noNsTokenText);
namespaceToken.setOffset(t.startOffset(), t.startOffset());
namespaceToken.setType(TOKEN_TYPE_PATH_ELEMENT_NAMESPACE);
namespaceToken.setPositionIncrement(1);
}
tokens.add(namespaceToken);
}
tokens.add(nameToken);
lengthCounter++;
if (pathSplitToken != null)
{
String countString = nf.format(lengthCounter);
countToken = new PackedTokenAttributeImpl();
countToken.setEmpty().append(countString);
countToken.setOffset(t.startOffset(), t.endOffset());
countToken.setType(TOKEN_TYPE_PATH_SEP);
countToken.setPositionIncrement(1);
tokens.add(insertCountAt, countToken);
tokens.add(pathSplitToken);
lengthCounter = 0;
insertCountAt = tokens.size();
pathSplitToken = null;
}
}
String countString = nf.format(lengthCounter);
countToken = new PackedTokenAttributeImpl();
countToken.setEmpty().append(countString);
countToken.setOffset(0, 0);
countToken.setType(TOKEN_TYPE_PATH_SEP);
countToken.setPositionIncrement(1);
tokens.add(insertCountAt, countToken);
if ((tokens.size() == 0) || !(termText(tokens.get(tokens.size() - 1)).equals(TOKEN_TYPE_PATH_SEP)))
{
pathSplitToken = new PackedTokenAttributeImpl();
pathSplitToken.setEmpty().append(separatorTokenText);
pathSplitToken.setOffset(0, 0);
pathSplitToken.setType(TOKEN_TYPE_PATH_SEP);
pathSplitToken.setPositionIncrement(1);
tokens.add(pathSplitToken);
}
it = tokens.iterator();
}
int readerPosition = 0;
private PackedTokenAttributeImpl nextToken() throws IOException
{
if (endOfStream)
{
return null;
}
StringBuilder buffer = new StringBuilder(64);
boolean inNameSpace = false;
int start = readerPosition;
int current;
char c;
while ((current = input.read()) != -1)
{
c = (char) current;
readerPosition++;
if (c == nsStartDelimiter)
{
inNameSpace = true;
}
else if (c == nsEndDelimiter)
{
inNameSpace = false;
}
else if (!inNameSpace && (c == '/'))
{
PackedTokenAttributeImpl qNameToken = new PackedTokenAttributeImpl();
qNameToken.setEmpty().append(buffer.toString());
qNameToken.setOffset(start, readerPosition - 1);
qNameToken.setType("QNAME");
return qNameToken;
}
else if (!inNameSpace && (c == ';'))
{
buffer.append(c);
PackedTokenAttributeImpl lastQNameToken = new PackedTokenAttributeImpl();
lastQNameToken.setEmpty().append(buffer.toString());
lastQNameToken.setOffset(start, readerPosition);
lastQNameToken.setType("LASTQNAME");
return lastQNameToken;
}
buffer.append(c);
}
int end = readerPosition - 1;
// Stop the final token being returned with an end before the start.
if (start > end)
{
end = start;
}
endOfStream = true;
if (!inNameSpace)
{
PackedTokenAttributeImpl qNameToken = new PackedTokenAttributeImpl();
qNameToken.setEmpty().append(buffer.toString());
qNameToken.setOffset(start, end);
qNameToken.setType("QNAME");
return qNameToken;
}
else
{
throw new IllegalStateException("QName terminated incorrectly: " + buffer.toString());
}
}
@Override
public final boolean incrementToken() throws IOException
{
clearAttributes();
PackedTokenAttributeImpl next = next();
if (next == null)
{
return false;
}
termAtt.copyBuffer(next.buffer(), 0, next.length());
offsetAtt.setOffset(correctOffset(next.startOffset()), correctOffset(next.endOffset()));
typeAtt.setType(next.type());
posIncAtt.setPositionIncrement(next.getPositionIncrement());
return true;
}
@Override
public void reset() throws IOException
{
super.reset();
tokens.clear();
it = null;
readerPosition = 0;
endOfStream = false;
}
@Override
public void end() throws IOException
{
super.end();
int finalOffset = correctOffset(readerPosition);
offsetAtt.setOffset(finalOffset, finalOffset);
}
}
@@ -1,109 +1,109 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.repo.search.MLAnalysisMode;
import org.alfresco.repo.search.impl.lucene.analysis.MLAnalayser;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.AnalyzerWrapper;
import org.apache.solr.schema.IndexSchema;
/**
* Wraps SOLR access to for localising tokens
* As analysers are cached, and anylysers themselves cache token streams we have to be able to switch locales
* inside the MLAnalyser.
*
* @author Andy
*
*/
public class AlfrescoAnalyzerWrapper extends AnalyzerWrapper
{
public static enum Mode
{
INDEX, QUERY;
}
IndexSchema schema;
Mode mode;
/**
* @param schema
* @param index
*/
public AlfrescoAnalyzerWrapper(IndexSchema schema, Mode mode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.schema = schema;
this.mode = mode;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.AnalyzerWrapper#getPositionIncrementGap(java.lang.String)
*/
@Override
public int getPositionIncrementGap(String fieldName)
{
return 100;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.AnalyzerWrapper#getWrappedAnalyzer(java.lang.String)
*/
@Override
protected Analyzer getWrappedAnalyzer(String fieldName)
{
if(fieldName.contains("l_@{"))
{
return new MLAnalayser(MLAnalysisMode.EXACT_LANGUAGE, schema, mode);
}
else if(fieldName.contains("lt@{"))
{
return new MLAnalayser(MLAnalysisMode.EXACT_LANGUAGE, schema, mode);
}
else
{
if(mode == Mode.INDEX)
{
return schema.getFieldTypeByName("text___").getIndexAnalyzer();
}
else if(mode == Mode.QUERY)
{
return schema.getFieldTypeByName("text___").getQueryAnalyzer();
}
else
{
throw new IllegalStateException();
}
}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.repo.search.MLAnalysisMode;
import org.alfresco.repo.search.impl.lucene.analysis.MLAnalayser;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.AnalyzerWrapper;
import org.apache.solr.schema.IndexSchema;
/**
* Wraps SOLR access to for localising tokens
* As analysers are cached, and anylysers themselves cache token streams we have to be able to switch locales
* inside the MLAnalyser.
*
* @author Andy
*
*/
public class AlfrescoAnalyzerWrapper extends AnalyzerWrapper
{
public static enum Mode
{
INDEX, QUERY;
}
IndexSchema schema;
Mode mode;
/**
* @param schema
* @param index
*/
public AlfrescoAnalyzerWrapper(IndexSchema schema, Mode mode)
{
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.schema = schema;
this.mode = mode;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.AnalyzerWrapper#getPositionIncrementGap(java.lang.String)
*/
@Override
public int getPositionIncrementGap(String fieldName)
{
return 100;
}
/* (non-Javadoc)
* @see org.apache.lucene.analysis.AnalyzerWrapper#getWrappedAnalyzer(java.lang.String)
*/
@Override
protected Analyzer getWrappedAnalyzer(String fieldName)
{
if(fieldName.contains("l_@{"))
{
return new MLAnalayser(MLAnalysisMode.EXACT_LANGUAGE, schema, mode);
}
else if(fieldName.contains("lt@{"))
{
return new MLAnalayser(MLAnalysisMode.EXACT_LANGUAGE, schema, mode);
}
else
{
if(mode == Mode.INDEX)
{
return schema.getFieldTypeByName("text___").getIndexAnalyzer();
}
else if(mode == Mode.QUERY)
{
return schema.getFieldTypeByName("text___").getQueryAnalyzer();
}
else
{
throw new IllegalStateException();
}
}
}
}
@@ -1,273 +1,273 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.text.Collator;
import java.util.Locale;
import org.alfresco.service.cmr.repository.MLText;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.LeafFieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*/
public class AlfrescoCollatableMLTextFieldType extends StrField
{
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return new SortField(field.getName(), new MLTextSortFieldComparatorSource(), reverse);
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#marshalSortValue(java.lang.Object)
*/
@Override
public Object marshalSortValue(Object value)
{
return value;
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#unmarshalSortValue(java.lang.Object)
*/
@Override
public Object unmarshalSortValue(Object value)
{
return value;
}
public static class MLTextSortFieldComparatorSource extends FieldComparatorSource
{
/*
* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
*/
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new MLTextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
}
/*
* Adapted from org.apache.lucene.search.FieldComparator.TermValComparator<T>
*/
public static final class MLTextSortFieldComparator extends FieldComparator<String> implements LeafFieldComparator
{
private final String[] values;
private BinaryDocValues docTerms;
/**
* An array of flags - one for each document in the segment. Each bit is set to true if the document has the
* field or false otherwise. If this is set to null then all docs in the segment have the field.
*/
Bits docsWithField;
private final String field;
Collator collator;
String bottom;
String top;
Locale collatorLocale;
MLTextSortFieldComparator(int numHits, String field, Locale collatorLocale)
{
values = new String[numHits];
this.field = field;
this.collatorLocale = collatorLocale;
collator = Collator.getInstance(collatorLocale);
}
public int compare(int slot1, int slot2)
{
final String val1 = values[slot1];
final String val2 = values[slot2];
return compareValues(val1, val2);
}
public void setBottom(final int bottom)
{
this.bottom = values[bottom];
}
public int compareBottom(int doc)
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(bottom, comparableString);
}
public void copy(int slot, int doc)
{
values[slot] = findBestValue(doc, docTerms.get(doc));
}
public String value(int slot)
{
return values[slot];
}
private String findBestValue(int doc, BytesRef term)
{
if (term.length == 0 && docsWithField != null && docsWithField.get(doc) == false)
{
return null;
}
String withLocale = term.utf8ToString();
// split string into MLText object
if (withLocale == null)
{
return withLocale;
}
else if (withLocale.startsWith("\u0000"))
{
MLText mlText = new MLText();
String[] parts = withLocale.split("\u0000");
for (int i = 0; (i + 2) <= parts.length; i += 3)
{
Locale locale = null;
String[] localeParts = parts[i + 1].split("_");
if (localeParts.length == 1)
{
locale = new Locale(localeParts[0]);
}
else if (localeParts.length == 2)
{
locale = new Locale(localeParts[0], localeParts[1]);
}
else if (localeParts.length == 3)
{
locale = new Locale(localeParts[0], localeParts[1], localeParts[2]);
}
if (locale != null)
{
if (i + 2 == parts.length)
{
mlText.addValue(locale, "");
}
else
{
mlText.addValue(locale, parts[i + 2]);
}
}
}
return mlText.getClosestValue(collatorLocale);
}
else
{
return withLocale;
}
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setTopValue(java.lang.Object)
*/
@Override
public void setTopValue(String value)
{
this.top = value;
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#compareTop(int)
*/
@Override
public int compareTop(int doc) throws IOException
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(top, comparableString);
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setNextReader(org.apache.lucene.index.AtomicReaderContext)
*/
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException
{
docTerms = DocValues.getBinary(context.reader(), field);
docsWithField = DocValues.getDocsWithField(context.reader(), field);
if (docsWithField instanceof Bits.MatchAllBits)
{
docsWithField = null;
}
return this;
}
@Override
public int compareValues(String val1, String val2)
{
if (val1 == null)
{
if (val2 == null)
{
return 0;
}
return -1;
}
else if (val2 == null)
{
return 1;
}
return collator.compare(val1, val2);
}
@Override
public void setScorer(Scorer scorer)
{
}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.text.Collator;
import java.util.Locale;
import org.alfresco.service.cmr.repository.MLText;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.LeafFieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*/
public class AlfrescoCollatableMLTextFieldType extends StrField
{
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return new SortField(field.getName(), new MLTextSortFieldComparatorSource(), reverse);
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#marshalSortValue(java.lang.Object)
*/
@Override
public Object marshalSortValue(Object value)
{
return value;
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#unmarshalSortValue(java.lang.Object)
*/
@Override
public Object unmarshalSortValue(Object value)
{
return value;
}
public static class MLTextSortFieldComparatorSource extends FieldComparatorSource
{
/*
* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
*/
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new MLTextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
}
/*
* Adapted from org.apache.lucene.search.FieldComparator.TermValComparator<T>
*/
public static final class MLTextSortFieldComparator extends FieldComparator<String> implements LeafFieldComparator
{
private final String[] values;
private BinaryDocValues docTerms;
/**
* An array of flags - one for each document in the segment. Each bit is set to true if the document has the
* field or false otherwise. If this is set to null then all docs in the segment have the field.
*/
Bits docsWithField;
private final String field;
Collator collator;
String bottom;
String top;
Locale collatorLocale;
MLTextSortFieldComparator(int numHits, String field, Locale collatorLocale)
{
values = new String[numHits];
this.field = field;
this.collatorLocale = collatorLocale;
collator = Collator.getInstance(collatorLocale);
}
public int compare(int slot1, int slot2)
{
final String val1 = values[slot1];
final String val2 = values[slot2];
return compareValues(val1, val2);
}
public void setBottom(final int bottom)
{
this.bottom = values[bottom];
}
public int compareBottom(int doc)
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(bottom, comparableString);
}
public void copy(int slot, int doc)
{
values[slot] = findBestValue(doc, docTerms.get(doc));
}
public String value(int slot)
{
return values[slot];
}
private String findBestValue(int doc, BytesRef term)
{
if (term.length == 0 && docsWithField != null && docsWithField.get(doc) == false)
{
return null;
}
String withLocale = term.utf8ToString();
// split string into MLText object
if (withLocale == null)
{
return withLocale;
}
else if (withLocale.startsWith("\u0000"))
{
MLText mlText = new MLText();
String[] parts = withLocale.split("\u0000");
for (int i = 0; (i + 2) <= parts.length; i += 3)
{
Locale locale = null;
String[] localeParts = parts[i + 1].split("_");
if (localeParts.length == 1)
{
locale = new Locale(localeParts[0]);
}
else if (localeParts.length == 2)
{
locale = new Locale(localeParts[0], localeParts[1]);
}
else if (localeParts.length == 3)
{
locale = new Locale(localeParts[0], localeParts[1], localeParts[2]);
}
if (locale != null)
{
if (i + 2 == parts.length)
{
mlText.addValue(locale, "");
}
else
{
mlText.addValue(locale, parts[i + 2]);
}
}
}
return mlText.getClosestValue(collatorLocale);
}
else
{
return withLocale;
}
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setTopValue(java.lang.Object)
*/
@Override
public void setTopValue(String value)
{
this.top = value;
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#compareTop(int)
*/
@Override
public int compareTop(int doc) throws IOException
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(top, comparableString);
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setNextReader(org.apache.lucene.index.AtomicReaderContext)
*/
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException
{
docTerms = DocValues.getBinary(context.reader(), field);
docsWithField = DocValues.getDocsWithField(context.reader(), field);
if (docsWithField instanceof Bits.MatchAllBits)
{
docsWithField = null;
}
return this;
}
@Override
public int compareValues(String val1, String val2)
{
if (val1 == null)
{
if (val2 == null)
{
return 0;
}
return -1;
}
else if (val2 == null)
{
return 1;
}
return collator.compare(val1, val2);
}
@Override
public void setScorer(Scorer scorer)
{
}
}
}
@@ -1,245 +1,245 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.text.Collator;
import java.util.Locale;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.LeafFieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class AlfrescoCollatableTextFieldType extends StrField
{
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return new SortField(field.getName(), new TextSortFieldComparatorSource(), reverse);
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#marshalSortValue(java.lang.Object)
*/
@Override
public Object marshalSortValue(Object value)
{
return value;
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#unmarshalSortValue(java.lang.Object)
*/
@Override
public Object unmarshalSortValue(Object value)
{
return value;
}
public static class TextSortFieldComparatorSource extends FieldComparatorSource
{
/*
* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
*/
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new TextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
}
/*
* Adapted from org.apache.lucene.search.FieldComparator.TermValComparator<T>
*/
public static final class TextSortFieldComparator extends FieldComparator<String> implements LeafFieldComparator
{
private final String[] values;
private BinaryDocValues docTerms;
/**
* An array of flags - one for each document in the segment. Each bit is set to true if the document has the
* field or false otherwise. If this is set to null then all docs in the segment have the field.
*/
Bits docsWithField;
private final String field;
Collator collator;
String bottom;
String top;
Locale collatorLocale;
TextSortFieldComparator(int numHits, String field, Locale collatorLocale)
{
values = new String[numHits];
this.field = field;
this.collatorLocale = collatorLocale;
collator = Collator.getInstance(collatorLocale);
}
public int compare(int slot1, int slot2)
{
final String val1 = values[slot1];
final String val2 = values[slot2];
return compareValues(val1, val2);
}
public void setBottom(final int bottom)
{
this.bottom = values[bottom];
}
public int compareBottom(int doc)
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(bottom, comparableString);
}
public void copy(int slot, int doc)
{
values[slot] = findBestValue(doc, docTerms.get(doc));
}
public String value(int slot)
{
return values[slot];
}
private String findBestValue(int doc, BytesRef term)
{
if (term.length == 0 && docsWithField != null && docsWithField.get(doc) == false)
{
return null;
}
String withLocale = term.utf8ToString();
// split strin into MLText object
if (withLocale == null)
{
return withLocale;
}
else if (withLocale.startsWith("\u0000"))
{
String[] parts = withLocale.split("\u0000");
return parts[2];
}
else
{
return withLocale;
}
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setTopValue(java.lang.Object)
*/
@Override
public void setTopValue(String value)
{
this.top = value;
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#compareTop(int)
*/
@Override
public int compareTop(int doc) throws IOException
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(top, comparableString);
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setNextReader(org.apache.lucene.index.AtomicReaderContext)
*/
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException
{
docTerms = DocValues.getBinary(context.reader(), field);
docsWithField = DocValues.getDocsWithField(context.reader(), field);
if (docsWithField instanceof Bits.MatchAllBits) {
docsWithField = null;
}
return this;
}
@Override
public int compareValues(String val1, String val2)
{
if (val1 == null)
{
if (val2 == null)
{
return 0;
}
return -1;
}
else if (val2 == null)
{
return 1;
}
return collator.compare(val1, val2);
}
@Override
public void setScorer(Scorer scorer) {}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.text.Collator;
import java.util.Locale;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.LeafFieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class AlfrescoCollatableTextFieldType extends StrField
{
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return new SortField(field.getName(), new TextSortFieldComparatorSource(), reverse);
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#marshalSortValue(java.lang.Object)
*/
@Override
public Object marshalSortValue(Object value)
{
return value;
}
/* (non-Javadoc)
* @see org.apache.solr.schema.StrField#unmarshalSortValue(java.lang.Object)
*/
@Override
public Object unmarshalSortValue(Object value)
{
return value;
}
public static class TextSortFieldComparatorSource extends FieldComparatorSource
{
/*
* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
*/
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new TextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
}
/*
* Adapted from org.apache.lucene.search.FieldComparator.TermValComparator<T>
*/
public static final class TextSortFieldComparator extends FieldComparator<String> implements LeafFieldComparator
{
private final String[] values;
private BinaryDocValues docTerms;
/**
* An array of flags - one for each document in the segment. Each bit is set to true if the document has the
* field or false otherwise. If this is set to null then all docs in the segment have the field.
*/
Bits docsWithField;
private final String field;
Collator collator;
String bottom;
String top;
Locale collatorLocale;
TextSortFieldComparator(int numHits, String field, Locale collatorLocale)
{
values = new String[numHits];
this.field = field;
this.collatorLocale = collatorLocale;
collator = Collator.getInstance(collatorLocale);
}
public int compare(int slot1, int slot2)
{
final String val1 = values[slot1];
final String val2 = values[slot2];
return compareValues(val1, val2);
}
public void setBottom(final int bottom)
{
this.bottom = values[bottom];
}
public int compareBottom(int doc)
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(bottom, comparableString);
}
public void copy(int slot, int doc)
{
values[slot] = findBestValue(doc, docTerms.get(doc));
}
public String value(int slot)
{
return values[slot];
}
private String findBestValue(int doc, BytesRef term)
{
if (term.length == 0 && docsWithField != null && docsWithField.get(doc) == false)
{
return null;
}
String withLocale = term.utf8ToString();
// split strin into MLText object
if (withLocale == null)
{
return withLocale;
}
else if (withLocale.startsWith("\u0000"))
{
String[] parts = withLocale.split("\u0000");
return parts[2];
}
else
{
return withLocale;
}
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setTopValue(java.lang.Object)
*/
@Override
public void setTopValue(String value)
{
this.top = value;
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#compareTop(int)
*/
@Override
public int compareTop(int doc) throws IOException
{
final String comparableString = findBestValue(doc, docTerms.get(doc));
return compareValues(top, comparableString);
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparator#setNextReader(org.apache.lucene.index.AtomicReaderContext)
*/
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException
{
docTerms = DocValues.getBinary(context.reader(), field);
docsWithField = DocValues.getDocsWithField(context.reader(), field);
if (docsWithField instanceof Bits.MatchAllBits) {
docsWithField = null;
}
return this;
}
@Override
public int compareValues(String val1, String val2)
{
if (val1 == null)
{
if (val2 == null)
{
return 0;
}
return -1;
}
else if (val2 == null)
{
return 1;
}
return collator.compare(val1, val2);
}
@Override
public void setScorer(Scorer scorer) {}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2232,4 +2232,4 @@ public class AlfrescoCoreAdminHandler extends CoreAdminHandler
return response;
}
}
}
@@ -1,271 +1,271 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.KeywordAnalyzer;
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.analysis.util.AbstractAnalysisFactory;
import org.apache.lucene.analysis.util.CharFilterFactory;
import org.apache.lucene.analysis.util.MultiTermAwareComponent;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.QueryBuilder;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.SolrException;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.QParser;
import org.apache.solr.uninverting.UninvertingReader.Type;
/**
* Basic behaviour filtched from TextField
*
* @author Andy
*/
public class AlfrescoFieldType extends FieldType
{
IndexSchema schema;
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#init(org.apache.solr.schema.IndexSchema, java.util.Map)
*/
@Override
protected void init(IndexSchema schema, Map<String, String> args)
{
this.schema = schema;
properties |= TOKENIZED;
properties &= ~OMIT_TF_POSITIONS;
super.init(schema, args);
// TODO: Wire up localised analysis driven from the schema
// for now we do something basic
setIndexAnalyzer(new AlfrescoAnalyzerWrapper(schema, AlfrescoAnalyzerWrapper.Mode.INDEX));
setQueryAnalyzer(new AlfrescoAnalyzerWrapper(schema, AlfrescoAnalyzerWrapper.Mode.QUERY));
}
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return getStringSort(field, reverse);
}
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#write(org.apache.solr.response.TextResponseWriter, java.lang.String,
* org.apache.lucene.index.IndexableField)
*/
@Override
public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException
{
writer.writeStr(name, f.stringValue(), true);
}
@Override
public Query getFieldQuery(QParser parser, SchemaField field, String externalVal)
{
return parseFieldQuery(parser, getQueryAnalyzer(), field.getName(), externalVal);
}
@Override
public Object toObject(SchemaField sf, BytesRef term)
{
return term.utf8ToString();
}
@Override
public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, boolean minInclusive, boolean maxInclusive)
{
Analyzer multiAnalyzer = constructMultiTermAnalyzer(getQueryAnalyzer());
BytesRef lower = analyzeMultiTerm(field.getName(), part1, multiAnalyzer);
BytesRef upper = analyzeMultiTerm(field.getName(), part2, multiAnalyzer);
return new TermRangeQuery(field.getName(), lower, upper, minInclusive, maxInclusive);
}
private Analyzer constructMultiTermAnalyzer(Analyzer queryAnalyzer)
{
if (queryAnalyzer == null)
return null;
if (!(queryAnalyzer instanceof TokenizerChain))
{
return new KeywordAnalyzer();
}
TokenizerChain tc = (TokenizerChain) queryAnalyzer;
MultiTermChainBuilder builder = new MultiTermChainBuilder();
CharFilterFactory[] charFactories = tc.getCharFilterFactories();
if (charFactories != null)
{
for (CharFilterFactory fact : charFactories)
{
builder.add(fact);
}
}
builder.add(tc.getTokenizerFactory());
for (TokenFilterFactory fact : tc.getTokenFilterFactories())
{
builder.add(fact);
}
return builder.build();
}
private static class MultiTermChainBuilder
{
static final KeywordTokenizerFactory keyFactory = new KeywordTokenizerFactory(new HashMap<String, String>());
ArrayList<CharFilterFactory> charFilters = null;
ArrayList<TokenFilterFactory> filters = new ArrayList<TokenFilterFactory>(2);
TokenizerFactory tokenizer = keyFactory;
public void add(Object current)
{
if (!(current instanceof MultiTermAwareComponent))
return;
AbstractAnalysisFactory newComponent = ((MultiTermAwareComponent) current).getMultiTermComponent();
if (newComponent instanceof TokenFilterFactory)
{
if (filters == null)
{
filters = new ArrayList<TokenFilterFactory>(2);
}
filters.add((TokenFilterFactory) newComponent);
}
else if (newComponent instanceof TokenizerFactory)
{
tokenizer = (TokenizerFactory) newComponent;
}
else if (newComponent instanceof CharFilterFactory)
{
if (charFilters == null)
{
charFilters = new ArrayList<CharFilterFactory>(1);
}
charFilters.add((CharFilterFactory) newComponent);
}
else
{
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown analysis component from MultiTermAwareComponent: " + newComponent);
}
}
public TokenizerChain build()
{
CharFilterFactory[] charFilterArr = charFilters == null ? null : charFilters.toArray(new CharFilterFactory[charFilters.size()]);
TokenFilterFactory[] filterArr = filters == null ? new TokenFilterFactory[0] : filters.toArray(new TokenFilterFactory[filters.size()]);
return new TokenizerChain(charFilterArr, tokenizer, filterArr);
}
}
public static BytesRef analyzeMultiTerm(String field, String part, Analyzer analyzerIn)
{
if (part == null || analyzerIn == null)
return null;
TokenStream source = null;
try
{
source = analyzerIn.tokenStream(field, part);
source.reset();
TermToBytesRefAttribute termAtt = source.getAttribute(TermToBytesRefAttribute.class);
BytesRef bytes = termAtt.getBytesRef();
if (!source.incrementToken())
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "analyzer returned no terms for multiTerm term: " + part);
if (source.incrementToken())
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "analyzer returned too many terms for multiTerm term: " + part);
source.end();
return BytesRef.deepCopyOf(bytes);
}
catch (IOException e)
{
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "error analyzing range part: " + part, e);
}
finally
{
IOUtils.closeWhileHandlingException(source);
}
}
static Query parseFieldQuery(QParser parser, Analyzer analyzer, String field, String queryText)
{
// note, this method always worked this way (but nothing calls it?) because it has no idea of quotes...
return new QueryBuilder(analyzer).createPhraseQuery(field, queryText);
}
@Override
public Object marshalSortValue(Object value)
{
return marshalStringSortValue(value);
}
@Override
public Object unmarshalSortValue(Object value)
{
return unmarshalStringSortValue(value);
}
protected boolean supportsAnalyzers()
{
return true;
}
@Override
public Type getUninversionType(SchemaField sf) {
return Type.SORTED_SET_BINARY;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.KeywordAnalyzer;
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.analysis.util.AbstractAnalysisFactory;
import org.apache.lucene.analysis.util.CharFilterFactory;
import org.apache.lucene.analysis.util.MultiTermAwareComponent;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.QueryBuilder;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.SolrException;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.QParser;
import org.apache.solr.uninverting.UninvertingReader.Type;
/**
* Basic behaviour filtched from TextField
*
* @author Andy
*/
public class AlfrescoFieldType extends FieldType
{
IndexSchema schema;
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#init(org.apache.solr.schema.IndexSchema, java.util.Map)
*/
@Override
protected void init(IndexSchema schema, Map<String, String> args)
{
this.schema = schema;
properties |= TOKENIZED;
properties &= ~OMIT_TF_POSITIONS;
super.init(schema, args);
// TODO: Wire up localised analysis driven from the schema
// for now we do something basic
setIndexAnalyzer(new AlfrescoAnalyzerWrapper(schema, AlfrescoAnalyzerWrapper.Mode.INDEX));
setQueryAnalyzer(new AlfrescoAnalyzerWrapper(schema, AlfrescoAnalyzerWrapper.Mode.QUERY));
}
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#getSortField(org.apache.solr.schema.SchemaField, boolean)
*/
@Override
public SortField getSortField(SchemaField field, boolean reverse)
{
return getStringSort(field, reverse);
}
/*
* (non-Javadoc)
* @see org.apache.solr.schema.FieldType#write(org.apache.solr.response.TextResponseWriter, java.lang.String,
* org.apache.lucene.index.IndexableField)
*/
@Override
public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException
{
writer.writeStr(name, f.stringValue(), true);
}
@Override
public Query getFieldQuery(QParser parser, SchemaField field, String externalVal)
{
return parseFieldQuery(parser, getQueryAnalyzer(), field.getName(), externalVal);
}
@Override
public Object toObject(SchemaField sf, BytesRef term)
{
return term.utf8ToString();
}
@Override
public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, boolean minInclusive, boolean maxInclusive)
{
Analyzer multiAnalyzer = constructMultiTermAnalyzer(getQueryAnalyzer());
BytesRef lower = analyzeMultiTerm(field.getName(), part1, multiAnalyzer);
BytesRef upper = analyzeMultiTerm(field.getName(), part2, multiAnalyzer);
return new TermRangeQuery(field.getName(), lower, upper, minInclusive, maxInclusive);
}
private Analyzer constructMultiTermAnalyzer(Analyzer queryAnalyzer)
{
if (queryAnalyzer == null)
return null;
if (!(queryAnalyzer instanceof TokenizerChain))
{
return new KeywordAnalyzer();
}
TokenizerChain tc = (TokenizerChain) queryAnalyzer;
MultiTermChainBuilder builder = new MultiTermChainBuilder();
CharFilterFactory[] charFactories = tc.getCharFilterFactories();
if (charFactories != null)
{
for (CharFilterFactory fact : charFactories)
{
builder.add(fact);
}
}
builder.add(tc.getTokenizerFactory());
for (TokenFilterFactory fact : tc.getTokenFilterFactories())
{
builder.add(fact);
}
return builder.build();
}
private static class MultiTermChainBuilder
{
static final KeywordTokenizerFactory keyFactory = new KeywordTokenizerFactory(new HashMap<String, String>());
ArrayList<CharFilterFactory> charFilters = null;
ArrayList<TokenFilterFactory> filters = new ArrayList<TokenFilterFactory>(2);
TokenizerFactory tokenizer = keyFactory;
public void add(Object current)
{
if (!(current instanceof MultiTermAwareComponent))
return;
AbstractAnalysisFactory newComponent = ((MultiTermAwareComponent) current).getMultiTermComponent();
if (newComponent instanceof TokenFilterFactory)
{
if (filters == null)
{
filters = new ArrayList<TokenFilterFactory>(2);
}
filters.add((TokenFilterFactory) newComponent);
}
else if (newComponent instanceof TokenizerFactory)
{
tokenizer = (TokenizerFactory) newComponent;
}
else if (newComponent instanceof CharFilterFactory)
{
if (charFilters == null)
{
charFilters = new ArrayList<CharFilterFactory>(1);
}
charFilters.add((CharFilterFactory) newComponent);
}
else
{
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown analysis component from MultiTermAwareComponent: " + newComponent);
}
}
public TokenizerChain build()
{
CharFilterFactory[] charFilterArr = charFilters == null ? null : charFilters.toArray(new CharFilterFactory[charFilters.size()]);
TokenFilterFactory[] filterArr = filters == null ? new TokenFilterFactory[0] : filters.toArray(new TokenFilterFactory[filters.size()]);
return new TokenizerChain(charFilterArr, tokenizer, filterArr);
}
}
public static BytesRef analyzeMultiTerm(String field, String part, Analyzer analyzerIn)
{
if (part == null || analyzerIn == null)
return null;
TokenStream source = null;
try
{
source = analyzerIn.tokenStream(field, part);
source.reset();
TermToBytesRefAttribute termAtt = source.getAttribute(TermToBytesRefAttribute.class);
BytesRef bytes = termAtt.getBytesRef();
if (!source.incrementToken())
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "analyzer returned no terms for multiTerm term: " + part);
if (source.incrementToken())
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "analyzer returned too many terms for multiTerm term: " + part);
source.end();
return BytesRef.deepCopyOf(bytes);
}
catch (IOException e)
{
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "error analyzing range part: " + part, e);
}
finally
{
IOUtils.closeWhileHandlingException(source);
}
}
static Query parseFieldQuery(QParser parser, Analyzer analyzer, String field, String queryText)
{
// note, this method always worked this way (but nothing calls it?) because it has no idea of quotes...
return new QueryBuilder(analyzer).createPhraseQuery(field, queryText);
}
@Override
public Object marshalSortValue(Object value)
{
return marshalStringSortValue(value);
}
@Override
public Object unmarshalSortValue(Object value)
{
return unmarshalStringSortValue(value);
}
protected boolean supportsAnalyzers()
{
return true;
}
@Override
public Type getUninversionType(SchemaField sf) {
return Type.SORTED_SET_BINARY;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,76 +1,76 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.repo.search.impl.parsers.AlfrescoFunctionEvaluationContext;
import org.alfresco.repo.search.impl.parsers.FTSQueryException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.solr.schema.IndexSchema;
/**
* @author Andy
*
*/
public class AlfrescoSolr4FunctionEvaluationContext extends AlfrescoFunctionEvaluationContext
{
private IndexSchema indexSchema;
/**
* @param namespacePrefixResolver
* @param dictionaryService
* @param defaultNamespace
* @param indexSchema
*/
public AlfrescoSolr4FunctionEvaluationContext(NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String defaultNamespace, IndexSchema indexSchema)
{
super(namespacePrefixResolver, dictionaryService, defaultNamespace);
this.indexSchema = indexSchema;
}
public String getLuceneFieldName(String propertyName)
{
if(indexSchema.getFieldOrNull(propertyName) != null)
{
return propertyName;
}
else
{
try
{
return super.getLuceneFieldName(propertyName);
}
catch(FTSQueryException e)
{
// unknown
return "_dummy_";
}
}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.repo.search.impl.parsers.AlfrescoFunctionEvaluationContext;
import org.alfresco.repo.search.impl.parsers.FTSQueryException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.solr.schema.IndexSchema;
/**
* @author Andy
*
*/
public class AlfrescoSolr4FunctionEvaluationContext extends AlfrescoFunctionEvaluationContext
{
private IndexSchema indexSchema;
/**
* @param namespacePrefixResolver
* @param dictionaryService
* @param defaultNamespace
* @param indexSchema
*/
public AlfrescoSolr4FunctionEvaluationContext(NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String defaultNamespace, IndexSchema indexSchema)
{
super(namespacePrefixResolver, dictionaryService, defaultNamespace);
this.indexSchema = indexSchema;
}
public String getLuceneFieldName(String propertyName)
{
if(indexSchema.getFieldOrNull(propertyName) != null)
{
return propertyName;
}
else
{
try
{
return super.getLuceneFieldName(propertyName);
}
catch(FTSQueryException e)
{
// unknown
return "_dummy_";
}
}
}
}
@@ -1,168 +1,168 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.util.Collection;
import org.alfresco.repo.search.adaptor.QueryConstants;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.ResultContext;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.DocList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Cloud consists of support methods for running solr queries in the cloud.
*
* @author Ahmed Owian
*/
public class Cloud
{
public static final String RESPONSE_SOLR_DOCUMENT_LIST = "responseSolrDocumentList";
public static final String PARAM_GET_SOLR_DOCUMENT_LIST = "alfresco.getSolrDocumentList";
protected final static Logger log = LoggerFactory.getLogger(Cloud.class);
/**
* Creates a query to select docs with any of the specified field values
* @param fieldName the name of the field in the condition
* @param operator currently only OR makes sense. To add AND, fieldName must become a list of fields.
* @param valueLists a bunch of possible values for the field
* @return the resulting query string
*/
@SuppressWarnings("rawtypes")
String getQuery(String fieldName, String operator, Collection... valueLists)
{
StringBuilder query = new StringBuilder();
for (Collection values : valueLists)
{
for (Object value : values)
{
query.append(fieldName).append(":").append("\"").append(value.toString()).append("\"").append(operator);
}
}
if (query.length() >= operator.length())
{
// Removes the last appended operator from the query string
query.delete(query.length() - operator.length(), query.length());
}
return query.toString();
}
/**
* Returns whether or not a doc exists that satisfies the specified query
* @param requestHandler the handler that handles the request
* @param request the request object to put the query on
* @param query the string that specifies the doc
* @return <code>true</code> if the specified query returns a doc
*/
boolean exists(SolrRequestHandler requestHandler, SolrQueryRequest request, String query)
{
ModifiableSolrParams params = new ModifiableSolrParams(request.getParams());
// Sets 1 because this is effectively a boolean query to see if there exists a single match
params.set("q", query).set("fl", "id").set("rows", "1");
ResultContext rc = this.getResultContext(requestHandler, request, params);
if (rc != null)
{
// TODO Should we use rc.docs.matches() instead?
if (rc.getDocList() != null) { return rc.getDocList().iterator().hasNext(); }
}
return false;
}
/**
* Returns the doc list resulting from running the query
* @param requestHandler the handler that handles the request
* @param request the request object to put the query on
* @param query the string that specifies the docs
* @return the docs that come back from the query
*/
DocList getDocList(SolrRequestHandler requestHandler, SolrQueryRequest request, String query)
{
// Getting the doc list is shard-specific, and not really cloud-friendly
ModifiableSolrParams params = new ModifiableSolrParams(request.getParams());
// Sets MAX_VALUE to get all the rows
params.set("q", query).set("fl", QueryConstants.FIELD_SOLR4_ID).set("rows", Integer.MAX_VALUE);
ResultContext rc = this.getResultContext(requestHandler, request, params);
return rc != null ? rc.getDocList() : null;
}
/**
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the result context from the handled request
*/
ResultContext getResultContext(SolrRequestHandler requestHandler, SolrQueryRequest request, SolrParams params)
{
SolrQueryResponse solrRsp = getResponse(requestHandler, request, params);
ResultContext rc = (ResultContext) solrRsp.getValues().get("response");
return rc;
}
/**
* Returns the SolrDocumentList from the response, assuming that the specified request handler uses the
* AlfrescoSearchHandler which puts it on the response values.
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the result context from the handled request
*/
SolrDocumentList getSolrDocumentList(SolrRequestHandler requestHandler, SolrQueryRequest request,
ModifiableSolrParams params)
{
// Tells the AlfrescoSearchHandler to get the SolrDocumentList from the default results and add to response
params.set(PARAM_GET_SOLR_DOCUMENT_LIST, true);
SolrQueryResponse solrRsp = getResponse(requestHandler, request, params);
SolrDocumentList docs = (SolrDocumentList) solrRsp.getValues().get(RESPONSE_SOLR_DOCUMENT_LIST);
return docs;
}
/**
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the response
*/
SolrQueryResponse getResponse(SolrRequestHandler requestHandler, SolrQueryRequest request, SolrParams params)
{
request.setParams(params);
log.info("Running query " + params.get("q"));
SolrQueryResponse solrRsp = new SolrQueryResponse();
requestHandler.handleRequest(request, solrRsp);
return solrRsp;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.util.Collection;
import org.alfresco.repo.search.adaptor.QueryConstants;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.ResultContext;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.DocList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Cloud consists of support methods for running solr queries in the cloud.
*
* @author Ahmed Owian
*/
public class Cloud
{
public static final String RESPONSE_SOLR_DOCUMENT_LIST = "responseSolrDocumentList";
public static final String PARAM_GET_SOLR_DOCUMENT_LIST = "alfresco.getSolrDocumentList";
protected final static Logger log = LoggerFactory.getLogger(Cloud.class);
/**
* Creates a query to select docs with any of the specified field values
* @param fieldName the name of the field in the condition
* @param operator currently only OR makes sense. To add AND, fieldName must become a list of fields.
* @param valueLists a bunch of possible values for the field
* @return the resulting query string
*/
@SuppressWarnings("rawtypes")
String getQuery(String fieldName, String operator, Collection... valueLists)
{
StringBuilder query = new StringBuilder();
for (Collection values : valueLists)
{
for (Object value : values)
{
query.append(fieldName).append(":").append("\"").append(value.toString()).append("\"").append(operator);
}
}
if (query.length() >= operator.length())
{
// Removes the last appended operator from the query string
query.delete(query.length() - operator.length(), query.length());
}
return query.toString();
}
/**
* Returns whether or not a doc exists that satisfies the specified query
* @param requestHandler the handler that handles the request
* @param request the request object to put the query on
* @param query the string that specifies the doc
* @return <code>true</code> if the specified query returns a doc
*/
boolean exists(SolrRequestHandler requestHandler, SolrQueryRequest request, String query)
{
ModifiableSolrParams params = new ModifiableSolrParams(request.getParams());
// Sets 1 because this is effectively a boolean query to see if there exists a single match
params.set("q", query).set("fl", "id").set("rows", "1");
ResultContext rc = this.getResultContext(requestHandler, request, params);
if (rc != null)
{
// TODO Should we use rc.docs.matches() instead?
if (rc.getDocList() != null) { return rc.getDocList().iterator().hasNext(); }
}
return false;
}
/**
* Returns the doc list resulting from running the query
* @param requestHandler the handler that handles the request
* @param request the request object to put the query on
* @param query the string that specifies the docs
* @return the docs that come back from the query
*/
DocList getDocList(SolrRequestHandler requestHandler, SolrQueryRequest request, String query)
{
// Getting the doc list is shard-specific, and not really cloud-friendly
ModifiableSolrParams params = new ModifiableSolrParams(request.getParams());
// Sets MAX_VALUE to get all the rows
params.set("q", query).set("fl", QueryConstants.FIELD_SOLR4_ID).set("rows", Integer.MAX_VALUE);
ResultContext rc = this.getResultContext(requestHandler, request, params);
return rc != null ? rc.getDocList() : null;
}
/**
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the result context from the handled request
*/
ResultContext getResultContext(SolrRequestHandler requestHandler, SolrQueryRequest request, SolrParams params)
{
SolrQueryResponse solrRsp = getResponse(requestHandler, request, params);
ResultContext rc = (ResultContext) solrRsp.getValues().get("response");
return rc;
}
/**
* Returns the SolrDocumentList from the response, assuming that the specified request handler uses the
* AlfrescoSearchHandler which puts it on the response values.
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the result context from the handled request
*/
SolrDocumentList getSolrDocumentList(SolrRequestHandler requestHandler, SolrQueryRequest request,
ModifiableSolrParams params)
{
// Tells the AlfrescoSearchHandler to get the SolrDocumentList from the default results and add to response
params.set(PARAM_GET_SOLR_DOCUMENT_LIST, true);
SolrQueryResponse solrRsp = getResponse(requestHandler, request, params);
SolrDocumentList docs = (SolrDocumentList) solrRsp.getValues().get(RESPONSE_SOLR_DOCUMENT_LIST);
return docs;
}
/**
* @param requestHandler the handler that handles the request
* @param request the request object to put the params on
* @param params Solr parameters
* @return the response
*/
SolrQueryResponse getResponse(SolrRequestHandler requestHandler, SolrQueryRequest request, SolrParams params)
{
request.setParams(params);
log.info("Running query " + params.get("q"));
SolrQueryResponse solrRsp = new SolrQueryResponse();
requestHandler.handleRequest(request, solrRsp);
return solrRsp;
}
}
@@ -1,120 +1,120 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import org.alfresco.service.cmr.search.SearchParameters;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Andy
*
*/
public class ContextAwareQuery extends Query
{
protected final static Logger log = LoggerFactory.getLogger(ContextAwareQuery.class);
private final Query luceneQuery;
private final SearchParameters searchParameters;
/**
* @param luceneQuery Query
* @param searchParameters SearchParameters
*/
public ContextAwareQuery(Query luceneQuery, SearchParameters searchParameters)
{
this.luceneQuery = luceneQuery;
this.searchParameters = searchParameters;
}
/**
* @param field String
* @return String
* @see org.apache.lucene.search.Query#toString(java.lang.String)
*/
public String toString(String field)
{
return luceneQuery.toString(field);
}
/**
* @param searcher IndexSearcher
* @return Weight
* @throws IOException
* @see org.apache.lucene.search.Query#createWeight(IndexSearcher, boolean)
*/
public Weight createWeight(IndexSearcher searcher, boolean needsScore) throws IOException
{
return luceneQuery.createWeight(searcher, needsScore);
}
/**
* @param reader IndexReader
* @return Query
* @throws IOException
* @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader)
*/
public Query rewrite(IndexReader reader) throws IOException
{
return luceneQuery.rewrite(reader);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ContextAwareQuery)) return false;
ContextAwareQuery that = (ContextAwareQuery) o;
if (luceneQuery != null ? !luceneQuery.equals(that.luceneQuery) : that.luceneQuery != null) return false;
return searchParameters != null ? searchParameters.equals(that.searchParameters) : that.searchParameters == null;
}
@Override
public int hashCode() {
int result = luceneQuery != null ? luceneQuery.hashCode() : 0;
result = 31 * result + (searchParameters != null ? searchParameters.hashCode() : 0);
return result;
}
public Query getLuceneQuery()
{
return luceneQuery;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.IOException;
import org.alfresco.service.cmr.search.SearchParameters;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Andy
*
*/
public class ContextAwareQuery extends Query
{
protected final static Logger log = LoggerFactory.getLogger(ContextAwareQuery.class);
private final Query luceneQuery;
private final SearchParameters searchParameters;
/**
* @param luceneQuery Query
* @param searchParameters SearchParameters
*/
public ContextAwareQuery(Query luceneQuery, SearchParameters searchParameters)
{
this.luceneQuery = luceneQuery;
this.searchParameters = searchParameters;
}
/**
* @param field String
* @return String
* @see org.apache.lucene.search.Query#toString(java.lang.String)
*/
public String toString(String field)
{
return luceneQuery.toString(field);
}
/**
* @param searcher IndexSearcher
* @return Weight
* @throws IOException
* @see org.apache.lucene.search.Query#createWeight(IndexSearcher, boolean)
*/
public Weight createWeight(IndexSearcher searcher, boolean needsScore) throws IOException
{
return luceneQuery.createWeight(searcher, needsScore);
}
/**
* @param reader IndexReader
* @return Query
* @throws IOException
* @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader)
*/
public Query rewrite(IndexReader reader) throws IOException
{
return luceneQuery.rewrite(reader);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ContextAwareQuery)) return false;
ContextAwareQuery that = (ContextAwareQuery) o;
if (luceneQuery != null ? !luceneQuery.equals(that.luceneQuery) : that.luceneQuery != null) return false;
return searchParameters != null ? searchParameters.equals(that.searchParameters) : that.searchParameters == null;
}
@Override
public int hashCode() {
int result = luceneQuery != null ? luceneQuery.hashCode() : 0;
result = 31 * result + (searchParameters != null ? searchParameters.hashCode() : 0);
return result;
}
public Query getLuceneQuery()
{
return luceneQuery;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -562,4 +562,4 @@ class HandlerReportHelper
report.add(cname, coreSummary);
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -4102,4 +4102,4 @@ public class SolrInformationServer implements InformationServer
return empty();
}
}
}
}
@@ -1,76 +1,76 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.alfresco.encryption.KeyResourceLoader;
import org.apache.solr.core.SolrResourceLoader;
/**
* Loads encryption key resources from a Solr core installation using a SolrResourceLoader.
*
* @since 4.0
*/
public class SolrKeyResourceLoader implements KeyResourceLoader
{
private SolrResourceLoader loader;
public SolrKeyResourceLoader(SolrResourceLoader loader)
{
this.loader = loader;
}
@Override
public InputStream getKeyStore(String location)
throws FileNotFoundException
{
try
{
return loader.openResource(location);
}
catch (IOException e)
{
// TODO: SOLR API changes mean that IOException must be handled.
// This may need revisiting.
throw new FileNotFoundException("Caused by " + e.getMessage());
}
}
@Override
public Properties loadKeyMetaData(String location) throws IOException
{
Properties p = new Properties();
InputStream stream = loader.openResource(location);
p.load(stream);
stream.close();
return p;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.alfresco.encryption.KeyResourceLoader;
import org.apache.solr.core.SolrResourceLoader;
/**
* Loads encryption key resources from a Solr core installation using a SolrResourceLoader.
*
* @since 4.0
*/
public class SolrKeyResourceLoader implements KeyResourceLoader
{
private SolrResourceLoader loader;
public SolrKeyResourceLoader(SolrResourceLoader loader)
{
this.loader = loader;
}
@Override
public InputStream getKeyStore(String location)
throws FileNotFoundException
{
try
{
return loader.openResource(location);
}
catch (IOException e)
{
// TODO: SOLR API changes mean that IOException must be handled.
// This may need revisiting.
throw new FileNotFoundException("Caused by " + e.getMessage());
}
}
@Override
public Properties loadKeyMetaData(String location) throws IOException
{
Properties p = new Properties();
InputStream stream = loader.openResource(location);
p.load(stream);
stream.close();
return p;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -48,4 +48,4 @@ public class StripLocaleStrField extends StrField
.orElse(null);
return super.createFields(field, newValue, boost);
}
}
}
@@ -1,79 +1,79 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* @author Andy
*
*/
public class TrackerStateException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = -3030261887767267309L;
/**
* @param msgId
*/
public TrackerStateException(String msgId)
{
super(msgId);
}
/**
* @param msgId
* @param msgParams
*/
public TrackerStateException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
/**
* @param msgId
* @param cause
*/
public TrackerStateException(String msgId, Throwable cause)
{
super(msgId, cause);
}
/**
* @param msgId
* @param msgParams
* @param cause
*/
public TrackerStateException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* @author Andy
*
*/
public class TrackerStateException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = -3030261887767267309L;
/**
* @param msgId
*/
public TrackerStateException(String msgId)
{
super(msgId);
}
/**
* @param msgId
* @param msgParams
*/
public TrackerStateException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
/**
* @param msgId
* @param cause
*/
public TrackerStateException(String msgId, Throwable cause)
{
super(msgId, cause);
}
/**
* @param msgId
* @param msgParams
* @param cause
*/
public TrackerStateException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}
@@ -1,77 +1,77 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.adapters;
import org.apache.lucene.util.LongBitSet;
/**
* The reason we have this class is so that lucene-free dependent classes can be dependent on IOpenBitSet instead of the
* lucene-version-specific OpenBitSet.
* @author Ahmed Owian
*/
public class SolrOpenBitSetAdapter implements IOpenBitSet
{
LongBitSet delegate;
public SolrOpenBitSetAdapter()
{
delegate = new LongBitSet(64);
}
@Override
public void set(long index)
{
delegate = LongBitSet.ensureCapacity(delegate, index);
delegate.set(index);
}
@Override
public void or(IOpenBitSet other)
{
delegate.or( ((SolrOpenBitSetAdapter)other).delegate);
}
@Override
public long nextSetBit(long index)
{
return delegate.nextSetBit(index);
}
@Override
public long cardinality()
{
return delegate.cardinality();
}
@Override
public boolean get(long index)
{
return delegate.get(index);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.adapters;
import org.apache.lucene.util.LongBitSet;
/**
* The reason we have this class is so that lucene-free dependent classes can be dependent on IOpenBitSet instead of the
* lucene-version-specific OpenBitSet.
* @author Ahmed Owian
*/
public class SolrOpenBitSetAdapter implements IOpenBitSet
{
LongBitSet delegate;
public SolrOpenBitSetAdapter()
{
delegate = new LongBitSet(64);
}
@Override
public void set(long index)
{
delegate = LongBitSet.ensureCapacity(delegate, index);
delegate.set(index);
}
@Override
public void or(IOpenBitSet other)
{
delegate.or( ((SolrOpenBitSetAdapter)other).delegate);
}
@Override
public long nextSetBit(long index)
{
return delegate.nextSetBit(index);
}
@Override
public long cardinality()
{
return delegate.cardinality();
}
@Override
public boolean get(long index)
{
return delegate.get(index);
}
}
@@ -1,39 +1,39 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.adapters;
import org.apache.solr.common.util.SimpleOrderedMap;
public class SolrSimpleOrderedMap<T> extends SimpleOrderedMap<T> implements ISimpleOrderedMap<T>
{
/**
*
*/
private static final long serialVersionUID = 2799724619330515239L;
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.adapters;
import org.apache.solr.common.util.SimpleOrderedMap;
public class SolrSimpleOrderedMap<T> extends SimpleOrderedMap<T> implements ISimpleOrderedMap<T>
{
/**
*
*/
private static final long serialVersionUID = 2799724619330515239L;
}
@@ -1,58 +1,58 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
import java.io.IOException;
import org.apache.lucene.search.Query;
import org.apache.solr.search.CacheRegenerator;
import org.apache.solr.search.SolrCache;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Cache regeneration for AUTHORITY and AUTHSET queries.
*
* @author Matt Ward
*/
public class AuthorityCacheRegenerator implements CacheRegenerator
{
@SuppressWarnings({ "rawtypes" })
@Override
public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache,
SolrCache oldCache, Object oldKey, Object oldVal) throws IOException
{
if (oldKey instanceof Query)
{
// The authority cache contains results keyed by SolrAuthorityQuery
// and SolrAuthoritySetQuery.
Query authQuery = (Query) oldKey;
// Execute the query on the new searcher - resulting in cache population as a side-effect.
newSearcher.getDocSet(authQuery);
}
return true;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
import java.io.IOException;
import org.apache.lucene.search.Query;
import org.apache.solr.search.CacheRegenerator;
import org.apache.solr.search.SolrCache;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Cache regeneration for AUTHORITY and AUTHSET queries.
*
* @author Matt Ward
*/
public class AuthorityCacheRegenerator implements CacheRegenerator
{
@SuppressWarnings({ "rawtypes" })
@Override
public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache,
SolrCache oldCache, Object oldKey, Object oldVal) throws IOException
{
if (oldKey instanceof Query)
{
// The authority cache contains results keyed by SolrAuthorityQuery
// and SolrAuthoritySetQuery.
Query authQuery = (Query) oldKey;
// Execute the query on the new searcher - resulting in cache population as a side-effect.
newSearcher.getDocSet(authQuery);
}
return true;
}
}
@@ -1,48 +1,48 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
/**
* Constants for per-searcher cache names and keys.
*
* @author Matt Ward
*/
public class CacheConstants
{
// Cache names
// public static String ALFRESCO_CACHE = "alfrescoCache";
// public static String ALFRESCO_ARRAYLIST_CACHE = "alfrescoArrayListCache";
// public static String ALFRESCO_PATH_CACHE = "alfrescoPathCache";
// public static String ALFRESCO_READER_TO_ACL_IDS_CACHE = "alfrescoReaderToAclIdsCache";
// public static String ALFRESCO_DENY_TO_ACL_IDS_CACHE = "alfrescoDenyToAclIdsCache";
public final static String ALFRESCO_AUTHORITY_CACHE = "alfrescoAuthorityCache";
public final static String ALFRESCO_OWNERLOOKUP_CACHE = "alfrescoOwnerCache";
public final static String ALFRESCO_READER_CACHE = "alfrescoReaderCache";
public final static String ALFRESCO_DENIED_CACHE = "alfrescoDeniedCache";
public final static String ALFRESCO_PATH_CACHE = "alfrescoPathCache";
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
/**
* Constants for per-searcher cache names and keys.
*
* @author Matt Ward
*/
public class CacheConstants
{
// Cache names
// public static String ALFRESCO_CACHE = "alfrescoCache";
// public static String ALFRESCO_ARRAYLIST_CACHE = "alfrescoArrayListCache";
// public static String ALFRESCO_PATH_CACHE = "alfrescoPathCache";
// public static String ALFRESCO_READER_TO_ACL_IDS_CACHE = "alfrescoReaderToAclIdsCache";
// public static String ALFRESCO_DENY_TO_ACL_IDS_CACHE = "alfrescoDenyToAclIdsCache";
public final static String ALFRESCO_AUTHORITY_CACHE = "alfrescoAuthorityCache";
public final static String ALFRESCO_OWNERLOOKUP_CACHE = "alfrescoOwnerCache";
public final static String ALFRESCO_READER_CACHE = "alfrescoReaderCache";
public final static String ALFRESCO_DENIED_CACHE = "alfrescoDeniedCache";
public final static String ALFRESCO_PATH_CACHE = "alfrescoPathCache";
}
@@ -1,59 +1,59 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
import java.io.IOException;
import org.alfresco.solr.query.SolrCachingPathQuery;
import org.alfresco.solr.query.SolrPathQuery;
import org.apache.solr.search.CacheRegenerator;
import org.apache.solr.search.SolrCache;
import org.apache.solr.search.SolrIndexSearcher;
/**
* {@link CacheRegenerator} for alfrescoPathCache
*
* @author Matt Ward
*/
public class PathCacheRegenerator implements CacheRegenerator
{
@SuppressWarnings({ "rawtypes" })
@Override
public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache,
SolrCache oldCache, Object oldKey, Object oldVal) throws IOException
{
if (oldKey instanceof SolrPathQuery)
{
SolrPathQuery pathQuery = (SolrPathQuery) oldKey;
// Re-execute the path query in a cache-aware context - causing new results to be cached.
SolrCachingPathQuery cachingPathQuery = new SolrCachingPathQuery(pathQuery);
newSearcher.getDocSet(cachingPathQuery);
}
return true;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.cache;
import java.io.IOException;
import org.alfresco.solr.query.SolrCachingPathQuery;
import org.alfresco.solr.query.SolrPathQuery;
import org.apache.solr.search.CacheRegenerator;
import org.apache.solr.search.SolrCache;
import org.apache.solr.search.SolrIndexSearcher;
/**
* {@link CacheRegenerator} for alfrescoPathCache
*
* @author Matt Ward
*/
public class PathCacheRegenerator implements CacheRegenerator
{
@SuppressWarnings({ "rawtypes" })
@Override
public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache,
SolrCache oldCache, Object oldKey, Object oldVal) throws IOException
{
if (oldKey instanceof SolrPathQuery)
{
SolrPathQuery pathQuery = (SolrPathQuery) oldKey;
// Re-execute the path query in a cache-aware context - causing new results to be cached.
SolrCachingPathQuery cachingPathQuery = new SolrCachingPathQuery(pathQuery);
newSearcher.getDocSet(cachingPathQuery);
}
return true;
}
}
@@ -1,78 +1,78 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class ClearLocaleComponent extends SearchComponent
{
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb) throws IOException
{
I18NUtil.setLocale(null);
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "clearLocale";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class ClearLocaleComponent extends SearchComponent
{
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb) throws IOException
{
I18NUtil.setLocale(null);
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "clearLocale";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
@@ -1,105 +1,105 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import org.alfresco.solr.AlfrescoCoreAdminHandler;
import org.alfresco.solr.InformationServer;
import org.alfresco.solr.TrackerState;
import org.alfresco.solr.tracker.MetadataTracker;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Date;
/**
* Adds consitency information to the search results
*/
public class ConsistencyComponent extends SearchComponent
{
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// No preparation required.
}
@Override
public void finishStage(ResponseBuilder rb)
{
super.finishStage(rb);
if (rb.stage != ResponseBuilder.STAGE_GET_FIELDS)
return;
try {
process(rb);
} catch (IOException e) {
LOG.error(e.getMessage());
}
}
@Override
public void process(ResponseBuilder rb) throws IOException
{
SolrQueryRequest req = rb.req;
AlfrescoCoreAdminHandler adminHandler = (AlfrescoCoreAdminHandler)
req.getCore().
getCoreContainer().
getMultiCoreHandler();
boolean isShard = rb.req.getParams().getBool(ShardParams.IS_SHARD, false);
MetadataTracker metaTrkr = adminHandler.getTrackerRegistry().getTrackerForCore(req.getCore().getName(), MetadataTracker.class);
if(metaTrkr != null && !isShard)
{
TrackerState metadataTrkrState = metaTrkr.getTrackerState();
long lastIndexedTx = metadataTrkrState.getLastIndexedTxId();
long lastIndexTxCommitTime = metadataTrkrState.getLastIndexedTxCommitTime();
long lastTxIdOnServer = metadataTrkrState.getLastTxIdOnServer();
long transactionsToDo = lastTxIdOnServer - lastIndexedTx;
if (transactionsToDo < 0)
{
transactionsToDo = 0;
}
rb.rsp.add("lastIndexedTx", lastIndexedTx);
rb.rsp.add("lastIndexedTxTime", lastIndexTxCommitTime);
rb.rsp.add("txRemaining", transactionsToDo);
}
}
@Override
public String getDescription()
{
return "Adds consitency information to the search results.";
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import org.alfresco.solr.AlfrescoCoreAdminHandler;
import org.alfresco.solr.InformationServer;
import org.alfresco.solr.TrackerState;
import org.alfresco.solr.tracker.MetadataTracker;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Date;
/**
* Adds consitency information to the search results
*/
public class ConsistencyComponent extends SearchComponent
{
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// No preparation required.
}
@Override
public void finishStage(ResponseBuilder rb)
{
super.finishStage(rb);
if (rb.stage != ResponseBuilder.STAGE_GET_FIELDS)
return;
try {
process(rb);
} catch (IOException e) {
LOG.error(e.getMessage());
}
}
@Override
public void process(ResponseBuilder rb) throws IOException
{
SolrQueryRequest req = rb.req;
AlfrescoCoreAdminHandler adminHandler = (AlfrescoCoreAdminHandler)
req.getCore().
getCoreContainer().
getMultiCoreHandler();
boolean isShard = rb.req.getParams().getBool(ShardParams.IS_SHARD, false);
MetadataTracker metaTrkr = adminHandler.getTrackerRegistry().getTrackerForCore(req.getCore().getName(), MetadataTracker.class);
if(metaTrkr != null && !isShard)
{
TrackerState metadataTrkrState = metaTrkr.getTrackerState();
long lastIndexedTx = metadataTrkrState.getLastIndexedTxId();
long lastIndexTxCommitTime = metadataTrkrState.getLastIndexedTxCommitTime();
long lastTxIdOnServer = metadataTrkrState.getLastTxIdOnServer();
long transactionsToDo = lastTxIdOnServer - lastIndexedTx;
if (transactionsToDo < 0)
{
transactionsToDo = 0;
}
rb.rsp.add("lastIndexedTx", lastIndexedTx);
rb.rsp.add("lastIndexedTxTime", lastIndexTxCommitTime);
rb.rsp.add("txRemaining", transactionsToDo);
}
}
@Override
public String getDescription()
{
return "Adds consitency information to the search results.";
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -135,4 +135,4 @@ public class FingerPrintComponent extends SearchComponent
{
return null;
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,279 +1,279 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import com.google.common.collect.BiMap;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
/**
* @author Andy
*
*/
public class RewriteFacetCountsComponent extends SearchComponent
{
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#finishStage(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void finishStage(ResponseBuilder rb)
{
/// wait until after distributed faceting is done
if (!rb.doFacets || rb.stage != ResponseBuilder.STAGE_GET_FIELDS)
{
return;
}
else
{
process(rb);
}
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb)
{
// rewrite
rewrite(rb, "_field_mappings_", "facet_counts", "facet_fields");
rewrite(rb, "_date_mappings_", "facet_counts", "facet_dates");
rewrite(rb, "_range_mappings_", "facet_counts", "facet_ranges");
rewrite(rb, "_interval_mappings_", "facet_counts", "facet_intervals");
rewrite(rb, "_pivot_mappings_", "facet_counts", "facet_pivot");
rewritePivotFields(rb, "facet_counts", "facet_pivot");
rewrite(rb, "_stats_field_mappings_", "stats", "stats_fields");
copyAnalytics(rb, "facet_counts", "facet_fields");
Map<String, String> mappings = (Map<String, String>) rb.rsp.getValues().get("_stats_field_mappings_");
if(mappings != null)
{
for(String key : mappings.keySet())
{
rewrite(rb, "_stats_facet_mappings_", "stats", "stats_fields", key, "facets");
}
}
}
/**
* @param rb
*/
private void copyAnalytics(ResponseBuilder rb, String ... sections)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for(String section : sections)
{
found = (NamedList<Object>)found.get(section);
if(found == null)
{
return;
}
}
NamedList<Object> analytics = (NamedList<Object>) rb.rsp.getValues();
analytics = (NamedList<Object>)analytics.get("analytics");
if(analytics != null)
{
for(int i = 0; i < analytics.size(); i++)
{
String name = analytics.getName(i);
Object value = analytics.getVal(i);
found.add(name, value);
}
}
}
/**
* Update pivot fields in the response to reference ACS properties rather than Solr fields.
*
* @param rb The response builder.
* @param sections The names of the sections in the response to update.
*/
private void rewritePivotFields(ResponseBuilder rb, String ... sections)
{
Map<String, String> mappings = (Map<String, String>) rb.rsp.getValues().get("_pivot_mappings_");
if(mappings != null)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for(String section : sections)
{
found = (NamedList<Object>)found.get(section);
if(found == null)
{
return;
}
}
for(int i = 0; i < found.size(); i++)
{
String pivotName = found.getName(i);
String[] fromParts = pivotName.split(",");
String mapping = mappings.get(pivotName);
String[] toParts = mapping != null ? mapping.split(",") : fromParts;
Collection<NamedList<Object>> current = (Collection<NamedList<Object>>)found.getVal(i);
processPivot(rb, fromParts, toParts, current, 0);
}
}
}
private void processPivot(ResponseBuilder rb, String[] fromParts, String[] toParts, Collection<NamedList<Object>> current, int level)
{
for(NamedList<Object> entry : current)
{
for(int i = 0; i < entry.size(); i++)
{
String name = entry.getName(i);
if(name.equals("field"))
{
entry.setVal(i, fromParts[level].trim());
}
else if(name.equals("pivot"))
{
Collection<NamedList<Object>> pivot = (Collection<NamedList<Object>>)entry.getVal(i);
processPivot(rb, fromParts, toParts, pivot, level+1);
}
else if(name.equals("ranges"))
{
SimpleOrderedMap ranges = (SimpleOrderedMap)entry.getVal(i);
processRanges(rb, ranges);
}
else
{
// leave alone
}
}
}
}
/**
* Update the returned ranges to reference ACS properties rather than Solr fields.
*
* @param rb The response builder.
* @param ranges The ranges to update.
*/
private void processRanges(ResponseBuilder rb, SimpleOrderedMap ranges) {
BiMap<String, String> mappings = (BiMap<String, String>) rb.rsp.getValues().get("_range_mappings_");
if(mappings != null)
{
updateToACSNaming(mappings, ranges);
}
}
/**
* Update the returned facet sections to reference ACS properties rather than Solr fields.
*
* @param rb the response builder.
* @param mappingName The name of the mapping definition created in {@link RewriteFacetParametersComponent}.
* @param sections The names of the sections to be updated.
*/
private void rewrite(ResponseBuilder rb, String mappingName, String ... sections)
{
BiMap<String, String> mappings = (BiMap<String, String>) rb.rsp.getValues().get(mappingName);
if(mappings != null)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for (String section : sections)
{
found = (NamedList<Object>) found.get(section);
if (found == null)
{
return;
}
}
// This found already contains the private buckets
updateToACSNaming(mappings, found);
}
}
/**
* Update entries in a list to reference ACS properties rather than Solr fields.
*
* @param mappings The mapping from ACS properties to Solr fields.
* @param propertyList The list to update.
*/
private void updateToACSNaming(BiMap<String, String> mappings, NamedList<Object> propertyList)
{
for (int i = 0; i < propertyList.size(); i++)
{
String name = propertyList.getName(i);
String newName = mappings.inverse().get(name);
if (newName != null)
{
propertyList.setName(i, newName);
}
}
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "RewriteFacetCounts";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import com.google.common.collect.BiMap;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
/**
* @author Andy
*
*/
public class RewriteFacetCountsComponent extends SearchComponent
{
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#finishStage(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void finishStage(ResponseBuilder rb)
{
/// wait until after distributed faceting is done
if (!rb.doFacets || rb.stage != ResponseBuilder.STAGE_GET_FIELDS)
{
return;
}
else
{
process(rb);
}
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb)
{
// rewrite
rewrite(rb, "_field_mappings_", "facet_counts", "facet_fields");
rewrite(rb, "_date_mappings_", "facet_counts", "facet_dates");
rewrite(rb, "_range_mappings_", "facet_counts", "facet_ranges");
rewrite(rb, "_interval_mappings_", "facet_counts", "facet_intervals");
rewrite(rb, "_pivot_mappings_", "facet_counts", "facet_pivot");
rewritePivotFields(rb, "facet_counts", "facet_pivot");
rewrite(rb, "_stats_field_mappings_", "stats", "stats_fields");
copyAnalytics(rb, "facet_counts", "facet_fields");
Map<String, String> mappings = (Map<String, String>) rb.rsp.getValues().get("_stats_field_mappings_");
if(mappings != null)
{
for(String key : mappings.keySet())
{
rewrite(rb, "_stats_facet_mappings_", "stats", "stats_fields", key, "facets");
}
}
}
/**
* @param rb
*/
private void copyAnalytics(ResponseBuilder rb, String ... sections)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for(String section : sections)
{
found = (NamedList<Object>)found.get(section);
if(found == null)
{
return;
}
}
NamedList<Object> analytics = (NamedList<Object>) rb.rsp.getValues();
analytics = (NamedList<Object>)analytics.get("analytics");
if(analytics != null)
{
for(int i = 0; i < analytics.size(); i++)
{
String name = analytics.getName(i);
Object value = analytics.getVal(i);
found.add(name, value);
}
}
}
/**
* Update pivot fields in the response to reference ACS properties rather than Solr fields.
*
* @param rb The response builder.
* @param sections The names of the sections in the response to update.
*/
private void rewritePivotFields(ResponseBuilder rb, String ... sections)
{
Map<String, String> mappings = (Map<String, String>) rb.rsp.getValues().get("_pivot_mappings_");
if(mappings != null)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for(String section : sections)
{
found = (NamedList<Object>)found.get(section);
if(found == null)
{
return;
}
}
for(int i = 0; i < found.size(); i++)
{
String pivotName = found.getName(i);
String[] fromParts = pivotName.split(",");
String mapping = mappings.get(pivotName);
String[] toParts = mapping != null ? mapping.split(",") : fromParts;
Collection<NamedList<Object>> current = (Collection<NamedList<Object>>)found.getVal(i);
processPivot(rb, fromParts, toParts, current, 0);
}
}
}
private void processPivot(ResponseBuilder rb, String[] fromParts, String[] toParts, Collection<NamedList<Object>> current, int level)
{
for(NamedList<Object> entry : current)
{
for(int i = 0; i < entry.size(); i++)
{
String name = entry.getName(i);
if(name.equals("field"))
{
entry.setVal(i, fromParts[level].trim());
}
else if(name.equals("pivot"))
{
Collection<NamedList<Object>> pivot = (Collection<NamedList<Object>>)entry.getVal(i);
processPivot(rb, fromParts, toParts, pivot, level+1);
}
else if(name.equals("ranges"))
{
SimpleOrderedMap ranges = (SimpleOrderedMap)entry.getVal(i);
processRanges(rb, ranges);
}
else
{
// leave alone
}
}
}
}
/**
* Update the returned ranges to reference ACS properties rather than Solr fields.
*
* @param rb The response builder.
* @param ranges The ranges to update.
*/
private void processRanges(ResponseBuilder rb, SimpleOrderedMap ranges) {
BiMap<String, String> mappings = (BiMap<String, String>) rb.rsp.getValues().get("_range_mappings_");
if(mappings != null)
{
updateToACSNaming(mappings, ranges);
}
}
/**
* Update the returned facet sections to reference ACS properties rather than Solr fields.
*
* @param rb the response builder.
* @param mappingName The name of the mapping definition created in {@link RewriteFacetParametersComponent}.
* @param sections The names of the sections to be updated.
*/
private void rewrite(ResponseBuilder rb, String mappingName, String ... sections)
{
BiMap<String, String> mappings = (BiMap<String, String>) rb.rsp.getValues().get(mappingName);
if(mappings != null)
{
NamedList<Object> found = (NamedList<Object>) rb.rsp.getValues();
for (String section : sections)
{
found = (NamedList<Object>) found.get(section);
if (found == null)
{
return;
}
}
// This found already contains the private buckets
updateToACSNaming(mappings, found);
}
}
/**
* Update entries in a list to reference ACS properties rather than Solr fields.
*
* @param mappings The mapping from ACS properties to Solr fields.
* @param propertyList The list to update.
*/
private void updateToACSNaming(BiMap<String, String> mappings, NamedList<Object> propertyList)
{
for (int i = 0; i < propertyList.size(); i++)
{
String name = propertyList.getName(i);
String newName = mappings.inverse().get(name);
if (newName != null)
{
propertyList.setName(i, newName);
}
}
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "RewriteFacetCounts";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,89 +1,89 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.util.Locale;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class SetLocaleComponent extends SearchComponent
{
private static final Logger log = LoggerFactory.getLogger(SetLocaleComponent.class);
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
SolrQueryRequest req = rb.req;
SolrParams params = req.getParams();
String localeStr = params.get("locale");
Locale locale = I18NUtil.parseLocale(localeStr);
I18NUtil.setLocale(locale);
log.info("Set locale to " + localeStr);
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "setLocale";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.util.Locale;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*
*/
public class SetLocaleComponent extends SearchComponent
{
private static final Logger log = LoggerFactory.getLogger(SetLocaleComponent.class);
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
SolrQueryRequest req = rb.req;
SolrParams params = req.getParams();
String localeStr = params.get("locale");
Locale locale = I18NUtil.parseLocale(localeStr);
I18NUtil.setLocale(locale);
log.info("Set locale to " + localeStr);
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#process(org.apache.solr.handler.component.ResponseBuilder)
*/
@Override
public void process(ResponseBuilder rb) throws IOException
{
// Nothing to do
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getDescription()
*/
@Override
public String getDescription()
{
return "setLocale";
}
/* (non-Javadoc)
* @see org.apache.solr.handler.component.SearchComponent#getSource()
*/
@Override
public String getSource()
{
return "";
}
}
@@ -1,87 +1,87 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
/**
* Sets a boolean flag ("processedDenies") in the JSON response indicating that
* the results (should) have been processed with respect to anyDenyDenies
* (i.e. {@link org.alfresco.solr.query.AbstractQParser} has added the correct clause to the search query).
*
* @author Matt Ward
*/
public class SetProcessedDeniesComponent extends SearchComponent
{
public static final String PROCESSED_DENIES = "processedDenies";
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// No preparation required
}
@Override
public void process(ResponseBuilder rb) throws IOException
{
Boolean processedDenies = (Boolean) rb.req.getContext().get(PROCESSED_DENIES);
processedDenies = (processedDenies == null) ? false : processedDenies;
rb.rsp.add(PROCESSED_DENIES, processedDenies);
}
@Override
public String getDescription()
{
return "Adds the processedDenies boolean flag to the search results.";
}
@Override
public String getSource()
{
return "http://www.alfresco.com";
}
@Override
public String getVersion()
{
return "1.0";
}
@Override
public void finishStage(ResponseBuilder rb) {
if (rb.stage != ResponseBuilder.STAGE_GET_FIELDS) {
return;
}
Boolean processedDenies = (Boolean) rb.req.getContext().get(PROCESSED_DENIES);
processedDenies = (processedDenies == null) ? false : processedDenies;
rb.rsp.add(PROCESSED_DENIES, processedDenies);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
/**
* Sets a boolean flag ("processedDenies") in the JSON response indicating that
* the results (should) have been processed with respect to anyDenyDenies
* (i.e. {@link org.alfresco.solr.query.AbstractQParser} has added the correct clause to the search query).
*
* @author Matt Ward
*/
public class SetProcessedDeniesComponent extends SearchComponent
{
public static final String PROCESSED_DENIES = "processedDenies";
@Override
public void prepare(ResponseBuilder rb) throws IOException
{
// No preparation required
}
@Override
public void process(ResponseBuilder rb) throws IOException
{
Boolean processedDenies = (Boolean) rb.req.getContext().get(PROCESSED_DENIES);
processedDenies = (processedDenies == null) ? false : processedDenies;
rb.rsp.add(PROCESSED_DENIES, processedDenies);
}
@Override
public String getDescription()
{
return "Adds the processedDenies boolean flag to the search results.";
}
@Override
public String getSource()
{
return "http://www.alfresco.com";
}
@Override
public String getVersion()
{
return "1.0";
}
@Override
public void finishStage(ResponseBuilder rb) {
if (rb.stage != ResponseBuilder.STAGE_GET_FIELDS) {
return;
}
Boolean processedDenies = (Boolean) rb.req.getContext().get(PROCESSED_DENIES);
processedDenies = (processedDenies == null) ? false : processedDenies;
rb.rsp.add(PROCESSED_DENIES, processedDenies);
}
}
@@ -1,109 +1,109 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.slf4j.Logger;
import org.springframework.util.StringUtils;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
/**
* Temp files may take up a lot of space, warn administrators
* of their existence, giving them the chance to manage them.
*
* @author Matt Ward
*/
public class TempFileWarningLogger
{
private final Logger log;
private final Path dir;
private final String glob;
public TempFileWarningLogger(Logger log, String prefix, String[] extensions, Path dir)
{
this.log = log;
this.dir = dir;
// Match files with glob, e.g. "SomePrefix*.{tmp,~bak}"
glob = prefix + ".{"+ StringUtils.arrayToCommaDelimitedString(extensions) + "}";
}
// Avoid FindBugs false positive (https://github.com/spotbugs/spotbugs/issues/756)
@SuppressWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
public boolean checkFiles()
{
if (log.isDebugEnabled())
{
log.debug("Looking for temp files matching " + glob + " in directory " + dir);
}
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir, glob))
{
for (Path file : stream)
{
if (log.isDebugEnabled())
{
log.debug("Solr suggester temp file found matching file pattern: " + glob + ", path: " + file);
log.debug("Removing suggester temp files.");
}
return true;
}
return false;
}
catch (IOException e)
{
throw new RuntimeException("Unable to create directory stream", e);
}
}
// Avoid FindBugs false positive (https://github.com/spotbugs/spotbugs/issues/756)
@SuppressWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
public void removeFiles()
{
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir, glob))
{
for (Path file : stream)
{
file.toFile().delete();
}
}
catch (IOException e)
{
log.debug("Unable to delete temp file", e);
}
}
protected String getGlob()
{
return glob;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.slf4j.Logger;
import org.springframework.util.StringUtils;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
/**
* Temp files may take up a lot of space, warn administrators
* of their existence, giving them the chance to manage them.
*
* @author Matt Ward
*/
public class TempFileWarningLogger
{
private final Logger log;
private final Path dir;
private final String glob;
public TempFileWarningLogger(Logger log, String prefix, String[] extensions, Path dir)
{
this.log = log;
this.dir = dir;
// Match files with glob, e.g. "SomePrefix*.{tmp,~bak}"
glob = prefix + ".{"+ StringUtils.arrayToCommaDelimitedString(extensions) + "}";
}
// Avoid FindBugs false positive (https://github.com/spotbugs/spotbugs/issues/756)
@SuppressWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
public boolean checkFiles()
{
if (log.isDebugEnabled())
{
log.debug("Looking for temp files matching " + glob + " in directory " + dir);
}
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir, glob))
{
for (Path file : stream)
{
if (log.isDebugEnabled())
{
log.debug("Solr suggester temp file found matching file pattern: " + glob + ", path: " + file);
log.debug("Removing suggester temp files.");
}
return true;
}
return false;
}
catch (IOException e)
{
throw new RuntimeException("Unable to create directory stream", e);
}
}
// Avoid FindBugs false positive (https://github.com/spotbugs/spotbugs/issues/756)
@SuppressWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
public void removeFiles()
{
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir, glob))
{
for (Path file : stream)
{
file.toFile().delete();
}
}
catch (IOException e)
{
log.debug("Unable to delete temp file", e);
}
}
protected String getGlob()
{
return glob;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,55 +1,55 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import org.apache.solr.spelling.SpellCheckCollation;
/**
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckCollation extends SpellCheckCollation
{
private String collationQueryString;
/**
* @return the collationQueryString
*/
public String getCollationQueryString()
{
return this.collationQueryString;
}
/**
* @param collationQueryString the collationQueryString to set
*/
public void setCollationQueryString(String collationQueryString)
{
this.collationQueryString = collationQueryString;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import org.apache.solr.spelling.SpellCheckCollation;
/**
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckCollation extends SpellCheckCollation
{
private String collationQueryString;
/**
* @return the collationQueryString
*/
public String getCollationQueryString()
{
return this.collationQueryString;
}
/**
* @param collationQueryString the collationQueryString to set
*/
public void setCollationQueryString(String collationQueryString)
{
this.collationQueryString = collationQueryString;
}
}
@@ -1,369 +1,369 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.solr.query.AbstractQParser;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.index.IndexReader;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.GroupParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.SpellingParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.handler.component.QueryComponent;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.EarlyTerminatingCollectorException;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.spelling.PossibilityIterator;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.spelling.SpellCheckCorrection;
import org.apache.solr.spelling.SpellingResult;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <b>Disclaimer</b>: The code copied from
* {@link org.apache.solr.spelling.SpellCheckCollator} but only modified the
* {@link org.apache.solr.spelling.SpellCheckCollator#collate(SpellingResult, String, ResponseBuilder)}
* method to pass the suggested term to the original alfresco JSON request rather
* than via 'q' parameter.
*
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckCollator
{
private final static Logger LOG = LoggerFactory.getLogger(AlfrescoSpellCheckCollator.class);
private int maxCollations = 1;
private int maxCollationTries = 0;
private int maxCollationEvaluations = 10000;
private boolean suggestionsMayOverlap = false;
private int docCollectionLimit = 0;
public List<AlfrescoSpellCheckCollation> collate(SpellingResult result, String originalQuery,
ResponseBuilder ultimateResponse)
{
List<AlfrescoSpellCheckCollation> collations = new ArrayList<>();
QueryComponent queryComponent = null;
if (ultimateResponse.components != null)
{
for (SearchComponent sc : ultimateResponse.components)
{
if (sc instanceof QueryComponent)
{
queryComponent = (QueryComponent) sc;
break;
}
}
}
boolean verifyCandidateWithQuery = true;
int maxTries = maxCollationTries;
int maxNumberToIterate = maxTries;
if (maxTries < 1)
{
maxTries = 1;
maxNumberToIterate = maxCollations;
verifyCandidateWithQuery = false;
}
if (queryComponent == null && verifyCandidateWithQuery)
{
LOG.info("Could not find an instance of QueryComponent. Disabling collation verification against the index.");
maxTries = 1;
verifyCandidateWithQuery = false;
}
docCollectionLimit = docCollectionLimit > 0 ? docCollectionLimit : 0;
int maxDocId = -1;
if (verifyCandidateWithQuery && docCollectionLimit > 0)
{
IndexReader reader = ultimateResponse.req.getSearcher().getIndexReader();
maxDocId = reader.maxDoc();
}
JSONObject alfrescoJSON = (JSONObject) ultimateResponse.req.getContext().get(AbstractQParser.ALFRESCO_JSON);
String originalAftsQuery = alfrescoJSON != null? alfrescoJSON.getString("query") : ultimateResponse.getQueryString();
int tryNo = 0;
int collNo = 0;
PossibilityIterator possibilityIter = new PossibilityIterator(result.getSuggestions(), maxNumberToIterate,
maxCollationEvaluations, suggestionsMayOverlap);
while (tryNo < maxTries && collNo < maxCollations && possibilityIter.hasNext())
{
PossibilityIterator.RankedSpellPossibility possibility = possibilityIter.next();
String collationQueryStr = getCollation(originalQuery, possibility.corrections);
int hits = 0;
String aftsQuery = null;
if (verifyCandidateWithQuery)
{
tryNo++;
SolrQueryRequest req = ultimateResponse.req;
SolrParams origParams = req.getParams();
ModifiableSolrParams params = new ModifiableSolrParams(origParams);
Iterator<String> origParamIterator = origParams.getParameterNamesIterator();
int pl = SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE.length();
while (origParamIterator.hasNext())
{
String origParamName = origParamIterator.next();
if (origParamName.startsWith(SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE)
&& origParamName.length() > pl)
{
String[] val = origParams.getParams(origParamName);
if (val.length == 1 && val[0].length() == 0)
{
params.set(origParamName.substring(pl), (String[]) null);
}
else
{
params.set(origParamName.substring(pl), val);
}
}
}
// we don't set the 'q' param, as we'll pass the query via JSON.
// params.set(CommonParams.Q, collationQueryStr);
params.remove(CommonParams.START);
params.set(CommonParams.ROWS, "" + docCollectionLimit);
// we don't want any stored fields
params.set(CommonParams.FL, "id");
// we'll sort by doc id to ensure no scoring is done.
params.set(CommonParams.SORT, "_docid_ asc");
// If a dismax query, don't add unnecessary clauses for scoring
params.remove(DisMaxParams.TIE);
params.remove(DisMaxParams.PF);
params.remove(DisMaxParams.PF2);
params.remove(DisMaxParams.PF3);
params.remove(DisMaxParams.BQ);
params.remove(DisMaxParams.BF);
// Collate testing does not support Grouping (see SOLR-2577)
params.remove(GroupParams.GROUP);
boolean useQStr = true;
if (alfrescoJSON != null)
{
try
{
aftsQuery = originalAftsQuery.replaceAll(Pattern.quote(originalQuery), Matcher.quoteReplacement(collationQueryStr));
alfrescoJSON.put("query", aftsQuery);
req.getContext().put(AbstractQParser.ALFRESCO_JSON, alfrescoJSON);
useQStr = false;
}
catch (JSONException e)
{
LOG.warn("Exception trying to get/set the query from/to ALFRESCO_JSON.]" + e);
}
}
else
{
aftsQuery = collationQueryStr;
}
req.setParams(params);
// creating a request here... make sure to close it!
ResponseBuilder checkResponse = new ResponseBuilder(req, new SolrQueryResponse(),
Arrays.<SearchComponent> asList(queryComponent));
checkResponse.setQparser(ultimateResponse.getQparser());
checkResponse.setFilters(ultimateResponse.getFilters());
checkResponse.components = Arrays.<SearchComponent> asList(queryComponent);
if (useQStr)
{
checkResponse.setQueryString(collationQueryStr);
}
try
{
queryComponent.prepare(checkResponse);
if (docCollectionLimit > 0)
{
int f = checkResponse.getFieldFlags();
checkResponse.setFieldFlags(f |= SolrIndexSearcher.TERMINATE_EARLY);
}
queryComponent.process(checkResponse);
hits = (Integer) checkResponse.rsp.getToLog().get("hits");
}
catch (EarlyTerminatingCollectorException etce)
{
assert (docCollectionLimit > 0);
assert 0 < etce.getNumberScanned();
assert 0 < etce.getNumberCollected();
if (etce.getNumberScanned() == maxDocId)
{
hits = etce.getNumberCollected();
}
else
{
hits = (int) (((float) (maxDocId * etce.getNumberCollected())) / (float) etce
.getNumberScanned());
}
}
catch (Exception e)
{
LOG.warn("Exception trying to re-query to check if a spell check possibility would return any hits." + e);
}
finally
{
checkResponse.req.close();
}
}
if (hits > 0 || !verifyCandidateWithQuery)
{
collNo++;
AlfrescoSpellCheckCollation collation = new AlfrescoSpellCheckCollation();
collation.setCollationQuery(aftsQuery);
collation.setCollationQueryString(collationQueryStr);
collation.setHits(hits);
collation.setInternalRank(suggestionsMayOverlap ? ((possibility.rank * 1000) + possibility.index)
: possibility.rank);
NamedList<String> misspellingsAndCorrections = new NamedList<>();
for (SpellCheckCorrection corr : possibility.corrections)
{
misspellingsAndCorrections.add(corr.getOriginal().toString(), corr.getCorrection());
}
collation.setMisspellingsAndCorrections(misspellingsAndCorrections);
collations.add(collation);
}
if (LOG.isDebugEnabled())
{
LOG.debug("Collation: " + aftsQuery + (verifyCandidateWithQuery ? (" will return " + hits + " hits.") : ""));
}
}
return collations;
}
@SuppressWarnings("deprecation")
private String getCollation(String origQuery, List<SpellCheckCorrection> corrections)
{
StringBuilder collation = new StringBuilder(origQuery);
int offset = 0;
String corr = "";
for (int i = 0; i < corrections.size(); i++)
{
SpellCheckCorrection correction = corrections.get(i);
Token tok = correction.getOriginal();
// we are replacing the query in order, but injected terms might
// cause illegal offsets due to previous replacements.
if (tok.getPositionIncrement() == 0)
continue;
corr = correction.getCorrection();
boolean addParenthesis = false;
Character requiredOrProhibited = null;
int indexOfSpace = corr.indexOf(' ');
StringBuilder corrSb = new StringBuilder(corr);
int bump = 1;
// If the correction contains whitespace (because it involved
// breaking a word in 2+ words),
// then be sure all of the new words have the same
// optional/required/prohibited status in the query.
while (indexOfSpace > -1 && indexOfSpace < corr.length() - 1)
{
addParenthesis = true;
char previousChar = tok.startOffset() > 0 ? origQuery.charAt(tok.startOffset() - 1) : ' ';
if (previousChar == '-' || previousChar == '+')
{
corrSb.insert(indexOfSpace + bump, previousChar);
if (requiredOrProhibited == null)
{
requiredOrProhibited = previousChar;
}
bump++;
}
else if ((tok.getFlags() & QueryConverter.TERM_IN_BOOLEAN_QUERY_FLAG) == QueryConverter.TERM_IN_BOOLEAN_QUERY_FLAG)
{
corrSb.insert(indexOfSpace + bump, "AND ");
bump += 4;
}
indexOfSpace = correction.getCorrection().indexOf(' ', indexOfSpace + bump);
}
int oneForReqOrProhib = 0;
if (addParenthesis)
{
if (requiredOrProhibited != null)
{
corrSb.insert(0, requiredOrProhibited);
oneForReqOrProhib++;
}
corrSb.insert(0, '(');
corrSb.append(')');
}
corr = corrSb.toString();
int startIndex = tok.startOffset() + offset - oneForReqOrProhib;
int endIndex = tok.endOffset() + offset;
collation.replace(startIndex, endIndex, corr);
offset += corr.length() - oneForReqOrProhib - (tok.endOffset() - tok.startOffset());
}
return collation.toString();
}
public AlfrescoSpellCheckCollator setMaxCollations(int maxCollations)
{
this.maxCollations = maxCollations;
return this;
}
public AlfrescoSpellCheckCollator setMaxCollationTries(int maxCollationTries)
{
this.maxCollationTries = maxCollationTries;
return this;
}
public AlfrescoSpellCheckCollator setMaxCollationEvaluations(int maxCollationEvaluations)
{
this.maxCollationEvaluations = maxCollationEvaluations;
return this;
}
public AlfrescoSpellCheckCollator setSuggestionsMayOverlap(boolean suggestionsMayOverlap)
{
this.suggestionsMayOverlap = suggestionsMayOverlap;
return this;
}
public AlfrescoSpellCheckCollator setDocCollectionLimit(int docCollectionLimit)
{
this.docCollectionLimit = docCollectionLimit;
return this;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.solr.query.AbstractQParser;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.index.IndexReader;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.GroupParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.SpellingParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.handler.component.QueryComponent;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.EarlyTerminatingCollectorException;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.spelling.PossibilityIterator;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.spelling.SpellCheckCorrection;
import org.apache.solr.spelling.SpellingResult;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <b>Disclaimer</b>: The code copied from
* {@link org.apache.solr.spelling.SpellCheckCollator} but only modified the
* {@link org.apache.solr.spelling.SpellCheckCollator#collate(SpellingResult, String, ResponseBuilder)}
* method to pass the suggested term to the original alfresco JSON request rather
* than via 'q' parameter.
*
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckCollator
{
private final static Logger LOG = LoggerFactory.getLogger(AlfrescoSpellCheckCollator.class);
private int maxCollations = 1;
private int maxCollationTries = 0;
private int maxCollationEvaluations = 10000;
private boolean suggestionsMayOverlap = false;
private int docCollectionLimit = 0;
public List<AlfrescoSpellCheckCollation> collate(SpellingResult result, String originalQuery,
ResponseBuilder ultimateResponse)
{
List<AlfrescoSpellCheckCollation> collations = new ArrayList<>();
QueryComponent queryComponent = null;
if (ultimateResponse.components != null)
{
for (SearchComponent sc : ultimateResponse.components)
{
if (sc instanceof QueryComponent)
{
queryComponent = (QueryComponent) sc;
break;
}
}
}
boolean verifyCandidateWithQuery = true;
int maxTries = maxCollationTries;
int maxNumberToIterate = maxTries;
if (maxTries < 1)
{
maxTries = 1;
maxNumberToIterate = maxCollations;
verifyCandidateWithQuery = false;
}
if (queryComponent == null && verifyCandidateWithQuery)
{
LOG.info("Could not find an instance of QueryComponent. Disabling collation verification against the index.");
maxTries = 1;
verifyCandidateWithQuery = false;
}
docCollectionLimit = docCollectionLimit > 0 ? docCollectionLimit : 0;
int maxDocId = -1;
if (verifyCandidateWithQuery && docCollectionLimit > 0)
{
IndexReader reader = ultimateResponse.req.getSearcher().getIndexReader();
maxDocId = reader.maxDoc();
}
JSONObject alfrescoJSON = (JSONObject) ultimateResponse.req.getContext().get(AbstractQParser.ALFRESCO_JSON);
String originalAftsQuery = alfrescoJSON != null? alfrescoJSON.getString("query") : ultimateResponse.getQueryString();
int tryNo = 0;
int collNo = 0;
PossibilityIterator possibilityIter = new PossibilityIterator(result.getSuggestions(), maxNumberToIterate,
maxCollationEvaluations, suggestionsMayOverlap);
while (tryNo < maxTries && collNo < maxCollations && possibilityIter.hasNext())
{
PossibilityIterator.RankedSpellPossibility possibility = possibilityIter.next();
String collationQueryStr = getCollation(originalQuery, possibility.corrections);
int hits = 0;
String aftsQuery = null;
if (verifyCandidateWithQuery)
{
tryNo++;
SolrQueryRequest req = ultimateResponse.req;
SolrParams origParams = req.getParams();
ModifiableSolrParams params = new ModifiableSolrParams(origParams);
Iterator<String> origParamIterator = origParams.getParameterNamesIterator();
int pl = SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE.length();
while (origParamIterator.hasNext())
{
String origParamName = origParamIterator.next();
if (origParamName.startsWith(SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE)
&& origParamName.length() > pl)
{
String[] val = origParams.getParams(origParamName);
if (val.length == 1 && val[0].length() == 0)
{
params.set(origParamName.substring(pl), (String[]) null);
}
else
{
params.set(origParamName.substring(pl), val);
}
}
}
// we don't set the 'q' param, as we'll pass the query via JSON.
// params.set(CommonParams.Q, collationQueryStr);
params.remove(CommonParams.START);
params.set(CommonParams.ROWS, "" + docCollectionLimit);
// we don't want any stored fields
params.set(CommonParams.FL, "id");
// we'll sort by doc id to ensure no scoring is done.
params.set(CommonParams.SORT, "_docid_ asc");
// If a dismax query, don't add unnecessary clauses for scoring
params.remove(DisMaxParams.TIE);
params.remove(DisMaxParams.PF);
params.remove(DisMaxParams.PF2);
params.remove(DisMaxParams.PF3);
params.remove(DisMaxParams.BQ);
params.remove(DisMaxParams.BF);
// Collate testing does not support Grouping (see SOLR-2577)
params.remove(GroupParams.GROUP);
boolean useQStr = true;
if (alfrescoJSON != null)
{
try
{
aftsQuery = originalAftsQuery.replaceAll(Pattern.quote(originalQuery), Matcher.quoteReplacement(collationQueryStr));
alfrescoJSON.put("query", aftsQuery);
req.getContext().put(AbstractQParser.ALFRESCO_JSON, alfrescoJSON);
useQStr = false;
}
catch (JSONException e)
{
LOG.warn("Exception trying to get/set the query from/to ALFRESCO_JSON.]" + e);
}
}
else
{
aftsQuery = collationQueryStr;
}
req.setParams(params);
// creating a request here... make sure to close it!
ResponseBuilder checkResponse = new ResponseBuilder(req, new SolrQueryResponse(),
Arrays.<SearchComponent> asList(queryComponent));
checkResponse.setQparser(ultimateResponse.getQparser());
checkResponse.setFilters(ultimateResponse.getFilters());
checkResponse.components = Arrays.<SearchComponent> asList(queryComponent);
if (useQStr)
{
checkResponse.setQueryString(collationQueryStr);
}
try
{
queryComponent.prepare(checkResponse);
if (docCollectionLimit > 0)
{
int f = checkResponse.getFieldFlags();
checkResponse.setFieldFlags(f |= SolrIndexSearcher.TERMINATE_EARLY);
}
queryComponent.process(checkResponse);
hits = (Integer) checkResponse.rsp.getToLog().get("hits");
}
catch (EarlyTerminatingCollectorException etce)
{
assert (docCollectionLimit > 0);
assert 0 < etce.getNumberScanned();
assert 0 < etce.getNumberCollected();
if (etce.getNumberScanned() == maxDocId)
{
hits = etce.getNumberCollected();
}
else
{
hits = (int) (((float) (maxDocId * etce.getNumberCollected())) / (float) etce
.getNumberScanned());
}
}
catch (Exception e)
{
LOG.warn("Exception trying to re-query to check if a spell check possibility would return any hits." + e);
}
finally
{
checkResponse.req.close();
}
}
if (hits > 0 || !verifyCandidateWithQuery)
{
collNo++;
AlfrescoSpellCheckCollation collation = new AlfrescoSpellCheckCollation();
collation.setCollationQuery(aftsQuery);
collation.setCollationQueryString(collationQueryStr);
collation.setHits(hits);
collation.setInternalRank(suggestionsMayOverlap ? ((possibility.rank * 1000) + possibility.index)
: possibility.rank);
NamedList<String> misspellingsAndCorrections = new NamedList<>();
for (SpellCheckCorrection corr : possibility.corrections)
{
misspellingsAndCorrections.add(corr.getOriginal().toString(), corr.getCorrection());
}
collation.setMisspellingsAndCorrections(misspellingsAndCorrections);
collations.add(collation);
}
if (LOG.isDebugEnabled())
{
LOG.debug("Collation: " + aftsQuery + (verifyCandidateWithQuery ? (" will return " + hits + " hits.") : ""));
}
}
return collations;
}
@SuppressWarnings("deprecation")
private String getCollation(String origQuery, List<SpellCheckCorrection> corrections)
{
StringBuilder collation = new StringBuilder(origQuery);
int offset = 0;
String corr = "";
for (int i = 0; i < corrections.size(); i++)
{
SpellCheckCorrection correction = corrections.get(i);
Token tok = correction.getOriginal();
// we are replacing the query in order, but injected terms might
// cause illegal offsets due to previous replacements.
if (tok.getPositionIncrement() == 0)
continue;
corr = correction.getCorrection();
boolean addParenthesis = false;
Character requiredOrProhibited = null;
int indexOfSpace = corr.indexOf(' ');
StringBuilder corrSb = new StringBuilder(corr);
int bump = 1;
// If the correction contains whitespace (because it involved
// breaking a word in 2+ words),
// then be sure all of the new words have the same
// optional/required/prohibited status in the query.
while (indexOfSpace > -1 && indexOfSpace < corr.length() - 1)
{
addParenthesis = true;
char previousChar = tok.startOffset() > 0 ? origQuery.charAt(tok.startOffset() - 1) : ' ';
if (previousChar == '-' || previousChar == '+')
{
corrSb.insert(indexOfSpace + bump, previousChar);
if (requiredOrProhibited == null)
{
requiredOrProhibited = previousChar;
}
bump++;
}
else if ((tok.getFlags() & QueryConverter.TERM_IN_BOOLEAN_QUERY_FLAG) == QueryConverter.TERM_IN_BOOLEAN_QUERY_FLAG)
{
corrSb.insert(indexOfSpace + bump, "AND ");
bump += 4;
}
indexOfSpace = correction.getCorrection().indexOf(' ', indexOfSpace + bump);
}
int oneForReqOrProhib = 0;
if (addParenthesis)
{
if (requiredOrProhibited != null)
{
corrSb.insert(0, requiredOrProhibited);
oneForReqOrProhib++;
}
corrSb.insert(0, '(');
corrSb.append(')');
}
corr = corrSb.toString();
int startIndex = tok.startOffset() + offset - oneForReqOrProhib;
int endIndex = tok.endOffset() + offset;
collation.replace(startIndex, endIndex, corr);
offset += corr.length() - oneForReqOrProhib - (tok.endOffset() - tok.startOffset());
}
return collation.toString();
}
public AlfrescoSpellCheckCollator setMaxCollations(int maxCollations)
{
this.maxCollations = maxCollations;
return this;
}
public AlfrescoSpellCheckCollator setMaxCollationTries(int maxCollationTries)
{
this.maxCollationTries = maxCollationTries;
return this;
}
public AlfrescoSpellCheckCollator setMaxCollationEvaluations(int maxCollationEvaluations)
{
this.maxCollationEvaluations = maxCollationEvaluations;
return this;
}
public AlfrescoSpellCheckCollator setSuggestionsMayOverlap(boolean suggestionsMayOverlap)
{
this.suggestionsMayOverlap = suggestionsMayOverlap;
return this;
}
public AlfrescoSpellCheckCollator setDocCollectionLimit(int docCollectionLimit)
{
this.docCollectionLimit = docCollectionLimit;
return this;
}
}
@@ -1,116 +1,116 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SpellCheckComponent;
import org.apache.solr.spelling.SpellingResult;
/**
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckComponent extends SpellCheckComponent
{
/**
* <b>Disclaimer</b>: The code copied from the super class (
* {@link org.apache.solr.handler.component.SpellCheckComponent}) but only
* replaced the collator with the AlfrescoSpellCheckCollator
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void addCollationsToResponse(SolrParams params, SpellingResult spellingResult, ResponseBuilder rb,
String q, NamedList response, boolean suggestionsMayOverlap)
{
int maxCollations = params.getInt(SPELLCHECK_MAX_COLLATIONS, 1);
int maxCollationTries = params.getInt(SPELLCHECK_MAX_COLLATION_TRIES, 0);
int maxCollationEvaluations = params.getInt(SPELLCHECK_MAX_COLLATION_EVALUATIONS, 10000);
boolean collationExtendedResults = params.getBool(SPELLCHECK_COLLATE_EXTENDED_RESULTS, false);
int maxCollationCollectDocs = params.getInt(SPELLCHECK_COLLATE_MAX_COLLECT_DOCS, 0);
// If not reporting hits counts, don't bother collecting more than 1 document per try.
if (!collationExtendedResults)
{
maxCollationCollectDocs = 1;
}
boolean shard = params.getBool(ShardParams.IS_SHARD, false);
AlfrescoSpellCheckCollator collator = new AlfrescoSpellCheckCollator();
collator.setMaxCollations(maxCollations);
collator.setMaxCollationTries(maxCollationTries);
collator.setMaxCollationEvaluations(maxCollationEvaluations);
collator.setSuggestionsMayOverlap(suggestionsMayOverlap);
collator.setDocCollectionLimit(maxCollationCollectDocs);
List<AlfrescoSpellCheckCollation> collations = collator.collate(spellingResult, q, rb);
// by sorting here we guarantee a non-distributed request returns all
// results in the same order as a distributed request would,
// even in cases when the internal rank is the same.
Collections.sort(collations);
NamedList collationList = new NamedList();
for (AlfrescoSpellCheckCollation collation : collations)
{
if (collationExtendedResults)
{
NamedList extendedResult = new SimpleOrderedMap();
extendedResult.add("collationQuery", collation.getCollationQuery());
extendedResult.add("hits", collation.getHits());
extendedResult.add("misspellingsAndCorrections", collation.getMisspellingsAndCorrections());
if (maxCollationTries > 0 && shard)
{
extendedResult.add("collationInternalRank", collation.getInternalRank());
}
extendedResult.add("collationQueryString", collation.getCollationQueryString());
collationList.add("collation", extendedResult);
}
else
{
collationList.add("collation", collation.getCollationQuery());
if (maxCollationTries > 0 && shard)
{
collationList.add("collationInternalRank", collation.getInternalRank());
}
}
}
//Support Solr 4 output format
NamedList suggestions = (NamedList)response.get("suggestions");
suggestions.addAll(collationList);
//Support Solr distributed merge format.
response.add("collations", collationList);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.component.spellcheck;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SpellCheckComponent;
import org.apache.solr.spelling.SpellingResult;
/**
* @author Jamal Kaabi-Mofrad
* @since 5.0
*/
public class AlfrescoSpellCheckComponent extends SpellCheckComponent
{
/**
* <b>Disclaimer</b>: The code copied from the super class (
* {@link org.apache.solr.handler.component.SpellCheckComponent}) but only
* replaced the collator with the AlfrescoSpellCheckCollator
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void addCollationsToResponse(SolrParams params, SpellingResult spellingResult, ResponseBuilder rb,
String q, NamedList response, boolean suggestionsMayOverlap)
{
int maxCollations = params.getInt(SPELLCHECK_MAX_COLLATIONS, 1);
int maxCollationTries = params.getInt(SPELLCHECK_MAX_COLLATION_TRIES, 0);
int maxCollationEvaluations = params.getInt(SPELLCHECK_MAX_COLLATION_EVALUATIONS, 10000);
boolean collationExtendedResults = params.getBool(SPELLCHECK_COLLATE_EXTENDED_RESULTS, false);
int maxCollationCollectDocs = params.getInt(SPELLCHECK_COLLATE_MAX_COLLECT_DOCS, 0);
// If not reporting hits counts, don't bother collecting more than 1 document per try.
if (!collationExtendedResults)
{
maxCollationCollectDocs = 1;
}
boolean shard = params.getBool(ShardParams.IS_SHARD, false);
AlfrescoSpellCheckCollator collator = new AlfrescoSpellCheckCollator();
collator.setMaxCollations(maxCollations);
collator.setMaxCollationTries(maxCollationTries);
collator.setMaxCollationEvaluations(maxCollationEvaluations);
collator.setSuggestionsMayOverlap(suggestionsMayOverlap);
collator.setDocCollectionLimit(maxCollationCollectDocs);
List<AlfrescoSpellCheckCollation> collations = collator.collate(spellingResult, q, rb);
// by sorting here we guarantee a non-distributed request returns all
// results in the same order as a distributed request would,
// even in cases when the internal rank is the same.
Collections.sort(collations);
NamedList collationList = new NamedList();
for (AlfrescoSpellCheckCollation collation : collations)
{
if (collationExtendedResults)
{
NamedList extendedResult = new SimpleOrderedMap();
extendedResult.add("collationQuery", collation.getCollationQuery());
extendedResult.add("hits", collation.getHits());
extendedResult.add("misspellingsAndCorrections", collation.getMisspellingsAndCorrections());
if (maxCollationTries > 0 && shard)
{
extendedResult.add("collationInternalRank", collation.getInternalRank());
}
extendedResult.add("collationQueryString", collation.getCollationQueryString());
collationList.add("collation", extendedResult);
}
else
{
collationList.add("collation", collation.getCollationQuery());
if (maxCollationTries > 0 && shard)
{
collationList.add("collationInternalRank", collation.getInternalRank());
}
}
}
//Support Solr 4 output format
NamedList suggestions = (NamedList)response.get("suggestions");
suggestions.addAll(collationList);
//Support Solr distributed merge format.
response.add("collations", collationList);
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,54 +1,54 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.data;
import java.util.HashSet;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.PermissionService;
/**
* Statically configured set of authorities that always have read access.
*
* @author Matt Ward
*/
public class GlobalReaders
{
private static HashSet<String> readers = new HashSet<String>();
static
{
readers.add(PermissionService.OWNER_AUTHORITY);
readers.add(PermissionService.ADMINISTRATOR_AUTHORITY);
readers.add(AuthenticationUtil.getSystemUserName());
}
public static HashSet<String> getReaders()
{
return readers;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.data;
import java.util.HashSet;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.PermissionService;
/**
* Statically configured set of authorities that always have read access.
*
* @author Matt Ward
*/
public class GlobalReaders
{
private static HashSet<String> readers = new HashSet<String>();
static
{
readers.add(PermissionService.OWNER_AUTHORITY);
readers.add(PermissionService.ADMINISTRATOR_AUTHORITY);
readers.add(AuthenticationUtil.getSystemUserName());
}
public static HashSet<String> getReaders()
{
return readers;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -462,4 +462,4 @@ public class SolrCoreLoadListener extends AbstractSolrEventListener
.map(isSlaveModeEnabled)
.orElse(false);
}
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -1,142 +1,142 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
/**
* This class patches a term at a specified location.
*
* @author andyh
*/
public class AbsoluteStructuredFieldPosition extends AbstractStructuredFieldPosition
{
int requiredPosition;
/**
* Search for a term at the specified position.
*/
public AbsoluteStructuredFieldPosition(String termText, int position)
{
super(termText, true, true);
this.requiredPosition = position;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.lucene.extensions.StructuredFieldPosition#matches(int,
* org.apache.lucene.index.TermPositions)
*/
public int matches(int start, int end, int offset) throws IOException
{
if (offset >= requiredPosition)
{
return -1;
}
if (getCachingTermPositions() != null)
{
// Doing "termText"
getCachingTermPositions().reset();
int count = getCachingTermPositions().freq();
int realPosition = 0;
int adjustedPosition = 0;
for (int i = 0; i < count; i++)
{
realPosition = getCachingTermPositions().nextPosition();
adjustedPosition = realPosition - start;
if ((end != -1) && (realPosition > end))
{
return -1;
}
if (adjustedPosition > requiredPosition)
{
return -1;
}
if (adjustedPosition == requiredPosition)
{
return adjustedPosition;
}
}
}
else
{
// Doing "*"
if ((offset + 1) == requiredPosition)
{
return offset + 1;
}
}
return -1;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.lucene.extensions.StructuredFieldPosition#getPosition()
*/
public int getPosition()
{
return requiredPosition;
}
public String getDescription()
{
return "Absolute Named child";
}
@Override
public int hashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + requiredPosition;
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
AbsoluteStructuredFieldPosition other = (AbsoluteStructuredFieldPosition) obj;
if (requiredPosition != other.requiredPosition)
return false;
return true;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
/**
* This class patches a term at a specified location.
*
* @author andyh
*/
public class AbsoluteStructuredFieldPosition extends AbstractStructuredFieldPosition
{
int requiredPosition;
/**
* Search for a term at the specified position.
*/
public AbsoluteStructuredFieldPosition(String termText, int position)
{
super(termText, true, true);
this.requiredPosition = position;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.lucene.extensions.StructuredFieldPosition#matches(int,
* org.apache.lucene.index.TermPositions)
*/
public int matches(int start, int end, int offset) throws IOException
{
if (offset >= requiredPosition)
{
return -1;
}
if (getCachingTermPositions() != null)
{
// Doing "termText"
getCachingTermPositions().reset();
int count = getCachingTermPositions().freq();
int realPosition = 0;
int adjustedPosition = 0;
for (int i = 0; i < count; i++)
{
realPosition = getCachingTermPositions().nextPosition();
adjustedPosition = realPosition - start;
if ((end != -1) && (realPosition > end))
{
return -1;
}
if (adjustedPosition > requiredPosition)
{
return -1;
}
if (adjustedPosition == requiredPosition)
{
return adjustedPosition;
}
}
}
else
{
// Doing "*"
if ((offset + 1) == requiredPosition)
{
return offset + 1;
}
}
return -1;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.lucene.extensions.StructuredFieldPosition#getPosition()
*/
public int getPosition()
{
return requiredPosition;
}
public String getDescription()
{
return "Absolute Named child";
}
@Override
public int hashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + requiredPosition;
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
AbsoluteStructuredFieldPosition other = (AbsoluteStructuredFieldPosition) obj;
if (requiredPosition != other.requiredPosition)
return false;
return true;
}
}
@@ -1,76 +1,76 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
/**
* Base class for queries relating to an authority.
*/
public abstract class AbstractAuthorityQuery extends Query
{
protected final String authority;
/**
* Construct with authority.
*
* @param authority
*/
public AbstractAuthorityQuery(String authority)
{
if (authority == null) throw new IllegalStateException("authority cannot be null");
this.authority = authority;
}
@Override
public abstract Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException;
public String toString(String field)
{
return toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AbstractAuthorityQuery)) return false;
AbstractAuthorityQuery that = (AbstractAuthorityQuery) o;
return authority.equals(that.authority);
}
@Override
public int hashCode() {
return authority.hashCode();
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
/**
* Base class for queries relating to an authority.
*/
public abstract class AbstractAuthorityQuery extends Query
{
protected final String authority;
/**
* Construct with authority.
*
* @param authority
*/
public AbstractAuthorityQuery(String authority)
{
if (authority == null) throw new IllegalStateException("authority cannot be null");
this.authority = authority;
}
@Override
public abstract Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException;
public String toString(String field)
{
return toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AbstractAuthorityQuery)) return false;
AbstractAuthorityQuery that = (AbstractAuthorityQuery) o;
return authority.equals(that.authority);
}
@Override
public int hashCode() {
return authority.hashCode();
}
}
@@ -1,85 +1,85 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Abstract {@link Weight} implementation for authority related queries.
*
* @see AbstractAuthoritySetQuery
*/
public abstract class AbstractAuthorityQueryWeight extends Weight
{
protected Query query;
protected SolrIndexSearcher searcher;
protected float value;
protected boolean needsScores;
public AbstractAuthorityQueryWeight(SolrIndexSearcher searcher, boolean needsScores, Query query, String authTermName, String authTermText) throws IOException
{
super(query);
this.searcher = searcher;
searcher.collectionStatistics(authTermName);
final IndexReaderContext context = searcher.getTopReaderContext();
final Term term = new Term(authTermName, authTermText);
final TermContext termContext = TermContext.build(context, term);
searcher.termStatistics(term, termContext);
this.needsScores = needsScores;
}
@Override
public Explanation explain(LeafReaderContext context, int doc)
{
throw new UnsupportedOperationException();
}
@Override
public float getValueForNormalization()
{
return sumOfSquaredWeights();
}
@Override
public void normalize(float queryNorm, float topLevelBoost)
{
}
protected float sumOfSquaredWeights()
{
return 0;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Weight;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Abstract {@link Weight} implementation for authority related queries.
*
* @see AbstractAuthoritySetQuery
*/
public abstract class AbstractAuthorityQueryWeight extends Weight
{
protected Query query;
protected SolrIndexSearcher searcher;
protected float value;
protected boolean needsScores;
public AbstractAuthorityQueryWeight(SolrIndexSearcher searcher, boolean needsScores, Query query, String authTermName, String authTermText) throws IOException
{
super(query);
this.searcher = searcher;
searcher.collectionStatistics(authTermName);
final IndexReaderContext context = searcher.getTopReaderContext();
final Term term = new Term(authTermName, authTermText);
final TermContext termContext = TermContext.build(context, term);
searcher.termStatistics(term, termContext);
this.needsScores = needsScores;
}
@Override
public Explanation explain(LeafReaderContext context, int doc)
{
throw new UnsupportedOperationException();
}
@Override
public float getValueForNormalization()
{
return sumOfSquaredWeights();
}
@Override
public void normalize(float queryNorm, float topLevelBoost)
{
}
protected float sumOfSquaredWeights()
{
return 0;
}
}
@@ -1,192 +1,192 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.search.adaptor.QueryConstants;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.FixedBitSet;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Base class for queries relating to a set of authorities, e.g. reader set query.
*/
public abstract class AbstractAuthoritySetQuery extends Query
{
protected final String authorities;
/**
* Construct with authorities.
*
* @param authorities
*/
public AbstractAuthoritySetQuery(String authorities)
{
super();
if (authorities == null) throw new IllegalStateException("authorities cannot be null");
this.authorities = authorities;
}
@Override
public abstract Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException;
@Override
public String toString(String field)
{
return toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AbstractAuthoritySetQuery)) return false;
AbstractAuthoritySetQuery that = (AbstractAuthoritySetQuery) o;
return authorities.equals(that.authorities);
}
@Override
public int hashCode() {
return authorities.hashCode();
}
/*
* This method collects the bitset of documents that match the authorities.
*/
protected HybridBitSet getACLSet(String[] auths, String field, SolrIndexSearcher searcher) throws IOException
{
/*
* Build a query that matches the authorities with a field in the ACL records in the index.
*/
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
for(String current : auths)
{
queryBuilder.add(new TermQuery(new Term(field, current)), BooleanClause.Occur.SHOULD);
}
/*
* Collect a docset containing the ACL records that match the query.
* This query will be in the filter cache. Ideally it would remain cached throughout the users session.
*/
DocSet docSet = searcher.getDocSet(queryBuilder.build());
DocIterator iterator = docSet.iterator();
if(!iterator.hasNext())
{
return new EmptyHybridBitSet();
}
//TODO : makes this configurable. For some systems this is huge and for others not big enough.
HybridBitSet hybridBitSet = new HybridBitSet(60000000);
/*
* Collect the ACLID's from the matching acl records.
* This is done in a separate step so the initial ACL query can be cached in the FilterCache
* The initial ACL query may be expensive if the number of authorities is very large.
*/
List<LeafReaderContext> leaves = searcher.getTopReaderContext().leaves();
LeafReaderContext context = leaves.get(0);
NumericDocValues aclValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, context.reader());
LeafReader reader = context.reader();
int ceil = reader.maxDoc();
int base = 0;
int ord = 0;
while (iterator.hasNext()) {
int doc = iterator.nextDoc();
if(doc >= ceil)
{
do
{
++ord;
context = leaves.get(ord);
reader = context.reader();
base = context.docBase;
ceil = base+reader.maxDoc();
aclValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, reader);
}
while(doc >= ceil);
}
if(aclValues != null) {
long aclId = aclValues.get(doc - base);
hybridBitSet.set(aclId);
}
}
return hybridBitSet;
}
protected BitsFilter getACLFilter(String[] auths, String field, SolrIndexSearcher searcher) throws IOException
{
HybridBitSet aclBits = getACLSet(auths, field, searcher);
List<LeafReaderContext> leaves = searcher.getTopReaderContext().leaves();
List<FixedBitSet> bitSets = new ArrayList<FixedBitSet>(leaves.size());
for(LeafReaderContext readerContext : leaves)
{
LeafReader reader = readerContext.reader();
int maxDoc = reader.maxDoc();
FixedBitSet bits = new FixedBitSet(maxDoc);
bitSets.add(bits);
NumericDocValues fieldValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, reader);
if (fieldValues != null) {
for (int i = 0; i < maxDoc; i++) {
long aclID = fieldValues.get(i);
if (aclBits.get(aclID)) {
bits.set(i);
}
}
}
}
return new BitsFilter(bitSets);
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.search.adaptor.QueryConstants;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.FixedBitSet;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
/**
* Base class for queries relating to a set of authorities, e.g. reader set query.
*/
public abstract class AbstractAuthoritySetQuery extends Query
{
protected final String authorities;
/**
* Construct with authorities.
*
* @param authorities
*/
public AbstractAuthoritySetQuery(String authorities)
{
super();
if (authorities == null) throw new IllegalStateException("authorities cannot be null");
this.authorities = authorities;
}
@Override
public abstract Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException;
@Override
public String toString(String field)
{
return toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AbstractAuthoritySetQuery)) return false;
AbstractAuthoritySetQuery that = (AbstractAuthoritySetQuery) o;
return authorities.equals(that.authorities);
}
@Override
public int hashCode() {
return authorities.hashCode();
}
/*
* This method collects the bitset of documents that match the authorities.
*/
protected HybridBitSet getACLSet(String[] auths, String field, SolrIndexSearcher searcher) throws IOException
{
/*
* Build a query that matches the authorities with a field in the ACL records in the index.
*/
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
for(String current : auths)
{
queryBuilder.add(new TermQuery(new Term(field, current)), BooleanClause.Occur.SHOULD);
}
/*
* Collect a docset containing the ACL records that match the query.
* This query will be in the filter cache. Ideally it would remain cached throughout the users session.
*/
DocSet docSet = searcher.getDocSet(queryBuilder.build());
DocIterator iterator = docSet.iterator();
if(!iterator.hasNext())
{
return new EmptyHybridBitSet();
}
//TODO : makes this configurable. For some systems this is huge and for others not big enough.
HybridBitSet hybridBitSet = new HybridBitSet(60000000);
/*
* Collect the ACLID's from the matching acl records.
* This is done in a separate step so the initial ACL query can be cached in the FilterCache
* The initial ACL query may be expensive if the number of authorities is very large.
*/
List<LeafReaderContext> leaves = searcher.getTopReaderContext().leaves();
LeafReaderContext context = leaves.get(0);
NumericDocValues aclValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, context.reader());
LeafReader reader = context.reader();
int ceil = reader.maxDoc();
int base = 0;
int ord = 0;
while (iterator.hasNext()) {
int doc = iterator.nextDoc();
if(doc >= ceil)
{
do
{
++ord;
context = leaves.get(ord);
reader = context.reader();
base = context.docBase;
ceil = base+reader.maxDoc();
aclValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, reader);
}
while(doc >= ceil);
}
if(aclValues != null) {
long aclId = aclValues.get(doc - base);
hybridBitSet.set(aclId);
}
}
return hybridBitSet;
}
protected BitsFilter getACLFilter(String[] auths, String field, SolrIndexSearcher searcher) throws IOException
{
HybridBitSet aclBits = getACLSet(auths, field, searcher);
List<LeafReaderContext> leaves = searcher.getTopReaderContext().leaves();
List<FixedBitSet> bitSets = new ArrayList<FixedBitSet>(leaves.size());
for(LeafReaderContext readerContext : leaves)
{
LeafReader reader = readerContext.reader();
int maxDoc = reader.maxDoc();
FixedBitSet bits = new FixedBitSet(maxDoc);
bitSets.add(bits);
NumericDocValues fieldValues = DocValuesCache.getNumericDocValues(QueryConstants.FIELD_ACLID, reader);
if (fieldValues != null) {
for (int i = 0; i < maxDoc; i++) {
long aclID = fieldValues.get(i);
if (aclBits.get(aclID)) {
bits.set(i);
}
}
}
}
return new BitsFilter(bitSets);
}
}
@@ -1,198 +1,198 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import java.util.stream.LongStream;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.FixedBitSet;
import org.apache.solr.search.BitDocSet;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
/**
* @author Andy
*
*/
public abstract class AbstractSolrCachingScorer extends Scorer
{
protected static class LongCache
{
private static int CACHE_SIZE = 1000000;
private LongCache(){}
static final long cache[] = LongStream.range(0, CACHE_SIZE).toArray();
}
protected static Long getLong(long l) {
if(l > LongCache.CACHE_SIZE)
{
return Long.valueOf(l);
}
else
{
return LongCache.cache[(int)l];
}
}
SolrCachingScorerDoIdSetIterator iterator;
AbstractSolrCachingScorer(Weight weight, DocSet in, LeafReaderContext context, SolrIndexSearcher searcher)
{
super(weight);
iterator = new SolrCachingScorerDoIdSetIterator(in, context, searcher);
}
@Override
public float score() throws IOException
{
return 1.0f;
}
// TODO: implement
@Override
public int freq() throws IOException
{
return 1;
}
@Override
public int docID()
{
return iterator.docID();
}
@Override
public DocIdSetIterator iterator()
{
return iterator;
}
private static class SolrCachingScorerDoIdSetIterator extends DocIdSetIterator
{
BitDocSet matches;
int doc = -1;
FixedBitSet bitSet;
LeafReaderContext context;
SolrCachingScorerDoIdSetIterator(DocSet in, LeafReaderContext context, SolrIndexSearcher searcher)
{
this.context = context;
if (in instanceof BitDocSet)
{
matches = (BitDocSet) in;
}
else
{
this.matches = new BitDocSet(new FixedBitSet(searcher.maxDoc()));
for (DocIterator it = in.iterator(); it.hasNext(); /* */)
{
matches.addUnique(it.nextDoc());
}
}
bitSet = matches.getBits();
doc = getBase() - 1;
}
private boolean next()
{
if(doc+1 < bitSet.length())
{
doc = bitSet.nextSetBit(doc+1);
return (doc != NO_MORE_DOCS) && (doc < (getBase() + context.reader().maxDoc()));
}
else
{
return false;
}
}
private int getBase()
{
return context.docBase;
}
@Override
public int nextDoc() throws IOException
{
while (next())
{
return docID();
}
return NO_MORE_DOCS;
}
@Override
public int docID()
{
// TODO: check this expression as for next()
if ((doc > -1) && (doc != NO_MORE_DOCS))
{
return doc - getBase();
}
return doc;
}
@Override
public int advance(int target) throws IOException
{
while (next())
{
final int current = docID();
if (current >= target)
{
return current;
}
}
return NO_MORE_DOCS;
}
// TODO: implement
@Override
public long cost()
{
return 1;
}
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
import java.io.IOException;
import java.util.stream.LongStream;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.FixedBitSet;
import org.apache.solr.search.BitDocSet;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
/**
* @author Andy
*
*/
public abstract class AbstractSolrCachingScorer extends Scorer
{
protected static class LongCache
{
private static int CACHE_SIZE = 1000000;
private LongCache(){}
static final long cache[] = LongStream.range(0, CACHE_SIZE).toArray();
}
protected static Long getLong(long l) {
if(l > LongCache.CACHE_SIZE)
{
return Long.valueOf(l);
}
else
{
return LongCache.cache[(int)l];
}
}
SolrCachingScorerDoIdSetIterator iterator;
AbstractSolrCachingScorer(Weight weight, DocSet in, LeafReaderContext context, SolrIndexSearcher searcher)
{
super(weight);
iterator = new SolrCachingScorerDoIdSetIterator(in, context, searcher);
}
@Override
public float score() throws IOException
{
return 1.0f;
}
// TODO: implement
@Override
public int freq() throws IOException
{
return 1;
}
@Override
public int docID()
{
return iterator.docID();
}
@Override
public DocIdSetIterator iterator()
{
return iterator;
}
private static class SolrCachingScorerDoIdSetIterator extends DocIdSetIterator
{
BitDocSet matches;
int doc = -1;
FixedBitSet bitSet;
LeafReaderContext context;
SolrCachingScorerDoIdSetIterator(DocSet in, LeafReaderContext context, SolrIndexSearcher searcher)
{
this.context = context;
if (in instanceof BitDocSet)
{
matches = (BitDocSet) in;
}
else
{
this.matches = new BitDocSet(new FixedBitSet(searcher.maxDoc()));
for (DocIterator it = in.iterator(); it.hasNext(); /* */)
{
matches.addUnique(it.nextDoc());
}
}
bitSet = matches.getBits();
doc = getBase() - 1;
}
private boolean next()
{
if(doc+1 < bitSet.length())
{
doc = bitSet.nextSetBit(doc+1);
return (doc != NO_MORE_DOCS) && (doc < (getBase() + context.reader().maxDoc()));
}
else
{
return false;
}
}
private int getBase()
{
return context.docBase;
}
@Override
public int nextDoc() throws IOException
{
while (next())
{
return docID();
}
return NO_MORE_DOCS;
}
@Override
public int docID()
{
// TODO: check this expression as for next()
if ((doc > -1) && (doc != NO_MORE_DOCS))
{
return doc - getBase();
}
return doc;
}
@Override
public int advance(int target) throws IOException
{
while (next())
{
final int current = docID();
if (current >= target)
{
return current;
}
}
return NO_MORE_DOCS;
}
// TODO: implement
@Override
public long cost()
{
return 1;
}
}
}
@@ -1,169 +1,169 @@
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
public abstract class AbstractStructuredFieldPosition implements StructuredFieldPosition
{
private String termText;
private boolean isTerminal;
private boolean isAbsolute;
private CachingTermPositions tps;
public AbstractStructuredFieldPosition(String termText, boolean isTerminal, boolean isAbsolute)
{
super();
this.termText = termText;
this.isTerminal = isTerminal;
this.isAbsolute = isAbsolute;
}
public boolean isTerminal()
{
return isTerminal;
}
protected void setTerminal(boolean isTerminal)
{
this.isTerminal = isTerminal;
}
public boolean isAbsolute()
{
return isAbsolute;
}
public boolean isRelative()
{
return !isAbsolute;
}
public String getTermText()
{
return termText;
}
public int getPosition()
{
return -1;
}
public void setCachingTermPositions(CachingTermPositions tps)
{
this.tps = tps;
}
public CachingTermPositions getCachingTermPositions()
{
return this.tps;
}
public boolean allowsLinkingBySelf()
{
return false;
}
public boolean allowslinkingByParent()
{
return true;
}
public boolean linkParent()
{
return true;
}
public boolean linkSelf()
{
return false;
}
public String toString()
{
StringBuffer buffer = new StringBuffer(256);
buffer.append(getDescription());
buffer.append("<"+getTermText()+"> at "+getPosition());
buffer.append(" Terminal = "+isTerminal());
buffer.append(" Absolute = "+isAbsolute());
return buffer.toString();
}
public abstract String getDescription();
public boolean isDescendant()
{
return false;
}
public boolean matchesAll()
{
return getCachingTermPositions() == null;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (isAbsolute ? 1231 : 1237);
result = prime * result + (isTerminal ? 1231 : 1237);
result = prime * result + ((termText == null) ? 0 : termText.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;
AbstractStructuredFieldPosition other = (AbstractStructuredFieldPosition) obj;
if (isAbsolute != other.isAbsolute)
return false;
if (isTerminal != other.isTerminal)
return false;
if (termText == null)
{
if (other.termText != null)
return false;
}
else if (!termText.equals(other.termText))
return false;
return true;
}
}
/*
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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.
*
* Alfresco is distributed in the hope that 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.solr.query;
public abstract class AbstractStructuredFieldPosition implements StructuredFieldPosition
{
private String termText;
private boolean isTerminal;
private boolean isAbsolute;
private CachingTermPositions tps;
public AbstractStructuredFieldPosition(String termText, boolean isTerminal, boolean isAbsolute)
{
super();
this.termText = termText;
this.isTerminal = isTerminal;
this.isAbsolute = isAbsolute;
}
public boolean isTerminal()
{
return isTerminal;
}
protected void setTerminal(boolean isTerminal)
{
this.isTerminal = isTerminal;
}
public boolean isAbsolute()
{
return isAbsolute;
}
public boolean isRelative()
{
return !isAbsolute;
}
public String getTermText()
{
return termText;
}
public int getPosition()
{
return -1;
}
public void setCachingTermPositions(CachingTermPositions tps)
{
this.tps = tps;
}
public CachingTermPositions getCachingTermPositions()
{
return this.tps;
}
public boolean allowsLinkingBySelf()
{
return false;
}
public boolean allowslinkingByParent()
{
return true;
}
public boolean linkParent()
{
return true;
}
public boolean linkSelf()
{
return false;
}
public String toString()
{
StringBuffer buffer = new StringBuffer(256);
buffer.append(getDescription());
buffer.append("<"+getTermText()+"> at "+getPosition());
buffer.append(" Terminal = "+isTerminal());
buffer.append(" Absolute = "+isAbsolute());
return buffer.toString();
}
public abstract String getDescription();
public boolean isDescendant()
{
return false;
}
public boolean matchesAll()
{
return getCachingTermPositions() == null;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (isAbsolute ? 1231 : 1237);
result = prime * result + (isTerminal ? 1231 : 1237);
result = prime * result + ((termText == null) ? 0 : termText.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;
AbstractStructuredFieldPosition other = (AbstractStructuredFieldPosition) obj;
if (isAbsolute != other.isAbsolute)
return false;
if (isTerminal != other.isTerminal)
return false;
if (termText == null)
{
if (other.termText != null)
return false;
}
else if (!termText.equals(other.termText))
return false;
return true;
}
}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Search Services
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of

Some files were not shown because too many files have changed in this diff Show More