package com.thinkbiganalytics.metadata.modeshape.common;
/*-
* #%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.modeshape.MetadataRepositoryException;
import com.thinkbiganalytics.metadata.modeshape.UnknownPropertyException;
import com.thinkbiganalytics.metadata.modeshape.support.JcrPropertyUtil;
import com.thinkbiganalytics.metadata.modeshape.support.JcrUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
/**
*/
public class JcrObject {
protected final Node node;
private String versionName;
private String versionableIdentifier;
/**
*
*/
public JcrObject(Node node) {
this.node = node;
String nodeName = null;
try {
nodeName = node.getName();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to create JcrObject from node " + nodeName, e);
}
}
public String getObjectId() throws RepositoryException {
if (this.node.isNodeType("nt:frozenNode")) {
return this.versionableIdentifier;
} else {
return this.node.getIdentifier();
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
try {
return getClass().getSimpleName() + ": " + this.node.getName();
} catch (RepositoryException e) {
return getClass().getSimpleName() + " - error: " + e.getMessage();
}
}
public String getTypeName() {
try {
return this.node.getPrimaryNodeType().getName();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to retrieve the entity type name", e);
}
}
public boolean isNew() {
return this.node.isNew();
}
public boolean isModified() {
return this.node.isModified();
}
public void refresh(boolean keepChanges) {
try {
this.node.refresh(keepChanges);
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to refresh Node. ", e);
}
}
public String getPath() {
try {
return this.node.getPath();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to get the Path", e);
}
}
public String getNodeName() {
try {
return this.node.getName();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to get the Node Name", e);
}
}
public void remove() {
try {
this.node.remove();
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to remove the node", e);
}
}
public boolean isLive() {
if (this.node != null) {
try {
if (this.node.getSession() != null) {
return this.node.getSession().isLive();
}
} catch (RepositoryException e) {
}
}
return false;
}
public Map<String, Object> getProperties() {
return JcrPropertyUtil.getProperties(this.node);
}
public Object getProperty(String name) {
return JcrPropertyUtil.getProperty(this.node, name);
}
public <T> Set<T> getPropertyAsSet(String name, Class<T> objectType) {
Object o = null;
try {
o = JcrPropertyUtil.getProperty(this.node, name);
} catch (UnknownPropertyException e) {
}
if (o != null) {
if (o instanceof Collection) {
//convert the objects to the correct type if needed
if (JcrObject.class.isAssignableFrom(objectType)) {
Set<T> objects = new HashSet<>();
for (Object collectionObj : (Collection) o) {
T obj = null;
if (collectionObj instanceof Node) {
try {
obj = ConstructorUtils.invokeConstructor(objectType, (Node) collectionObj);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
obj = (T) collectionObj;
}
} else {
obj = (T) collectionObj;
}
objects.add(obj);
}
return objects;
} else {
return new HashSet<T>((Collection) o);
}
} else {
Set<T> set = new HashSet<>();
if (JcrObject.class.isAssignableFrom(objectType) && o instanceof Node) {
T obj = null;
try {
obj = ConstructorUtils.invokeConstructor(objectType, (Node) o);
set.add((T) obj);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
}
set.add(obj);
} else {
set.add((T) o);
}
return set;
}
}
return new HashSet<T>();
}
public <T> T getProperty(String name, Class<T> type) {
return getProperty(name, type, false);
}
public <T> T getProperty(String name, Class<T> type, boolean allowNotFound) {
return getPropertyFromNode(this.node, name, type, allowNotFound);
}
public <T> T getPropertyFromNode(Node node, String name, Class<T> type, boolean allowNotFound) {
Object o = JcrPropertyUtil.getProperty(node, name, allowNotFound);
if (allowNotFound && o == null) {
return null;
}
if (type.isEnum()) {
String savedType = o.toString();
if (StringUtils.isNotBlank(savedType)) {
Class<? extends Enum> x = (Class<? extends Enum>) type;
return (T) Enum.valueOf(x, savedType);
}
}
if (!o.getClass().isAssignableFrom(type)) {
//if it cant be matched and it is a Node > JcrObject, do the conversion
if (o instanceof Node && JcrObject.class.isAssignableFrom(type)) {
return JcrUtil.constructNodeObject((Node) o, type, null);
} else {
throw new MetadataRepositoryException("Unable to convert Property " + name + " to type " + type);
}
} else {
return (T) o;
}
}
public void setProperty(String name, Object value) {
JcrPropertyUtil.setProperty(this.node, name, value);
}
public Node getNode() {
return this.node;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public String getVersionableIdentifier() {
return versionableIdentifier;
}
public void setVersionableIdentifier(String versionableIdentifier) {
this.versionableIdentifier = versionableIdentifier;
}
@Override
public boolean equals(Object obj) {
if (getClass().isInstance(obj)) {
JcrObject that = (JcrObject) obj;
return this.node.equals(that.node);
} else {
return false;
}
}
@Override
public int hashCode() {
return this.node.hashCode();
}
}