mirror of
https://github.com/Alfresco/SearchServices.git
synced 2026-09-16 18:12:56 +00:00
SEARCH-2548: Upgrade license headers
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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
-2
@@ -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}}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
-2
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
|
||||
|
||||
+1
-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
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
+63
-63
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+391
-391
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+284
-284
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+47
-47
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+396
-396
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+109
-109
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+273
-273
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+245
-245
@@ -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
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+271
-271
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+76
-76
@@ -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_";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1892
-1892
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+120
-120
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
-1
@@ -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
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+76
-76
@@ -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
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+79
-79
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+77
-77
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+39
-39
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
search-services/alfresco-search/src/main/java/org/alfresco/solr/cache/AuthorityCacheRegenerator.java
Vendored
+58
-58
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+48
-48
@@ -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";
|
||||
}
|
||||
|
||||
Vendored
+59
-59
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+78
-78
@@ -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 "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+105
-105
@@ -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
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+279
-279
@@ -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 "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+568
-568
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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
|
||||
|
||||
+89
-89
@@ -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 "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+87
-87
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+109
-109
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+55
-55
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+369
-369
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+116
-116
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+54
-54
@@ -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
-2
@@ -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
|
||||
|
||||
+142
-142
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+76
-76
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+85
-85
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+192
-192
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+707
-707
File diff suppressed because it is too large
Load Diff
+198
-198
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+169
-169
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
Reference in New Issue
Block a user