/** * */ package com.thinkbiganalytics.metadata.modeshape.extension; /*- * #%L * thinkbig-metadata-modeshape * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import com.thinkbiganalytics.metadata.api.extension.ExtensibleEntity; import com.thinkbiganalytics.metadata.api.extension.ExtensibleEntity.ID; import com.thinkbiganalytics.metadata.api.extension.ExtensibleEntityProvider; import com.thinkbiganalytics.metadata.api.extension.ExtensibleType; import com.thinkbiganalytics.metadata.api.extension.ExtensibleTypeProvider; import com.thinkbiganalytics.metadata.modeshape.JcrMetadataAccess; import com.thinkbiganalytics.metadata.modeshape.MetadataRepositoryException; import com.thinkbiganalytics.metadata.modeshape.common.EntityUtil; import com.thinkbiganalytics.metadata.modeshape.support.JcrPropertyUtil; import com.thinkbiganalytics.metadata.modeshape.support.JcrQueryUtil; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import javax.inject.Inject; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.query.QueryResult; /** * */ public class JcrExtensibleEntityProvider implements ExtensibleEntityProvider { @Inject ExtensibleTypeProvider typeProvider; @Override public ExtensibleEntity createEntity(ExtensibleType type, Map<String, Object> props) { JcrExtensibleType typeImpl = (JcrExtensibleType) type; Session session = getSession(); try { String path = EntityUtil.pathForExtensibleEntity(); Node entitiesNode = session.getNode(path); Node typesNode = null; if (entitiesNode.hasNode(typeImpl.getJcrName())) { typesNode = entitiesNode.getNode(typeImpl.getJcrName()); } else { typesNode = entitiesNode.addNode(typeImpl.getJcrName(), "nt:folder"); } Node entNode = typesNode.addNode(typeImpl.getName() + "-" + UUID.randomUUID().toString(), typeImpl.getJcrName()); Map<String, Object> reassignedProps = mapCollectionProperties(typeImpl, props); entNode = JcrPropertyUtil.setProperties(session, entNode, reassignedProps); return new JcrExtensibleEntity(entNode); } catch (RepositoryException e) { throw new MetadataRepositoryException("Failed to create new extensible entity of type: " + typeImpl.getJcrName(), e); } } /** * If the incoming set of props contains a collection it needs to be converted into an object that knows the correct JCRType for that collection */ private Map<String, Object> mapCollectionProperties(JcrExtensibleType typeImpl, Map<String, Object> props) { //remap any Collections into JcrExtensiblePropertyCollection Map<String, Object> reassignedProps = new HashMap<>(); if (props != null) { for (Map.Entry<String, Object> prop : props.entrySet()) { String key = prop.getKey(); Object v = prop.getValue(); if (v instanceof Collection) { int typeCode = ((JcrExtensibleTypeProvider) typeProvider).asCode(typeImpl.getFieldDescriptor(key).getType()); JcrExtensiblePropertyCollection collection = new JcrExtensiblePropertyCollection(typeCode, (Collection) v); reassignedProps.put(key, collection); } else { reassignedProps.put(key, v); } } } return reassignedProps; } public ExtensibleEntity updateEntity(ExtensibleEntity extensibleEntity, Map<String, Object> props) { JcrExtensibleEntity jcrExtensibleEntity = (JcrExtensibleEntity) extensibleEntity; JcrExtensibleType typeImpl = (JcrExtensibleType) typeProvider.getType(jcrExtensibleEntity.getTypeName()); Map<String, Object> reassignedProps = mapCollectionProperties(typeImpl, props); JcrPropertyUtil.setProperties(getSession(), jcrExtensibleEntity.getNode(), reassignedProps); return extensibleEntity; } @Override public List<ExtensibleEntity> getEntities() { List<ExtensibleEntity> list = new ArrayList<>(); Session session = getSession(); try { String path = EntityUtil.pathForExtensibleEntity(); Node genericsNode = session.getNode(path); NodeIterator typeNameItr = genericsNode.getNodes(); while (typeNameItr.hasNext()) { Node typeNameNode = (Node) typeNameItr.next(); NodeIterator entityItr = typeNameNode.getNodes(); while (entityItr.hasNext()) { Node entNode = (Node) entityItr.next(); list.add(new JcrExtensibleEntity(entNode)); } } return list; } catch (RepositoryException e) { throw new MetadataRepositoryException("Failed to retrieve list of extensible entities", e); } } public List<ExtensibleEntity> getEntities(String typeName) { List<ExtensibleEntity> list = new ArrayList<>(); Session session = getSession(); try { String path = EntityUtil.pathForExtensibleEntity(typeName); Node typeNameNode = session.getNode(path); NodeIterator entityItr = typeNameNode.getNodes(); while (entityItr.hasNext()) { Node entNode = (Node) entityItr.next(); list.add(new JcrExtensibleEntity(entNode)); } return list; } catch (RepositoryException e) { throw new MetadataRepositoryException("Failed to retrieve list of extensible entities", e); } } /** * Return a list of the ExtensibleEntity objects that match a given ExtensibleEntity property and value * restricting to a specific jcr extension type */ public List<? extends ExtensibleEntity> findEntitiesMatchingProperty(String typeName, String propName, Object value) { String path = EntityUtil.pathForExtensibleEntity(typeName); HashMap<String, String> params = new HashMap<>(); String query = "SELECT * FROM [" + typeName + "] as t WHERE t.[" + propName + "] = $v"; params.put("v", value.toString()); QueryResult result = null; try { result = JcrQueryUtil.query(getSession(), query, params); List<JcrExtensibleEntity> entities = JcrQueryUtil.queryResultToList(result, JcrExtensibleEntity.class); return entities; } catch (RepositoryException e) { throw new MetadataRepositoryException("Unable to execute Criteria Query for " + typeName + ". Query is: " + query, e); } } @Override public ExtensibleEntity getEntity(ID id) { JcrExtensibleEntity.EntityId idImpl = (JcrExtensibleEntity.EntityId) id; try { Session session = getSession(); Node node = session.getNodeByIdentifier(idImpl.getIdValue()); if (node != null) { return new JcrExtensibleEntity(node); } else { return null; } } catch (RepositoryException e) { throw new MetadataRepositoryException("Failure while finding entity by ID: " + idImpl.getIdValue(), e); } } private Session getSession() { return JcrMetadataAccess.getActiveSession(); } }