/* * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Florent Guillaume */ package org.nuxeo.ecm.core.schema; import static org.apache.commons.lang.ObjectUtils.NULL; import static org.nuxeo.ecm.core.schema.types.ComplexTypeImpl.canonicalXPath; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.nuxeo.ecm.core.schema.types.Schema; import org.nuxeo.runtime.api.Framework; /** * Information about what's to be prefetched: individual properties and whole schemas. */ public class Prefetch implements Serializable { private static final long serialVersionUID = 1L; /** * map of prefix:name -> value * <p> * key can be a canonical xpath like prefix:name/0/othername * <p> * null values are stored as actual nulls */ public Map<String, Serializable> values; /** * map of schema -> list of prefix:name */ public Map<String, List<String>> keysBySchema; /** * map of schema -> name -> prefix:name */ public Map<String, Map<String, String>> keysBySchemaAndName; public Prefetch() { values = new HashMap<String, Serializable>(); keysBySchema = new HashMap<String, List<String>>(); keysBySchemaAndName = new HashMap<String, Map<String, String>>(); } public boolean isEmpty() { return values.isEmpty(); } public void put(String prefixedName, String schemaName, String name, Serializable value) { values.put(prefixedName, value); if (schemaName != null) { Map<String, String> keysByName = keysBySchemaAndName.get(schemaName); if (keysByName == null) { keysBySchemaAndName.put(schemaName, keysByName = new HashMap<String, String>()); } keysByName.put(name, prefixedName); List<String> keys = keysBySchema.get(schemaName); if (keys == null) { keysBySchema.put(schemaName, keys = new LinkedList<String>()); } keys.add(prefixedName); } } public Serializable get(String xpath) { xpath = canonicalXPath(xpath); if (values.containsKey(xpath)) { return cloned(values.get(xpath)); } return NULL; } public Serializable get(String schemaName, String name) { Map<String, String> keysByName = keysBySchemaAndName.get(schemaName); if (keysByName != null) { String prefixedName = keysByName.get(name); if (prefixedName != null && values.containsKey(prefixedName)) { return cloned(values.get(prefixedName)); } } return NULL; } // make sure we return a new array protected Serializable cloned(Serializable value) { if (value instanceof Object[]) { value = ((Object[]) value).clone(); } return value; } public boolean isPrefetched(String xpath) { xpath = canonicalXPath(xpath); return values.containsKey(xpath); } public boolean isPrefetched(String schemaName, String name) { Map<String, String> keysByName = keysBySchemaAndName.get(schemaName); if (keysByName == null) { return false; } String prefixedName = keysByName.get(name); if (prefixedName == null) { return false; } return values.containsKey(prefixedName); } /** * Clears the prefetches for a given schema. */ public void clearPrefetch(String schemaName) { keysBySchemaAndName.remove(schemaName); List<String> keys = keysBySchema.remove(schemaName); if (keys != null) { for (String prefixedName : keys) { values.remove(prefixedName); } } } /** * Gets the schema name for a given xpath. * <p> * The type is used to resolve non-prefixed properties. * * @return the schema name or {@code null} */ public String getXPathSchema(String xpath, DocumentType type) { xpath = canonicalXPath(xpath); int i = xpath.indexOf('/'); String prop = i == -1 ? xpath : xpath.substring(0, i); int p = prop.indexOf(':'); if (p == -1) { for (Schema schema : type.getSchemas()) { if (schema.hasField(prop)) { return schema.getName(); } } return null; } else { String prefix = prop.substring(0, p); SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class); Schema schema = schemaManager.getSchemaFromPrefix(prefix); if (schema == null) { schema = schemaManager.getSchema(prefix); } return schema == null ? null : schema.getName(); } } }