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.ExtensibleType;
import com.thinkbiganalytics.metadata.api.extension.FieldDescriptor;
import com.thinkbiganalytics.metadata.api.extension.UserFieldDescriptor;
import com.thinkbiganalytics.metadata.core.BaseId;
import com.thinkbiganalytics.metadata.modeshape.JcrMetadataAccess;
import com.thinkbiganalytics.metadata.modeshape.MetadataRepositoryException;
import org.joda.time.DateTime;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
/**
* An implementation of {@link ExtensibleType} backed by JCR {@link NodeType} objects.
*/
public class JcrExtensibleType implements ExtensibleType {
public static final String LAST_MODIFIED_TIME = "jcr:lastModified";
public static final String CREATED_TIME = "jcr:created";
public static final String DESCRIPTION = "jcr:description";
public static final String NAME = "jcr:title";
private final NodeType nodeType;
private TypeId id;
private Node typeNode;
/**
*
*/
public JcrExtensibleType(Node typeNode, NodeType nodeDef) {
this.typeNode = typeNode;
this.nodeType = nodeDef;
try {
this.id = new TypeId(this.typeNode.getIdentifier());
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to retrieve the entity id", e);
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.nodeType.toString();
}
/* (non-Javadoc)
* @see com.thinkbiganalytics.metadata.api.extension.ExtensibleType#getId()
*/
@Override
public ID getId() {
return this.id;
}
/* (non-Javadoc)
* @see com.thinkbiganalytics.metadata.api.extension.ExtensibleType#getName()
*/
@Override
public String getName() {
return getJcrName().replace(JcrMetadataAccess.TBA_PREFIX + ":", "");
}
/* (non-Javadoc)
* @see com.thinkbiganalytics.metadata.api.extension.ExtensibleType#getParentType()
*/
@Override
public ExtensibleType getSupertype() {
try {
for (NodeType parent : this.nodeType.getDeclaredSupertypes()) {
if (parent.isNodeType(ExtensionsConstants.EXTENSIBLE_ENTITY_TYPE) &&
!parent.getName().equals(ExtensionsConstants.EXTENSIBLE_ENTITY_TYPE)) {
Node supertypeNode = this.typeNode.getParent().getNode(parent.getName());
return new JcrExtensibleType(supertypeNode, parent);
}
}
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to get parent type for type: " + this.nodeType.getName(), e);
}
return null;
}
@Override
public String getDiplayName() {
try {
return this.typeNode.getProperty(NAME).getString();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to get the display name (title) for type: " + this.nodeType.getName(), e);
}
}
@Override
public String getDesciption() {
try {
return this.typeNode.getProperty(DESCRIPTION).getString();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to get the description of type: " + this.nodeType.getName(), e);
}
}
@Override
public DateTime getCreatedTime() {
try {
return new DateTime(this.typeNode.getProperty(CREATED_TIME).getDate());
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to get created time for type: " + this.nodeType.getName(), e);
}
}
@Override
public DateTime getModifiedTime() {
try {
return new DateTime(this.typeNode.getProperty(LAST_MODIFIED_TIME).getDate());
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to get modified time for type: " + this.nodeType.getName(), e);
}
}
public String getJcrName() {
return this.nodeType.getName();
}
@Override
public Set<FieldDescriptor> getFieldDescriptors() {
try {
Set<FieldDescriptor> set = new HashSet<>();
for (PropertyDefinition def : this.nodeType.getPropertyDefinitions()) {
if (this.typeNode.hasNode(def.getName())) {
Node descrNode = this.typeNode.getNode(def.getName());
set.add(new JcrFieldDescriptor(descrNode, def));
}
}
return set;
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to get property descriptors for type: " + this.nodeType.getName(), e);
}
}
@Override
public FieldDescriptor getFieldDescriptor(String name) {
try {
for (PropertyDefinition def : this.nodeType.getPropertyDefinitions()) {
if (def.getName().equalsIgnoreCase(name)) {
Node descrNode = this.typeNode.getNode(def.getName());
return new JcrFieldDescriptor(descrNode, def);
}
}
return null;
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to get property descriptor for type: " + this.nodeType.getName(), e);
}
}
@Nonnull
@Override
public Set<UserFieldDescriptor> getUserFieldDescriptors() {
final String prefix = JcrMetadataAccess.USR_PREFIX + ":";
return Arrays.stream(nodeType.getPropertyDefinitions())
.filter(property -> property.getName().startsWith(prefix))
.map(property -> {
try {
final Node descNode = typeNode.getNode(property.getName());
return new JcrUserFieldDescriptor(descNode, property);
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to access property: " + property, e);
}
})
.collect(Collectors.toSet());
}
public static class TypeId extends BaseId implements ID {
private static final long serialVersionUID = -7707175033124386499L;
private String idValue;
public TypeId() {
}
public TypeId(Serializable ser) {
super(ser);
}
public String getIdValue() {
return idValue;
}
@Override
public String toString() {
return idValue;
}
@Override
public UUID getUuid() {
return UUID.fromString(idValue);
}
@Override
public void setUuid(UUID uuid) {
this.idValue = uuid.toString();
}
}
}