// Copyright 2000-2005, FreeHEP.
package hep.graphics.heprep.ref;
import java.io.*;
import java.util.*;
import hep.graphics.heprep.*;
import hep.graphics.heprep.util.*;
/**
*
* @author M.Donszelmann
*
* @version $Id: DefaultHepRepInstance.java 8584 2006-08-10 23:06:37Z duns $
*/
public class DefaultHepRepInstance extends DefaultHepRepAttribute implements HepRepInstance, Serializable {
private HepRepType type = null;
private HepRepInstance parent;
private List/*<HepRepPoint>*/ pointList;
private double[][] points;
private List/*<HepRepInstance>*/ instanceList;
private transient Object userObject; // to cache information, not persistent
private transient boolean valid; // is cache info up to date
private transient String layer; // cached info
private transient boolean hasFrame; // cached info
protected DefaultHepRepInstance(HepRepInstance parent, HepRepType type) {
super();
if (type == null) throw new RuntimeException("HepRepInstance cannot be created without a HepRepType.");
this.type = type;
this.parent = parent;
this.valid = false;
this.layer = null;
this.hasFrame = false;
if (parent != null) parent.addInstance(this);
}
protected DefaultHepRepInstance(HepRepInstanceTree parent, HepRepType type) {
this((HepRepInstance)null, type);
this.valid = false;
this.layer = null;
this.hasFrame = false;
parent.addInstance(this);
}
// private DefaultHepRepInstance(HepRepType type) {
// this((HepRepInstance)null, type);
// }
public HepRepInstance getSuperInstance() {
return parent;
}
public void overlay(HepRepInstance instance) {
// check #of subinstances are equal
if (getInstances().size() != instance.getInstances().size()) {
throw new RuntimeException("HepRepInstance cannot overlay; not a compatible structure in terms of sub-instances.");
}
// check #of points are equal if greater than 0
if ((getPoints().size() > 0) && (getPoints().size() != instance.getPoints().size())) {
throw new RuntimeException("HepRepInstance cannot overlay; not a compatible structure in terms of points.");
}
// add points of instance if #of points is 0
for (Iterator i=instance.getPoints().iterator(); i.hasNext(); ) {
HepRepPoint point = (HepRepPoint)i.next();
addPoint(point);
}
// merge all attValues, where instance overrides the values of "this".
for (Iterator i=instance.getAttValuesFromNode().iterator(); i.hasNext(); ) {
HepRepAttValue value = (HepRepAttValue)i.next();
addAttValue(value);
}
optimize();
validate();
}
private void writeObject(ObjectOutputStream stream) throws IOException {
// System.out.println("DHRInstance: Serializing "+this);
stream.defaultWriteObject();
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
// System.out.println("DHRInstance: Deserializing "+this);
stream.defaultReadObject();
}
public HepRepInstance copy(HepRepTypeTree typeTree, HepRepInstance parent)
throws CloneNotSupportedException {
return copy(typeTree, parent, null);
}
public HepRepInstance copy(HepRepTypeTree typeTree, HepRepInstanceTree parent)
throws CloneNotSupportedException {
return copy(typeTree, parent, null);
}
public HepRepInstance copy(HepRepTypeTree typeTree, HepRepInstance parent, HepRepSelectFilter filter)
throws CloneNotSupportedException {
HepRepType type = typeTree.getType(getType().getFullName());
DefaultHepRepInstance instanceCopy = new DefaultHepRepInstance(parent, type);
return copy(typeTree, instanceCopy, filter);
}
public HepRepInstance copy(HepRepTypeTree typeTree, HepRepInstanceTree parent, HepRepSelectFilter filter)
throws CloneNotSupportedException {
HepRepType type = typeTree.getType(getType().getFullName());
DefaultHepRepInstance instanceCopy = new DefaultHepRepInstance(parent, type);
return copy(typeTree, instanceCopy, filter);
}
private HepRepInstance copy(HepRepTypeTree typeTree, DefaultHepRepInstance instanceCopy, HepRepSelectFilter filter)
throws CloneNotSupportedException {
HepRepUtil.copyAttributes(this, instanceCopy);
// copy points
for (Iterator i=getPoints().iterator(); i.hasNext(); ) {
HepRepPoint point = (HepRepPoint)i.next();
// auto addition due to parent
point.copy(instanceCopy);
}
// copy sub-instances
for (Iterator i=getInstances().iterator(); i.hasNext(); ) {
HepRepInstance instance = (HepRepInstance)i.next();
if ((filter == null) || (filter.select(instance))) {
// auto addition due to parent
instance.copy(typeTree, instanceCopy, filter);
}
}
// FIXME may not be the smartest way to handle this.
instanceCopy.optimize();
instanceCopy.validate();
return instanceCopy;
}
public void setUserObject(Object object) {
userObject = object;
}
public Object getUserObject() {
return userObject;
}
public HepRepType getType() {
return type;
}
public void addPoint(HepRepPoint point) throws UnsupportedOperationException {
if (pointList == null) pointList = new ArrayList();
pointList.add(point);
}
public List/*<HepRepPoint>*/ getPoints() {
if ((pointList == null) && (points == null)) return Collections.EMPTY_LIST;
if (pointList != null) return pointList;
// convert the array to a list of HepRepPoints
List list = new ArrayList(points.length);
for (int i=0; i<points.length; i++) {
list.add(new DefaultHepRepPoint(this, points[0][i], points[1][i], points[2][i]));
}
return list;
}
public int getPoints(double[][] xyz) {
if ((pointList == null) && (points == null)) return 0;
if (points == null) optimize();
if (points == null) return -1;
int nPoints = points[0].length;
int xPoints = xyz[0].length;
// skip points in case the array is too small
int inc = (xPoints < nPoints) ? nPoints / xPoints : 0;
inc++;
int i=0;
int j=0;
while (j<nPoints) {
xyz[0][i] = points[0][j];
xyz[1][i] = points[1][j];
xyz[2][i] = points[2][j];
i++;
j+=inc;
}
// FIXME !!! this should be ok.
/*
System.arraycopy(points[0], 0, xyz[0], 0, points[0].length);
System.arraycopy(points[1], 0, xyz[1], 0, points[1].length);
System.arraycopy(points[2], 0, xyz[2], 0, points[2].length);
*/
return (inc > 1) ? -nPoints : nPoints;
}
/**
* Optimizes the internal storage of the instance.
* If no HepRepPoints contain attributes the points are converted to an array.
*/
public void optimize() {
//
// Convert List<HepRepPoint> to double[3][n]
//
if ((points != null) || (pointList == null)) return;
points = new double[3][pointList.size()];
int j = 0;
for (Iterator i = pointList.iterator(); i.hasNext(); ) {
HepRepPoint p = (HepRepPoint)i.next();
// check if any points have attributes defined
if (!p.getAttValuesFromNode().isEmpty()) {
// System.out.println("Could not optimize data, points contain attributes");
points = null;
return;
}
points[0][j] = p.getX();
points[1][j] = p.getY();
points[2][j] = p.getZ();
j++;
}
// FIXME later
// pointList = null;
}
public void addInstance(HepRepInstance instance) throws UnsupportedOperationException {
if (instanceList == null) instanceList = new ArrayList();
instanceList.add(instance);
}
public void removeInstance(HepRepInstance instance) throws UnsupportedOperationException {
if (instanceList != null) instanceList.remove(instance);
}
public List/*<HepRepInstance>*/ getInstances() {
if (instanceList == null) return Collections.EMPTY_LIST;
return instanceList;
}
/**
* search for attribute on node, then search on type
*/
public HepRepAttValue getAttValue(String name) {
String lowerCaseName = name.toLowerCase();
HepRepAttValue value = getAttValueFromNode(lowerCaseName);
return (value != null) ? value : type.getAttValue(lowerCaseName);
}
public String toString() {
return "DefaultHepRepInstance: "+getType();
}
int getNoOfInstances() {
int n = 0;
for (Iterator i=getInstances().iterator(); i.hasNext(); ) {
DefaultHepRepInstance instance = (DefaultHepRepInstance)i.next();
n++;
n += instance.getNoOfInstances();
}
return n;
}
int getNoOfPoints() {
int p = getPoints().size();
for (Iterator i=getInstances().iterator(); i.hasNext(); ) {
DefaultHepRepInstance instance = (DefaultHepRepInstance)i.next();
p += instance.getNoOfPoints();
}
return p;
}
int getNoOfAttValues() {
int v = getAttValuesFromNode().size();
for (Iterator i=getInstances().iterator(); i.hasNext(); ) {
DefaultHepRepInstance instance = (DefaultHepRepInstance)i.next();
v += instance.getNoOfAttValues();
}
return v;
}
/* Disabled for FREEHEP-386
public boolean equals(Object o) {
if (!super.equals(o)) return false;
if (o instanceof HepRepInstance) {
HepRepInstance ref = (HepRepInstance)o;
if (!ref.getType().equals(getType())) return false;
if (!ref.getPoints().equals(getPoints())) return false;
if (!ref.getInstances().equals(getInstances())) return false;
return true;
}
return false;
}
public int hashCode() {
long code = getType().hashCode();
code += getInstances().hashCode();
code += getPoints().hashCode();
return (int)code;
}
*/
//
// public methods not in HepRepInstance interface
//
/**
* Verifies if the cached values are valid.
* @return true if cache is valid
*/
public boolean isValid() {
return valid;
}
/**
* Validates the cache.
*/
public void validate() {
if (valid) return;
layer = getAttValue("layer").getString();
hasFrame = getAttValue("hasframe").getBoolean();
valid = true;
}
public String getLayer() {
validate();
return layer;
}
public boolean hasFrame() {
validate();
return hasFrame;
}
}