/** * Copyright 2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.safehaus.penrose.ldap; import java.util.TreeMap; import java.util.Map; import java.util.Collection; import java.util.Iterator; import java.io.Serializable; /** * This class holds source's column values. Each value is an single object, not necessarily a collection. * * @author Endi S. Dewata */ public class RDN implements Serializable, Comparable { public final static long serialVersionUID = 1L; public Map<String,Object> values = new TreeMap<String,Object>(); protected String original; protected String normalized; public String pattern; public RDN() { } public RDN(String rdn) throws Exception { values = new DN(rdn).getRdn().values; } public RDN(Map<String,Object> values) { this.values.putAll(values); } public RDN(RDN rdn) { values.putAll(rdn.getValues()); } public boolean isEmpty() { return values.isEmpty(); } public Object get(String name) { return values.get(name); } public String getName() { return values.keySet().iterator().next(); } public Collection<String> getNames() { return values.keySet(); } public boolean contains(String name) { return values.containsKey(name); } public Object getValue() { return values.values().iterator().next(); } public Map<String,Object> getValues() { return values; } public String getOriginal() throws Exception { if (original != null) return original; original = buildString(false); return original; } public String getNormalized() throws Exception { if (normalized != null) return normalized; normalized = buildString(true); return normalized; } private String buildString(boolean normalize) throws Exception { StringBuilder sb = new StringBuilder(); for (String name : values.keySet()) { Object value = values.get(name); if (value == null) continue; if (sb.length() > 0) sb.append('+'); sb.append(normalize ? name.toLowerCase() : name); sb.append('='); if (value instanceof byte[]) { sb.append('#'); byte[] bytes = (byte[]) value; for (byte b : bytes) { sb.append(hex((char)b)); } } else { sb.append(LDAP.escape(normalize ? value.toString().toLowerCase() : value.toString())); } } return sb.toString(); } private static String hex(char b) { String hex = Integer.toHexString(b); if (hex.length() % 2 == 1) { hex = "0" + hex; } return hex; } public int hashCode() { try { return getOriginal().hashCode(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } boolean equals(Object o1, Object o2) { if (o1 == null && o2 == null) return true; if (o1 != null) return o1.equals(o2); return o2.equals(o1); } public boolean equals(Object object) { if (this == object) return true; if (object == null) return false; if (object.getClass() != this.getClass()) return false; RDN rdn = (RDN)object; try { if (!equals(getOriginal(), rdn.getOriginal())) return false; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } return true; } public int compareTo(Object object) { if (object == null) return 0; if (!(object instanceof RDN)) return 0; RDN rdn = (RDN)object; Iterator i = values.keySet().iterator(); Iterator j = rdn.values.keySet().iterator(); while (i.hasNext() && j.hasNext()) { String name1 = (String)i.next(); String name2 = (String)j.next(); int c = name1.compareTo(name2); if (c != 0) return c; Object value1 = values.get(name1); Object value2 = rdn.values.get(name2); if (value1 instanceof Comparable && value2 instanceof Comparable) { String v1 = value1.toString(); String v2 = value2.toString(); c = v1.compareTo(v2); if (c != 0) return c; } } if (i.hasNext()) return 1; if (j.hasNext()) return -1; return 0; } public String toString() { try { return getOriginal(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } public String getPattern() { if (pattern == null) createPattern(0); return pattern; } public int createPattern(int counter) { StringBuilder sb = new StringBuilder(); for (String name : values.keySet()) { String value = (String) values.get(name); if (sb.length() > 0) sb.append('+'); sb.append(name); sb.append('='); if ("...".equals(value)) { sb.append('{'); sb.append(counter++); sb.append('}'); } else { sb.append(value); } } pattern = sb.toString(); return counter; } public boolean matches(RDN rdn) throws Exception { if (rdn == null) return false; if (getNormalized().equals(rdn.getNormalized())) return true; Collection names = values.keySet(); Collection names2 = rdn.values.keySet(); if (names.size() != names2.size()) return false; Iterator i = names.iterator(); Iterator j = names2.iterator(); while (i.hasNext() && j.hasNext()) { String name = (String)i.next(); String name2 = (String)j.next(); if (!name.equalsIgnoreCase(name2)) { return false; } Object value = values.get(name); Object value2 = rdn.values.get(name2); if ("...".equals(value)) continue; if ("...".equals(value2)) continue; String s1 = value.toString(); String s2 = value2.toString(); if (!s1.equalsIgnoreCase(s2)) return false; } return true; } public synchronized DN append(DN dn) throws Exception { DNBuilder db = new DNBuilder(); db.append(this); db.append(dn); return db.toDn(); } }