001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Benoit Delbosc 018 */ 019package org.nuxeo.ecm.platform.query.core; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.nuxeo.ecm.core.api.DocumentModel; 029import org.nuxeo.ecm.platform.query.api.Aggregate; 030import org.nuxeo.ecm.platform.query.api.AggregateDefinition; 031import org.nuxeo.ecm.platform.query.api.AggregateRangeDateDefinition; 032import org.nuxeo.ecm.platform.query.api.AggregateRangeDefinition; 033import org.nuxeo.ecm.platform.query.api.Bucket; 034import org.nuxeo.ecm.platform.query.api.PredicateFieldDefinition; 035 036import com.fasterxml.jackson.annotation.JsonIgnore; 037 038/** 039 * @since 6.0 040 */ 041public class AggregateBase<B extends Bucket> implements Aggregate<B> { 042 043 protected final AggregateDefinition definition; 044 045 protected final DocumentModel searchDocument; 046 047 protected List<String> selection; 048 049 protected List<B> buckets; 050 051 protected List<Bucket> extendedBuckets; 052 053 protected Map<String, Bucket> bucketMap = null; 054 055 public AggregateBase(AggregateDefinition definition, DocumentModel searchDocument) { 056 assert (definition != null); 057 this.definition = definition; 058 this.searchDocument = searchDocument; 059 } 060 061 @Override 062 public String getId() { 063 return definition.getId(); 064 } 065 066 @Override 067 public String getType() { 068 return definition.getType(); 069 } 070 071 @Override 072 public String getField() { 073 return definition.getDocumentField(); 074 } 075 076 @Override 077 public Map<String, String> getProperties() { 078 return definition.getProperties(); 079 } 080 081 @Override 082 public List<AggregateRangeDefinition> getRanges() { 083 return definition.getRanges(); 084 } 085 086 @Override 087 public List<AggregateRangeDateDefinition> getDateRanges() { 088 return definition.getDateRanges(); 089 } 090 091 @SuppressWarnings("unchecked") 092 @Override 093 public List<String> getSelection() { 094 if (selection == null) { 095 PredicateFieldDefinition field = definition.getSearchField(); 096 if (searchDocument != null) { 097 // property must be nxs:stringList 098 List<String> value = null; 099 Object resolvedProperties = searchDocument.getProperty(field.getSchema(), field.getName()); 100 if (resolvedProperties instanceof String[]) { 101 value = Arrays.asList((String[]) resolvedProperties); 102 } else if (resolvedProperties instanceof List<?>) { 103 value = (List<String>) searchDocument.getProperty(field.getSchema(), field.getName()); 104 } 105 selection = value; 106 } 107 if (selection == null) { 108 selection = Collections.<String> emptyList(); 109 } 110 } 111 return selection; 112 } 113 114 @Override 115 public void setSelection(List<String> selection) { 116 this.selection = selection; 117 } 118 119 @Override 120 public List<B> getBuckets() { 121 return buckets; 122 } 123 124 @Override 125 public List<Bucket> getExtendedBuckets() { 126 if (extendedBuckets == null) { 127 extendedBuckets = new ArrayList<>(); 128 final List<String> currentSelection = getSelection(); 129 if (currentSelection != null) { 130 for (String s : currentSelection) { 131 if (!hasBucket(s)) { 132 extendedBuckets.add(new MockBucket(s)); 133 } 134 } 135 } 136 extendedBuckets.addAll(buckets); 137 } 138 return extendedBuckets; 139 } 140 141 @Override 142 public void setBuckets(List<B> buckets) { 143 this.buckets = buckets; 144 this.bucketMap = null; 145 this.extendedBuckets = null; 146 } 147 148 @JsonIgnore 149 public DocumentModel getSearchDocument() { 150 return searchDocument; 151 } 152 153 @Override 154 public String toString() { 155 return String.format("Aggregate(%s, %s, %s, %s, %s)", getId(), getType(), getField(), 156 (getSelection() != null) ? Arrays.toString(getSelection().toArray()) : null, 157 (buckets != null) ? Arrays.toString(buckets.toArray()) : null); 158 } 159 160 @Override 161 public boolean hasBucket(final String key) { 162 return getBucketMap().containsKey(key); 163 } 164 165 @Override 166 public Bucket getBucket(final String key) { 167 return getBucketMap().get(key); 168 } 169 170 public Map<String, Bucket> getBucketMap() { 171 if (bucketMap == null && getBuckets() != null) { 172 bucketMap = new HashMap<>(); 173 for (Bucket b : getBuckets()) { 174 bucketMap.put(b.getKey(), b); 175 } 176 } 177 return bucketMap; 178 } 179 180 @Override 181 public void resetSelection() { 182 PredicateFieldDefinition field = definition.getSearchField(); 183 if (searchDocument != null) { 184 searchDocument.setProperty(field.getSchema(), field.getName(), null); 185 selection = Collections.<String> emptyList(); 186 } 187 } 188 189 @Override 190 public String getXPathField() { 191 return getField(); 192 } 193 194}