001/* 002 * (C) Copyright 2014 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Benoit Delbosc 016 */ 017package org.nuxeo.ecm.platform.query.core; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.codehaus.jackson.annotate.JsonIgnore; 027import org.nuxeo.ecm.core.api.DocumentModel; 028import org.nuxeo.ecm.platform.query.api.Aggregate; 029import org.nuxeo.ecm.platform.query.api.AggregateDefinition; 030import org.nuxeo.ecm.platform.query.api.AggregateRangeDateDefinition; 031import org.nuxeo.ecm.platform.query.api.AggregateRangeDefinition; 032import org.nuxeo.ecm.platform.query.api.Bucket; 033import org.nuxeo.ecm.platform.query.api.PredicateFieldDefinition; 034 035/** 036 * @since 6.0 037 */ 038public class AggregateBase<B extends Bucket> implements Aggregate<B> { 039 040 protected final AggregateDefinition definition; 041 042 protected final DocumentModel searchDocument; 043 044 protected List<String> selection; 045 046 protected List<B> buckets; 047 048 protected List<Bucket> extendedBuckets; 049 050 protected Map<String, Bucket> bucketMap = null; 051 052 public AggregateBase(AggregateDefinition definition, DocumentModel searchDocument) { 053 assert (definition != null); 054 this.definition = definition; 055 this.searchDocument = searchDocument; 056 } 057 058 @Override 059 public String getId() { 060 return definition.getId(); 061 } 062 063 @Override 064 public String getType() { 065 return definition.getType(); 066 } 067 068 @Override 069 public String getField() { 070 return definition.getDocumentField(); 071 } 072 073 @Override 074 public Map<String, String> getProperties() { 075 return definition.getProperties(); 076 } 077 078 @Override 079 public List<AggregateRangeDefinition> getRanges() { 080 return definition.getRanges(); 081 } 082 083 @Override 084 public List<AggregateRangeDateDefinition> getDateRanges() { 085 return definition.getDateRanges(); 086 } 087 088 @SuppressWarnings("unchecked") 089 @Override 090 public List<String> getSelection() { 091 if (selection == null) { 092 PredicateFieldDefinition field = definition.getSearchField(); 093 if (searchDocument != null) { 094 // property must be nxs:stringList 095 List<String> value = null; 096 Object resolvedProperties = searchDocument.getProperty(field.getSchema(), field.getName()); 097 if (resolvedProperties instanceof String[]) { 098 value = Arrays.asList((String[]) resolvedProperties); 099 } else if (resolvedProperties instanceof List<?>) { 100 value = (List<String>) searchDocument.getProperty(field.getSchema(), field.getName()); 101 } 102 selection = value; 103 } 104 if (selection == null) { 105 selection = Collections.<String> emptyList(); 106 } 107 } 108 return selection; 109 } 110 111 @Override 112 public void setSelection(List<String> selection) { 113 this.selection = selection; 114 } 115 116 @Override 117 public List<B> getBuckets() { 118 return buckets; 119 } 120 121 @Override 122 public List<Bucket> getExtendedBuckets() { 123 if (extendedBuckets == null) { 124 extendedBuckets = new ArrayList<Bucket>(); 125 final List<String> currentSelection = getSelection(); 126 if (currentSelection != null) { 127 for (String s : currentSelection) { 128 if (!hasBucket(s)) { 129 extendedBuckets.add(new MockBucket(s)); 130 } 131 } 132 } 133 extendedBuckets.addAll(buckets); 134 } 135 return extendedBuckets; 136 } 137 138 @Override 139 public void setBuckets(List<B> buckets) { 140 this.buckets = buckets; 141 this.bucketMap = null; 142 this.extendedBuckets = null; 143 } 144 145 @JsonIgnore 146 public DocumentModel getSearchDocument() { 147 return searchDocument; 148 } 149 150 @Override 151 public String toString() { 152 return String.format("Aggregate(%s, %s, %s, %s, %s)", getId(), getType(), getField(), 153 (getSelection() != null) ? Arrays.toString(getSelection().toArray()) : null, 154 (buckets != null) ? Arrays.toString(buckets.toArray()) : null); 155 } 156 157 @Override 158 public boolean hasBucket(final String key) { 159 return getBucketMap().containsKey(key); 160 } 161 162 @Override 163 public Bucket getBucket(final String key) { 164 return getBucketMap().get(key); 165 } 166 167 public Map<String, Bucket> getBucketMap() { 168 if (bucketMap == null && getBuckets() != null) { 169 bucketMap = new HashMap<String, Bucket>(); 170 for (Bucket b : getBuckets()) { 171 bucketMap.put(b.getKey(), b); 172 } 173 } 174 return bucketMap; 175 } 176 177 @Override 178 public void resetSelection() { 179 PredicateFieldDefinition field = definition.getSearchField(); 180 if (searchDocument != null) { 181 searchDocument.setProperty(field.getSchema(), field.getName(), null); 182 selection = Collections.<String> emptyList(); 183 } 184 } 185 186}